5.3.73
This commit is contained in:
commit
8348ab91f4
38607 changed files with 10264427 additions and 0 deletions
91
CHANGELOG.md
Normal file
91
CHANGELOG.md
Normal file
|
@ -0,0 +1,91 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
# Preamble
|
||||
|
||||
This changelog file keeps track of changes made to the linphone-sdk project, which is a only an unbrella project
|
||||
that bundles liblinphone and its dependencies as git submodules.
|
||||
Please refer to CHANGELOG.md files of submodules (mainly: *liblinphone*, *mediastreamer2*, *ortp*) for the actual
|
||||
changes made to these components.
|
||||
|
||||
## [5.3.68] - 2024-07-10
|
||||
|
||||
## Added
|
||||
- Use locale encoding from setlocale() on Windows and fallback to CP_APC if not found.
|
||||
|
||||
## [5.3.0] 2023-12-18
|
||||
|
||||
### Added
|
||||
- dav1d and libaom dependencies for AV-1 codec
|
||||
|
||||
### Changed
|
||||
- Improved CMake build scripts, so that they are faster and integrate smoothly with IDEs.
|
||||
- Update ZLib to 1.2.13
|
||||
- Enum relocations dictionnary is now automatically computed, causing an API change in C++, Swift & Java wrappers!
|
||||
- Update macOS deployment target version to 10.14 and iOS deployment target version to iOS12
|
||||
- Android 14 ready
|
||||
- Update to mbdetls 3.3
|
||||
- TLS Client certificate request authentication callback removed (due to mbedtls update).
|
||||
Application using TLS client certificate must provide it before any TLS connexion needing it.
|
||||
|
||||
# Removed
|
||||
- Jazzy dependency (used to generate Swift documentation), replaced by docc (xcodebuild docbuild)
|
||||
|
||||
|
||||
## [5.2.0] - 2022-11-14
|
||||
|
||||
### Added
|
||||
- Upgrade of zxing-cpp library in order to support QR-code generation.
|
||||
- OpenH264 compilation for UWP.
|
||||
- Support for ARM64 GNU/Linux, XCode 14, Android NDK r25.
|
||||
- New dependencies: Libyuv (image scaling/conversion) and liboqs (quantum-safe cryptographic algorithms).
|
||||
|
||||
### Changed
|
||||
- Updated firebase messaging dependency for Android, now requires at least 23.0.6 (BoM 30.2.0)
|
||||
|
||||
|
||||
## [5.1.0] 2022-02-14
|
||||
|
||||
### Added
|
||||
- Support for Android NDK r23b
|
||||
- Android device rotation is now handled by linphone's PlatformHelper, apps no longer need to do it.
|
||||
|
||||
### Changed
|
||||
- Link Android build to OpenGLESv3 instead of OpenGLESv2
|
||||
|
||||
|
||||
## [5.0.0] - 2021-07-08
|
||||
|
||||
### Added
|
||||
- Native Windows 10 UWP platform support.
|
||||
- OpenLDAP dependency - desktop platforms only.
|
||||
|
||||
## Changed
|
||||
- Windows build now relying on MSYS2 (for parts not built with MSVC)
|
||||
|
||||
|
||||
## [4.5.0] - 2021-03-29
|
||||
|
||||
### Added
|
||||
- Windows Store compatibility
|
||||
|
||||
### Changed
|
||||
- Android minimum compatibility has been increased to Android 6 (Android SDK 23).
|
||||
- Most of changes are documented in liblinphone and mediastreamer2's CHANGELOG.md files.
|
||||
- Python >= 3.6 is now required for build (was python 2.7 previously)
|
||||
|
||||
### Changed
|
||||
- Update libvpx to 1.9.0
|
||||
|
||||
## [4.4.0] - 2020-06-16
|
||||
|
||||
### Added
|
||||
- Windows Store compatibility
|
||||
|
||||
### Changed
|
||||
- liblinphone is now placed into the *liblinphone* directory, naturally.
|
||||
- Android min SDK version updated from 21 to 23.
|
||||
|
146
CMakeLists.txt
Normal file
146
CMakeLists.txt
Normal file
|
@ -0,0 +1,146 @@
|
|||
############################################################################
|
||||
# CMakeLists.txt
|
||||
# Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This file is part of Linphone SDK
|
||||
# (see https://gitlab.linphone.org/BC/public/linphone-sdk).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
############################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
include("bctoolbox/cmake/BCToolboxCMakeUtils.cmake")
|
||||
include("cmake/LinphoneSdkUtils.cmake")
|
||||
|
||||
# Unset PROJECT_VERSION for the case linphone-sdk is included from an other project
|
||||
unset(PROJECT_VERSION)
|
||||
|
||||
if(NOT LINPHONESDK_VERSION) # If LINPHONESDK_VERSION exists (ie: is in cache), then the variable has been overriden by user
|
||||
bc_compute_full_version(LINPHONESDK_VERSION)
|
||||
endif()
|
||||
if(NOT LINPHONESDK_STATE)
|
||||
bc_compute_snapshots_or_releases_state(LINPHONESDK_STATE)
|
||||
endif()
|
||||
if(NOT LINPHONESDK_BRANCH)
|
||||
linphone_sdk_compute_git_branch(LINPHONESDK_BRANCH)
|
||||
endif()
|
||||
set(LINPHONESDK_VERSION_CACHED ${LINPHONESDK_VERSION} CACHE STRING "" FORCE) # Put in cache the current version : it is used to read version in cache
|
||||
|
||||
bc_parse_full_version("${LINPHONESDK_VERSION}" MAJOR MINOR PATCH)
|
||||
|
||||
project(linphone-sdk VERSION "${MAJOR}.${MINOR}.${PATCH}" LANGUAGES C CXX)
|
||||
|
||||
unset(MAJOR)
|
||||
unset(MINOR)
|
||||
unset(PATCH)
|
||||
|
||||
|
||||
if(APPLE)
|
||||
if(LINPHONESDK_PLATFORM MATCHES "Desktop") # On Apple, Desktop == Macos
|
||||
set(LINPHONESDK_PLATFORM "Macos" CACHE STRING "Platform to build" FORCE)
|
||||
else()
|
||||
set(LINPHONESDK_PLATFORM "Macos" CACHE STRING "Platform to build")
|
||||
endif()
|
||||
else()
|
||||
set(LINPHONESDK_PLATFORM "Desktop" CACHE STRING "Platform to build")
|
||||
endif()
|
||||
set_property(CACHE LINPHONESDK_PLATFORM PROPERTY STRINGS "Android" "Desktop" "IOS" "Macos" "UWP" "Yocto")
|
||||
|
||||
set(LINPHONESDK_BUILD_TYPE "Default" CACHE STRING "Type of build")
|
||||
set_property(CACHE LINPHONESDK_BUILD_TYPE PROPERTY STRINGS "Default" "Android" "Flexisip" "IOS" "Macos" "Packager" "UWP" "Windows")
|
||||
|
||||
set(LINPHONESDK_PACKAGER "" CACHE STRING "Packager name")
|
||||
set_property(CACHE LINPHONESDK_PACKAGER PROPERTY STRINGS "Nuget" "")
|
||||
|
||||
|
||||
if(LINPHONESDK_PLATFORM STREQUAL "Android")
|
||||
set(ANDROID TRUE)
|
||||
elseif(LINPHONESDK_PLATFORM STREQUAL "IOS")
|
||||
set(IOS TRUE)
|
||||
elseif(LINPHONESDK_PLATFORM STREQUAL "UWP")
|
||||
set(UWP TRUE)
|
||||
endif()
|
||||
|
||||
include("cmake/Options.cmake")
|
||||
include("cmake/CheckBuildTools${LINPHONESDK_PLATFORM}.cmake")
|
||||
|
||||
if(ENABLE_SANITIZER)
|
||||
include("cmake/Sanitizer.cmake")
|
||||
endif()
|
||||
if(ENABLE_HW_SANITIZER)
|
||||
include("cmake/HWSanitizer.cmake")
|
||||
endif()
|
||||
|
||||
include("cmake/Platform${LINPHONESDK_PLATFORM}.cmake")
|
||||
|
||||
if(LINPHONESDK_BUILD_TYPE STREQUAL "Default" OR LINPHONESDK_BUILD_TYPE STREQUAL "Flexisip")
|
||||
add_custom_target(sdk)
|
||||
if(ENABLE_EKT_SERVER_PLUGIN)
|
||||
include("cmake/EktServerClone.cmake")
|
||||
endif()
|
||||
if(ENABLE_TUNNEL)
|
||||
include("cmake/TunnelClone.cmake")
|
||||
endif()
|
||||
|
||||
# Need to activate ASM and ASM_NASM at the top level and in this order to workaround a bug of CMake
|
||||
enable_language(ASM)
|
||||
enable_language(ASM_NASM)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Modules")
|
||||
include("cmake/ExternalDependencies.cmake")
|
||||
include("cmake/BCProjects.cmake")
|
||||
|
||||
elseif(LINPHONESDK_BUILD_TYPE STREQUAL "Packager")
|
||||
|
||||
include("cmake/LinphoneSdkPackager.cmake")
|
||||
|
||||
else()
|
||||
|
||||
include("cmake/Tasks${LINPHONESDK_BUILD_TYPE}.cmake")
|
||||
|
||||
endif()
|
||||
|
||||
# Give a feature summary
|
||||
include(FeatureSummary)
|
||||
feature_summary(FILENAME "${CMAKE_BINARY_DIR}/enabled_features.txt" WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
|
||||
feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
|
||||
feature_summary(FILENAME "${CMAKE_BINARY_DIR}/disabled_features.txt" WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:")
|
||||
feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:")
|
||||
|
||||
if(ENABLE_GPL_THIRD_PARTIES)
|
||||
message(WARNING "
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
***** CAUTION, this Linphone SDK is built using third party GPL code *****
|
||||
***** Even if you acquired a proprietary license from Belledonne *****
|
||||
***** Communications, this SDK is GPL and GPL only. *****
|
||||
***** To disable third party GPL code, set the *****
|
||||
***** ENABLE_GPL_THIRD_PARTIES option to OFF *****
|
||||
***************************************************************************
|
||||
***************************************************************************")
|
||||
else()
|
||||
message("
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
***** Linphone SDK without third party GPL software *****
|
||||
***** If you acquired a proprietary license from Belledonne *****
|
||||
***** Communications, this SDK can be used to create *****
|
||||
***** a proprietary Linphone-based application. *****
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
")
|
||||
endif()
|
467
CMakePresets.json
Normal file
467
CMakePresets.json
Normal file
|
@ -0,0 +1,467 @@
|
|||
{
|
||||
"version": 3,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 22,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "android-common",
|
||||
"inherits": "default",
|
||||
"hidden": true,
|
||||
"generator": "Unix Makefiles",
|
||||
"cacheVariables": {
|
||||
"BUILD_BCG729_SHARED_LIBS": "OFF",
|
||||
"BUILD_BCUNIT_SHARED_LIBS": "OFF",
|
||||
"BUILD_BELCARD_SHARED_LIBS": "OFF",
|
||||
"BUILD_BELLESIP_SHARED_LIBS": "OFF",
|
||||
"BUILD_BELR_SHARED_LIBS": "OFF",
|
||||
"BUILD_BV16_SHARED_LIBS": "OFF",
|
||||
"BUILD_BZRTP_SHARED_LIBS": "OFF",
|
||||
"BUILD_DECAF_SHARED_LIBS": "OFF",
|
||||
"BUILD_GSM_SHARED_LIBS": "OFF",
|
||||
"BUILD_LIBXML2_SHARED_LIBS": "OFF",
|
||||
"BUILD_LIBYUV_SHARED_LIBS": "OFF",
|
||||
"BUILD_LIME_SHARED_LIBS": "OFF",
|
||||
"BUILD_MBEDTLS_SHARED_LIBS": "OFF",
|
||||
"BUILD_MBEDTLS_WITH_FATAL_WARNINGS": "OFF",
|
||||
"BUILD_OPENLDAP_SHARED_LIBS": "OFF",
|
||||
"BUILD_OPUS_SHARED_LIBS": "OFF",
|
||||
"BUILD_PQCRYPTO_SHARED_LIBS": "OFF",
|
||||
"BUILD_SOCI_SHARED_LIBS": "OFF",
|
||||
"BUILD_SPEEX_SHARED_LIBS": "OFF",
|
||||
"BUILD_SQLITE3_SHARED_LIBS": "OFF",
|
||||
"BUILD_XERCESC_SHARED_LIBS": "OFF",
|
||||
"BUILD_ZLIB": "OFF",
|
||||
"ENABLE_ANDROIDSND": "ON",
|
||||
"ENABLE_CXX_WRAPPER": "OFF",
|
||||
"ENABLE_DAEMON": "OFF",
|
||||
"ENABLE_FLEXIAPI": "ON",
|
||||
"ENABLE_FLOAT_API": "OFF",
|
||||
"ENABLE_FIXED_POINT": "ON",
|
||||
"ENABLE_ISAC": "ON",
|
||||
"ENABLE_JAVA_WRAPPER": "ON",
|
||||
"ENABLE_JNI": "OFF",
|
||||
"ENABLE_LDAP": "ON",
|
||||
"ENABLE_AAUDIO": "ON",
|
||||
"ENABLE_OBOE": "OFF",
|
||||
"ENABLE_RELATIVE_PREFIX": "ON",
|
||||
"ENABLE_STRICT": "OFF",
|
||||
"ENABLE_TOOLS": "OFF",
|
||||
"ENABLE_UNIT_TESTS": "OFF",
|
||||
"ENABLE_TESTS_COMPONENT": "OFF",
|
||||
"ENABLE_WEBRTC_AECM": "ON",
|
||||
"LINPHONESDK_PLATFORM": "Android"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "android-arm64",
|
||||
"inherits": "android-common",
|
||||
"displayName": "Config for Android arm64",
|
||||
"description": "Build for Android arm64 using Unix Makefiles",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-android-arm64.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "android-armv7",
|
||||
"inherits": "android-common",
|
||||
"displayName": "Config for Android armv7",
|
||||
"description": "Build for Android armv7 using Unix Makefiles",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-android-armv7.cmake",
|
||||
"ENABLE_ARM_NEON_INTRINSICS": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "android-x86",
|
||||
"inherits": "android-common",
|
||||
"displayName": "Config for Android x86",
|
||||
"description": "Build for Android x86 using Unix Makefiles",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-android-x86.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "android-x86_64",
|
||||
"inherits": "android-common",
|
||||
"displayName": "Config for Android x86_64",
|
||||
"description": "Build for Android x86_64 using Unix Makefiles",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-android-x86_64.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "android-sdk",
|
||||
"inherits": "android-common",
|
||||
"displayName": "Config for Android",
|
||||
"description": "Build for Android (package for all selected archs)",
|
||||
"cacheVariables": {
|
||||
"LINPHONESDK_BUILD_TYPE": "Android"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "default",
|
||||
"displayName": "Default Config",
|
||||
"description": "Default build using Unix Makefiles generator",
|
||||
"generator": "Unix Makefiles",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ios-common",
|
||||
"inherits": "default",
|
||||
"hidden": true,
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
},
|
||||
"generator": "Xcode",
|
||||
"cacheVariables": {
|
||||
"BUILD_BCG729_SHARED_LIBS": "OFF",
|
||||
"BUILD_BCUNIT_SHARED_LIBS": "OFF",
|
||||
"BUILD_BV16_SHARED_LIBS": "OFF",
|
||||
"BUILD_BZRTP_SHARED_LIBS": "OFF",
|
||||
"BUILD_DECAF_SHARED_LIBS": "OFF",
|
||||
"BUILD_GSM_SHARED_LIBS": "OFF",
|
||||
"BUILD_JSONCPP_SHARED_LIBS": "OFF",
|
||||
"BUILD_LIBJPEGTURBO_SHARED_LIBS": "OFF",
|
||||
"BUILD_LIBOQS_SHARED_LIBS": "OFF",
|
||||
"BUILD_LIBSRTP2_SHARED_LIBS": "OFF",
|
||||
"BUILD_LIBXML2": "OFF",
|
||||
"BUILD_LIBYUV_SHARED_LIBS": "OFF",
|
||||
"BUILD_MBEDTLS_SHARED_LIBS": "OFF",
|
||||
"BUILD_MBEDTLS_WITH_FATAL_WARNINGS": "OFF",
|
||||
"BUILD_OPENLDAP_SHARED_LIBS": "OFF",
|
||||
"BUILD_OPUS_SHARED_LIBS": "OFF",
|
||||
"BUILD_PQCRYPTO_SHARED_LIBS": "OFF",
|
||||
"BUILD_SOCI_SHARED_LIBS": "OFF",
|
||||
"BUILD_SPEEX_SHARED_LIBS": "OFF",
|
||||
"BUILD_SQLITE3": "OFF",
|
||||
"BUILD_TUNNEL_SHARED_LIBS": "OFF",
|
||||
"BUILD_XERCESC_SHARED_LIBS": "OFF",
|
||||
"BUILD_ZLIB": "OFF",
|
||||
"BUILD_ZXINGCPP_SHARED_LIBS": "OFF",
|
||||
"ENABLE_DAEMON": "OFF",
|
||||
"ENABLE_FLEXIAPI": "ON",
|
||||
"ENABLE_FLOAT_API": "OFF",
|
||||
"ENABLE_FIXED_POINT": "ON",
|
||||
"ENABLE_ISAC": "ON",
|
||||
"ENABLE_LDAP": "ON",
|
||||
"ENABLE_RELATIVE_PREFIX": "ON",
|
||||
"ENABLE_STRICT": "OFF",
|
||||
"ENABLE_SWIFT_WRAPPER": "ON",
|
||||
"ENABLE_SWIFT_WRAPPER_COMPILATION": "OFF",
|
||||
"ENABLE_TOOLS": "OFF",
|
||||
"ENABLE_UNIT_TESTS": "OFF",
|
||||
"LINPHONESDK_PLATFORM": "IOS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ios-arm64",
|
||||
"inherits": "ios-common",
|
||||
"displayName": "Config for IOS arm64",
|
||||
"description": "Build for IOS arm64 using Xcode",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-ios-arm64.cmake",
|
||||
"ENABLE_ARM_NEON_INTRINSICS": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ios-arm64-simulator",
|
||||
"inherits": "ios-common",
|
||||
"displayName": "Config for IOS arm64 simulator",
|
||||
"description": "Build for IOS arm64 simulator using Xcode",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-ios-arm64-simulator.cmake",
|
||||
"ENABLE_VPX": "OFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ios-x86_64-simulator",
|
||||
"inherits": "ios-common",
|
||||
"displayName": "Config for IOS x86_64 simulator",
|
||||
"description": "Build for IOS x86_64 simulator using Xcode",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-ios-x86_64-simulator.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ios-sdk",
|
||||
"inherits": "ios-common",
|
||||
"displayName": "Config for IOS",
|
||||
"description": "Build for IOS (package for all selected archs)",
|
||||
"cacheVariables": {
|
||||
"LINPHONESDK_BUILD_TYPE": "IOS",
|
||||
"ENABLE_FAT_BINARY": "OFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mac-common",
|
||||
"inherits": "default",
|
||||
"hidden": true,
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
},
|
||||
"generator": "Xcode",
|
||||
"cacheVariables": {
|
||||
"ENABLE_SWIFT_WRAPPER": "ON",
|
||||
"ENABLE_SWIFT_WRAPPER_COMPILATION": "OFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mac-arm64",
|
||||
"inherits": "mac-common",
|
||||
"displayName": "Config for Mac arm64",
|
||||
"description": "Build for Mac arm64 using Xcode",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-mac-arm64.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mac-x86_64",
|
||||
"inherits": "mac-common",
|
||||
"displayName": "Config for Mac x86_64",
|
||||
"description": "Build for Mac x86_64 using Xcode",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-mac-x86_64.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mac-sdk",
|
||||
"inherits": "mac-common",
|
||||
"displayName": "Config for Mac",
|
||||
"description": "Build for Mac (package for all selected archs)",
|
||||
"cacheVariables": {
|
||||
"LINPHONESDK_BUILD_TYPE": "Macos",
|
||||
"ENABLE_FAT_BINARY": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "raspberrypi-common",
|
||||
"inherits": "default",
|
||||
"hidden": true,
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
},
|
||||
"generator": "Unix Makefiles",
|
||||
"cacheVariables": {
|
||||
"BUILD_BV16_SHARED_LIBS": "OFF",
|
||||
"BUILD_DECAF_SHARED_LIBS": "OFF",
|
||||
"BUILD_GSM_SHARED_LIBS": "OFF",
|
||||
"BUILD_JSONCPP_SHARED_LIBS": "OFF",
|
||||
"BUILD_LIBSRTP2_SHARED_LIBS": "OFF",
|
||||
"BUILD_LIBVPX": "OFF",
|
||||
"BUILD_LIBXML2_SHARED_LIBS": "OFF",
|
||||
"BUILD_LIBYUV_SHARED_LIBS": "OFF",
|
||||
"BUILD_MBEDTLS_SHARED_LIBS": "OFF",
|
||||
"BUILD_MBEDTLS_WITH_FATAL_WARNINGS": "OFF",
|
||||
"BUILD_OPENLDAP_SHARED_LIBS": "OFF",
|
||||
"BUILD_OPUS_SHARED_LIBS": "OFF",
|
||||
"BUILD_SOCI_SHARED_LIBS": "OFF",
|
||||
"BUILD_SPEEX_SHARED_LIBS": "OFF",
|
||||
"BUILD_SQLITE3_SHARED_LIBS": "OFF",
|
||||
"BUILD_XERCESC_SHARED_LIBS": "OFF",
|
||||
"BUILD_ZXINGCPP_SHARED_LIBS": "OFF",
|
||||
"ENABLE_AV1": "OFF",
|
||||
"ENABLE_FLOAT_API": "OFF",
|
||||
"ENABLE_FIXED_POINT": "ON",
|
||||
"ENABLE_STRICT": "OFF",
|
||||
"ENABLE_WEBRTC_AEC": "OFF",
|
||||
"ENABLE_WEBRTC_AECM": "ON",
|
||||
"LINPHONESDK_PLATFORM": "Raspberry",
|
||||
"OPUS_FIXED_POINT": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "raspberrypi-0-1",
|
||||
"inherits": "raspberrypi-common",
|
||||
"displayName": "Config for Raspberry PI Zero/W/WH & 1 Model A/B/A+/B+",
|
||||
"description": "Build for Raspberry PI Zero/W/WH & 1 Model A/B/A+/B+ using Unix Makefiles",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-raspberrypi-0-1.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "raspberrypi-2-3",
|
||||
"inherits": "raspberrypi-common",
|
||||
"displayName": "Config for Raspberry PI 2 & 3 Model A/B",
|
||||
"description": "Build for Raspberry PI 2 & 3 Model A/B using Unix Makefiles",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-raspberrypi-2-3.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "raspberrypi-3+",
|
||||
"inherits": "raspberrypi-common",
|
||||
"displayName": "Config for Raspberry PI 3 & 4 Model A+/B+ & Compute 3/3-lite/3+ (32 bits)",
|
||||
"description": "Build for Raspberry PI 3 & 4 Model A+/B+ & Compute 3/3-lite/3+ (32 bits)",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-raspberrypi-3+.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uwp-common",
|
||||
"inherits": "default",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"generator": "Visual Studio 16 2019",
|
||||
"cacheVariables": {
|
||||
"BUILD_MBEDTLS_WITH_FATAL_WARNINGS": "OFF",
|
||||
"ENABLE_AV1": "OFF",
|
||||
"ENABLE_CSHARP_WRAPPER": "ON",
|
||||
"ENABLE_DAEMON": "OFF",
|
||||
"ENABLE_FLEXIAPI": "ON",
|
||||
"ENABLE_G729B_CNG": "OFF",
|
||||
"ENABLE_LDAP": "ON",
|
||||
"ENABLE_RELATIVE_PREFIX": "ON",
|
||||
"ENABLE_TOOLS": "OFF",
|
||||
"ENABLE_TUTORIALS": "OFF",
|
||||
"ENABLE_UNIT_TESTS": "OFF",
|
||||
"ENABLE_WEBRTC_AECM": "ON",
|
||||
"ENABLE_WINDOWS_TOOLS_CHECK": "OFF",
|
||||
"LINPHONESDK_PLATFORM": "UWP"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uwp-x64",
|
||||
"inherits": "uwp-common",
|
||||
"displayName": "Config for UWP 64 bits",
|
||||
"description": "Build for UWP 64 bits using Visual Studio 2019",
|
||||
"architecture": "x64",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-uwp-x64.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uwp-x86",
|
||||
"inherits": "uwp-common",
|
||||
"displayName": "Config for UWP 32 bits",
|
||||
"description": "Build for UWP 32 bits using Visual Studio 2019",
|
||||
"architecture": "Win32",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-uwp-x86.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uwp-sdk",
|
||||
"inherits": "uwp-common",
|
||||
"displayName": "Config for UWP",
|
||||
"description": "Build for UWP (package for all selected archs)",
|
||||
"cacheVariables": {
|
||||
"LINPHONESDK_BUILD_TYPE": "UWP"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-common",
|
||||
"inherits": "default",
|
||||
"hidden": true,
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"generator": "Visual Studio 16 2019",
|
||||
"cacheVariables": {
|
||||
"ENABLE_LDAP": "ON",
|
||||
"BUILD_MBEDTLS_WITH_FATAL_WARNINGS": "OFF",
|
||||
"ENABLE_CSHARP_WRAPPER": "ON",
|
||||
"ENABLE_RELATIVE_PREFIX": "ON",
|
||||
"ENABLE_WINDOWS_TOOLS_CHECK": "OFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-32bits",
|
||||
"inherits": "windows-common",
|
||||
"displayName": "Config for Windows 32 bits",
|
||||
"description": "Build for Windows 32 bits using Visual Studio 2019",
|
||||
"architecture": "Win32"
|
||||
},
|
||||
{
|
||||
"name": "windows-64bits",
|
||||
"inherits": "windows-common",
|
||||
"displayName": "Config for Windows 64 bits",
|
||||
"description": "Build for Windows 64 bits using Visual Studio 2019",
|
||||
"architecture": "x64"
|
||||
},
|
||||
{
|
||||
"name": "windows-sdk",
|
||||
"inherits": "windows-common",
|
||||
"displayName": "Config for Windows",
|
||||
"description": "Build for Windows (package for all selected archs)",
|
||||
"cacheVariables": {
|
||||
"LINPHONESDK_BUILD_TYPE": "Windows"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-ninja-common",
|
||||
"inherits": "windows-common",
|
||||
"hidden": true,
|
||||
"generator": "Ninja"
|
||||
},
|
||||
{
|
||||
"name": "windows-ninja-32bits",
|
||||
"inherits": "windows-ninja-common",
|
||||
"displayName": "Config for Windows 32 bits",
|
||||
"description": "Build for Windows 32 bits using Ninja"
|
||||
},
|
||||
{
|
||||
"name": "windows-ninja-64bits",
|
||||
"inherits": "windows-common",
|
||||
"displayName": "Config for Windows 64 bits",
|
||||
"description": "Build for Windows 64 bits using Ninja"
|
||||
},
|
||||
{
|
||||
"name": "windows-ninja-sdk",
|
||||
"inherits": "windows-ninja-common",
|
||||
"displayName": "Config for Windows",
|
||||
"description": "Build for Windows (package for all selected archs)",
|
||||
"cacheVariables": {
|
||||
"LINPHONESDK_BUILD_TYPE": "Windows",
|
||||
"LINPHONESDK_WINDOWS_PRESET_PREFIX": "windows-ninja-"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-store-32bits",
|
||||
"inherits": "windows-common",
|
||||
"displayName": "Config for Windows Store 32 bits",
|
||||
"description": "Build for Windows Store 32 bits using Visual Studio 2019",
|
||||
"architecture": "Win32",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-windows-store-x86.cmake",
|
||||
"ENABLE_MICROSOFT_STORE_APP": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-store-64bits",
|
||||
"inherits": "windows-common",
|
||||
"displayName": "Config for Windows Store 64 bits",
|
||||
"description": "Build for Windows Store 64 bits using Visual Studio 2019",
|
||||
"architecture": "x64",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/toolchain-windows-store-x64.cmake",
|
||||
"ENABLE_MICROSOFT_STORE_APP": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-store-sdk",
|
||||
"inherits": "windows-common",
|
||||
"displayName": "Config for Windows Store",
|
||||
"description": "Build for Windows Store (package for all selected archs)",
|
||||
"cacheVariables": {
|
||||
"ENABLE_MICROSOFT_STORE_APP": "ON",
|
||||
"LINPHONESDK_BUILD_TYPE": "Windows"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
661
LICENSE.txt
Normal file
661
LICENSE.txt
Normal file
|
@ -0,0 +1,661 @@
|
|||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
314
README.md
Normal file
314
README.md
Normal file
|
@ -0,0 +1,314 @@
|
|||
[](https://gitlab.linphone.org/BC/public/linphone-sdk/commits/master)
|
||||
|
||||
# Linphone-SDK
|
||||
|
||||
Linphone-SDK is a project that bundles Liblinphone and its dependencies as git submodules, in the purpose of simplifying
|
||||
the compilation and packaging of the whole Liblinphone suite, comprising Mediastreamer2, Belle-sip, oRTP and many others.
|
||||
Its compilation produces a SDK suitable to create applications running on top of these components.
|
||||
The submodules that are not developed or maintained by the Linphone team are grouped in the external/ directory.
|
||||
The currently supported platforms are Android, iOS, Desktop (Linux, Windows, Mac OS X) and UWP (Universal Windows Platform).
|
||||
|
||||
## License
|
||||
|
||||
Copyright © Belledonne Communications
|
||||
|
||||
The software products developed in the context of the Linphone project are dual licensed, and are available either :
|
||||
|
||||
- under a [GNU/AGPLv3 license](https://www.gnu.org/licenses/agpl-3.0.html), for free (open source). Please make sure that you understand and agree with the terms of this license before using it (see LICENSE.txt file for details). AGPLv3 is choosen over GPLv3 because linphone-sdk can be used to create server-side applications, not just client-side ones. Any product incorporating linphone-sdk to provide a remote service then has to be licensed under AGPLv3.
|
||||
For a client-side product, the "remote interaction" clause of AGPLv3 being irrelevant, the usual terms GPLv3 terms do apply (the two licences differ by this only clause).
|
||||
|
||||
- under a proprietary license, for a fee, to be used in closed source applications. Contact [Belledonne Communications](https://www.linphone.org/contact) for any question about costs and services.
|
||||
|
||||
**For more information about de third-party licences, please see the [Licensing: GPL third parties versus non GPL third parties](#licensing-gpl-third-parties-versus-non-gpl-third-parties) section
|
||||
|
||||
## Build dependencies
|
||||
|
||||
### Common to all target platforms
|
||||
|
||||
The following tools must be installed on the build machine:
|
||||
- Cmake >= 3.22
|
||||
- python >= 3.6
|
||||
- pip (or pip3 if the build machine has both python2 and python3)
|
||||
- yasm
|
||||
- nasm
|
||||
- doxygen
|
||||
- Pystache (use `pip install pystache` or `pip3 install pystache`)
|
||||
- six (use `pip install six` or `pip3 install six`)
|
||||
|
||||
If you are building the AV1 codec, which is enabled by default (`ENABLE_AV1=Off` to disable), you will also need:
|
||||
- Meson
|
||||
- Ninja
|
||||
- Perl
|
||||
|
||||
### Retrieve the dependencies
|
||||
|
||||
Linphone-SDK's git repository comprises git submodules. It must be cloned with the `--recursive` option. After updating or switching branches, never forget to checkout and update the submodules with:
|
||||
|
||||
git submodule update --init --recursive
|
||||
|
||||
### Windows
|
||||
|
||||
SDK compilation is supported on `Visual Studio 15 2017`/`Visual Studio 16 2019` and `MSYS2` https://www.msys2.org/.
|
||||
|
||||
Only [CMake](https://cmake.org/), [7Zip](https://www.7-zip.org/download.html) and [MSYS2](https://www.msys2.org/) are needed before the build.
|
||||
Add the 7Zip executable in your PATH as it is not automatically done.
|
||||
|
||||
|
||||
#### MSYS2
|
||||
|
||||
Follow MSYS2 instructions on their ["Getting Started" page](https://www.msys2.org/).
|
||||
|
||||
Both MinGW32 and MinGW64 are supported.
|
||||
|
||||
When building the SDK and if you set `-DENABLE_WINDOWS_TOOLS_CHECK=ON`, it will install automatically from MSYS2 : `toolchain`, `python`, `doxygen`, `perl`, `yasm`, `gawk`, `bzip2`, `nasm`, `sed`, `intltool`, `graphviz`, `meson` and `ninja` (if needed)
|
||||
|
||||
In this order, add `C:\msys64\mingw<N>\bin`, `C:\msys64\` and `C:\msys64\usr\bin` in your PATH environement variable from Windows advanced settings. Binaries from the msys folder (not from mingw32/64) doesn't fully support Windows Path and thus, they are to be avoided.
|
||||
*<N> is the version of MinGW32/64*
|
||||
|
||||
#### Visual Studio
|
||||
|
||||
Visual Studio must also be properly configured with addons. Under "Tools"->"Obtain tools and features", make sure that the following components are installed:
|
||||
- Tasks: Select Windows Universal Platform development, Desktop C++ Development, .NET Development
|
||||
|
||||
For Visual Studio 2017 :
|
||||
- Under "Installation details". Go to "Desktop C++ Development" and add "SDK Windows 8.1 and SDK UCRT"
|
||||
- Individual component: Windows 8.1 SDK
|
||||
|
||||
## Build
|
||||
|
||||
A build with the Ninja generator (`-G "Ninja"`) or the Ninja Multi-Config generator (`-G "Ninja Multi-Config"`) is preferred for speed-up build times.
|
||||
|
||||
There are two slightly different ways to build, depending on whether you use a multi-config CMake generator (`Xcode`, `Ninja Multi-Config`, Visual Studio) or not (`Unix Makefiles`, `Ninja`). In both cases, the steps are:
|
||||
1. Configure the project
|
||||
2. Build the project
|
||||
|
||||
The steps described here are the base for building, but a few specifics behaviors for each platform are good to know and are described in the next subsections.
|
||||
|
||||
#### Multi-Config generator
|
||||
|
||||
In the case of a multi-config generator, you will:
|
||||
1. Execute CMake to configure the project by giving the preset you want to build (you can get the list of presets available with the `cmake --list-presets` command), the build directory where you want the build to take place, the generator you want to use and eventually some additional options:
|
||||
`cmake --preset=<PRESET> -B <BUILD DIRECTORY> -G <MULTI-CONFIG GENERATOR> <SOME OPTIONS>`
|
||||
2. Build the SDK:
|
||||
`cmake --build <BUILD DIRECTORY> --config <CONFIG>`
|
||||
or
|
||||
`cmake --build <BUILD DIRECTORY> --config <CONFIG> --parallel <number of jobs>` (which is faster).
|
||||
|
||||
The `<CONFIG>` is one of these:
|
||||
- `RelWithDebInfo` to build in release mode keeping the debug information (this is the recommended configuration to use).
|
||||
- `Release` to build in release mode without the debug information.
|
||||
- `Debug` to ease the debugging.
|
||||
- On Android, use `ASAN` to make a build linking with the Android Adress Sanitizer (https://github.com/google/sanitizers/wiki/AddressSanitizerOnAndroid).
|
||||
|
||||
### Unique config generator
|
||||
|
||||
In this case, you will need to choose the build configuration in the first step, the configuration one. For that, you need to use the `CMAKE_BUILD_TYPE=<CONFIG>` option, and then you do not need to pass the `--config <CONFIG>` option in the build step. This will give:
|
||||
1. Configure the project:
|
||||
`cmake --preset=<PRESET> -B <BUILD DIRECTORY> -G <GENERATOR> -DCMAKE_BUILD_TYPE=<CONFIG> <SOME OPTIONS>`
|
||||
2. Build the SDK:
|
||||
`cmake --build <BUILD DIRECTORY>`
|
||||
|
||||
|
||||
### iOS
|
||||
|
||||
Requirement:
|
||||
- Xcode >= 15
|
||||
|
||||
`cmake --preset=ios-sdk -G Xcode -B build-ios -DLINPHONESDK_IOS_PLATFORM=Iphone -DLINPHONESDK_IOS_ARCHS="arm64"`
|
||||
`cmake --build build-ios --config Debug`
|
||||
|
||||
You can also build using the 'Ninja' or 'Unix makefiles' generators:
|
||||
|
||||
`cmake --preset=ios-sdk -G Ninja -B build-ios -DCMAKE_BUILD_TYPE=Debug`
|
||||
`cmake --build build-ios`
|
||||
|
||||
The generation of the Swift documentation (docc) requires the Xcode generator, and hence won't be generated with the above command.
|
||||
In order to generate the swift documentation, a new separate build needs to be done using the ios-arm64-simulator preset:
|
||||
|
||||
`cmake --preset=ios-arm64-simulator -G Xcode -B build-ios`
|
||||
|
||||
|
||||
⚙ Note to developers: If a new Apple `.framework` folder needs to be added to the iOS build, remember to update the [NuGet iOS project] to include it.
|
||||
|
||||
[NuGet iOS project]: cmake/NuGet/Xamarin/LinphoneSDK.Xamarin/LinphoneSDK.Xamarin.iOS/LinphoneSDK.Xamarin.iOS.csproj
|
||||
|
||||
### Android (using Docker)
|
||||
|
||||
Download the Docker image of the Android build environment:
|
||||
|
||||
|
||||
---
|
||||
**public access, with token**
|
||||
|
||||
Use this token to access the Docker registry :
|
||||
|
||||
user : gitlab+deploy-token-17
|
||||
|
||||
pass : fFVgA_5Mf-qn2WbvsKRL
|
||||
|
||||
---
|
||||
|
||||
|
||||
**private access**
|
||||
|
||||
A simple login with your Gitlab account should work.
|
||||
To know what docker image to pull, first check [.gitlab-ci-files/android/builds.yml](https://gitlab.linphone.org/BC/public/linphone-sdk/-/blob/master/.gitlab-ci-files/android/builds.yml)
|
||||
Currently we are using `bc-dev-android-r25` image name.
|
||||
|
||||
You'll find the associated tag in [.gitlab-ci-files/.docker-images.yml](https://gitlab.linphone.org/BC/public/linphone-sdk/-/blob/master/.gitlab-ci-files/.docker-images.yml) (for Android R25 image it is currently `20230519_use_cmake_3.22`).
|
||||
|
||||
Replace `<name>` and `<tag>` in the commands below by the value you found.
|
||||
|
||||
---
|
||||
|
||||
```bash
|
||||
docker login gitlab.linphone.org:4567/bc/public/linphone-sdk
|
||||
docker pull gitlab.linphone.org:4567/bc/public/linphone-sdk/<name>:<tag>
|
||||
```
|
||||
|
||||
Load the build environment:
|
||||
|
||||
```bash
|
||||
cd <linphone-sdk-source>
|
||||
docker run -it --volume=$PWD:/home/bc/linphone-sdk gitlab.linphone.org:4567/bc/public/linphone-sdk/<name>:<tag> /bin/bash -i
|
||||
```
|
||||
|
||||
Next command lines must be typed in the docker shell:
|
||||
|
||||
```bash
|
||||
# Configure the build
|
||||
cmake --preset=android-sdk -B build-android -DLINPHONESDK_ANDROID_ARCHS=arm64 -DCMAKE_BUILD_TYPE=RelWithDebInfo <extra-variable-definitions>
|
||||
|
||||
# Build
|
||||
cmake --build build-android --parallel <number of jobs>
|
||||
|
||||
# Quit build environment
|
||||
exit
|
||||
```
|
||||
|
||||
The freshly built SDK is located in the `build-android/` directory.
|
||||
|
||||
### MacOS
|
||||
|
||||
Requirement:
|
||||
- Xcode >= 12
|
||||
|
||||
Configure the project with:
|
||||
|
||||
`cmake --preset=mac-sdk -B build-mac -G Xcode`
|
||||
|
||||
And build it with:
|
||||
|
||||
`cmake --build build-mac --config RelWithDebInfo`
|
||||
|
||||
As for the iOS build, you can alternatively build with Ninja instead of Xcode by specifying it during the configuration step:
|
||||
|
||||
`cmake --preset=mac-sdk -B build-mac -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo`
|
||||
`cmake --build build-mac`
|
||||
|
||||
### Windows
|
||||
|
||||
Configure the project with:
|
||||
|
||||
`cmake --preset=windows-sdk -B build-windows`
|
||||
|
||||
As for all other platforms, you can then build with:
|
||||
|
||||
`cmake --build build-windows --config RelWithDebInfo`
|
||||
|
||||
However it may be convenient to build from Visual Studio, which you can do:
|
||||
- open `linphone-sdk.sln` with Visual Studio
|
||||
- select the configuration you want to build
|
||||
- use `Build solution` to build.
|
||||
|
||||
### Windows UWP and Stores
|
||||
|
||||
You can use linphone-sdk in your Windows UWP app with the UWP mode.
|
||||
Win32 application can use the Windows Store mode in order to be publishable in Windows Stores.
|
||||
The Windows Bridge mode is built by using the `windows-store` preset instead of the `windows` one.
|
||||
The UWP mode is built by using the `uwp` preset instead of the `windows` one. If `-DLINPHONESDK_UWP_ARCHS` is not used, x86 and x64 will be build.
|
||||
|
||||
Then, you can inject directly all your libraries that you need or package the SDK in a Nuget package.
|
||||
|
||||
### NuGet packaging
|
||||
|
||||
The Linphone SDK is available as a `.nuget` package for .NET applications (Windows & Xamarin).
|
||||
|
||||
See the [`cmake/NuGet`](cmake/NuGet/README.md) folder for build instructions.
|
||||
|
||||
|
||||
## Upgrading your SDK
|
||||
|
||||
Simply re-invoking `cmake --build <BUILD DIRECTORY>` in your build directory should update your SDK. If compilation fails, you may need to rebuilding everything by erasing your build directory and restarting your build as explained above.
|
||||
|
||||
## Customizing the build
|
||||
|
||||
The SDK compilation can be customized by passing `-D` options to CMake when configuring the project. If you know the options you want to use, just pass them to CMake.
|
||||
|
||||
Otherwise, you can use the `cmake-gui` or `ccmake` commands to configure all the available options interactively.
|
||||
|
||||
The following options control the cpu architectures built for a target platform:
|
||||
- `LINPHONESDK_ANDROID_ARCHS`: A comma-separated list of the architectures for which you want to build the Android Linphone SDK for.
|
||||
- `LINPHONESDK_IOS_ARCHS`: Same as `LINPHONESDK_ANDROID_ARCHS` but for an iOS build.
|
||||
- `LINPHONESDK_IOS_BASE_URL`: The base of the URL that will be used to download the zip file of the SDK when building for iOS.
|
||||
- `LINPHONESDK_MACOS_ARCHS`: Same as `LINPHONESDK_ANDROID_ARCHS` but for a MacOS build. Currently supported : x86_64, arm64
|
||||
- `LINPHONESDK_MACOS_BASE_URL`: The base of the URL that will be used to download the zip file of the SDK when building for macos.
|
||||
- `LINPHONESDK_WINDOWS_ARCHS`: Same as `LINPHONESDK_ANDROID_ARCHS` but for a windows build.
|
||||
- `LINPHONESDK_WINDOWS_BASE_URL`: The base of the URL that will be used to download the zip file of the SDK when building for windows.
|
||||
- `LINPHONESDK_UWP_ARCHS`: Same as `LINPHONESDK_ANDROID_ARCHS` but for an UWP build and Nuget.
|
||||
|
||||
These ON/OFF options control the enablement of important features of the SDK, which have an effect on the size of produced size object code:
|
||||
- `ENABLE_VIDEO`: enablement of video call features.
|
||||
- `ENABLE_ADVANCED_IM`: enablement of group chat and secure IM features
|
||||
- `ENABLE_ZRTP`: enablement of ZRTP ciphering
|
||||
- `ENABLE_DB_STORAGE`: enablement of database storage for IM.
|
||||
- `ENABLE_VCARD`: enablement of Vcard features.
|
||||
- `ENABLE_MKV`: enablement of Matroska video file reader/writer.
|
||||
- `ENABLE_LDAP`: enablement of OpenLDAP.
|
||||
|
||||
<a name="licensing-gpl-third-parties-versus-non-gpl-third-parties"></a>
|
||||
## Licensing: GPL third parties versus non GPL third parties
|
||||
|
||||
This SDK can be generated in 2 flavors:
|
||||
|
||||
* GPL third parties enabled means that the Linphone SDK includes GPL third parties like FFmpeg. If you choose this flavor, your final application **must comply with GPL in any case**.
|
||||
|
||||
* NO GPL third parties means that the Linphone SDK will only use non GPL code except for the code from Belledonne Communications. If you choose this flavor, your final application is **still subject to the GPL except if you have a [commercial license from Belledonne Communications](http://www.belledonne-communications.com/products.html)**. **This is the default mode.**
|
||||
|
||||
To generate the a SDK with GPL third parties, use the `-DENABLE_GPL_THIRD_PARTIES=YES` option when configuring the project (you can set "NO" to disable explicitly).
|
||||
|
||||
## Note regarding third party components subject to license
|
||||
|
||||
The Linphone SDK can be compiled with third parties code that are subject to patent license, especially: AMR, SILK and H264 codecs.
|
||||
To build a SDK with any of these features you need to enable the `ENABLE_NON_FREE_FEATURES` option (**disabled by default**).
|
||||
Before embedding these features in your final application, **make sure to have the right to do so**.
|
||||
|
||||
For more information, please visit [our dedicated wiki page](https://wiki.linphone.org/xwiki/wiki/public/view/Linphone/Third%20party%20components%20/)
|
||||
|
||||
### Nuget packaging
|
||||
You can package 3 kinds of binaries : win32, uwp and win32 with Windows Store Compatibility.
|
||||
|
||||
- win32: this is the win32 version of Linphone-SDK without any restrictions. The framework is 'win'.
|
||||
- uwp : this is a uwp x64/x86 version of Linphone-SDK. The framework is 'uap10.0'.
|
||||
- win32 Windows Store : this is the win32 version of Linphone-SDK with the Windows Store Compatibility enabled for Windows Bridge. The framework is 'netcore'.
|
||||
|
||||
In an another build folder (like buildNuget), set these options. At least one path is needed :
|
||||
- (Needed) -DLINPHONESDK_PACKAGER=Nuget
|
||||
- (Optional) -DLINPHONESDK_DESKTOP_ZIP_PATH=<path of the zip file containing the Desktop binaries> (eg. C:/projects/desktop-uwp/linphone-sdk/buildx86/linphone-sdk)
|
||||
- (Optional) -DLINPHONESDK_UWP_ZIP_PATH=<path of the zip file containing the UWP binaries> (eg. C:/projects/desktop-uwp/linphone-sdk/builduwp/linphone-sdk)
|
||||
- (Optional) -DLINPHONESDK_WINDOWSSTORE_ZIP_PATH=<path of the zip file containing the Desktop binaries with Store compatibility enabled> (eg. C:/projects/desktop-uwp/linphone-sdk/buildx86_store/linphone-sdk)
|
||||
- (Optional) -DLINPHONESDK_UWP_ARCHS=<list of archs to package> (eg. "x86, x64" or "x64")
|
||||
|
||||
Build the Package:
|
||||
|
||||
cmake .. -DLINPHONESDK_PACKAGER=Nuget -DLINPHONESDK_UWP_ZIP_PATH=C:/projects/desktop-uwp/linphone-sdk/builduwp/linphone-sdk
|
||||
cmake --build . --target ALL_BUILD --config=RelWithDebInfo
|
||||
|
||||
The nuget package will be in linphone-sdk/packages
|
||||
The generated package can keep the same file name between each generations on the same git version. Visual studio keep a cache of the Nuget and you need to delete its internal folder to take account any newer version for the same name.
|
||||
The folder can be found in your system path at <User>/.nuget/packages/linphonesdk
|
||||
|
||||
### Demo app
|
||||
|
||||
There is a very limited version of an application that can use this nuget at `https://gitlab.linphone.org/BC/public/linphone-windows10`
|
||||
|
2
bcg729/AUTHORS.md
Normal file
2
bcg729/AUTHORS.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
* Johan Pascal
|
||||
* Jehan Monnier
|
36
bcg729/Android.mk
Normal file
36
bcg729/Android.mk
Normal file
|
@ -0,0 +1,36 @@
|
|||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := libbcg729
|
||||
|
||||
LOCAL_ARM_MODE := arm
|
||||
|
||||
LOCAL_SRC_FILES = src/LP2LSPConversion.c \
|
||||
src/LPSynthesisFilter.c \
|
||||
src/LSPQuantization.c \
|
||||
src/adaptativeCodebookSearch.c \
|
||||
src/codebooks.c \
|
||||
src/computeAdaptativeCodebookGain.c \
|
||||
src/computeLP.c \
|
||||
src/computeWeightedSpeech.c \
|
||||
src/decodeAdaptativeCodeVector.c \
|
||||
src/decodeFixedCodeVector.c \
|
||||
src/decodeGains.c \
|
||||
src/decodeLSP.c \
|
||||
src/decoder.c \
|
||||
src/encoder.c \
|
||||
src/findOpenLoopPitchDelay.c \
|
||||
src/fixedCodebookSearch.c \
|
||||
src/gainQuantization.c \
|
||||
src/interpolateqLSP.c \
|
||||
src/postFilter.c \
|
||||
src/postProcessing.c \
|
||||
src/preProcessing.c \
|
||||
src/qLSP2LP.c \
|
||||
src/utils.c
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(LOCAL_PATH)/include
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
|
47
bcg729/BCG729Config.cmake.in
Normal file
47
bcg729/BCG729Config.cmake.in
Normal file
|
@ -0,0 +1,47 @@
|
|||
############################################################################
|
||||
# BCG729Config.cmake
|
||||
# Copyright (C) 2015-2023 Belledonne Communications, Grenoble France
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# Config file for the bcg729 package.
|
||||
#
|
||||
# Targets
|
||||
# ^^^^^^^
|
||||
#
|
||||
# The following targets are defined:
|
||||
# bcg729 - The bcg729 library target
|
||||
#
|
||||
#
|
||||
# Result variables
|
||||
# ^^^^^^^^^^^^^^^^
|
||||
#
|
||||
# This config file will set the following variables in your project:
|
||||
#
|
||||
# BCG729_FOUND - The bcg729 library has been found
|
||||
# BCG729_TARGET - The name of the CMake target for the bcg729 library
|
||||
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/BCG729Targets.cmake")
|
||||
|
||||
set(BCG729_TARGET bcg729)
|
||||
|
||||
check_required_components(BZRTP)
|
23
bcg729/CHANGELOG.md
Normal file
23
bcg729/CHANGELOG.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.1.1] - 2020-11-17
|
||||
|
||||
### Fixed
|
||||
- compatibility with old compilers
|
||||
|
||||
## [1.1.0] - 2020-11-17
|
||||
|
||||
### Fixed
|
||||
- infinite loop in VAD module and overflow in encoder
|
||||
- build scripts
|
||||
### Changed
|
||||
- License is changed to GNU GPLv3.
|
||||
|
||||
## [1.0.4] - 2017-07-20
|
||||
|
||||
### Fixed
|
||||
- build system issues.
|
118
bcg729/CMakeLists.txt
Normal file
118
bcg729/CMakeLists.txt
Normal file
|
@ -0,0 +1,118 @@
|
|||
############################################################################
|
||||
# CMakeLists.txt
|
||||
# Copyright (C) 2014-2023 Belledonne Communications, Grenoble France
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
project(BCG729 VERSION 1.1.1 LANGUAGES C)
|
||||
|
||||
|
||||
set(PACKAGE "${PROJECT_NAME}")
|
||||
set(PACKAGE_NAME "${PROJECT_NAME}")
|
||||
set(PACKAGE_VERSION "${PROJECT_VERSION}")
|
||||
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
||||
set(PACKAGE_BUGREPORT "support@belledonne-communications.com")
|
||||
set(PACKAGE_TARNAME "bcg729")
|
||||
set(PACKAGE_URL "")
|
||||
set(VERSION "${PACKAGE_VERSION}")
|
||||
|
||||
|
||||
option(ENABLE_STRICT "Build with strict compile options." YES)
|
||||
option(ENABLE_UNIT_TESTS "Enable compilation of the tests." NO)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
|
||||
|
||||
set(BCG729_CPPFLAGS )
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
set(BCG729_STATIC 1)
|
||||
list(APPEND BCG729_CPPFLAGS "-DBCG729_STATIC")
|
||||
endif()
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
|
||||
if(MSVC)
|
||||
add_definitions("/W3")
|
||||
else()
|
||||
add_definitions("-Wall")
|
||||
if(ENABLE_STRICT)
|
||||
if (NOT IOS)
|
||||
add_definitions(" -Werror -Wextra -Wno-unused-parameter -Wno-missing-field-initializers ")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT ENABLE_UNIT_TESTS) # test access inner functions so maintain visibility if we want to run tests
|
||||
add_definitions("-fvisibility=hidden")
|
||||
endif()
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_definitions("-Wno-error=unused-command-line-argument")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
configure_file(${PROJECT_SOURCE_DIR}/config.h.cmake ${PROJECT_BINARY_DIR}/config.h)
|
||||
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(src)
|
||||
if(ENABLE_UNIT_TESTS AND NOT WIN32)
|
||||
# Deactivated on Windows because of symbol export issues (TODO: fix that)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
set(CMAKE_MODULES_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake")
|
||||
configure_package_config_file("${PROJECT_NAME}Config.cmake.in" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION "${CMAKE_MODULES_INSTALL_DIR}"
|
||||
NO_SET_AND_CHECK_MACRO
|
||||
)
|
||||
write_basic_package_version_file("${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion
|
||||
)
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
DESTINATION ${CMAKE_MODULES_INSTALL_DIR}
|
||||
)
|
||||
|
||||
export(EXPORT ${PROJECT_NAME}Targets
|
||||
FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake"
|
||||
)
|
||||
install(EXPORT ${PROJECT_NAME}Targets
|
||||
FILE "${PROJECT_NAME}Targets.cmake"
|
||||
DESTINATION ${CMAKE_MODULES_INSTALL_DIR}
|
||||
)
|
||||
|
||||
|
||||
set(prefix "${CMAKE_INSTALL_PREFIX}")
|
||||
set(exec_prefix "\${prefix}")
|
||||
set(includedir "\${prefix}/include")
|
||||
set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
|
||||
configure_file(libbcg729.pc.in
|
||||
"${PROJECT_BINARY_DIR}/libbcg729.pc"
|
||||
@ONLY
|
||||
)
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/libbcg729.pc"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
||||
)
|
||||
|
||||
|
||||
add_subdirectory(build)
|
621
bcg729/LICENSE.txt
Normal file
621
bcg729/LICENSE.txt
Normal file
|
@ -0,0 +1,621 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
14
bcg729/Makefile.am
Normal file
14
bcg729/Makefile.am
Normal file
|
@ -0,0 +1,14 @@
|
|||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
EXTRA_DIST = bcg729.spec Bcg729Config.cmake CMakeLists.txt config.h.cmake src/CMakeLists.txt
|
||||
SUBDIRS = include src
|
||||
|
||||
if RUN_TESTS
|
||||
SUBDIRS += test
|
||||
endif
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libbcg729.pc
|
||||
|
||||
rpm:
|
||||
$(MAKE) dist
|
||||
TAR_OPTIONS=--wildcards rpmbuild -ta --clean --rmsource --rmspec $(PACKAGE)-$(VERSION).tar.gz
|
86
bcg729/README.md
Normal file
86
bcg729/README.md
Normal file
|
@ -0,0 +1,86 @@
|
|||
[](https://gitlab.linphone.org/BC/public/bcg729/commits/master)
|
||||
|
||||
Bcg729
|
||||
======
|
||||
|
||||
About bcg729
|
||||
------------
|
||||
|
||||
Bcg729 is an opensource implementation of both encoder and decoder of the ITU G729 Annex A/B speech codec.
|
||||
|
||||
The library written in C 99 is fully portable and can be executed on many platforms including both ARM and x86 processors.
|
||||
libbcg729 supports concurrent channels encoding/decoding for multi call application such as conferencing.
|
||||
|
||||
For more information, [please visit bcg729's homepage on **linphone.org**](https://linphone.org/technical-corner/bcg729).
|
||||
|
||||
Licensing
|
||||
---------
|
||||
|
||||
Copyright © Belledonne Communications
|
||||
|
||||
bcg729 is dual licensed, and is available either :
|
||||
|
||||
- under a [GNU/GPLv3 license](https://www.gnu.org/licenses/gpl-3.0.en.html), for free (open source). Please make sure that you understand and agree with the terms of this license before using it (see LICENSE.txt file for details).
|
||||
|
||||
- under a proprietary license, for a fee, to be used in closed source applications. Contact [Belledonne Communications](https://www.linphone.org/contact) for any question about costs and services.
|
||||
|
||||
Patents
|
||||
-------
|
||||
|
||||
ITU G729 Annex A/B were offically released October/November 1996 (https://www.itu.int/rec/T-REC-G.729),
|
||||
hence all patents covering these specifications shall have expired in November 2016.
|
||||
Patent pool administrator confirmed most licensed patents under the G.729 Consortium have expired (<http://www.sipro.com/G729.html>).
|
||||
|
||||
Compilation
|
||||
-----------
|
||||
|
||||
### Dependencies
|
||||
|
||||
No dependency is requested.
|
||||
|
||||
|
||||
### Build procedure
|
||||
|
||||
Building by Autotools way is deprecated. Use [CMake][cmake-website] to configure the source code.
|
||||
|
||||
cmake . -DCMAKE_INSTALL_PREFIX=<prefix> -DCMAKE_PREFIX_PATH=<search_prefixes>
|
||||
|
||||
make
|
||||
make install
|
||||
|
||||
|
||||
### Supported build options
|
||||
|
||||
* `CMAKE_INSTALL_PREFIX=<string>` : install prefix
|
||||
* `CMAKE_PREFIX_PATH=<string>` : column-separated list of prefixes where to look for dependencies
|
||||
* `ENABLE_UNIT_TESTS=NO` : do not build non-regression tests
|
||||
|
||||
|
||||
### Note for packagers
|
||||
|
||||
Our CMake scripts may automatically add some paths into research paths of generated binaries.
|
||||
To ensure that the installed binaries are striped of any rpath, use `-DCMAKE_SKIP_INSTALL_RPATH=ON`
|
||||
while you invoke cmake.
|
||||
|
||||
Tests suite
|
||||
-----------
|
||||
|
||||
- Tests are defined for each functional bloc (more or less matching a source file)
|
||||
and for global encoding/decoding
|
||||
|
||||
- Use `-DENABLE_TESTS=YES` to compile with tests To run all tests available in the test directory, run testCampaignAll from test directory
|
||||
|
||||
- Input tests pattern have been generated by ITU code using ITU tests patterns.
|
||||
The test patterns are not part of this repository but can be downloaded [here][bcg729-patern]. However, the first
|
||||
run of `make check` will get them for you.
|
||||
|
||||
- To run partial test, use perl executable `testCampaign` in the test directory.
|
||||
`./testCampaign <functional bloc name>`
|
||||
You must first download the tests patterns using `make check` or manually
|
||||
|
||||
|
||||
---------------------------------------
|
||||
|
||||
|
||||
[bcg729-patern]: http://www.belledonne-communications.com/bc-downloads/bcg729-patterns.zip
|
||||
[cmake-website]: https://cmake.org/
|
60
bcg729/autogen.sh
Executable file
60
bcg729/autogen.sh
Executable file
|
@ -0,0 +1,60 @@
|
|||
#!/bin/sh
|
||||
##
|
||||
## Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
##
|
||||
## This file is part of bcg729.
|
||||
##
|
||||
## This program is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
THEDIR=`pwd`
|
||||
cd $srcdir
|
||||
|
||||
#AM_VERSION="1.11"
|
||||
if ! type aclocal-$AM_VERSION 1>/dev/null 2>&1; then
|
||||
AUTOMAKE=automake
|
||||
ACLOCAL=aclocal
|
||||
else
|
||||
ACLOCAL=aclocal-${AM_VERSION}
|
||||
AUTOMAKE=automake-${AM_VERSION}
|
||||
fi
|
||||
|
||||
if test -f /opt/local/bin/glibtoolize ; then
|
||||
# darwin
|
||||
LIBTOOLIZE=/opt/local/bin/glibtoolize
|
||||
elif test -f /usr/local/bin/glibtoolize ; then
|
||||
# also darwin
|
||||
LIBTOOLIZE=/usr/local/bin/glibtoolize
|
||||
else
|
||||
LIBTOOLIZE=libtoolize
|
||||
fi
|
||||
if test -d /opt/local/share/aclocal ; then
|
||||
ACLOCAL_ARGS="-I /opt/local/share/aclocal"
|
||||
fi
|
||||
|
||||
ln -s README.md README
|
||||
|
||||
echo "Generating build scripts for G729 codec..."
|
||||
set -x
|
||||
$LIBTOOLIZE --copy --force
|
||||
$ACLOCAL $ACLOCAL_ARGS
|
||||
autoheader
|
||||
$AUTOMAKE --force-missing --add-missing --copy
|
||||
autoconf
|
||||
|
||||
cd $THEDIR
|
||||
|
32
bcg729/config.h.cmake
Normal file
32
bcg729/config.h.cmake
Normal file
|
@ -0,0 +1,32 @@
|
|||
/***************************************************************************
|
||||
* config.h.cmake
|
||||
* Copyright (C) 2014 Belledonne Communications, Grenoble France
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#cmakedefine PACKAGE "@PACKAGE@"
|
||||
#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@"
|
||||
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
||||
#cmakedefine PACKAGE_TARNAME "@PACKAGE_TARNAME@"
|
||||
#cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
|
||||
#cmakedefine PACKAGE_URL "@PACKAGE_URL@"
|
||||
#cmakedefine VERSION "@VERSION@"
|
||||
|
||||
#cmakedefine BCG729_STATIC
|
71
bcg729/configure.ac
Normal file
71
bcg729/configure.ac
Normal file
|
@ -0,0 +1,71 @@
|
|||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
|
||||
|
||||
AC_INIT([bcg729],[1.1.1])
|
||||
AC_CANONICAL_SYSTEM
|
||||
AC_PREREQ(2.63)
|
||||
AC_CONFIG_SRCDIR([src/encoder.c])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AM_INIT_AUTOMAKE([tar-ustar --warnings=no-portability])
|
||||
LT_INIT
|
||||
AC_PROG_CC
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
AC_ARG_ENABLE(strict,
|
||||
[ --enable-strict Enable error on compilation warning [default=yes]],
|
||||
[wall_werror=$enableval],
|
||||
[wall_werror=yes]
|
||||
)
|
||||
dnl configure option to disable the tests
|
||||
AC_ARG_ENABLE([tests],
|
||||
AS_HELP_STRING([--disable-tests], [Disable the tests]))
|
||||
AM_CONDITIONAL([RUN_TESTS], [test "x$enable_tests" != "xno"])
|
||||
|
||||
CFLAGS="$CFLAGS -Wall"
|
||||
|
||||
if test $GCC = yes && test $wall_werror = yes; then
|
||||
CFLAGS="$CFLAGS -Werror "
|
||||
fi
|
||||
|
||||
VISIBILITY_CFLAGS=
|
||||
case "$target_os" in
|
||||
*mingw*)
|
||||
CFLAGS="$CFLAGS -D_WIN32_WINNT=0x0501"
|
||||
mingw_found=yes
|
||||
;;
|
||||
*)
|
||||
VISIBILITY_CFLAGS="-fvisibility=hidden"
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(VISIBILITY_CFLAGS)
|
||||
|
||||
dnl Initialize libtool
|
||||
LT_INIT([win32-dll shared ])
|
||||
|
||||
AC_CONFIG_COMMANDS([libtool-hacking],
|
||||
[if test "$mingw_found" = "yes" ; then
|
||||
echo "Hacking libtool to work with mingw..."
|
||||
sed -e 's/\*\" \$a_deplib \"\*/\*/' < ./libtool > libtool.tmp
|
||||
cp -f ./libtool.tmp ./libtool
|
||||
rm -f ./libtool.tmp
|
||||
fi],
|
||||
[mingw_found=$mingw_found]
|
||||
)
|
||||
|
||||
dnl Create the following files from their .in counterparts
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
src/Makefile
|
||||
include/Makefile
|
||||
include/bcg729/Makefile
|
||||
test/Makefile
|
||||
test/bin/Makefile
|
||||
libbcg729.pc
|
||||
bcg729.spec
|
||||
])
|
||||
|
||||
|
||||
AC_OUTPUT
|
37
bcg729/include/CMakeLists.txt
Normal file
37
bcg729/include/CMakeLists.txt
Normal file
|
@ -0,0 +1,37 @@
|
|||
############################################################################
|
||||
# CMakeLists.txt
|
||||
# Copyright (C) 2017 Belledonne Communications, Grenoble France
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
set(HEADER_FILES
|
||||
decoder.h
|
||||
encoder.h
|
||||
)
|
||||
|
||||
set(BCG729_HEADER_FILES )
|
||||
foreach(HEADER_FILE ${HEADER_FILES})
|
||||
list(APPEND BCG729_HEADER_FILES "${CMAKE_CURRENT_LIST_DIR}/bcg729/${HEADER_FILE}")
|
||||
endforeach()
|
||||
set(BCG729_HEADER_FILES ${BCG729_HEADER_FILES} PARENT_SCOPE)
|
||||
|
||||
install(FILES ${BCG729_HEADER_FILES}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/bcg729
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||
)
|
247
bcg729/include/MSVC/stdint.h
Normal file
247
bcg729/include/MSVC/stdint.h
Normal file
|
@ -0,0 +1,247 @@
|
|||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
2
bcg729/include/Makefile.am
Normal file
2
bcg729/include/Makefile.am
Normal file
|
@ -0,0 +1,2 @@
|
|||
SUBDIRS = bcg729
|
||||
|
6
bcg729/include/bcg729/Makefile.am
Normal file
6
bcg729/include/bcg729/Makefile.am
Normal file
|
@ -0,0 +1,6 @@
|
|||
bcg729_includedir=$(includedir)/bcg729
|
||||
|
||||
public_headers=encoder.h decoder.h
|
||||
|
||||
bcg729_include_HEADERS=$(public_headers)
|
||||
|
71
bcg729/include/bcg729/decoder.h
Normal file
71
bcg729/include/bcg729/decoder.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef DECODER_H
|
||||
#define DECODER_H
|
||||
typedef struct bcg729DecoderChannelContextStruct_struct bcg729DecoderChannelContextStruct;
|
||||
#include <stdint.h>
|
||||
|
||||
// Version number is 1.1.1, map it on an integer
|
||||
// Note: This define starts with version 1.1.1
|
||||
#define BCG729_VERSION_NUMBER 0x010101
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef BCG729_STATIC
|
||||
#define BCG729_VISIBILITY
|
||||
#else
|
||||
#ifdef BCG729_EXPORTS
|
||||
#define BCG729_VISIBILITY __declspec(dllexport)
|
||||
#else
|
||||
#define BCG729_VISIBILITY __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define BCG729_VISIBILITY __attribute__ ((visibility ("default")))
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* initBcg729DecoderChannel : create context structure and initialise it */
|
||||
/* return value : */
|
||||
/* - the decoder channel context data */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
BCG729_VISIBILITY bcg729DecoderChannelContextStruct *initBcg729DecoderChannel(void);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* closeBcg729DecoderChannel : free memory of context structure */
|
||||
/* parameters: */
|
||||
/* -(i) decoderChannelContext : the channel context data */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
BCG729_VISIBILITY void closeBcg729DecoderChannel(bcg729DecoderChannelContextStruct *decoderChannelContext);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* bcg729Decoder : */
|
||||
/* parameters: */
|
||||
/* -(i) decoderChannelContext : the channel context data */
|
||||
/* -(i) bitStream : 15 parameters on 80 bits */
|
||||
/* -(i): bitStreamLength : in bytes, length of previous buffer */
|
||||
/* -(i) frameErased: flag: true, frame has been erased */
|
||||
/* -(i) SIDFrameFlag: flag: true, frame is a SID one */
|
||||
/* -(i) rfc3389PayloadFlag: true when CN payload follow rfc3389 */
|
||||
/* -(o) signal : a decoded frame 80 samples (16 bits PCM) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
BCG729_VISIBILITY void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, const uint8_t bitStream[], uint8_t bitStreamLength, uint8_t frameErasureFlag, uint8_t SIDFrameFlag, uint8_t rfc3389PayloadFlag, int16_t signal[]);
|
||||
#endif /* ifndef DECODER_H */
|
81
bcg729/include/bcg729/encoder.h
Normal file
81
bcg729/include/bcg729/encoder.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef ENCODER_H
|
||||
#define ENCODER_H
|
||||
#include <stdint.h>
|
||||
typedef struct bcg729EncoderChannelContextStruct_struct bcg729EncoderChannelContextStruct;
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef BCG729_STATIC
|
||||
#define BCG729_VISIBILITY
|
||||
#else
|
||||
#ifdef BCG729_EXPORTS
|
||||
#define BCG729_VISIBILITY __declspec(dllexport)
|
||||
#else
|
||||
#define BCG729_VISIBILITY __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define BCG729_VISIBILITY __attribute__ ((visibility ("default")))
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* initBcg729EncoderChannel : create context structure and initialise it */
|
||||
/* parameters: */
|
||||
/* -(i) enanbleVAD : flag set to 1: VAD/DTX is enabled */
|
||||
/* return value : */
|
||||
/* - the encoder channel context data */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
BCG729_VISIBILITY bcg729EncoderChannelContextStruct *initBcg729EncoderChannel(uint8_t enableVAD);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* closeBcg729EncoderChannel : free memory of context structure */
|
||||
/* parameters: */
|
||||
/* -(i) encoderChannelContext : the channel context data */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
BCG729_VISIBILITY void closeBcg729EncoderChannel(bcg729EncoderChannelContextStruct *encoderChannelContext);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* bcg729Encoder : */
|
||||
/* parameters: */
|
||||
/* -(i) encoderChannelContext : context for this encoder channel */
|
||||
/* -(i) inputFrame : 80 samples (16 bits PCM) */
|
||||
/* -(o) bitStream : The 15 parameters for a frame on 80 bits */
|
||||
/* on 80 bits (5 16bits words) for voice frame, 4 on 2 byte for */
|
||||
/* noise frame, 0 for untransmitted frames */
|
||||
/* -(o) bitStreamLength : actual length of output, may be 0, 2 or 10 */
|
||||
/* if VAD/DTX is enabled */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
BCG729_VISIBILITY void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, const int16_t inputFrame[], uint8_t bitStream[], uint8_t *bitStreamLength);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* bcg729GetRFC3389Payload : return the comfort noise payload according to */
|
||||
/* RFC3389 for the last CN frame generated by encoder */
|
||||
/* */
|
||||
/* parameters: */
|
||||
/* -(i) encoderChannelContext : retrieve the last CN frame encoded */
|
||||
/* using this context */
|
||||
/* -(o) payload : 11 parameters following RFC3389 with filter order 10 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
BCG729_VISIBILITY void bcg729GetRFC3389Payload(bcg729EncoderChannelContextStruct *encoderChannelContext, uint8_t payload[]);
|
||||
#endif /* ifndef ENCODER_H */
|
10
bcg729/libbcg729.pc.in
Normal file
10
bcg729/libbcg729.pc.in
Normal file
|
@ -0,0 +1,10 @@
|
|||
# This is a comment
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libbcg729
|
||||
Description: Implement the ITU G729 speech codec.
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L@libdir@ -lbcg729
|
||||
Cflags: -I@includedir@
|
80
bcg729/src/CMakeLists.txt
Normal file
80
bcg729/src/CMakeLists.txt
Normal file
|
@ -0,0 +1,80 @@
|
|||
############################################################################
|
||||
# CMakeLists.txt
|
||||
# Copyright (C) 2014-2023 Belledonne Communications, Grenoble France
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
set(BCG729_SOURCE_FILES
|
||||
adaptativeCodebookSearch.c
|
||||
codebooks.c
|
||||
computeAdaptativeCodebookGain.c
|
||||
computeLP.c
|
||||
computeWeightedSpeech.c
|
||||
decodeAdaptativeCodeVector.c
|
||||
decodeFixedCodeVector.c
|
||||
decodeGains.c
|
||||
decodeLSP.c
|
||||
decoder.c
|
||||
encoder.c
|
||||
findOpenLoopPitchDelay.c
|
||||
fixedCodebookSearch.c
|
||||
gainQuantization.c
|
||||
interpolateqLSP.c
|
||||
LP2LSPConversion.c
|
||||
LPSynthesisFilter.c
|
||||
LSPQuantization.c
|
||||
postFilter.c
|
||||
postProcessing.c
|
||||
preProcessing.c
|
||||
qLSP2LP.c
|
||||
utils.c
|
||||
cng.c
|
||||
dtx.c
|
||||
vad.c
|
||||
)
|
||||
|
||||
add_library(bcg729 ${BCG729_SOURCE_FILES})
|
||||
target_compile_definitions(bcg729 PRIVATE "BCG729_EXPORTS")
|
||||
set_target_properties(bcg729 PROPERTIES VERSION 0)
|
||||
target_include_directories(bcg729
|
||||
PUBLIC
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_BINARY_DIR}
|
||||
)
|
||||
|
||||
if(MSVC AND BUILD_SHARED_LIBS)
|
||||
install(FILES $<TARGET_PDB_FILE:bcg729>
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||
CONFIGURATIONS Debug RelWithDebInfo
|
||||
)
|
||||
set_target_properties(bcg729 PROPERTIES PREFIX "lib")
|
||||
endif()
|
||||
|
||||
|
||||
install(TARGETS bcg729 EXPORT ${PROJECT_NAME}Targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||
)
|
163
bcg729/src/LP2LSPConversion.c
Normal file
163
bcg729/src/LP2LSPConversion.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "LP2LSPConversion.h"
|
||||
|
||||
/* local functions and codebook */
|
||||
word32_t ChebyshevPolynomial(word16_t x, word32_t f[]); /* return value in Q24 */
|
||||
static const word16_t cosW0pi[NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL]; /* cos(w) from 0 to Pi in 50 steps */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* LP2LSPConversion : Compute polynomials, find their roots as in spec A3.2.3*/
|
||||
/* parameters: */
|
||||
/* -(i) LPCoefficients[] : 10 coefficients in Q12 */
|
||||
/* -(o) LSPCoefficients[] : 10 coefficients in Q15 */
|
||||
/* */
|
||||
/* return value : */
|
||||
/* - boolean: 1 if all roots found, 0 if unable to compute 10 roots */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
int LP2LSPConversion(word16_t LPCoefficients[], word16_t LSPCoefficients[])
|
||||
{
|
||||
uint8_t i;
|
||||
word32_t f1[6];
|
||||
word32_t f2[6]; /* coefficients for polynomials F1 anf F2 in Q12 for computation, then converted in Q15 for the Chebyshev Polynomial function */
|
||||
uint8_t numberOfRootFound = 0; /* used to check the final number of roots found and exit the loop on each polynomial computation when we have 10 roots */
|
||||
word32_t *polynomialCoefficients;
|
||||
word32_t previousCx;
|
||||
word32_t Cx; /* value of Chebyshev Polynomial at current point in Q15 */
|
||||
|
||||
/*** Compute the polynomials coefficients according to spec 3.2.3 eq15 ***/
|
||||
f1[0] = ONE_IN_Q12; /* values 0 are not part of the output, they are just used for computation purpose */
|
||||
f2[0] = ONE_IN_Q12;
|
||||
/* for (i = 0; i< 5; i++) { */
|
||||
/* f1[i+1] = a[i+1] + a[10-i] - f1[i]; */
|
||||
/* f2[i+1] = a[i+1] - a[10-i] + f2[i]; */
|
||||
/* } */
|
||||
for (i=0; i<5; i++) {
|
||||
f1[i+1] = ADD32(LPCoefficients[i], SUB32(LPCoefficients[9-i], f1[i])); /* note: index on LPCoefficients are -1 respect to spec because the unused value 0 is not stored */
|
||||
f2[i+1] = ADD32(f2[i], SUB32(LPCoefficients[i], LPCoefficients[9-i])); /* note: index on LPCoefficients are -1 respect to spec because the unused value 0 is not stored */
|
||||
}
|
||||
/* convert the coefficients from Q12 to Q15 to be used by the Chebyshev Polynomial function (f1/2[0] aren't used so they are not converted) */
|
||||
for (i=1; i<6; i++) {
|
||||
f1[i] = SSHL(f1[i], 3);
|
||||
f2[i] = SSHL(f2[i], 3);
|
||||
}
|
||||
|
||||
/*** Compute at each step(50 steps for the AnnexA version) the Chebyshev polynomial to find the 10 roots ***/
|
||||
/* start using f1 polynomials coefficients and altern with f2 after founding each root (spec 3.2.3 eq13 and eq14) */
|
||||
polynomialCoefficients = f1; /* start with f1 coefficients */
|
||||
previousCx = ChebyshevPolynomial(cosW0pi[0], polynomialCoefficients); /* compute the first point and store it as the previous value for polynomial */
|
||||
|
||||
for (i=1; i<NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL; i++) {
|
||||
Cx = ChebyshevPolynomial(cosW0pi[i], polynomialCoefficients);
|
||||
if ((previousCx^Cx)&0x10000000) { /* check signe change by XOR on the value of first bit */
|
||||
/* divide 2 times the interval to find a more accurate root */
|
||||
uint8_t j;
|
||||
word16_t xLow = cosW0pi[i-1];
|
||||
word16_t xHigh = cosW0pi[i];
|
||||
word16_t xMean;
|
||||
for (j=0; j<2; j++) {
|
||||
word32_t middleCx;
|
||||
xMean = (word16_t)SHR(ADD32(xLow, xHigh), 1);
|
||||
middleCx = ChebyshevPolynomial(xMean, polynomialCoefficients); /* compute the polynome for the value in the middle of current interval */
|
||||
|
||||
if ((previousCx^middleCx)&0x10000000) { /* check signe change by XOR on the value of first bit */
|
||||
xHigh = xMean;
|
||||
Cx = middleCx; /* used for linear interpolation on root */
|
||||
} else {
|
||||
xLow = xMean;
|
||||
previousCx = middleCx;
|
||||
}
|
||||
}
|
||||
|
||||
/* toggle the polynomial coefficients in use between f1 and f2 */
|
||||
if (polynomialCoefficients==f1) {
|
||||
polynomialCoefficients = f2;
|
||||
} else {
|
||||
polynomialCoefficients = f1;
|
||||
}
|
||||
|
||||
/* linear interpolation for better root accuracy */
|
||||
/* xMean = xLow - (xHigh-xLow)* previousCx/(Cx-previousCx); */
|
||||
xMean = (word16_t)SUB32(xLow, MULT16_32_Q15(SUB32(xHigh, xLow), DIV32(SSHL(SATURATE(previousCx, MAXINT17), 14), SHR(SUB32(Cx, previousCx), 1)))); /* Cx are in Q2.15 so we can shift them left 14 bits, the denominator is shifted righ by 1 so the division result is in Q15 */
|
||||
|
||||
/* recompute previousCx with the new coefficients */
|
||||
previousCx = ChebyshevPolynomial(xMean, polynomialCoefficients);
|
||||
|
||||
LSPCoefficients[numberOfRootFound] = xMean;
|
||||
|
||||
numberOfRootFound++;
|
||||
if (numberOfRootFound == NB_LSP_COEFF) break; /* exit the for loop as soon as we habe all the LSP*/
|
||||
}
|
||||
|
||||
}
|
||||
if (numberOfRootFound != NB_LSP_COEFF) return 0; /* we were not able to find the 10 roots */
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* ChebyshevPolynomial : Compute the Chebyshev polynomial, spec 3.2.3 eq17 */
|
||||
/* parameters: */
|
||||
/* -(i) x : input value of polynomial function in Q15 */
|
||||
/* -(i) f : the polynome coefficients, 6 values in Q15 on 32 bits */
|
||||
/* f[0] is not used */
|
||||
/* return value : */
|
||||
/* - result of polynomial function in Q15 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
word32_t ChebyshevPolynomial(word16_t x, word32_t f[])
|
||||
{
|
||||
/* bk in Q15*/
|
||||
word32_t bk;
|
||||
word32_t bk1 = ADD32(SSHL(x,1), f[1]); /* init: b4=2x+f1 */
|
||||
word32_t bk2 = ONE_IN_Q15; /* init: b5=1 */
|
||||
uint8_t k;
|
||||
for (k=3; k>0; k--) { /* at the end of loop execution we have b1 in bk1 and b2 in bk2 */
|
||||
bk = SUB32(ADD32(SSHL(MULT16_32_Q15(x,bk1), 1), f[5-k]), bk2); /* bk = 2*x*bk1 − bk2 + f(5-k) all in Q15*/
|
||||
bk2 = bk1;
|
||||
bk1 = bk;
|
||||
}
|
||||
|
||||
return SUB32(ADD32(MULT16_32_Q15(x,bk1), SHR(f[5],1)), bk2); /* C(x) = x*b1 - b2 + f(5)/2 */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Codebook: */
|
||||
/* */
|
||||
/* x = cos(w) with w in [0,Pi] in 50 steps */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static const word16_t cosW0pi[NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL] = { /* in Q15 */
|
||||
32760, 32703, 32509, 32187, 31738, 31164,
|
||||
30466, 29649, 28714, 27666, 26509, 25248,
|
||||
23886, 22431, 20887, 19260, 17557, 15786,
|
||||
13951, 12062, 10125, 8149, 6140, 4106,
|
||||
2057, 0, -2057, -4106, -6140, -8149,
|
||||
-10125, -12062, -13951, -15786, -17557, -19260,
|
||||
-20887, -22431, -23886, -25248, -26509, -27666,
|
||||
-28714, -29649, -30466, -31164, -31738, -32187,
|
||||
-32509, -32703, -32760};
|
32
bcg729/src/LP2LSPConversion.h
Normal file
32
bcg729/src/LP2LSPConversion.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LP2LSPCONVERSION_H
|
||||
#define LP2LSPCONVERSION_H
|
||||
/*****************************************************************************/
|
||||
/* LP2LSPConversion : Compute polynomials, find their roots as in spec A3.2.3*/
|
||||
/* parameters: */
|
||||
/* -(i) LPCoefficients[] : 10 coefficients in Q12 */
|
||||
/* -(o) LSPCoefficients[] : 10 coefficients in Q15 */
|
||||
/* */
|
||||
/* return value : */
|
||||
/* - boolean: 1 if all roots found, 0 if unable to compute 10 roots */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
int LP2LSPConversion(word16_t LPCoefficients[], word16_t LSPCoefficients[]);
|
||||
#endif /* ifndef LP2LSPCONVERSION_H */
|
47
bcg729/src/LPSynthesisFilter.c
Normal file
47
bcg729/src/LPSynthesisFilter.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* LPSynthesisFilter : as decribed in spec 4.1.6 eq77 */
|
||||
/* parameters: */
|
||||
/* -(i) excitationVector: u(n), the excitation, 40 values in Q0 */
|
||||
/* -(i) LPCoefficients: 10 LP coefficients in Q12 */
|
||||
/* -(i/o) recontructedSpeech: 50 values in Q0 */
|
||||
/* [-NB_LSP_COEFF, -1] of previous values as input */
|
||||
/* [0, L_SUBFRAME[ as output */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void LPSynthesisFilter (word16_t *excitationVector, word16_t *LPCoefficients, word16_t *reconstructedSpeech)
|
||||
{
|
||||
int i;
|
||||
/* compute excitationVector[i] - Sum0-9(LPCoefficients[j]*reconstructedSpeech[i-j]) */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
word32_t acc = SSHL(excitationVector[i],12); /* acc get the first term of the sum, in Q12 (excitationVector is in Q0)*/
|
||||
int j;
|
||||
for (j=0; j<NB_LSP_COEFF; j++) {
|
||||
acc = MSU16_16(acc, LPCoefficients[j], reconstructedSpeech[i-j-1]);
|
||||
}
|
||||
reconstructedSpeech[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* shift right acc to get it back in Q0 and check overflow on 16 bits */
|
||||
}
|
||||
return;
|
||||
}
|
32
bcg729/src/LPSynthesisFilter.h
Normal file
32
bcg729/src/LPSynthesisFilter.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LPSYNTHESISFILTER_H
|
||||
#define LPSYNTHESISFILTER_H
|
||||
/*****************************************************************************/
|
||||
/* LPSynthesisFilter : as decribed in spec 4.1.6 eq77 */
|
||||
/* parameters: */
|
||||
/* -(i) excitationVector: u(n), the excitation, 40 values in Q0 */
|
||||
/* -(i) LPCoefficients: 10 LP coefficients in Q12 */
|
||||
/* -(i/o) recontructedSpeech: 50 values in Q0 */
|
||||
/* [-NB_LSP_COEFF, -1] of previous values as input */
|
||||
/* [0, L_SUBFRAME[ as output */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void LPSynthesisFilter (word16_t *excitationVector, word16_t *LPCoefficients, word16_t *reconstructedSpeech);
|
||||
#endif /* ifndef LPSYNTHESISFILTER_H */
|
466
bcg729/src/LSPQuantization.c
Normal file
466
bcg729/src/LSPQuantization.c
Normal file
|
@ -0,0 +1,466 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "g729FixedPointMath.h"
|
||||
#include "codebooks.h"
|
||||
|
||||
#include "LSPQuantization.h"
|
||||
#include "string.h"
|
||||
|
||||
/* static buffers */
|
||||
word16_t previousqLSFInit[NB_LSP_COEFF] = {2339, 4679, 7018, 9358, 11698, 14037, 16377, 18717, 21056, 23396}; /* PI*(float)(j+1)/(float)(M+1) */
|
||||
|
||||
/* initialise the stactic buffers */
|
||||
void initLSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<MA_MAX_K; i++) {
|
||||
memcpy(encoderChannelContext->previousqLSF[i], previousqLSFInit, NB_LSP_COEFF*sizeof(word16_t));
|
||||
}
|
||||
return;
|
||||
}
|
||||
/**********************************************************************************/
|
||||
/* noiseLSPQuantization : Convert LSP to LSF, Quantize LSF and find L parameters, */
|
||||
/* qLSF->qLSP as described in spec A3.2.4 */
|
||||
/* parameters: */
|
||||
/* -(i/o) previousqLSF : 4 previousqLSF, is updated by this function */
|
||||
/* -(i) LSPCoefficients : 10 LSP coefficients in Q15 */
|
||||
/* -(o) qLSPCoefficients : 10 qLSP coefficients in Q15 */
|
||||
/* -(o) parameters : 3 parameters L0, L1, L2 */
|
||||
/* */
|
||||
/**********************************************************************************/
|
||||
void noiseLSPQuantization(word16_t previousqLSF[MA_MAX_K][NB_LSP_COEFF], word16_t LSPCoefficients[], word16_t qLSPCoefficients[], uint8_t parameters[])
|
||||
{
|
||||
int i,j;
|
||||
int L0;
|
||||
word16_t LSF[NB_LSP_COEFF]; /* LSF coefficients in Q2.13 range [0, Pi[ */
|
||||
uword16_t weights[NB_LSP_COEFF]; /* weights in Q11 */
|
||||
word16_t weightsThreshold[NB_LSP_COEFF]; /* store in Q13 the threshold used to compute the weights */
|
||||
word16_t L1index[L0_RANGE];
|
||||
word16_t L2index[L0_RANGE];
|
||||
uword32_t weightedMeanSquareError[L0_RANGE];
|
||||
word16_t quantizerOutput[NB_LSP_COEFF];
|
||||
word16_t qLSF[NB_LSP_COEFF];
|
||||
|
||||
/*** compute LSF in Q2.13 : lsf = arcos(lsp) range [0, Pi[ spec 3.2.4 eq18 ***/
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
LSF[i] = g729Acos_Q15Q13(LSPCoefficients[i]);
|
||||
}
|
||||
|
||||
/*** compute the weights vector as in spec 3.2.4 eq22 ***/
|
||||
weightsThreshold[0] = SUB16(LSF[1], OO4PIPLUS1_IN_Q13);
|
||||
for (i=1; i<NB_LSP_COEFF-1; i++) {
|
||||
weightsThreshold[i] = SUB16(SUB16(LSF[i+1], LSF[i-1]), ONE_IN_Q13);
|
||||
}
|
||||
weightsThreshold[NB_LSP_COEFF-1] = SUB16(O92PIMINUS1_IN_Q13, LSF[NB_LSP_COEFF-2]);
|
||||
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
if (weightsThreshold[i]>0) {
|
||||
weights[i] = ONE_IN_Q11;
|
||||
} else {
|
||||
weights[i] = (word16_t)SATURATE(ADD32(PSHR(MULT16_16(MULT16_16_Q13(weightsThreshold[i], weightsThreshold[i]), 10), 2), ONE_IN_Q11), MAXINT16);
|
||||
}
|
||||
}
|
||||
weights[4] = MULT16_16_Q14(weights[4], ONE_POINT_2_IN_Q14);
|
||||
weights[5] = MULT16_16_Q14(weights[5], ONE_POINT_2_IN_Q14);
|
||||
|
||||
/*** compute the coefficients for the two noise noise MA Predictors ***/
|
||||
for (L0=0; L0<L0_RANGE; L0++) {
|
||||
/* compute the target Vector (l) to be quantized as in spec 3.2.4 eq23 */
|
||||
word16_t targetVector[NB_LSP_COEFF]; /* vector to be quantized in Q13 */
|
||||
word32_t meanSquareDiff = MAXINT32;
|
||||
word16_t quantizedVector[NB_LSP_COEFF]; /* in Q13, the current state of quantized vector */
|
||||
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
word32_t acc = SHL(LSF[i],15); /* acc in Q2.28 */
|
||||
for (j=0; j<MA_MAX_K; j++) {
|
||||
acc = MSU16_16(acc, previousqLSF[j][i], noiseMAPredictor[L0][j][i]); /* previousqLSF in Q2.13 and MAPredictor in Q0.15-> acc in Q2.28 */
|
||||
}
|
||||
targetVector[i] = MULT16_16_Q12((word16_t)PSHR(acc, 15), invNoiseMAPredictorSum[L0][i]); /* acc->Q13 and invMAPredictorSum in Q12 -> targetVector in Q13 */
|
||||
}
|
||||
|
||||
/* find closest match for predictionError (minimize mean square diff) in L1 subset codebook: 32 entries from L1 codebook */
|
||||
for (i=0; i<NOISE_L1_RANGE; i++) {
|
||||
word32_t acc = 0;
|
||||
for (j=0; j<NB_LSP_COEFF; j++) {
|
||||
word16_t difftargetVectorL1 = SATURATE(SUB32(targetVector[j], L1[L1SubsetIndex[i]][j]), MAXINT16);
|
||||
acc = MAC16_16(acc, difftargetVectorL1, difftargetVectorL1);
|
||||
}
|
||||
|
||||
if (acc<meanSquareDiff) {
|
||||
meanSquareDiff = acc;
|
||||
L1index[L0] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* find the closest match in L2 subset wich will minimise the weighted sum of (targetVector - L1 result - L2)^2 */
|
||||
/* using eq20, eq21 and eq23 in spec 3.2.4 -> l[i] - l^[i] = (wi - w^[i])/(1-SumMAPred[i]) but ITU code ignores this denominator */
|
||||
/* works on the first five coefficients only */
|
||||
meanSquareDiff = MAXINT32;
|
||||
for (i=0; i<NOISE_L2_RANGE; i++) {
|
||||
word32_t acc = 0;
|
||||
for (j=0; j<NB_LSP_COEFF/2; j++) {
|
||||
/* commented code : compute in the same way of the ITU code: ignore the denonimator and minimize (wi - w^[i])/(1-SumMAPred[i]) instead of (wi - w^[i]) square sum */
|
||||
word16_t difftargetVectorL1L2 = SATURATE(MULT16_16_Q15(SUB32(SUB32(targetVector[j], L1[L1SubsetIndex[L1index[L0]]][j]), L2L3[L2SubsetIndex[i]][j]), noiseMAPredictorSum[L0][j]), MAXINT16); /* targetVector, L1 and L2L3 in Q13 -> result in Q13 */
|
||||
acc = MAC16_16(acc, difftargetVectorL1L2, MULT16_16_Q11(difftargetVectorL1L2, weights[j])); /* weights in Q11, diff in Q13 */
|
||||
}
|
||||
|
||||
for (j=NB_LSP_COEFF/2; j<NB_LSP_COEFF; j++) {
|
||||
word16_t difftargetVectorL1L3 = SATURATE(MULT16_16_Q15(SUB32(SUB32(targetVector[j], L1[L1SubsetIndex[L1index[L0]]][j]), L2L3[L3SubsetIndex[i]][j]), noiseMAPredictorSum[L0][j]), MAXINT16); /* targetVector, L1 and L2L3 in Q13 -> result in Q13 */
|
||||
acc = MAC16_16(acc, difftargetVectorL1L3, MULT16_16_Q11(difftargetVectorL1L3, weights[j])); /* weights in Q11, diff in Q13 */
|
||||
}
|
||||
|
||||
|
||||
if (acc<meanSquareDiff) {
|
||||
meanSquareDiff = acc;
|
||||
L2index[L0] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute the quantized vector L1+L2/L3 and rearrange it as specified in spec 3.2.4 */
|
||||
/* Note: according to the spec, the rearrangement shall be done on each candidate while looking for best match, but the ITU code does it after picking the best match and so we do */
|
||||
for (i=0; i<NB_LSP_COEFF/2; i++) {
|
||||
quantizedVector[i] = ADD16(L1[L1SubsetIndex[L1index[L0]]][i], L2L3[L2SubsetIndex[L2index[L0]]][i]);
|
||||
}
|
||||
for (i=NB_LSP_COEFF/2; i<NB_LSP_COEFF; i++) {
|
||||
quantizedVector[i] = ADD16(L1[L1index[L0]][i], L2L3[L3SubsetIndex[L2index[L0]]][i]);
|
||||
}
|
||||
|
||||
/* rearrange with a minimum distance of 0.0012 */
|
||||
for (i=1; i<NB_LSP_COEFF/2; i++) {
|
||||
if (quantizedVector[i-1]>SUB16(quantizedVector[i],GAP1)) {
|
||||
quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1);
|
||||
quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1);
|
||||
}
|
||||
}
|
||||
for (i=NB_LSP_COEFF/2+1; i<NB_LSP_COEFF; i++) {
|
||||
if (quantizedVector[i-1]>SUB16(quantizedVector[i],GAP1)) {
|
||||
quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1);
|
||||
quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* rearrange the whole quantizedVector with a distance of 0.0006 */
|
||||
for (i=1; i<NB_LSP_COEFF; i++) {
|
||||
if (quantizedVector[i-1]>SUB16(quantizedVector[i],GAP2)) {
|
||||
quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP2), 1);
|
||||
quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP2), 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* compute the weighted mean square distance using the final quantized vector according to eq21 */
|
||||
weightedMeanSquareError[L0]=0;
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
uword16_t difftargetVectorQuantizedVector = USATURATE(ABS(MULT16_16_Q15(SUB32(targetVector[i], quantizedVector[i]), noiseMAPredictorSum[L0][i])), MAXUINT16); /* targetVector and quantizedVector in Q13 -> result in Q13 */
|
||||
weightedMeanSquareError[L0] = UMAC16_16(weightedMeanSquareError[L0], difftargetVectorQuantizedVector, MULT16_16_Q11(difftargetVectorQuantizedVector, weights[i])); /* weights in Q11, diff in Q13 */
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* now select L0 and copy the selected coefficients to the output buffer */
|
||||
if (weightedMeanSquareError[0]<weightedMeanSquareError[1]) {
|
||||
parameters[0] = 0;
|
||||
parameters[1] = L1index[0];
|
||||
parameters[2] = L2index[0];
|
||||
} else {
|
||||
parameters[0] = 1;
|
||||
parameters[1] = L1index[1];
|
||||
parameters[2] = L2index[1];
|
||||
}
|
||||
|
||||
/*** Compute the quantized LSF from the L coefficients ***/
|
||||
/* reconstruct vector from the codebooks using the selected parameters spec 3.2.4 eq19 */
|
||||
for (i=0; i<NB_LSP_COEFF/2; i++) {
|
||||
quantizerOutput[i] = ADD16(L1[L1SubsetIndex[parameters[1]]][i], L2L3[L2SubsetIndex[parameters[2]]][i]); /* codebooks are in Q2.13 for L1 and Q0.13 for L2L3, due to actual values stored in the codebooks, result in Q2.13 */
|
||||
}
|
||||
for ( i=NB_LSP_COEFF/2; i<NB_LSP_COEFF; i++) {
|
||||
quantizerOutput[i] = ADD16(L1[L1SubsetIndex[parameters[1]]][i], L2L3[L3SubsetIndex[parameters[2]]][i]); /* same as previous, output in Q2.13 */
|
||||
}
|
||||
/* rearrange in order to have a minimum distance between two consecutives coefficients spec 3.2.4 */
|
||||
rearrangeCoefficients(quantizerOutput, GAP1);
|
||||
rearrangeCoefficients(quantizerOutput, GAP2); /* currentqLSF still in Q2.13 */
|
||||
|
||||
/* compute qLSF spec 3.2.4 eq20 */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
word32_t acc = MULT16_16(noiseMAPredictorSum[parameters[0]][i], quantizerOutput[i]); /* (1 - ∑Pi,k)*lˆi(m) Q15 * Q13 -> Q28 */
|
||||
for (j=0; j<MA_MAX_K; j++) {
|
||||
acc = MAC16_16(acc, noiseMAPredictor[parameters[0]][j][i], previousqLSF[j][i]);
|
||||
}
|
||||
/* acc in Q2.28, shift back the acc to a Q2.13 with rounding */
|
||||
qLSF[i] = (word16_t)PSHR(acc, 15); /* qLSF in Q2.13 */
|
||||
}
|
||||
|
||||
/* update the previousqLSF buffer with current quantizer output */
|
||||
for (i=MA_MAX_K-1; i>0; i--) {
|
||||
memcpy(previousqLSF[i], previousqLSF[i-1], NB_LSP_COEFF*sizeof(word16_t));
|
||||
}
|
||||
memcpy(previousqLSF[0], quantizerOutput, NB_LSP_COEFF*sizeof(word16_t));
|
||||
|
||||
/*** qLSF stability check ***/
|
||||
insertionSort(qLSF, NB_LSP_COEFF);
|
||||
|
||||
/* check for low limit on qLSF[0] */
|
||||
if (qLSF[1]<qLSF_MIN) {
|
||||
qLSF[1] = qLSF_MIN;
|
||||
}
|
||||
|
||||
/* check and rectify minimum distance between two consecutive qLSF */
|
||||
for (i=0; i<NB_LSP_COEFF-1; i++) {
|
||||
if (SUB16(qLSF[i+1],qLSF[i])<MIN_qLSF_DISTANCE) {
|
||||
qLSF[i+1] = qLSF[i]+MIN_qLSF_DISTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for upper limit on qLSF[NB_LSP_COEFF-1] */
|
||||
if (qLSF[NB_LSP_COEFF-1]>qLSF_MAX) {
|
||||
qLSF[NB_LSP_COEFF-1] = qLSF_MAX;
|
||||
}
|
||||
|
||||
/* convert qLSF to qLSP: qLSP = cos(qLSF) */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
qLSPCoefficients[i] = g729Cos_Q13Q15(qLSF[i]); /* ouput in Q0.15 */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* LSPQuantization : Convert LSP to LSF, Quantize LSF and find L parameters, */
|
||||
/* qLSF->qLSP as described in spec A3.2.4 */
|
||||
/* parameters: */
|
||||
/* -(i/o) encoderChannelContext : the channel context data */
|
||||
/* -(i) LSPCoefficients : 10 LSP coefficients in Q15 */
|
||||
/* -(o) qLSPCoefficients : 10 qLSP coefficients in Q15 */
|
||||
/* -(o) parameters : 4 parameters L0, L1, L2, L3 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void LSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, word16_t LSPCoefficients[], word16_t qLSPCoefficients[], uint16_t parameters[])
|
||||
{
|
||||
int i,j;
|
||||
word16_t LSF[NB_LSP_COEFF]; /* LSF coefficients in Q2.13 range [0, Pi[ */
|
||||
uword16_t weights[NB_LSP_COEFF]; /* weights in Q11 */
|
||||
word16_t weightsThreshold[NB_LSP_COEFF]; /* store in Q13 the threshold used to compute the weights */
|
||||
int L0;
|
||||
uword32_t weightedMeanSquareError[L0_RANGE];
|
||||
word16_t L1index[L0_RANGE];
|
||||
word16_t L2index[L0_RANGE];
|
||||
word16_t L3index[L0_RANGE];
|
||||
word16_t quantizerOutput[NB_LSP_COEFF];
|
||||
word16_t qLSF[NB_LSP_COEFF];
|
||||
|
||||
/*** compute LSF in Q2.13 : lsf = arcos(lsp) range [0, Pi[ spec 3.2.4 eq18 ***/
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
LSF[i] = g729Acos_Q15Q13(LSPCoefficients[i]);
|
||||
}
|
||||
|
||||
/*** compute the weights vector as in spec 3.2.4 eq22 ***/
|
||||
weightsThreshold[0] = SUB16(LSF[1], OO4PIPLUS1_IN_Q13);
|
||||
for (i=1; i<NB_LSP_COEFF-1; i++) {
|
||||
weightsThreshold[i] = SUB16(SUB16(LSF[i+1], LSF[i-1]), ONE_IN_Q13);
|
||||
|
||||
}
|
||||
weightsThreshold[NB_LSP_COEFF-1] = SUB16(O92PIMINUS1_IN_Q13, LSF[NB_LSP_COEFF-2]);
|
||||
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
if (weightsThreshold[i]>0) {
|
||||
weights[i] = ONE_IN_Q11;
|
||||
} else {
|
||||
weights[i] = (word16_t)SATURATE(ADD32(PSHR(MULT16_16(MULT16_16_Q13(weightsThreshold[i], weightsThreshold[i]), 10), 2), ONE_IN_Q11), MAXINT16);
|
||||
}
|
||||
}
|
||||
weights[4] = MULT16_16_Q14(weights[4], ONE_POINT_2_IN_Q14);
|
||||
weights[5] = MULT16_16_Q14(weights[5], ONE_POINT_2_IN_Q14);
|
||||
|
||||
/*** compute the coefficients for the two MA Predictors ***/
|
||||
for (L0=0; L0<L0_RANGE; L0++) {
|
||||
/* compute the target Vector (l) to be quantized as in spec 3.2.4 eq23 */
|
||||
word16_t targetVector[NB_LSP_COEFF]; /* vector to be quantized in Q13 */
|
||||
word32_t meanSquareDiff = MAXINT32;
|
||||
word16_t quantizedVector[NB_LSP_COEFF]; /* in Q13, the current state of quantized vector */
|
||||
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
word32_t acc = SHL(LSF[i],15); /* acc in Q2.28 */
|
||||
for (j=0; j<MA_MAX_K; j++) {
|
||||
acc = MSU16_16(acc, encoderChannelContext->previousqLSF[j][i], MAPredictor[L0][j][i]); /* previousqLSF in Q2.13 and MAPredictor in Q0.15-> acc in Q2.28 */
|
||||
}
|
||||
targetVector[i] = MULT16_16_Q12((word16_t)PSHR(acc, 15), invMAPredictorSum[L0][i]); /* acc->Q13 and invMAPredictorSum in Q12 -> targetVector in Q13 */
|
||||
}
|
||||
|
||||
/* find closest match for predictionError (minimize mean square diff) in L1 codebook */
|
||||
for (i=0; i<L1_RANGE; i++) {
|
||||
word32_t acc = 0;
|
||||
for (j=0; j<NB_LSP_COEFF; j++) {
|
||||
word16_t difftargetVectorL1 = SATURATE(SUB32(targetVector[j], L1[i][j]), MAXINT16);
|
||||
acc = MAC16_16(acc, difftargetVectorL1, difftargetVectorL1);
|
||||
}
|
||||
|
||||
if (acc<meanSquareDiff) {
|
||||
meanSquareDiff = acc;
|
||||
L1index[L0] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* find the closest match in L2 wich will minimise the weighted sum of (targetVector - L1 result - L2)^2 */
|
||||
/* using eq20, eq21 and eq23 in spec 3.2.4 -> l[i] - l^[i] = (wi - w^[i])/(1-SumMAPred[i]) but ITU code ignores this denominator */
|
||||
/* works on the first five coefficients only */
|
||||
meanSquareDiff = MAXINT32;
|
||||
for (i=0; i<L2_RANGE; i++) {
|
||||
word32_t acc = 0;
|
||||
for (j=0; j<NB_LSP_COEFF/2; j++) {
|
||||
/* commented code : compute in the same way of the ITU code: ignore the denonimator and minimize (wi - w^[i])/(1-SumMAPred[i]) instead of (wi - w^[i]) square sum */
|
||||
//word16_t difftargetVectorL1L2 = SATURATE(SUB32(SUB32(targetVector[j], L1[L1index[L0]][j]), L2L3[i][j]), MAXINT16); /* targetVector, L1 and L2L3 in Q13 -> result in Q13 */
|
||||
word16_t difftargetVectorL1L2 = SATURATE(MULT16_16_Q15(SUB32(SUB32(targetVector[j], L1[L1index[L0]][j]), L2L3[i][j]), MAPredictorSum[L0][j]), MAXINT16); /* targetVector, L1 and L2L3 in Q13 -> result in Q13 */
|
||||
acc = MAC16_16(acc, difftargetVectorL1L2, MULT16_16_Q11(difftargetVectorL1L2, weights[j])); /* weights in Q11, diff in Q13 */
|
||||
}
|
||||
|
||||
if (acc<meanSquareDiff) {
|
||||
meanSquareDiff = acc;
|
||||
L2index[L0] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* find the closest match in L3 wich will minimise the weighted sum of (targetVector - L1 result - L3)^2 */
|
||||
/* using eq20, eq21 and eq23 in spec 3.2.4 -> l[i] - l^[i] = (wi - w^[i])/(1-SumMAPred[i]) but ITU code ignores this denominator */
|
||||
/* works on the first five coefficients only */
|
||||
meanSquareDiff = MAXINT32;
|
||||
for (i=0; i<L2_RANGE; i++) {
|
||||
word32_t acc = 0;
|
||||
for (j=NB_LSP_COEFF/2; j<NB_LSP_COEFF; j++) {
|
||||
/* commented code : compute in the same way of the ITU code: ignore the denonimator and minimize (wi - w^[i])/(1-SumMAPred[i]) instead of (wi - w^[i]) square sum */
|
||||
//word16_t difftargetVectorL1L3 = SATURATE(SUB32(SUB32(targetVector[j], L1[L1index[L0]][j]), L2L3[i][j]), MAXINT16); /* targetVector, L1 and L2L3 in Q13 -> result in Q13 */
|
||||
word16_t difftargetVectorL1L3 = SATURATE(MULT16_16_Q15(SUB32(SUB32(targetVector[j], L1[L1index[L0]][j]), L2L3[i][j]), MAPredictorSum[L0][j]), MAXINT16); /* targetVector, L1 and L2L3 in Q13 -> result in Q13 */
|
||||
acc = MAC16_16(acc, difftargetVectorL1L3, MULT16_16_Q11(difftargetVectorL1L3, weights[j])); /* weights in Q11, diff in Q13 */
|
||||
}
|
||||
|
||||
if (acc<meanSquareDiff) {
|
||||
meanSquareDiff = acc;
|
||||
L3index[L0] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute the quantized vector L1+L2/L3 and rearrange it as specified in spec 3.2.4(first the higher part (L2) and then the lower part (L3)) */
|
||||
/* Note: according to the spec, the rearrangement shall be done on each candidate while looking for best match, but the ITU code does it after picking the best match and so we do */
|
||||
for (i=0; i<NB_LSP_COEFF/2; i++) {
|
||||
quantizedVector[i] = ADD16(L1[L1index[L0]][i], L2L3[L2index[L0]][i]);
|
||||
}
|
||||
for (i=NB_LSP_COEFF/2; i<NB_LSP_COEFF; i++) {
|
||||
quantizedVector[i] = ADD16(L1[L1index[L0]][i], L2L3[L3index[L0]][i]);
|
||||
}
|
||||
|
||||
/* rearrange with a minimum distance of 0.0012 */
|
||||
for (i=1; i<NB_LSP_COEFF/2; i++) {
|
||||
if (quantizedVector[i-1]>SUB16(quantizedVector[i],GAP1)) {
|
||||
quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1);
|
||||
quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1);
|
||||
}
|
||||
}
|
||||
for (i=NB_LSP_COEFF/2+1; i<NB_LSP_COEFF; i++) {
|
||||
if (quantizedVector[i-1]>SUB16(quantizedVector[i],GAP1)) {
|
||||
quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1);
|
||||
quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* rearrange the whole quantizedVector with a distance of 0.0006 */
|
||||
for (i=1; i<NB_LSP_COEFF; i++) {
|
||||
if (quantizedVector[i-1]>SUB16(quantizedVector[i],GAP2)) {
|
||||
quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP2), 1);
|
||||
quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP2), 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* compute the weighted mean square distance using the final quantized vector according to eq21 */
|
||||
weightedMeanSquareError[L0]=0;
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
uword16_t difftargetVectorQuantizedVector = USATURATE(ABS(MULT16_16_Q15(SUB32(targetVector[i], quantizedVector[i]), MAPredictorSum[L0][i])), MAXUINT16); /* targetVector and quantizedVector in Q13 -> result in Q13 */
|
||||
weightedMeanSquareError[L0] = UMAC16_16(weightedMeanSquareError[L0], difftargetVectorQuantizedVector, MULT16_16_Q11(difftargetVectorQuantizedVector, weights[i])); /* weights in Q11, diff in Q13 */
|
||||
}
|
||||
}
|
||||
|
||||
/* now select L0 and copy the selected coefficients to the output buffer */
|
||||
if (weightedMeanSquareError[0]<weightedMeanSquareError[1]) {
|
||||
parameters[0] = 0;
|
||||
parameters[1] = L1index[0];
|
||||
parameters[2] = L2index[0];
|
||||
parameters[3] = L3index[0];
|
||||
} else {
|
||||
parameters[0] = 1;
|
||||
parameters[1] = L1index[1];
|
||||
parameters[2] = L2index[1];
|
||||
parameters[3] = L3index[1];
|
||||
}
|
||||
|
||||
/*** Compute the quantized LSF from the L coefficients ***/
|
||||
/* reconstruct vector from the codebooks using the selected parameters spec 3.2.4 eq19 */
|
||||
for (i=0; i<NB_LSP_COEFF/2; i++) {
|
||||
quantizerOutput[i] = ADD16(L1[parameters[1]][i], L2L3[parameters[2]][i]); /* codebooks are in Q2.13 for L1 and Q0.13 for L2L3, due to actual values stored in the codebooks, result in Q2.13 */
|
||||
}
|
||||
for ( i=NB_LSP_COEFF/2; i<NB_LSP_COEFF; i++) {
|
||||
quantizerOutput[i] = ADD16(L1[parameters[1]][i], L2L3[parameters[3]][i]); /* same as previous, output in Q2.13 */
|
||||
}
|
||||
/* rearrange in order to have a minimum distance between two consecutives coefficients spec 3.2.4 */
|
||||
rearrangeCoefficients(quantizerOutput, GAP1);
|
||||
rearrangeCoefficients(quantizerOutput, GAP2); /* currentqLSF still in Q2.13 */
|
||||
|
||||
/* compute qLSF spec 3.2.4 eq20 */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
word32_t acc = MULT16_16(MAPredictorSum[parameters[0]][i], quantizerOutput[i]); /* (1 - ∑Pi,k)*lˆi(m) Q15 * Q13 -> Q28 */
|
||||
for (j=0; j<MA_MAX_K; j++) {
|
||||
acc = MAC16_16(acc, MAPredictor[parameters[0]][j][i], encoderChannelContext->previousqLSF[j][i]);
|
||||
}
|
||||
/* acc in Q2.28, shift back the acc to a Q2.13 with rounding */
|
||||
qLSF[i] = (word16_t)PSHR(acc, 15); /* qLSF in Q2.13 */
|
||||
}
|
||||
|
||||
/* update the previousqLSF buffer with current quantizer output */
|
||||
for (i=MA_MAX_K-1; i>0; i--) {
|
||||
memcpy(encoderChannelContext->previousqLSF[i], encoderChannelContext->previousqLSF[i-1], NB_LSP_COEFF*sizeof(word16_t));
|
||||
}
|
||||
memcpy(encoderChannelContext->previousqLSF[0], quantizerOutput, NB_LSP_COEFF*sizeof(word16_t));
|
||||
|
||||
/*** qLSF stability check ***/
|
||||
insertionSort(qLSF, NB_LSP_COEFF);
|
||||
|
||||
/* check for low limit on qLSF[0] */
|
||||
if (qLSF[1]<qLSF_MIN) {
|
||||
qLSF[1] = qLSF_MIN;
|
||||
}
|
||||
|
||||
/* check and rectify minimum distance between two consecutive qLSF */
|
||||
for (i=0; i<NB_LSP_COEFF-1; i++) {
|
||||
if (SUB16(qLSF[i+1],qLSF[i])<MIN_qLSF_DISTANCE) {
|
||||
qLSF[i+1] = qLSF[i]+MIN_qLSF_DISTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for upper limit on qLSF[NB_LSP_COEFF-1] */
|
||||
if (qLSF[NB_LSP_COEFF-1]>qLSF_MAX) {
|
||||
qLSF[NB_LSP_COEFF-1] = qLSF_MAX;
|
||||
}
|
||||
|
||||
/* convert qLSF to qLSP: qLSP = cos(qLSF) */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
qLSPCoefficients[i] = g729Cos_Q13Q15(qLSF[i]); /* ouput in Q0.15 */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
46
bcg729/src/LSPQuantization.h
Normal file
46
bcg729/src/LSPQuantization.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LSPQUANTIZATION_H
|
||||
#define LSPQUANTIZATION_H
|
||||
void initLSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* LSPQuantization : Convert LSP to LSF, Quantize LSF and find L parameters, */
|
||||
/* qLSF->qLSP as described in spec A3.2.4 */
|
||||
/* parameters: */
|
||||
/* -(i/o) encoderChannelContext : the channel context data */
|
||||
/* -(i) LSPCoefficients : 10 LSP coefficients in Q15 */
|
||||
/* -(i) qLSPCoefficients : 10 qLSP coefficients in Q15 */
|
||||
/* -(o) parameters : 4 parameters L0, L1, L2, L3 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void LSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, word16_t LSPCoefficients[], word16_t qLSPCoefficients[], uint16_t parameters[]);
|
||||
|
||||
/**********************************************************************************/
|
||||
/* noiseLSPQuantization : Convert LSP to LSF, Quantize LSF and find L parameters, */
|
||||
/* qLSF->qLSP as described in spec A3.2.4 */
|
||||
/* parameters: */
|
||||
/* -(i/o) previousqLSF : 4 previousqLSF, is updated by this function */
|
||||
/* -(i) LSPCoefficients : 10 LSP coefficients in Q15 */
|
||||
/* -(o) qLSPCoefficients : 10 qLSP coefficients in Q15 */
|
||||
/* -(o) parameters : 3 parameters L0, L1, L2 */
|
||||
/* */
|
||||
/**********************************************************************************/
|
||||
void noiseLSPQuantization(word16_t previousqLSF[MA_MAX_K][NB_LSP_COEFF], word16_t LSPCoefficients[], word16_t qLSPCoefficients[], uint8_t parameters[]);
|
||||
#endif /* LSPQUANTIZATION_H */
|
69
bcg729/src/Makefile.am
Normal file
69
bcg729/src/Makefile.am
Normal file
|
@ -0,0 +1,69 @@
|
|||
|
||||
lib_LTLIBRARIES = libbcg729.la
|
||||
|
||||
|
||||
libbcg729_la_SOURCES= LP2LSPConversion.c \
|
||||
LPSynthesisFilter.c \
|
||||
LSPQuantization.c \
|
||||
adaptativeCodebookSearch.c \
|
||||
codebooks.c \
|
||||
computeAdaptativeCodebookGain.c \
|
||||
computeLP.c \
|
||||
computeWeightedSpeech.c \
|
||||
decodeAdaptativeCodeVector.c \
|
||||
decodeFixedCodeVector.c \
|
||||
decodeGains.c \
|
||||
decodeLSP.c \
|
||||
decoder.c \
|
||||
encoder.c \
|
||||
findOpenLoopPitchDelay.c \
|
||||
fixedCodebookSearch.c \
|
||||
gainQuantization.c \
|
||||
interpolateqLSP.c \
|
||||
postFilter.c \
|
||||
postProcessing.c \
|
||||
preProcessing.c \
|
||||
qLSP2LP.c \
|
||||
utils.c \
|
||||
cng.c \
|
||||
vad.c \
|
||||
dtx.c
|
||||
|
||||
libbcg729_la_LDFLAGS= -no-undefined
|
||||
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
AM_CFLAGS=$(VISIBILITY_CFLAGS)
|
||||
|
||||
private_headers= adaptativeCodebookSearch.h \
|
||||
basicOperationsMacros.h \
|
||||
codebooks.h \
|
||||
codecParameters.h \
|
||||
computeAdaptativeCodebookGain.h \
|
||||
computeLP.h \
|
||||
computeWeightedSpeech.h \
|
||||
cng.h \
|
||||
decodeAdaptativeCodeVector.h \
|
||||
decodeFixedCodeVector.h \
|
||||
decodeGains.h \
|
||||
decodeLSP.h \
|
||||
dtx.h \
|
||||
findOpenLoopPitchDelay.h \
|
||||
fixedCodebookSearch.h \
|
||||
fixedPointMacros.h \
|
||||
floatingPointMacros.h \
|
||||
g729FixedPointMath.h \
|
||||
gainQuantization.h \
|
||||
interpolateqLSP.h \
|
||||
LP2LSPConversion.h \
|
||||
LPSynthesisFilter.h \
|
||||
LSPQuantization.h \
|
||||
postFilter.h \
|
||||
postProcessing.h \
|
||||
preProcessing.h \
|
||||
qLSP2LP.h \
|
||||
typedef.h \
|
||||
utils.h \
|
||||
vad.h
|
||||
|
||||
EXTRA_DIST=$(private_headers)
|
193
bcg729/src/adaptativeCodebookSearch.c
Normal file
193
bcg729/src/adaptativeCodebookSearch.c
Normal file
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
#include "codebooks.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "adaptativeCodebookSearch.h"
|
||||
|
||||
/*** local functions ***/
|
||||
void generateAdaptativeCodebookVector(word16_t excitationVector[], int16_t intPitchDelay, int16_t fracPitchDelay);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* adaptativeCodebookSearch: compute parameter P1 and P2 as in spec A.3.7 */
|
||||
/* compute also adaptative codebook vector as in spec 3.7.1 */
|
||||
/* parameters: */
|
||||
/* -(i/o) excitationVector: [-154,0[ previous excitation as input */
|
||||
/* Range [0,39[ */
|
||||
/* 40 words of LPResidualSignal as substitute for current */
|
||||
/* excitation (spec A.3.7) as input */
|
||||
/* 40 words of adaptative codebook vector in Q0 as output */
|
||||
/* Buffer in Q0 accessed in range [-154, 39] */
|
||||
/* -(i/o) intPitchDelayMin: low boundary for pitch delay search */
|
||||
/* -(i/o) intPitchDelayMax: low boundary for pitch delay search */
|
||||
/* Boundaries are updated during first subframe search */
|
||||
/* -(i) impulseResponse: 40 values as in spec A.3.5 in Q12 */
|
||||
/* -(i) targetSignal: 40 values as in spec A.3.6 in Q0 */
|
||||
/* */
|
||||
/* -(o) intPitchDelay: the integer pitch delay */
|
||||
/* -(o) fracPitchDelay: the fractionnal part of pitch delay */
|
||||
/* -(o) pitchDelayCodeword: P1 or P2 codeword as in spec 3.7.2 */
|
||||
/* -(o) adaptativeCodebookVector: 40 words of adaptative codebook vector*/
|
||||
/* as described in spec 3.7.1, in Q0. */
|
||||
/* -(i) subFrameIndex: 0 for the first subframe, 40 for the second */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void adaptativeCodebookSearch(word16_t excitationVector[], int16_t *intPitchDelayMin, int16_t *intPitchDelayMax, word16_t impulseResponse[], word16_t targetSignal[],
|
||||
int16_t *intPitchDelay, int16_t *fracPitchDelay, uint16_t *pitchDelayCodeword, uint16_t subFrameIndex)
|
||||
{
|
||||
int i,j;
|
||||
word32_t backwardFilteredTargetSignal[L_SUBFRAME];
|
||||
word32_t correlationMax = MININT32;
|
||||
|
||||
/* compute the backward Filtered Target Signal as specified in A.3.7: correlation of target signal and impulse response */
|
||||
correlateVectors(targetSignal, impulseResponse, backwardFilteredTargetSignal); /* targetSignal in Q0, impulseResponse in Q12 -> backwardFilteredTargetSignal in Q12 */
|
||||
|
||||
/* maximise the sum as in spec A.3.7, eq A.7 */
|
||||
for (i=*intPitchDelayMin; i<=*intPitchDelayMax; i++) {
|
||||
word32_t correlation = 0;
|
||||
for (j=0; j<L_SUBFRAME; j++) {
|
||||
correlation = MAC16_32_Q12(correlation, excitationVector[j-i], backwardFilteredTargetSignal[j]);
|
||||
}
|
||||
|
||||
if (correlation>correlationMax) {
|
||||
correlationMax=correlation;
|
||||
*intPitchDelay = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute the adaptativeCodebookVector (with fracPitchDelay at 0) */
|
||||
/* output is in excitationVector[0,L_SUBRAME[ */
|
||||
generateAdaptativeCodebookVector(excitationVector, *intPitchDelay, 0);
|
||||
|
||||
/* if we are at first subframe and intPitchDelay >= 85 -> do not compute fracPitchDelay, set it to 0 */
|
||||
*fracPitchDelay=0;
|
||||
if (!(subFrameIndex==0 && *intPitchDelay>=85)) {
|
||||
/* compute the fracPitchDelay*/
|
||||
word16_t adaptativeCodebookVector[L_SUBFRAME]; /* as the adaptativeCodebookVector is computed in the excitation vector, use this buffer to backup the one giving the highest numerator */
|
||||
word32_t correlation=0;
|
||||
/* search the fractionnal part to get the best correlation */
|
||||
/* we already have in excitationVector for fracPitchDelay = 0 the adaptativeCodebookVector (see specA.3.7) */
|
||||
correlationMax = 0;
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
correlationMax = MAC16_32_Q12(correlationMax, excitationVector[i], backwardFilteredTargetSignal[i]);
|
||||
}
|
||||
/* backup the adaptativeCodebookVector */
|
||||
memcpy(adaptativeCodebookVector, excitationVector, L_SUBFRAME*sizeof(word16_t));
|
||||
|
||||
/* Fractionnal part = -1 */
|
||||
generateAdaptativeCodebookVector(excitationVector, *intPitchDelay, -1);
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
correlation = MAC16_32_Q12(correlation, excitationVector[i], backwardFilteredTargetSignal[i]);
|
||||
}
|
||||
if (correlation>correlationMax) { /* fractional part at -1 gives higher correlation */
|
||||
*fracPitchDelay=-1;
|
||||
correlationMax = correlation;
|
||||
/* backup the adaptativeCodebookVector */
|
||||
memcpy(adaptativeCodebookVector, excitationVector, L_SUBFRAME*sizeof(word16_t));
|
||||
}
|
||||
|
||||
/* Fractionnal part = 1 */
|
||||
generateAdaptativeCodebookVector(excitationVector, *intPitchDelay, 1);
|
||||
correlation=0;
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
correlation = MAC16_32_Q12(correlation, excitationVector[i], backwardFilteredTargetSignal[i]);
|
||||
}
|
||||
if (correlation>correlationMax) { /* fractional part at -1 gives higher correlation */
|
||||
*fracPitchDelay=1;
|
||||
} else { /* previously computed fractional part gives better result */
|
||||
/* restore the adaptativeCodebookVector*/
|
||||
memcpy(excitationVector, adaptativeCodebookVector, L_SUBFRAME*sizeof(word16_t));
|
||||
}
|
||||
}
|
||||
|
||||
/* compute the codeword and intPitchDelayMin/intPitchDelayMax if needed (first subframe only) */
|
||||
if (subFrameIndex==0) { /* first subframe */
|
||||
/* compute intPitchDelayMin/intPitchDelayMax as in spec A.3.7 */
|
||||
*intPitchDelayMin = *intPitchDelay - 5;
|
||||
if (*intPitchDelayMin < 20) {
|
||||
*intPitchDelayMin = 20;
|
||||
}
|
||||
*intPitchDelayMax = *intPitchDelayMin + 9;
|
||||
if (*intPitchDelayMax > MAXIMUM_INT_PITCH_DELAY) {
|
||||
*intPitchDelayMax = MAXIMUM_INT_PITCH_DELAY;
|
||||
*intPitchDelayMin = MAXIMUM_INT_PITCH_DELAY - 9;
|
||||
}
|
||||
|
||||
/* compute the codeword as in spec 3.7.2 */
|
||||
if (*intPitchDelay<=85) {
|
||||
*pitchDelayCodeword = 3*(*intPitchDelay) - 58 + *fracPitchDelay;
|
||||
} else {
|
||||
*pitchDelayCodeword = *intPitchDelay + 112;
|
||||
}
|
||||
} else { /* second subframe */
|
||||
/* compute the codeword as in spec 3.7.2 */
|
||||
*pitchDelayCodeword = 3*(*intPitchDelay-*intPitchDelayMin) + *fracPitchDelay +2;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* generateAdaptativeCodebookVector : according to spec 3.7.1 eq40: */
|
||||
/* generates the adaptative codebook vector by interpolation of past */
|
||||
/* excitation */
|
||||
/* Note : specA.3.7 mention that excitation vector in range [0,39[ being */
|
||||
/* unknown is replaced by LP Residual signal, the ITU code use this */
|
||||
/* buffer to store the adaptative codebok vector and then use it in case*/
|
||||
/* of intPitchDelay<40. */
|
||||
/* parameters : */
|
||||
/* -(i/o) excitationVector: in Q0 the past excitation vector accessed */
|
||||
/* [-154,0[. Range [0,39[ is the output in Q0 */
|
||||
/* -(i) intPitchDelay: the integer pitch delay used to access the past */
|
||||
/* excitation */
|
||||
/* -(i) fracPitchDelay: fractional part of the pitch delay: -1, 0 or 1 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void generateAdaptativeCodebookVector(word16_t excitationVector[], int16_t intPitchDelay, int16_t fracPitchDelay)
|
||||
{
|
||||
int n,i,j;
|
||||
word16_t *delayedExcitationVector;
|
||||
word16_t *b30Increased;
|
||||
word16_t *b30Decreased;
|
||||
|
||||
/* fracPitchDelay is in range [-1, 1], convert it to [0,2] needed by eqA.8 */
|
||||
fracPitchDelay = -fracPitchDelay;
|
||||
if (fracPitchDelay <0) { /* if fracPitchDelay is 1 -> pitchDelay of int+(1/3) -> int+1-(2/3)*/
|
||||
intPitchDelay++;
|
||||
fracPitchDelay = 2;
|
||||
}
|
||||
|
||||
/**/
|
||||
delayedExcitationVector = &(excitationVector[-intPitchDelay]); /* delayedExcitationVector is used to address the excitation vector at index -intPitchDelay (-k in eq40) */
|
||||
b30Increased = &(b30[fracPitchDelay]); /* b30 increased points to b30[fracPitchDelay] : b30[t] in eq40. b30 in Q15 */
|
||||
b30Decreased = &(b30[3-fracPitchDelay]); /* b30 decreased points to b30[-fracPitchDelay] : b30[3-t] in eq40. b30 in Q15 */
|
||||
|
||||
|
||||
for (n=0; n<L_SUBFRAME; n++) {
|
||||
word32_t acc = 0; /* acc in Q15 */
|
||||
for (i=0, j=0; i<10; i++, j+=3) { /* j is used as a 3*i index */
|
||||
acc = MAC16_16(acc, delayedExcitationVector[n-i], b30Increased[j]); /* WARNING: spec 3.7.1 and A.8 give an equation leading to delayedExcitationVector[n+i] but ITU code uses delayedExcitationVector[n-i], implemented as code */
|
||||
acc = MAC16_16(acc, delayedExcitationVector[n+1+i], b30Decreased[j]);
|
||||
}
|
||||
excitationVector[n] = SATURATE(PSHR(acc, 15), MAXINT16); /* acc in Q15, shift/round to unscaled value and check overflow on 16 bits */
|
||||
}
|
||||
}
|
47
bcg729/src/adaptativeCodebookSearch.h
Normal file
47
bcg729/src/adaptativeCodebookSearch.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef ADAPTATIVECODEBOOKSEARCH_H
|
||||
#define ADAPTATIVECODEBOOKSEARCH_H
|
||||
/*****************************************************************************/
|
||||
/* adaptativeCodebookSearch: compute parameter P1 and P2 as in spec A.3.7 */
|
||||
/* compute also adaptative codebook vector as in spec 3.7.1 */
|
||||
/* parameters: */
|
||||
/* -(i/o) excitationVector: [-154,0[ previous excitation as input */
|
||||
/* Range [0,39[ */
|
||||
/* 40 words of LPResidualSignal as substitute for current */
|
||||
/* excitation (spec A.3.7) as input */
|
||||
/* 40 words of adaptative codebook vector in Q0 as output */
|
||||
/* Buffer in Q0 accessed in range [-154, 39] */
|
||||
/* -(i/o) intPitchDelayMin: low boundary for pitch delay search */
|
||||
/* -(i/o) intPitchDelayMax: low boundary for pitch delay search */
|
||||
/* Boundaries are updated during first subframe search */
|
||||
/* -(i) impulseResponse: 40 values as in spec A.3.5 in Q12 */
|
||||
/* -(i) targetSignal: 40 values as in spec A.3.6 in Q0 */
|
||||
/* */
|
||||
/* -(o) intPitchDelay: the integer pitch delay */
|
||||
/* -(o) fracPitchDelay: the fractionnal part of pitch delay */
|
||||
/* -(o) pitchDelayCodeword: P1 or P2 codeword as in spec 3.7.2 */
|
||||
/* -(o) adaptativeCodebookVector: 40 words of adaptative codebook vector*/
|
||||
/* as described in spec 3.7.1, in Q0. */
|
||||
/* -(i) subFrameIndex: 0 for the first subframe, 40 for the second */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void adaptativeCodebookSearch(word16_t excitationVector[], int16_t *intPitchDelayMin, int16_t *intPitchDelayMax, word16_t impulseResponse[], word16_t targetSignal[],
|
||||
int16_t *intPitchDelay, int16_t *fracPitchDelay, uint16_t *pitchDelayCodeword, uint16_t subFrameIndex);
|
||||
#endif /* ifndef ADAPTATIVECODEBOOKSEARCH_H */
|
24
bcg729/src/basicOperationsMacros.h
Normal file
24
bcg729/src/basicOperationsMacros.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef BASICOPERATIONSMACROS_H
|
||||
#define BASICOPERATIONSMACROS_H
|
||||
|
||||
#include "fixedPointMacros.h"
|
||||
|
||||
#endif /* ifndef BASICOPERATIONSMACROS_H */
|
362
bcg729/src/cng.c
Normal file
362
bcg729/src/cng.c
Normal file
|
@ -0,0 +1,362 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "cng.h"
|
||||
#include "decodeAdaptativeCodeVector.h"
|
||||
#include "decodeLSP.h"
|
||||
#include "interpolateqLSP.h"
|
||||
#include "qLSP2LP.h"
|
||||
#include "g729FixedPointMath.h"
|
||||
#include "codebooks.h"
|
||||
#include "LP2LSPConversion.h"
|
||||
|
||||
/* buffers allocation */
|
||||
static const word16_t SIDqLSPInitialValues[NB_LSP_COEFF] = {31441, 27566, 21458, 13612, 4663, -4663, -13612, -21458, -27566, -31441}; /* in Q0.15 the initials values for the previous qLSP buffer */
|
||||
|
||||
bcg729CNGChannelContextStruct *initBcg729CNGChannel() {
|
||||
/* create the context structure */
|
||||
bcg729CNGChannelContextStruct *CNGChannelContext = malloc(sizeof(bcg729CNGChannelContextStruct));
|
||||
memset(CNGChannelContext, 0, sizeof(*CNGChannelContext));
|
||||
|
||||
memcpy(CNGChannelContext->qLSP, SIDqLSPInitialValues, NB_LSP_COEFF*sizeof(word16_t)); /* initialise the previousqLSP buffer */
|
||||
|
||||
return CNGChannelContext;
|
||||
}
|
||||
|
||||
/*******************************************************************************************/
|
||||
/* computeComfortNoiseExcitationVector : as is spec B4.4 and B4.5 */
|
||||
/* parameters: */
|
||||
/* -(i): targetGain : the gain from ea B.19 in Q3 */
|
||||
/* -(i/o): randomGeneratorSeed : used to get a pseudo random number, is updated */
|
||||
/* -(i/o): excitationVector in Q0, accessed in range [-L_PAST_EXCITATION,L_FRAME-1] */
|
||||
/* [-154,79] */
|
||||
/* */
|
||||
/*******************************************************************************************/
|
||||
void computeComfortNoiseExcitationVector(word16_t targetGain, uint16_t *randomGeneratorSeed, word16_t *excitationVector) {
|
||||
int16_t fracPitchDelay,intPitchDelay;
|
||||
uint16_t randomNumberBuffer;
|
||||
uint8_t subframeIndex = 0;
|
||||
int i,j;
|
||||
/* shall we check targetGain is 0?? and set excitation vector[0,L_FRAME[ to 0 in this case?*/
|
||||
|
||||
for (subframeIndex=0; subframeIndex<L_FRAME; subframeIndex+=L_SUBFRAME) { /* process 2 subframes */
|
||||
word16_t gaussianRandomExcitation[L_SUBFRAME];
|
||||
word32_t Eg = 0;
|
||||
word32_t Gg = 0; /* gain to be applied to the randomly generated gaussian to reach a Eg of 1/4*L_SUBFRAME*targetGain(note this doesn't appears in spec, only in ITU code)*/
|
||||
word16_t Ga = 0; /* gain to be applied to adaptative subframe excitation in Q0.15 */
|
||||
word32_t Ea = 0;
|
||||
word32_t Ei = 0; /* inter excitation : Sum[0..39] adaptativeExcitation*fixedExcitation, defined in eq B21*/
|
||||
word32_t K = 0;
|
||||
word32_t Gf = 0; /* gain to be applied to the fixed codebook excitation */
|
||||
word32_t x2 = 0; /* second root of the 2nd degre equation solved to get Gf */
|
||||
word16_t sign[4]; /* sign of the impulses of fixed codebook excitation */
|
||||
word16_t position[4]; /* positions of the impulses of fixed codebook excitation */
|
||||
uint8_t deltaScaleFactor=0;
|
||||
word64_t delta;
|
||||
|
||||
/* generate pseudo random pitch delay in range [40,103] for adaptative codebook */
|
||||
randomNumberBuffer = pseudoRandom(randomGeneratorSeed); /* get 16 bits of pseudoRandom value*/
|
||||
fracPitchDelay = (int16_t)(randomNumberBuffer&0x0003)-1; /* fraction part of the pitch delay shall be -1, 0 or 1 */
|
||||
if (fracPitchDelay==2) fracPitchDelay = 0;
|
||||
randomNumberBuffer = randomNumberBuffer>>2; /* 14 random bits left */
|
||||
intPitchDelay = (randomNumberBuffer&0x003F) + 40; /* intPitchDelay in [40,103] */
|
||||
randomNumberBuffer = randomNumberBuffer>>6; /* 8 random bits left */
|
||||
/* generate pseudo random sign and position for fixed codebook */
|
||||
position[0] = (randomNumberBuffer&0x0007)*5;
|
||||
randomNumberBuffer = randomNumberBuffer>>3; /* 5 random bits left */
|
||||
sign[0] = randomNumberBuffer&0x0001;
|
||||
randomNumberBuffer = randomNumberBuffer>>1; /* 4 random bits left */
|
||||
position[1] = (randomNumberBuffer&0x0007)*5+1;
|
||||
randomNumberBuffer = randomNumberBuffer>>3; /* 1 random bits left */
|
||||
sign[1] = randomNumberBuffer&0x0001,
|
||||
randomNumberBuffer = pseudoRandom(randomGeneratorSeed); /* get 16 bits of pseudoRandom value*/
|
||||
position[2] = (randomNumberBuffer&0x0007)*5+2;
|
||||
randomNumberBuffer = randomNumberBuffer>>3; /* 13 random bits left */
|
||||
sign[2] = randomNumberBuffer&0x0001;
|
||||
randomNumberBuffer = randomNumberBuffer>>1; /* 12 random bits left */
|
||||
position[3] = (randomNumberBuffer&0x0001)+3; /*j+3*/
|
||||
randomNumberBuffer = randomNumberBuffer>>1; /* 11 random bits left */
|
||||
position[3] += (randomNumberBuffer&0x0007)*5;
|
||||
randomNumberBuffer = randomNumberBuffer>>3; /* 8 random bits left */
|
||||
sign[3] = randomNumberBuffer&0x0001;
|
||||
randomNumberBuffer = randomNumberBuffer>>1; /* 7 random bits left */
|
||||
/* randomly generate Ga : adaptative gain eqB.22: max is 0,5 */
|
||||
Ga = (pseudoRandom(randomGeneratorSeed)&0x1fff)<<1; /* get 16 bits of pseudoRandom value but make sure it is < 0.5 in Q15 */
|
||||
|
||||
|
||||
|
||||
/* generate gaussian random excitation : get generation algo from ITU code, no reference to this in the spec...
|
||||
* Compute also the subframe energy(Sum [0..39] excitation^2) and then scale the sample to get an subframe average energy to targetGain/4 */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
word32_t tmpBuffer=0;
|
||||
for (j=0; j<12; j++) {
|
||||
tmpBuffer=ADD32(tmpBuffer, (word16_t)pseudoRandom(randomGeneratorSeed)); /* cast the unsigned 16 bits value to a signed one */
|
||||
}
|
||||
gaussianRandomExcitation[i]=(word16_t)(SHR(tmpBuffer,7));
|
||||
Eg = MAC16_16(Eg, gaussianRandomExcitation[i], gaussianRandomExcitation[i]);
|
||||
}
|
||||
|
||||
/* compute coefficient = 1/2*sqrt(L_SUBFRAME/gaussianRandomExcitationSubframeEnergy)*targetGain (always>0) - retrieved from ITU code, no mention of this in the spec */
|
||||
/* comments in code say 1/4*sqrt() but code actually implement 1/2... */
|
||||
Gg = MULT16_32_Q15(GAUSSIAN_EXCITATION_COEFF_FACTOR, g729InvSqrt_Q0Q31(Eg)); /* multiplicand in Q1.13 and Q0.31 -> result in Q1.29 */
|
||||
Gg = MULT16_32_Q15(targetGain, Gg); /* multiplicand in Q3 and Q1.29 -> result in Q17 */
|
||||
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
/* operate on positive value only to avoid problem when shifting to 0 a negative one */
|
||||
if (gaussianRandomExcitation[i]<0) {
|
||||
gaussianRandomExcitation[i] = -SATURATE(PSHR( MULT16_32_Q15(-gaussianRandomExcitation[i], Gg), 2), MAXINT16); /* gaussianRandom in Q0, targetGain in Q17 -> result in Q2, need to shift it by 2. */
|
||||
} else {
|
||||
gaussianRandomExcitation[i] = PSHR( MULT16_32_Q15(gaussianRandomExcitation[i], Gg), 2);
|
||||
}
|
||||
}
|
||||
/* generate random adaptative excitation and apply random gain Ga */
|
||||
computeAdaptativeCodebookVector(excitationVector+subframeIndex, fracPitchDelay, intPitchDelay);
|
||||
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
excitationVector[i+subframeIndex] = SATURATE(MULT16_16_P15(excitationVector[i+subframeIndex], Ga), MAXINT16);
|
||||
}
|
||||
|
||||
|
||||
/* add gaussian excitation to the adaptative one */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
excitationVector[i+subframeIndex] = SATURATE(ADD32(excitationVector[i+subframeIndex], gaussianRandomExcitation[i]),MAXINT16);
|
||||
}
|
||||
|
||||
/* Compute Gf: fixed excitation gain salving equation B.21 in form 4*Gf^2 + 2I*Ga*Gf + Ea*Ga^2 - K = 0 (4Gf^2 + 2bGf + c = 0)*/
|
||||
/* compute Ea*Ga^2 */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
Ea = MAC16_16(Ea, excitationVector[i+subframeIndex], excitationVector[i+subframeIndex]); /* Ea actually contains Ea*Ga^2 as we already applied gain Ga on adaptative excitation, in Q0 */
|
||||
}
|
||||
|
||||
/* compute Ei = I*Ga : fixed codebook hasn't been scaled yet, so it just 4 signed pulses of height 1, just get these one in our computation, in Q0 */
|
||||
Ei = 0;
|
||||
for (i=0; i<4; i++) {
|
||||
if (sign[i] == 0) { /* negative impulse */
|
||||
Ei = SUB32(Ei,excitationVector[position[i]+subframeIndex]);
|
||||
} else { /* positive impulse */
|
||||
Ei = ADD32(Ei,excitationVector[position[i]+subframeIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
/* compute K = L_SUBRAME*targetGain in Q3 */
|
||||
K = MULT16_32(targetGain, SHR(MULT16_16(L_SUBFRAME, targetGain), 3));
|
||||
|
||||
/* compute delta = b^2 -ac = Ei^2 + 4*(K-Ea) in Q0 */
|
||||
delta = ADD64(MULT32_32(Ei,Ei), SHR(SUB64(K,SHL64((word64_t)Ea,3)),1));
|
||||
|
||||
if (delta<0) {
|
||||
/* cancel adaptative excitation, keep gaussian one only */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
excitationVector[i+subframeIndex] = gaussianRandomExcitation[i];
|
||||
}
|
||||
|
||||
/* compute again Ei and delta = Ei^2 + 3/4*K (from ITU code, no idea why) */
|
||||
for (i=0; i<4; i++) {
|
||||
if (sign[i] == 0) { /* negative impulse */
|
||||
Ei = SUB32(Ei,excitationVector[position[i]+subframeIndex]);
|
||||
} else { /* positive impulse */
|
||||
Ei = ADD32(Ei,excitationVector[position[i]+subframeIndex]);
|
||||
}
|
||||
}
|
||||
delta = ADD64(MULT32_32(Ei,Ei), MULT16_32_P15(COEFF_K,K)); /* COEFF_K is 0.75 in Q15 */
|
||||
}
|
||||
|
||||
/* scale delta to have it fitting on 32 bits */
|
||||
deltaScaleFactor = 0;
|
||||
while (delta>=0x0000000080000000) {
|
||||
delta = delta>>1;
|
||||
deltaScaleFactor++;
|
||||
}
|
||||
/* deltaScaleFactor must be even */
|
||||
if (deltaScaleFactor%2==1) {
|
||||
delta = delta >> 1;
|
||||
deltaScaleFactor++;
|
||||
}
|
||||
|
||||
delta = g729Sqrt_Q0Q7((word32_t)delta); /* delta in Q(7-deltaScaleFactor/2)*/
|
||||
|
||||
/* scale b (Ei) to the same scale */
|
||||
Ei = SVSHR32(Ei, deltaScaleFactor/2-7);
|
||||
|
||||
/* compute the two roots and pick the one with smaller absolute value */
|
||||
/* roots are (-b +-sqrt(delta))/a. We always have a=4, divide by four when rescaling from Q(7-deltaScaleFactor) to Q0 the final result */
|
||||
Gf = SUB32(delta, Ei); /* x1 = -b + sqrt(delta) in Q(7-deltaScaleFactor) */
|
||||
x2 = -ADD32(delta, Ei); /* x2 = -b - sqrt(delta) in Q(7-deltaScaleFactor) */
|
||||
if (ABS(x2)<ABS(Gf)) Gf = x2; /* pick the smallest (in absolute value of the roots) */
|
||||
Gf = VSHR32(Gf, 2+7-deltaScaleFactor/2); /* scale back Gf in Q0 and divide by 4 (+2 in the right shift) to get the actual root */
|
||||
|
||||
/* add fixed codebook excitation */
|
||||
for (i=0; i<4; i++) {
|
||||
if (sign[i] == 0) { /* negative impulse */
|
||||
excitationVector[position[i]+subframeIndex] = SUB32(excitationVector[position[i]+subframeIndex], Gf);
|
||||
} else { /* positive impulse */
|
||||
excitationVector[position[i]+subframeIndex] = ADD32(excitationVector[position[i]+subframeIndex], Gf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************************/
|
||||
/* decodeSIDframe : as is spec B4.4 and B4.5 */
|
||||
/* first check if we have a SID frame or a missing/untransmitted frame */
|
||||
/* for SID frame get paremeters(gain and LSP) */
|
||||
/* Then generate excitation vector and update qLSP */
|
||||
/* parameters: */
|
||||
/* -(i/o):CNGChannelContext : context containing all informations needed for CNG */
|
||||
/* -(i): previousFrameIsActiveFlag: true if last decoded frame was an active one */
|
||||
/* -(i): bitStream: for SID frame contains received params as in spec B4.3, */
|
||||
/* NULL for missing/untransmitted frame */
|
||||
/* -(i): bitStreamLength : in bytes, length of previous buffer */
|
||||
/* -(i/o): excitationVector in Q0, accessed in range [-L_PAST_EXCITATION,L_FRAME-1] */
|
||||
/* [-154,79] */
|
||||
/* -(o): LP: 20 LP coefficients in Q12 */
|
||||
/* -(i/o): previousqLSP : previous quantised LSP in Q0.15 (NB_LSP_COEFF values) */
|
||||
/* -(i/o): pseudoRandomSeed : seed used in the pseudo random number generator */
|
||||
/* -(i/o): previousLCodeWord: in Q2.13, buffer to store the last 4 frames codewords, */
|
||||
/* used to compute the current qLSF */
|
||||
/* */
|
||||
/*******************************************************************************************/
|
||||
void decodeSIDframe(bcg729CNGChannelContextStruct *CNGChannelContext, uint8_t previousFrameIsActiveFlag, const uint8_t *bitStream, uint8_t bitStreamLength, word16_t *excitationVector, word16_t *previousqLSP, word16_t *LP, uint16_t *pseudoRandomSeed, word16_t previousLCodeWord[MA_MAX_K][NB_LSP_COEFF], uint8_t rfc3389PayloadFlag) {
|
||||
int i;
|
||||
word16_t interpolatedqLSP[NB_LSP_COEFF]; /* interpolated qLSP in Q0.15 */
|
||||
/* if this is a SID frame, decode received parameters */
|
||||
if (bitStream!=NULL) {
|
||||
if (rfc3389PayloadFlag) {
|
||||
int j;
|
||||
word32_t LPCoefficients[NB_LSP_COEFF+1]; /* in Q4.27 */
|
||||
word16_t LPCoefficientsQ12[NB_LSP_COEFF]; /* in Q12 */
|
||||
word32_t previousIterationLPCoefficients[NB_LSP_COEFF+1]; /* in Q4.27 */
|
||||
uint8_t CNFilterOrder = (bitStreamLength-1); /* first byte is noise energy level */
|
||||
word16_t k[NB_LSP_COEFF];
|
||||
word32_t receivedSIDGainLog;
|
||||
|
||||
if (CNFilterOrder>NB_LSP_COEFF) { /* if rfc3389 payload have a filter order > than supported, just ignore the last coefficients */
|
||||
CNFilterOrder = NB_LSP_COEFF;
|
||||
}
|
||||
/* retrieve gain from codebook according to Gain parameter */
|
||||
//CNGChannelContext->receivedSIDGain = SIDGainCodebook[bitStream[0]];
|
||||
/* received parameter is -(10*log10(meanE) -90) so retrieve mean energy : 10^((param+90)/10) */
|
||||
/* but expected parameter is a gain applied to single sample so sqrt of previous result */
|
||||
receivedSIDGainLog = ADD32(-bitStream[0], 90);
|
||||
if (receivedSIDGainLog > 66) {
|
||||
receivedSIDGainLog = 66; /* noise level shall not be too high in any case */
|
||||
} /* receivedSIDGainLog is param+90 in Q0 */
|
||||
receivedSIDGainLog = MULT16_16(receivedSIDGainLog, 680); /* 680 is 1/(10*log10(2)) in Q11 -> receivedSIDGainLog is ((param+90)/10)/log10(2) = log2(meanE) in Q11 */
|
||||
receivedSIDGainLog = g729Exp2_Q11Q16(receivedSIDGainLog); /* receivedSIDGainLog in meanE in Q16 */
|
||||
if (receivedSIDGainLog > 0 ) { /* avoid arithmetic problem if energy is too low */
|
||||
CNGChannelContext->receivedSIDGain = (word16_t)(SHR(g729Sqrt_Q0Q7(receivedSIDGainLog), 12)); /* output of sqrt in Q15, result needed in Q3 */
|
||||
if (CNGChannelContext->receivedSIDGain < SIDGainCodebook[0]) {
|
||||
CNGChannelContext->receivedSIDGain = SIDGainCodebook[0];
|
||||
}
|
||||
} else { /* minimum target gain extracted from codebook */
|
||||
CNGChannelContext->receivedSIDGain = SIDGainCodebook[0];
|
||||
}
|
||||
|
||||
/* retrieve LP from rfc3389 payload*/
|
||||
/* rebuild the LP coefficients using algo given in G711 Appendix II section 5.2.1.3 */
|
||||
/* first get back the quantized reflection coefficients from Index as in RFC3389 3.2 */
|
||||
for (i=0; i<CNFilterOrder; i++) {
|
||||
k[i] = MULT16_16(ADD16(bitStream[i+1],127), 258); /* k in Q15 */
|
||||
}
|
||||
for (i=CNFilterOrder; i<NB_LSP_COEFF; i++) { /* rfc3389 payload may provide a filter of order < NB_LSP_COEFF */
|
||||
k[i] = 0; /* in that case, just set the last coefficients to 0 */
|
||||
}
|
||||
|
||||
/* rebuild LP coefficients */
|
||||
LPCoefficients[0] = ONE_IN_Q27;
|
||||
LPCoefficients[1] = -SHL(k[0],12);
|
||||
for (i=2; i<NB_LSP_COEFF+1; i++) {
|
||||
/* update the previousIterationLPCoefficients needed for this one */
|
||||
for (j=1; j<i; j++) {
|
||||
previousIterationLPCoefficients[j] = LPCoefficients[j];
|
||||
}
|
||||
|
||||
LPCoefficients[i] = -SHL(k[i-1],16); /* current coeff in Q31 while older one in Q27*/
|
||||
for (j=1; j<i; j++) {
|
||||
LPCoefficients[j] = MAC32_32_Q31(LPCoefficients[j], LPCoefficients[i], previousIterationLPCoefficients[i-j]); /*LPCoefficients in Q27 except for LPCoefficients[i] in Q31 */
|
||||
}
|
||||
LPCoefficients[i] = SHR(LPCoefficients[i], 4);
|
||||
}
|
||||
|
||||
/* convert with rounding the LP Coefficients form Q27 to Q12, ignore first coefficient which is always 1 */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
LPCoefficientsQ12[i] = (word16_t)SATURATE(PSHR(LPCoefficients[i+1], 15), MAXINT16);
|
||||
}
|
||||
|
||||
/* compute LSP from LP as we need to store LSP in context as the LP to use are interpolated with previous ones. Note: use LSP as qLSP */
|
||||
if (!LP2LSPConversion(LPCoefficientsQ12, CNGChannelContext->qLSP)) {
|
||||
/* unable to find the 10 roots repeat previous LSP */
|
||||
memcpy(CNGChannelContext->qLSP, previousqLSP, NB_LSP_COEFF*sizeof(word16_t));
|
||||
}
|
||||
} else { /* regular G729 SID payload on 2 bytes */
|
||||
word16_t currentqLSF[NB_LSP_COEFF]; /* buffer to the current qLSF in Q2.13 */
|
||||
uint8_t L0 = (bitStream[0]>>7)&0x01;
|
||||
uint8_t L1Index = (bitStream[0]>>2)&0x1F;
|
||||
uint8_t L2Index = ((bitStream[0]&0x03)<<2) | ((bitStream[1]>>6)&0x03);
|
||||
|
||||
/* retrieve gain from codebook according to Gain parameter */
|
||||
CNGChannelContext->receivedSIDGain = SIDGainCodebook[((bitStream[1])>>1)&0x1F];
|
||||
/* Use L1 and L2(parameter for first and second stage vector of LSF quantizer) to retrieve LSP using subset index to address the complete L1 and L2L3 codebook */
|
||||
for (i=0; i<NB_LSP_COEFF/2; i++) {
|
||||
currentqLSF[i]=ADD16(L1[L1SubsetIndex[L1Index]][i], L2L3[L2SubsetIndex[L2Index]][i]);
|
||||
}
|
||||
for (i=NB_LSP_COEFF/2; i<NB_LSP_COEFF; i++) {
|
||||
currentqLSF[i]=ADD16(L1[L1SubsetIndex[L1Index]][i], L2L3[L3SubsetIndex[L2Index]][i]);
|
||||
}
|
||||
computeqLSF(currentqLSF, previousLCodeWord, L0, noiseMAPredictor, noiseMAPredictorSum);
|
||||
|
||||
/* convert qLSF to qLSP: qLSP = cos(qLSF) */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
CNGChannelContext->qLSP[i] = g729Cos_Q13Q15(currentqLSF[i]); /* ouput in Q0.15 */
|
||||
}
|
||||
}
|
||||
} /* Note: Itu implementation have information to sort missing and untransmitted packets and perform reconstruction of missed SID packet when it detects it, we cannot differentiate lost vs untransmitted packet so we don't do it */
|
||||
|
||||
/* compute the LP coefficients */
|
||||
interpolateqLSP(previousqLSP, CNGChannelContext->qLSP, interpolatedqLSP);
|
||||
/* copy the current qLSP(SID ones) to previousqLSP buffer */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
previousqLSP[i] = CNGChannelContext->qLSP[i];
|
||||
}
|
||||
|
||||
/* call the qLSP2LP function for first subframe */
|
||||
qLSP2LP(interpolatedqLSP, LP);
|
||||
/* call the qLSP2LP function for second subframe */
|
||||
qLSP2LP(CNGChannelContext->qLSP, &(LP[NB_LSP_COEFF]));
|
||||
|
||||
|
||||
/* apply target gain smoothing eq B.19 */
|
||||
if (previousFrameIsActiveFlag) {
|
||||
/* this is the first SID frame use transmitted(or recomputed from last valid frame energy) SID gain */
|
||||
CNGChannelContext->smoothedSIDGain = CNGChannelContext->receivedSIDGain;
|
||||
} else { /* otherwise 7/8 of last smoothed gain and 1/8 of last received gain */
|
||||
CNGChannelContext->smoothedSIDGain = SUB16(CNGChannelContext->smoothedSIDGain, (CNGChannelContext->smoothedSIDGain>>3));
|
||||
CNGChannelContext->smoothedSIDGain = ADD16(CNGChannelContext->smoothedSIDGain, (CNGChannelContext->receivedSIDGain>>3));
|
||||
}
|
||||
|
||||
/* get the excitation vector */
|
||||
computeComfortNoiseExcitationVector(CNGChannelContext->smoothedSIDGain, pseudoRandomSeed, excitationVector);
|
||||
}
|
54
bcg729/src/cng.h
Normal file
54
bcg729/src/cng.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef CNG_H
|
||||
#define CNG_H
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* initBcg729CNGChannel : create context structure and initialise it */
|
||||
/* return value : */
|
||||
/* - the CNG channel context data */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
bcg729CNGChannelContextStruct *initBcg729CNGChannel();
|
||||
|
||||
void computeComfortNoiseExcitationVector(word16_t targetGain, uint16_t *randomGeneratorSeed, word16_t *excitationVector);
|
||||
/*******************************************************************************************/
|
||||
/* decodeSIDframe : as is spec B4.4 and B4.5 */
|
||||
/* first check if we have a SID frame or a missing/untransmitted frame */
|
||||
/* for SID frame get paremeters(gain and LSP) */
|
||||
/* Then generate excitation vector and update qLSP */
|
||||
/* parameters: */
|
||||
/* -(i/o):CNGChannelContext : context containing all informations needed for CNG */
|
||||
/* -(i): previousFrameIsActiveFlag: true if last decoded frame was an active one */
|
||||
/* -(i): bitStream: for SID frame contains received params as in spec B4.3, */
|
||||
/* NULL for missing/untransmitted frame */
|
||||
/* -(i): bitStreamLength : in bytes, length of previous buffer */
|
||||
/* -(i/o): excitationVector in Q0, accessed in range [-L_PAST_EXCITATION,L_FRAME-1] */
|
||||
/* [-154,79] */
|
||||
/* -(i/o): previousqLSP : previous quantised LSP in Q0.15 (NB_LSP_COEFF values) */
|
||||
/* -(o): LP: 20 LP coefficients in Q12 */
|
||||
/* -(i/o): pseudoRandomSeed : seed used in the pseudo random number generator */
|
||||
/* -(i/o): previousLCodeWord: in Q2.13, buffer to store the last 4 frames codewords, */
|
||||
/* used to compute the current qLSF */
|
||||
/* -(i) rfc3389PayloadFlag: true when CN payload follow rfc3389 */
|
||||
/* */
|
||||
/*******************************************************************************************/
|
||||
void decodeSIDframe(bcg729CNGChannelContextStruct *CNGChannelContext, uint8_t previousFrameIsActiveFlag, const uint8_t *bitStream, uint8_t bitStreamLength, word16_t *excitationVector, word16_t *previousqLSP, word16_t *LP, uint16_t *pseudoRandomSeed, word16_t previousLCodeWord[MA_MAX_K][NB_LSP_COEFF], uint8_t rfc3389PayloadFlag);
|
||||
#endif /* ifndef CNG_H */
|
354
bcg729/src/codebooks.c
Normal file
354
bcg729/src/codebooks.c
Normal file
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
/*** codebooks for quantization of the LSP coefficient - doc: 3.2.4 ***/
|
||||
word16_t L1[L1_RANGE][NB_LSP_COEFF] = { /* The first stage is a 10-dimensional VQ using codebook L1 with 128 entries (7 bits) */
|
||||
/* Q2.13 */
|
||||
{ 1486, 2168, 3751, 9074, 12134, 13944, 17983, 19173, 21190, 21820},
|
||||
{ 1730, 2640, 3450, 4870, 6126, 7876, 15644, 17817, 20294, 21902},
|
||||
{ 1568, 2256, 3088, 4874, 11063, 13393, 18307, 19293, 21109, 21741},
|
||||
{ 1733, 2512, 3357, 4708, 6977, 10296, 17024, 17956, 19145, 20350},
|
||||
{ 1744, 2436, 3308, 8731, 10432, 12007, 15614, 16639, 21359, 21913},
|
||||
{ 1786, 2369, 3372, 4521, 6795, 12963, 17674, 18988, 20855, 21640},
|
||||
{ 1631, 2433, 3361, 6328, 10709, 12013, 13277, 13904, 19441, 21088},
|
||||
{ 1489, 2364, 3291, 6250, 9227, 10403, 13843, 15278, 17721, 21451},
|
||||
{ 1869, 2533, 3475, 4365, 9152, 14513, 15908, 17022, 20611, 21411},
|
||||
{ 2070, 3025, 4333, 5854, 7805, 9231, 10597, 16047, 20109, 21834},
|
||||
{ 1910, 2673, 3419, 4261, 11168, 15111, 16577, 17591, 19310, 20265},
|
||||
{ 1141, 1815, 2624, 4623, 6495, 9588, 13968, 16428, 19351, 21286},
|
||||
{ 2192, 3171, 4707, 5808, 10904, 12500, 14162, 15664, 21124, 21789},
|
||||
{ 1286, 1907, 2548, 3453, 9574, 11964, 15978, 17344, 19691, 22495},
|
||||
{ 1921, 2720, 4604, 6684, 11503, 12992, 14350, 15262, 16997, 20791},
|
||||
{ 2052, 2759, 3897, 5246, 6638, 10267, 15834, 16814, 18149, 21675},
|
||||
{ 1798, 2497, 5617, 11449, 13189, 14711, 17050, 18195, 20307, 21182},
|
||||
{ 1009, 1647, 2889, 5709, 9541, 12354, 15231, 18494, 20966, 22033},
|
||||
{ 3016, 3794, 5406, 7469, 12488, 13984, 15328, 16334, 19952, 20791},
|
||||
{ 2203, 3040, 3796, 5442, 11987, 13512, 14931, 16370, 17856, 18803},
|
||||
{ 2912, 4292, 7988, 9572, 11562, 13244, 14556, 16529, 20004, 21073},
|
||||
{ 2861, 3607, 5923, 7034, 9234, 12054, 13729, 18056, 20262, 20974},
|
||||
{ 3069, 4311, 5967, 7367, 11482, 12699, 14309, 16233, 18333, 19172},
|
||||
{ 2434, 3661, 4866, 5798, 10383, 11722, 13049, 15668, 18862, 19831},
|
||||
{ 2020, 2605, 3860, 9241, 13275, 14644, 16010, 17099, 19268, 20251},
|
||||
{ 1877, 2809, 3590, 4707, 11056, 12441, 15622, 17168, 18761, 19907},
|
||||
{ 2107, 2873, 3673, 5799, 13579, 14687, 15938, 17077, 18890, 19831},
|
||||
{ 1612, 2284, 2944, 3572, 8219, 13959, 15924, 17239, 18592, 20117},
|
||||
{ 2420, 3156, 6542, 10215, 12061, 13534, 15305, 16452, 18717, 19880},
|
||||
{ 1667, 2612, 3534, 5237, 10513, 11696, 12940, 16798, 18058, 19378},
|
||||
{ 2388, 3017, 4839, 9333, 11413, 12730, 15024, 16248, 17449, 18677},
|
||||
{ 1875, 2786, 4231, 6320, 8694, 10149, 11785, 17013, 18608, 19960},
|
||||
{ 679, 1411, 4654, 8006, 11446, 13249, 15763, 18127, 20361, 21567},
|
||||
{ 1838, 2596, 3578, 4608, 5650, 11274, 14355, 15886, 20579, 21754},
|
||||
{ 1303, 1955, 2395, 3322, 12023, 13764, 15883, 18077, 20180, 21232},
|
||||
{ 1438, 2102, 2663, 3462, 8328, 10362, 13763, 17248, 19732, 22344},
|
||||
{ 860, 1904, 6098, 7775, 9815, 12007, 14821, 16709, 19787, 21132},
|
||||
{ 1673, 2723, 3704, 6125, 7668, 9447, 13683, 14443, 20538, 21731},
|
||||
{ 1246, 1849, 2902, 4508, 7221, 12710, 14835, 16314, 19335, 22720},
|
||||
{ 1525, 2260, 3862, 5659, 7342, 11748, 13370, 14442, 18044, 21334},
|
||||
{ 1196, 1846, 3104, 7063, 10972, 12905, 14814, 17037, 19922, 22636},
|
||||
{ 2147, 3106, 4475, 6511, 8227, 9765, 10984, 12161, 18971, 21300},
|
||||
{ 1585, 2405, 2994, 4036, 11481, 13177, 14519, 15431, 19967, 21275},
|
||||
{ 1778, 2688, 3614, 4680, 9465, 11064, 12473, 16320, 19742, 20800},
|
||||
{ 1862, 2586, 3492, 6719, 11708, 13012, 14364, 16128, 19610, 20425},
|
||||
{ 1395, 2156, 2669, 3386, 10607, 12125, 13614, 16705, 18976, 21367},
|
||||
{ 1444, 2117, 3286, 6233, 9423, 12981, 14998, 15853, 17188, 21857},
|
||||
{ 2004, 2895, 3783, 4897, 6168, 7297, 12609, 16445, 19297, 21465},
|
||||
{ 1495, 2863, 6360, 8100, 11399, 14271, 15902, 17711, 20479, 22061},
|
||||
{ 2484, 3114, 5718, 7097, 8400, 12616, 14073, 14847, 20535, 21396},
|
||||
{ 2424, 3277, 5296, 6284, 11290, 12903, 16022, 17508, 19333, 20283},
|
||||
{ 2565, 3778, 5360, 6989, 8782, 10428, 14390, 15742, 17770, 21734},
|
||||
{ 2727, 3384, 6613, 9254, 10542, 12236, 14651, 15687, 20074, 21102},
|
||||
{ 1916, 2953, 6274, 8088, 9710, 10925, 12392, 16434, 20010, 21183},
|
||||
{ 3384, 4366, 5349, 7667, 11180, 12605, 13921, 15324, 19901, 20754},
|
||||
{ 3075, 4283, 5951, 7619, 9604, 11010, 12384, 14006, 20658, 21497},
|
||||
{ 1751, 2455, 5147, 9966, 11621, 13176, 14739, 16470, 20788, 21756},
|
||||
{ 1442, 2188, 3330, 6813, 8929, 12135, 14476, 15306, 19635, 20544},
|
||||
{ 2294, 2895, 4070, 8035, 12233, 13416, 14762, 17367, 18952, 19688},
|
||||
{ 1937, 2659, 4602, 6697, 9071, 12863, 14197, 15230, 16047, 18877},
|
||||
{ 2071, 2663, 4216, 9445, 10887, 12292, 13949, 14909, 19236, 20341},
|
||||
{ 1740, 2491, 3488, 8138, 9656, 11153, 13206, 14688, 20896, 21907},
|
||||
{ 2199, 2881, 4675, 8527, 10051, 11408, 14435, 15463, 17190, 20597},
|
||||
{ 1943, 2988, 4177, 6039, 7478, 8536, 14181, 15551, 17622, 21579},
|
||||
{ 1825, 3175, 7062, 9818, 12824, 15450, 18330, 19856, 21830, 22412},
|
||||
{ 2464, 3046, 4822, 5977, 7696, 15398, 16730, 17646, 20588, 21320},
|
||||
{ 2550, 3393, 5305, 6920, 10235, 14083, 18143, 19195, 20681, 21336},
|
||||
{ 3003, 3799, 5321, 6437, 7919, 11643, 15810, 16846, 18119, 18980},
|
||||
{ 3455, 4157, 6838, 8199, 9877, 12314, 15905, 16826, 19949, 20892},
|
||||
{ 3052, 3769, 4891, 5810, 6977, 10126, 14788, 15990, 19773, 20904},
|
||||
{ 3671, 4356, 5827, 6997, 8460, 12084, 14154, 14939, 19247, 20423},
|
||||
{ 2716, 3684, 5246, 6686, 8463, 10001, 12394, 14131, 16150, 19776},
|
||||
{ 1945, 2638, 4130, 7995, 14338, 15576, 17057, 18206, 20225, 20997},
|
||||
{ 2304, 2928, 4122, 4824, 5640, 13139, 15825, 16938, 20108, 21054},
|
||||
{ 1800, 2516, 3350, 5219, 13406, 15948, 17618, 18540, 20531, 21252},
|
||||
{ 1436, 2224, 2753, 4546, 9657, 11245, 15177, 16317, 17489, 19135},
|
||||
{ 2319, 2899, 4980, 6936, 8404, 13489, 15554, 16281, 20270, 20911},
|
||||
{ 2187, 2919, 4610, 5875, 7390, 12556, 14033, 16794, 20998, 21769},
|
||||
{ 2235, 2923, 5121, 6259, 8099, 13589, 15340, 16340, 17927, 20159},
|
||||
{ 1765, 2638, 3751, 5730, 7883, 10108, 13633, 15419, 16808, 18574},
|
||||
{ 3460, 5741, 9596, 11742, 14413, 16080, 18173, 19090, 20845, 21601},
|
||||
{ 3735, 4426, 6199, 7363, 9250, 14489, 16035, 17026, 19873, 20876},
|
||||
{ 3521, 4778, 6887, 8680, 12717, 14322, 15950, 18050, 20166, 21145},
|
||||
{ 2141, 2968, 6865, 8051, 10010, 13159, 14813, 15861, 17528, 18655},
|
||||
{ 4148, 6128, 9028, 10871, 12686, 14005, 15976, 17208, 19587, 20595},
|
||||
{ 4403, 5367, 6634, 8371, 10163, 11599, 14963, 16331, 17982, 18768},
|
||||
{ 4091, 5386, 6852, 8770, 11563, 13290, 15728, 16930, 19056, 20102},
|
||||
{ 2746, 3625, 5299, 7504, 10262, 11432, 13172, 15490, 16875, 17514},
|
||||
{ 2248, 3556, 8539, 10590, 12665, 14696, 16515, 17824, 20268, 21247},
|
||||
{ 1279, 1960, 3920, 7793, 10153, 14753, 16646, 18139, 20679, 21466},
|
||||
{ 2440, 3475, 6737, 8654, 12190, 14588, 17119, 17925, 19110, 19979},
|
||||
{ 1879, 2514, 4497, 7572, 10017, 14948, 16141, 16897, 18397, 19376},
|
||||
{ 2804, 3688, 7490, 10086, 11218, 12711, 16307, 17470, 20077, 21126},
|
||||
{ 2023, 2682, 3873, 8268, 10255, 11645, 15187, 17102, 18965, 19788},
|
||||
{ 2823, 3605, 5815, 8595, 10085, 11469, 16568, 17462, 18754, 19876},
|
||||
{ 2851, 3681, 5280, 7648, 9173, 10338, 14961, 16148, 17559, 18474},
|
||||
{ 1348, 2645, 5826, 8785, 10620, 12831, 16255, 18319, 21133, 22586},
|
||||
{ 2141, 3036, 4293, 6082, 7593, 10629, 17158, 18033, 21466, 22084},
|
||||
{ 1608, 2375, 3384, 6878, 9970, 11227, 16928, 17650, 20185, 21120},
|
||||
{ 2774, 3616, 5014, 6557, 7788, 8959, 17068, 18302, 19537, 20542},
|
||||
{ 1934, 4813, 6204, 7212, 8979, 11665, 15989, 17811, 20426, 21703},
|
||||
{ 2288, 3507, 5037, 6841, 8278, 9638, 15066, 16481, 21653, 22214},
|
||||
{ 2951, 3771, 4878, 7578, 9016, 10298, 14490, 15242, 20223, 20990},
|
||||
{ 3256, 4791, 6601, 7521, 8644, 9707, 13398, 16078, 19102, 20249},
|
||||
{ 1827, 2614, 3486, 6039, 12149, 13823, 16191, 17282, 21423, 22041},
|
||||
{ 1000, 1704, 3002, 6335, 8471, 10500, 14878, 16979, 20026, 22427},
|
||||
{ 1646, 2286, 3109, 7245, 11493, 12791, 16824, 17667, 18981, 20222},
|
||||
{ 1708, 2501, 3315, 6737, 8729, 9924, 16089, 17097, 18374, 19917},
|
||||
{ 2623, 3510, 4478, 5645, 9862, 11115, 15219, 18067, 19583, 20382},
|
||||
{ 2518, 3434, 4728, 6388, 8082, 9285, 13162, 18383, 19819, 20552},
|
||||
{ 1726, 2383, 4090, 6303, 7805, 12845, 14612, 17608, 19269, 20181},
|
||||
{ 2860, 3735, 4838, 6044, 7254, 8402, 14031, 16381, 18037, 19410},
|
||||
{ 4247, 5993, 7952, 9792, 12342, 14653, 17527, 18774, 20831, 21699},
|
||||
{ 3502, 4051, 5680, 6805, 8146, 11945, 16649, 17444, 20390, 21564},
|
||||
{ 3151, 4893, 5899, 7198, 11418, 13073, 15124, 17673, 20520, 21861},
|
||||
{ 3960, 4848, 5926, 7259, 8811, 10529, 15661, 16560, 18196, 20183},
|
||||
{ 4499, 6604, 8036, 9251, 10804, 12627, 15880, 17512, 20020, 21046},
|
||||
{ 4251, 5541, 6654, 8318, 9900, 11686, 15100, 17093, 20572, 21687},
|
||||
{ 3769, 5327, 7865, 9360, 10684, 11818, 13660, 15366, 18733, 19882},
|
||||
{ 3083, 3969, 6248, 8121, 9798, 10994, 12393, 13686, 17888, 19105},
|
||||
{ 2731, 4670, 7063, 9201, 11346, 13735, 16875, 18797, 20787, 22360},
|
||||
{ 1187, 2227, 4737, 7214, 9622, 12633, 15404, 17968, 20262, 23533},
|
||||
{ 1911, 2477, 3915, 10098, 11616, 12955, 16223, 17138, 19270, 20729},
|
||||
{ 1764, 2519, 3887, 6944, 9150, 12590, 16258, 16984, 17924, 18435},
|
||||
{ 1400, 3674, 7131, 8718, 10688, 12508, 15708, 17711, 19720, 21068},
|
||||
{ 2322, 3073, 4287, 8108, 9407, 10628, 15862, 16693, 19714, 21474},
|
||||
{ 2630, 3339, 4758, 8360, 10274, 11333, 12880, 17374, 19221, 19936},
|
||||
{ 1721, 2577, 5553, 7195, 8651, 10686, 15069, 16953, 18703, 19929}
|
||||
};
|
||||
|
||||
word16_t L2L3[L2_RANGE][NB_LSP_COEFF] = { /* The second stage is a 10-bit VQ splitted in L2(first 5 values of a vector) and L3(last five value in each vector) containing 32 entries (5 bits). */
|
||||
/* Q0.13 but max value<0.5 so fitting actually on 12+1(sign) bits */
|
||||
{ -435, -815, -742, 1033, -518, 582, -1201, 829, 86, 385},
|
||||
{ -833, -891, 463, -8, -1251, 1450, 72, -231, 864, 661},
|
||||
{-1021, 231, -306, 321, -220, -163, -526, -754, -1633, 267},
|
||||
{ 57, -198, -339, -33, -1468, 573, 796, -169, -631, 816},
|
||||
{ 171, -350, 294, 1660, 453, 519, 291, 159, -640, -1296},
|
||||
{ -701, -842, -58, 950, 892, 1549, 715, 527, -714, -193},
|
||||
{ 584, 31, -289, 356, -333, -457, 612, -283, -1381, -741},
|
||||
{ -109, -808, 231, 77, -87, -344, 1341, 1087, -654, -569},
|
||||
{ -859, 1236, 550, 854, 714, -543, -1752, -195, -98, -276},
|
||||
{ -877, -954, -1248, -299, 212, -235, -728, 949, 1517, 895},
|
||||
{ -77, 344, -620, 763, 413, 502, -362, -960, -483, 1386},
|
||||
{ -314, -307, -256, -1260, -429, 450, -466, -108, 1010, 2223},
|
||||
{ 711, 693, 521, 650, 1305, -28, -378, 744, -1005, 240},
|
||||
{ -112, -271, -500, 946, 1733, 271, -15, 909, -259, 1688},
|
||||
{ 575, -10, -468, -199, 1101, -1011, 581, -53, -747, 878},
|
||||
{ 145, -285, -1280, -398, 36, -498, -1377, 18, -444, 1483},
|
||||
{-1133, -835, 1350, 1284, -95, 1015, -222, 443, 372, -354},
|
||||
{-1459, -1237, 416, -213, 466, 669, 659, 1640, 932, 534},
|
||||
{ -15, 66, 468, 1019, -748, 1385, -182, -907, -721, -262},
|
||||
{ -338, 148, 1445, 75, -760, 569, 1247, 337, 416, -121},
|
||||
{ 389, 239, 1568, 981, 113, 369, -1003, -507, -587, -904},
|
||||
{ -312, -98, 949, 31, 1104, 72, -141, 1465, 63, -785},
|
||||
{ 1127, 584, 835, 277, -1159, 208, 301, -882, 117, -404},
|
||||
{ 539, -114, 856, -493, 223, -912, 623, -76, 276, -440},
|
||||
{ 2197, 2337, 1268, 670, 304, -267, -525, 140, 882, -139},
|
||||
{-1596, 550, 801, -456, -56, -697, 865, 1060, 413, 446},
|
||||
{ 1154, 593, -77, 1237, -31, 581, -1037, -895, 669, 297},
|
||||
{ 397, 558, 203, -797, -919, 3, 692, -292, 1050, 782},
|
||||
{ 334, 1475, 632, -80, 48, -1061, -484, 362, -597, -852},
|
||||
{ -545, -330, -429, -680, 1133, -1182, -744, 1340, 262, 63},
|
||||
{ 1320, 827, -398, -576, 341, -774, -483, -1247, -70, 98},
|
||||
{ -163, 674, -11, -886, 531, -1125, -265, -242, 724, 934}
|
||||
};
|
||||
|
||||
/* index used by CNG to reach a subset of L1, L2 and L3 codebooks */
|
||||
uint8_t L1SubsetIndex[32] = {96,52,20,54,86,114,82,68,36,121,48,92,18,120,
|
||||
94,124,50,125,4,100,28,76,12,117,81,22,90,116,
|
||||
127,21,108,66};
|
||||
uint8_t L2SubsetIndex[16] = {31,21,9,3,10,2,19,26,4,3,11,29,15,27,21,12};
|
||||
uint8_t L3SubsetIndex[16] = {16,1,0,0,8,25,22,20,19,23,20,31,4,31,20,31};
|
||||
|
||||
word16_t MAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF] = { /* the MA predictor coefficients in Q0.15 but max value < 0.5 so it fits on 15 bits */
|
||||
{
|
||||
{ 8421, 9109, 9175, 8965, 9034, 9057, 8765, 8775, 9106, 8673},
|
||||
{ 7018, 7189, 7638, 7307, 7444, 7379, 7038, 6956, 6930, 6868},
|
||||
{ 5472, 4990, 5134, 5177, 5246, 5141, 5206, 5095, 4830, 5147},
|
||||
{ 4056, 3031, 2614, 3024, 2916, 2713, 3309, 3237, 2857, 3473}
|
||||
},
|
||||
{
|
||||
{ 7733, 7880, 8188, 8175, 8247, 8490, 8637, 8601, 8359, 7569},
|
||||
{ 4210, 3031, 2552, 3473, 3876, 3853, 4184, 4154, 3909, 3968},
|
||||
{ 3214, 1930, 1313, 2143, 2493, 2385, 2755, 2706, 2542, 2919},
|
||||
{ 3024, 1592, 940, 1631, 1723, 1579, 2034, 2084, 1913, 2601}
|
||||
}
|
||||
};
|
||||
|
||||
word16_t MAPredictorSum[L0_RANGE][NB_LSP_COEFF] = {/* 1 - Sum(MAPredictor) in Q0.15 */
|
||||
{ 7798, 8447, 8205, 8293, 8126, 8477, 8447, 8703, 9043, 8604},
|
||||
{14585, 18333, 19772, 17344, 16426, 16459, 15155, 15220, 16043, 15708}
|
||||
};
|
||||
|
||||
word16_t invMAPredictorSum[L0_RANGE][NB_LSP_COEFF] = {/* 1/(1 - Sum(MAPredictor)) in Q3.12 */
|
||||
{17210, 15888, 16357, 16183, 16516, 15833, 15888, 15421, 14840, 15597},
|
||||
{ 9202, 7320, 6788, 7738, 8170, 8154, 8856, 8818, 8366, 8544}
|
||||
};
|
||||
|
||||
/* DTX/CNG use different values for MA predictor */
|
||||
word16_t noiseMAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF] = { /* the MA predictor coefficients in Q0.15 but max value < 0.5 so it fits on 15 bits */
|
||||
{
|
||||
{ 8421, 9109, 9175, 8965, 9034, 9057, 8765, 8775, 9106, 8673},
|
||||
{ 7018, 7189, 7638, 7307, 7444, 7379, 7038, 6956, 6930, 6868},
|
||||
{ 5472, 4990, 5134, 5177, 5246, 5141, 5206, 5095, 4830, 5147},
|
||||
{ 4056, 3031, 2614, 3024, 2916, 2713, 3309, 3237, 2857, 3473}
|
||||
},
|
||||
{
|
||||
{ 8145, 8617, 8779, 8648, 8718, 8829, 8713, 8705, 8806, 8231 },
|
||||
{ 5894, 5525, 5603, 5773, 6016, 5968, 5896, 5835, 5721, 5707 },
|
||||
{ 4568, 3765, 3605, 3963, 4144, 4038, 4225, 4139, 3914, 4255 },
|
||||
{ 3643, 2455, 1944, 2466, 2438, 2259, 2798, 2775, 2479, 3124 }
|
||||
}
|
||||
};
|
||||
|
||||
word16_t noiseMAPredictorSum[L0_RANGE][NB_LSP_COEFF] = {/* 1 - Sum(MAPredictor) in Q0.15 */
|
||||
{ 7798, 8447, 8205, 8293, 8126, 8477, 8447, 8703, 9043, 8604},
|
||||
{10514, 12402, 12833, 11914, 11447, 11670, 11132, 11311, 11844, 11447}
|
||||
};
|
||||
|
||||
word16_t invNoiseMAPredictorSum[L0_RANGE][NB_LSP_COEFF] = {/* 1/(1 - Sum(MAPredictor)) in Q3.12 */
|
||||
{17210, 15888, 16357, 16183, 16516, 15833, 15888, 15421, 14840, 15597},
|
||||
{12764, 10821, 10458, 11264, 11724, 11500, 12056, 11865, 11331, 11724}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* codebook for adaptative code vector */
|
||||
word16_t b30[31] = { /* in Q0.15 */
|
||||
29443, 25207, 14701, 3143, -4402, -5850, -2783, 1211, 3130, 2259, 0, -1652, -1666, -464, 756, 1099, 550, -245, -634, -451, 0, 308, 296, 78, -120, -165, -79, 34, 91, 70, 0};
|
||||
|
||||
/*** Gains related codebooks ***/
|
||||
/* codebook index mapping */
|
||||
uint16_t reverseIndexMappingGA[8] = {5, 1, 7, 4, 2, 0, 6, 3};
|
||||
uint16_t reverseIndexMappingGB[16] = {2, 14, 3, 13, 0, 15, 1, 12, 6, 10, 7, 9, 4, 11, 5, 8};
|
||||
uint16_t indexMappingGA[8] = {5, 1, 4, 7, 3, 0, 6, 2};
|
||||
uint16_t indexMappingGB[16] = {4, 6, 0, 2, 12, 14, 8, 10, 15, 11, 9, 13, 7, 3, 1, 5};
|
||||
|
||||
/* GA and GB codebooks: first element is for adaptativeCodebookGain (in Q14), second element is for fixedCodebookGain computation (in Q12) */
|
||||
word16_t GACodebook[8][2] = {
|
||||
/* Q14 Q12 */
|
||||
{ 0 , 758 },
|
||||
{ 1551 , 1213 },
|
||||
{ 1831 , 2511 },
|
||||
{ 57 , 2702 },
|
||||
{ 1921 , 4646 },
|
||||
{ 3242 , 4975 },
|
||||
{ 356 , 7378 },
|
||||
{ 2678 , 13581 }
|
||||
};
|
||||
|
||||
word16_t GBCodebook[16][2] = {
|
||||
/* Q14 Q12 */
|
||||
{ 826 , 1003 },
|
||||
{ 1994 , 0 },
|
||||
{ 5142 , 296 },
|
||||
{ 6160 , 1197 },
|
||||
{ 8091 , 2431 },
|
||||
{ 9120 , 263 },
|
||||
{ 10573 , 1483 },
|
||||
{ 11569 , 598 },
|
||||
{ 13260 , 1628 },
|
||||
{ 14194 , 815 },
|
||||
{ 15132 , 2457 },
|
||||
{ 15161 , 7138 },
|
||||
{ 15434 , 119 },
|
||||
{ 16112 , 1696 },
|
||||
{ 17299 , 931 },
|
||||
{ 18973 , 2968 }
|
||||
};
|
||||
|
||||
/* according to spec 3.9.1: MA predictionCoefficients {0.68, 0.58, 0.34, 0.19} in Q14 */
|
||||
word16_t MAPredictionCoefficients[4] = { 11141, 9503, 5571, 3113 };
|
||||
|
||||
/* Hamming_cos window for LPC analysis as defined in spec 3.2.1 eq3 */
|
||||
word16_t wlp[L_LP_ANALYSIS_WINDOW] = { /* in Q15 */
|
||||
2621, 2623, 2629, 2638, 2651, 2668, 2689, 2713, 2741, 2772,
|
||||
2808, 2847, 2890, 2936, 2986, 3040, 3097, 3158, 3223, 3291,
|
||||
3363, 3438, 3517, 3599, 3685, 3774, 3867, 3963, 4063, 4166,
|
||||
4272, 4382, 4495, 4611, 4731, 4853, 4979, 5108, 5240, 5376,
|
||||
5514, 5655, 5800, 5947, 6097, 6250, 6406, 6565, 6726, 6890,
|
||||
7057, 7227, 7399, 7573, 7750, 7930, 8112, 8296, 8483, 8672,
|
||||
8863, 9057, 9252, 9450, 9650, 9852, 10055, 10261, 10468, 10677,
|
||||
10888, 11101, 11315, 11531, 11748, 11967, 12187, 12409, 12632, 12856,
|
||||
13082, 13308, 13536, 13764, 13994, 14225, 14456, 14688, 14921, 15155,
|
||||
15389, 15624, 15859, 16095, 16331, 16568, 16805, 17042, 17279, 17516,
|
||||
17754, 17991, 18228, 18465, 18702, 18939, 19175, 19411, 19647, 19882,
|
||||
20117, 20350, 20584, 20816, 21048, 21279, 21509, 21738, 21967, 22194,
|
||||
22420, 22644, 22868, 23090, 23311, 23531, 23749, 23965, 24181, 24394,
|
||||
24606, 24816, 25024, 25231, 25435, 25638, 25839, 26037, 26234, 26428,
|
||||
26621, 26811, 26999, 27184, 27368, 27548, 27727, 27903, 28076, 28247,
|
||||
28415, 28581, 28743, 28903, 29061, 29215, 29367, 29515, 29661, 29804,
|
||||
29944, 30081, 30214, 30345, 30472, 30597, 30718, 30836, 30950, 31062,
|
||||
31170, 31274, 31376, 31474, 31568, 31659, 31747, 31831, 31911, 31988,
|
||||
32062, 32132, 32198, 32261, 32320, 32376, 32428, 32476, 32521, 32561,
|
||||
32599, 32632, 32662, 32688, 32711, 32729, 32744, 32755, 32763, 32767,
|
||||
32767, 32741, 32665, 32537, 32359, 32129, 31850, 31521, 31143, 30716,
|
||||
30242, 29720, 29151, 28538, 27879, 27177, 26433, 25647, 24821, 23957,
|
||||
23055, 22117, 21145, 20139, 19102, 18036, 16941, 15820, 14674, 13505,
|
||||
12315, 11106, 9879, 8637, 7381, 6114, 4838, 3554, 2264, 971};
|
||||
|
||||
/* lag window as defined in spec 3.2.1 eq6 : up to 12 values for VAD */
|
||||
/* wlag[0] = 1.00000000 not used
|
||||
wlag[1] = 0.99879038
|
||||
wlag[2] = 0.99546897
|
||||
wlag[3] = 0.98995781
|
||||
wlag[4] = 0.98229337
|
||||
wlag[5] = 0.97252619
|
||||
wlag[6] = 0.96072036
|
||||
wlag[7] = 0.94695264
|
||||
wlag[8] = 0.93131179
|
||||
wlag[9] = 0.91389757
|
||||
wlag[10]= 0.89481968
|
||||
wlag[11]= 0.87419660
|
||||
wlag[12]= 0.85215437
|
||||
*/
|
||||
word16_t wlag[NB_LSP_COEFF+3] = { /* in Q15 note first coeff is not used */
|
||||
32767, 32728, 32619, 32438, 32187, 31867, 31480, 31029, 30517, 29946, 29321, 28646, 27923};
|
||||
|
||||
/* quantised SID gain retrieved from ITU code, in Q3 */
|
||||
word16_t SIDGainCodebook[32] = {
|
||||
2, 5, 8, 13, 20, 32, 50, 64,
|
||||
80, 101, 127, 160, 201, 253, 318, 401,
|
||||
505, 635, 800, 1007, 1268, 1596, 2010, 2530,
|
||||
3185, 4009, 5048, 6355, 8000,10071,12679,15962 };
|
||||
|
||||
/* Low Band Filter FIR for VAD in Q15 */
|
||||
word16_t lowBandFilter[NB_LSP_COEFF+3] = {7869, 7011, 4838, 2299, 321, -660, -782, -484, -164, 3, 39, 21, 4};
|
||||
|
59
bcg729/src/codebooks.h
Normal file
59
bcg729/src/codebooks.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef CODEBOOKS_H
|
||||
#define CODEBOOKS_H
|
||||
|
||||
#include "codecParameters.h"
|
||||
/* this codebooks are defined in codebook.c */
|
||||
|
||||
/*** codebooks for quantization of the LSP coefficient - doc: 3.2.4 ***/
|
||||
extern word16_t L1[L1_RANGE][NB_LSP_COEFF]; /* The first stage is a 10-dimensional VQ using codebook L1 with 128 entries (7 bits). in Q2.13 */
|
||||
extern word16_t L2L3[L2_RANGE][NB_LSP_COEFF]; /* Doc : The second stage is a 10-bit VQ splitted in L2(first 5 values of a vector) and L3(last five value in each vector) containing 32 entries (5 bits). in Q0.13 but max value < 0.5 so fits in 13 bits. */
|
||||
|
||||
extern word16_t MAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF]; /* the MA predictor coefficients in Q0.15 but max value < 0.5 so it fits on 15 bits */
|
||||
extern word16_t MAPredictorSum[L0_RANGE][NB_LSP_COEFF]; /* 1 - Sum(MAPredictor) in Q0.15 */
|
||||
extern word16_t invMAPredictorSum[L0_RANGE][NB_LSP_COEFF]; /* 1/(1 - Sum(MAPredictor)) in Q3.12 */
|
||||
/* same as above but used for SID frame */
|
||||
extern word16_t noiseMAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF]; /* the MA predictor coefficients in Q0.15 but max value < 0.5 so it fits on 15 bits */
|
||||
extern word16_t noiseMAPredictorSum[L0_RANGE][NB_LSP_COEFF]; /* 1 - Sum(MAPredictor) in Q0.15 */
|
||||
extern word16_t invNoiseMAPredictorSum[L0_RANGE][NB_LSP_COEFF]; /* 1/(1 - Sum(MAPredictor)) in Q3.12 */
|
||||
|
||||
/* codebook for adaptative code vector */
|
||||
extern word16_t b30[31];
|
||||
|
||||
/* codebook for gains */
|
||||
extern uint16_t reverseIndexMappingGA[8];
|
||||
extern uint16_t reverseIndexMappingGB[16];
|
||||
extern uint16_t indexMappingGA[8];
|
||||
extern uint16_t indexMappingGB[16];
|
||||
extern word16_t GACodebook[8][2];
|
||||
extern word16_t GBCodebook[16][2];
|
||||
extern word16_t MAPredictionCoefficients[4];
|
||||
extern word16_t SIDGainCodebook[32];
|
||||
extern uint8_t L1SubsetIndex[32];
|
||||
extern uint8_t L2SubsetIndex[16];
|
||||
extern uint8_t L3SubsetIndex[16];
|
||||
|
||||
/* codebook for VAD */
|
||||
extern word16_t lowBandFilter[NB_LSP_COEFF+3];
|
||||
|
||||
/* codebook for LP Analysis */
|
||||
extern word16_t wlp[L_LP_ANALYSIS_WINDOW];
|
||||
extern word16_t wlag[NB_LSP_COEFF+3];
|
||||
#endif /* ifndef CODEBOOKS_H */
|
136
bcg729/src/codecParameters.h
Normal file
136
bcg729/src/codecParameters.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef CODECPARAMETERS_H
|
||||
#define CODECPARAMETERS_H
|
||||
|
||||
#define L_FRAME 80 /* Frame size. */
|
||||
#define L_SUBFRAME 40 /* subFrame size. */
|
||||
|
||||
#define L_LP_ANALYSIS_WINDOW 240 /* Size of the window used in the LP Analysis */
|
||||
/******************************************************************************/
|
||||
/*** LSP coefficients ***/
|
||||
/******************************************************************************/
|
||||
/* define each coefficient bit number and range */
|
||||
#define L0_LENGTH 1
|
||||
#define L1_LENGTH 7
|
||||
#define L2_LENGTH 5
|
||||
#define L3_LENGTH 5
|
||||
#define L0_RANGE (1<<L0_LENGTH)
|
||||
#define L1_RANGE (1<<L1_LENGTH)
|
||||
#define L2_RANGE (1<<L2_LENGTH)
|
||||
#define L3_RANGE (1<<L3_LENGTH)
|
||||
/* SID frame use a subset of L1 and L2 */
|
||||
#define NOISE_L1_RANGE 32
|
||||
#define NOISE_L2_RANGE 16
|
||||
|
||||
/* MA Prediction history length: maximum number of previous LSP used */
|
||||
#define MA_MAX_K 4
|
||||
|
||||
/* Linear Prediction filters order: 10th order filters gives 10 (quantized) LP coefficients */
|
||||
/* NB_LSP_COEFF is the number of LSP coefficient */
|
||||
#define NB_LSP_COEFF 10
|
||||
|
||||
/* Maximum value of integer part of pitch delay */
|
||||
#define MAXIMUM_INT_PITCH_DELAY 143
|
||||
/* past excitation vector length: Maximum Pitch Delay (143 + 1(fractionnal part)) + Interpolation Windows Length (10) */
|
||||
#define L_PAST_EXCITATION 154
|
||||
|
||||
/* rearrange coefficient gap in Q13 */
|
||||
/* GAP1 is 0.0012, GAP2 is 0.0006 */
|
||||
#define GAP1 10
|
||||
#define GAP2 5
|
||||
|
||||
/* qLSF stability in Q13*/
|
||||
/* Limits for quantized LSF */
|
||||
/* in Q2.13, Max is 3.135 and Min is 0.005 */
|
||||
#define qLSF_MIN 40
|
||||
#define qLSF_MAX 25681
|
||||
/* min distance between 2 consecutive qLSF is 0.0391 */
|
||||
#define MIN_qLSF_DISTANCE 321
|
||||
|
||||
/* pitch gain boundaries in Q14 */
|
||||
#define BOUNDED_PITCH_GAIN_MIN 3277
|
||||
#define BOUNDED_PITCH_GAIN_MAX 13107
|
||||
|
||||
/* post filters values defined in 4.2.2 in Q15 pow 1 to 10 */
|
||||
#define GAMMA_N1 18022
|
||||
#define GAMMA_N2 9912
|
||||
#define GAMMA_N3 5452
|
||||
#define GAMMA_N4 2998
|
||||
#define GAMMA_N5 1649
|
||||
#define GAMMA_N6 907
|
||||
#define GAMMA_N7 499
|
||||
#define GAMMA_N8 274
|
||||
#define GAMMA_N9 151
|
||||
#define GAMMA_N10 83
|
||||
#define GAMMA_D1 22938
|
||||
#define GAMMA_D2 16056
|
||||
#define GAMMA_D3 11239
|
||||
#define GAMMA_D4 7868
|
||||
#define GAMMA_D5 5507
|
||||
#define GAMMA_D6 3855
|
||||
#define GAMMA_D7 2699
|
||||
#define GAMMA_D8 1889
|
||||
#define GAMMA_D9 1322
|
||||
#define GAMMA_D10 926
|
||||
|
||||
/* post filter value GAMMA_T 0.8 in Q15 (spec A.4.2.3)*/
|
||||
#define GAMMA_T 26214
|
||||
|
||||
/* weighted speech for open-loop pitch delay (spec A3.3.3) in Q15 0.75^(1..10)*/
|
||||
#define GAMMA_E1 24756
|
||||
#define GAMMA_E2 18432
|
||||
#define GAMMA_E3 13824
|
||||
#define GAMMA_E4 10368
|
||||
#define GAMMA_E5 7776
|
||||
#define GAMMA_E6 5832
|
||||
#define GAMMA_E7 4374
|
||||
#define GAMMA_E8 3280
|
||||
#define GAMMA_E9 2460
|
||||
#define GAMMA_E10 1845
|
||||
|
||||
/*** Number of parameters in the encoded signal ***/
|
||||
#define NB_PARAMETERS 15
|
||||
|
||||
/*** LP to LSP conversion ***/
|
||||
#define NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL 51
|
||||
|
||||
/*** CNG ***/
|
||||
/* 1/2sqrt*(40) in Q1.13 */
|
||||
#define GAUSSIAN_EXCITATION_COEFF_FACTOR 25905
|
||||
/* 0.75 in Q15 */
|
||||
#define COEFF_K 24576
|
||||
|
||||
/*** VAD ***/
|
||||
#define LOG2_240_Q16 518186
|
||||
#define INV_LOG2_10_Q15 9864
|
||||
|
||||
/* buffer size for history on different values (defined in spec table B.1)*/
|
||||
#define Ni 32
|
||||
#define N0 128
|
||||
|
||||
/*** DTX ***/
|
||||
/* 1.12202 in Q20 */
|
||||
#define THRESHOLD3_IN_Q20 1176553
|
||||
/* 1.20226 in Q20 */
|
||||
#define THRESHOLD1_IN_Q20 1260661
|
||||
#define CNG_DTX_RANDOM_SEED_INIT 11111
|
||||
|
||||
|
||||
#endif /* ifndef CODECPARAMETERS_H */
|
67
bcg729/src/computeAdaptativeCodebookGain.c
Normal file
67
bcg729/src/computeAdaptativeCodebookGain.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "computeAdaptativeCodebookGain.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeAdaptativeCodebookGain: compute gain, return result in Q14 */
|
||||
/* in range [0,1.2]. Spec 3.7.3 */
|
||||
/* parameters: */
|
||||
/* -(i) targetSignal: 40 values in Q0 */
|
||||
/* -(i) filteredAdaptativeCodebookVector: 40 values in Q0 */
|
||||
/* -(o) gainQuantizationXy in Q0 on 64 bits used for gain quantization */
|
||||
/* -(o) gainQuantizationYy in Q0 on 64 bits used for gain quantization */
|
||||
/* return value: */
|
||||
/* - the adaptative codebook gain on 16 bits in Q14 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
word16_t computeAdaptativeCodebookGain(word16_t targetSignal[], word16_t filteredAdaptativeCodebookVector[], word64_t *gainQuantizationXy, word64_t *gainQuantizationYy)
|
||||
{
|
||||
int i;
|
||||
word32_t gain;
|
||||
|
||||
*gainQuantizationXy = 0; /* contains the scalar product targetSignal, filteredAdaptativeCodebookVector : numerator */
|
||||
*gainQuantizationYy = 0; /* contains the scalar product filteredAdaptativeCodebookVector^2 : denominator */
|
||||
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
*gainQuantizationXy = MAC64(*gainQuantizationXy, targetSignal[i], filteredAdaptativeCodebookVector[i]);
|
||||
*gainQuantizationYy = MAC64(*gainQuantizationYy, filteredAdaptativeCodebookVector[i], filteredAdaptativeCodebookVector[i]);
|
||||
}
|
||||
|
||||
/* check on values of xx and xy */
|
||||
if (*gainQuantizationXy<=0) { /* gain would be negative -> return 0 */
|
||||
/* this test covers the case of yy(denominator)==0 because if yy==0 then all y==0 and thus xy==0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* output shall be in Q14 */
|
||||
gain = DIV64(SHL64(*gainQuantizationXy,14),*gainQuantizationYy); /* gain in Q14 */
|
||||
|
||||
/* check if it is not above 1.2 */
|
||||
if (gain>ONE_POINT_2_IN_Q14) {
|
||||
gain = ONE_POINT_2_IN_Q14;
|
||||
}
|
||||
|
||||
return (word16_t)gain;
|
||||
}
|
35
bcg729/src/computeAdaptativeCodebookGain.h
Normal file
35
bcg729/src/computeAdaptativeCodebookGain.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef COMPUTEADAPTATIVECODEBOOKGAIN_H
|
||||
#define COMPUTEADAPTATIVECODEBOOKGAIN_H
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeAdaptativeCodebookGain: compute gain, return result in Q14 */
|
||||
/* in range [0,1.2]. Spec 3.7.3 */
|
||||
/* parameters: */
|
||||
/* -(i) targetSignal: 40 values in Q0 */
|
||||
/* -(i) filteredAdaptativeCodebookVector: 40 values in Q0 */
|
||||
/* -(o) gainQuantizationXy in Q0 on 64 bits used for gain quantization */
|
||||
/* -(o) gainQuantizationYy in Q0 on 64 bits used for gain quantization */
|
||||
/* return value: */
|
||||
/* - the adaptative codebook gain on 16 bits in Q14 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
word16_t computeAdaptativeCodebookGain(word16_t targetSignal[], word16_t filteredAdaptativeCodebookVector[], word64_t *gainQuantizationXy, word64_t *gainQuantizationYy);
|
||||
#endif /* ifndef COMPUTEADAPTATIVECODEBOOKGAIN_H */
|
217
bcg729/src/computeLP.c
Normal file
217
bcg729/src/computeLP.c
Normal file
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "codebooks.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "computeLP.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* autoCorrelation2LP: convert autocorrelation coefficients to LP using */
|
||||
/* Levinson-Durbin algo described in spec 3.2.2 */
|
||||
/* parameters : */
|
||||
/* -(i) autoCorrelationCoefficients : 11 values in variable scale */
|
||||
/* scale is not needed here as a division cancel it */
|
||||
/* -(o) LPCoefficientsQ12: 10 LP coefficients in Q12 */
|
||||
/* -(o) reflectionCoefficient: 10 values Q31, k generated during Levinson */
|
||||
/* Durbin LP coefficient generation and needed for VAD and RFC3389 */
|
||||
/* -(o) residualEnergy : with the same scale factor as input */
|
||||
/* autoCorrelationCoefficients, needed by DTX */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void autoCorrelation2LP(word32_t autoCorrelationCoefficients[], word16_t LPCoefficientsQ12[], word32_t reflectionCoefficients[], word32_t *residualEnergy) {
|
||||
/*********************************************************************************/
|
||||
/* Compute the LP Coefficient using Levinson-Durbin algo spec 3.2.2 */
|
||||
/*********************************************************************************/
|
||||
/* start a iteration i=2, init values as after iteration i=1 : */
|
||||
/* a[0] = 1 */
|
||||
/* a[1] = -r1/r0 */
|
||||
/* E = r0(1 - a[1]^2) */
|
||||
/* */
|
||||
/* iterations i = 2..10 */
|
||||
/* sum = r[i] + ∑ a[j]*r[i-j] with j = 1..i-1 (a[0] is always 1) */
|
||||
/* a[i] = -sum/E */
|
||||
/* iterations j = 1..i-1 */
|
||||
/* a[j] += a[i]*a{i-1}[i-j] use a{i-1}: from previous iteration */
|
||||
/* E *=(1-a[i]^2) */
|
||||
/* */
|
||||
/* r in Q31 (normalised) stored in array autoCorrelationCoefficients */
|
||||
/* E in Q31 (can't be > 1) */
|
||||
/* sum in Q27 (sum can't be > 1 but intermediate accumulation can) */
|
||||
/* a in Q4.27 with full range possible */
|
||||
/* Note: during iteration, current a[i] is in Q31 (can't be >1) and is */
|
||||
/* set to Q27 at the end of current iteration */
|
||||
/* */
|
||||
/*********************************************************************************/
|
||||
word32_t previousIterationLPCoefficients[NB_LSP_COEFF+1]; /* to compute a[]*/
|
||||
word32_t LPCoefficients[NB_LSP_COEFF+1]; /* in Q4.27 */
|
||||
|
||||
word32_t E = 0; /* in Q31 */
|
||||
word32_t sum = 0; /* in Q27 */
|
||||
int i,j;
|
||||
|
||||
/* init */
|
||||
LPCoefficients[0] = ONE_IN_Q27;
|
||||
LPCoefficients[1] = -DIV32_32_Q27(autoCorrelationCoefficients[1], autoCorrelationCoefficients[0]); /* result in Q27(but<1) */
|
||||
reflectionCoefficients[0] = SSHL(LPCoefficients[1],4); /* k[0] is -r1/r0 in Q31 */
|
||||
/* E = r0(1 - a[1]^2) in Q31 */
|
||||
E = MULT32_32_Q31(autoCorrelationCoefficients[0], SUB32(ONE_IN_Q31, MULT32_32_Q23(LPCoefficients[1], LPCoefficients[1]))); /* LPCoefficient[1] is in Q27, using a Q23 operation will result in a Q31 variable */
|
||||
|
||||
for (i=2; i<NB_LSP_COEFF+1; i++) {
|
||||
/* update the previousIterationLPCoefficients needed for this one */
|
||||
for (j=1; j<i; j++) {
|
||||
previousIterationLPCoefficients[j] = LPCoefficients[j];
|
||||
}
|
||||
|
||||
/* sum = r[i] + ∑ a[j]*r[i-j] with j = 1..i-1 (a[0] is always 1) */
|
||||
sum = 0;
|
||||
for (j=1; j<i; j++) {
|
||||
sum = MAC32_32_Q31(sum, LPCoefficients[j], autoCorrelationCoefficients[i-j]);/* LPCoefficients in Q27, autoCorrelation in Q31 -> result in Q27 -> sum in Q27 */
|
||||
}
|
||||
sum = ADD32(SSHL(sum, 4), autoCorrelationCoefficients[i]); /* set sum in Q31 and add r[0] */
|
||||
|
||||
/* a[i] = -sum/E */
|
||||
LPCoefficients[i] = -DIV32_32_Q31(sum,E); /* LPCoefficient of current iteration is in Q31 for now, it will be set to Q27 at the end of this iteration */
|
||||
reflectionCoefficients[i-1] = LPCoefficients[i]; /* k[1] is needed by VAD others by RFC3389 RTP payload for Comfort Noise spectral information encoding */
|
||||
|
||||
/* iterations j = 1..i-1 */
|
||||
/* a[j] += a[i]*a[i-j] */
|
||||
for (j=1; j<i; j++) {
|
||||
LPCoefficients[j] = MAC32_32_Q31(LPCoefficients[j], LPCoefficients[i], previousIterationLPCoefficients[i-j]); /*LPCoefficients in Q27 except for LPCoefficients[i] in Q31 */
|
||||
}
|
||||
/* E *=(1-a[i]^2) */
|
||||
E = MULT32_32_Q31(E, SUB32(ONE_IN_Q31, MULT32_32_Q31(LPCoefficients[i], LPCoefficients[i]))); /* all in Q31 */
|
||||
/* set LPCoefficients[i] from Q31 to Q27 */
|
||||
LPCoefficients[i] = SHR(LPCoefficients[i], 4);
|
||||
}
|
||||
*residualEnergy = E;
|
||||
|
||||
/* convert with rounding the LP Coefficients form Q27 to Q12, ignore first coefficient which is always 1 */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
LPCoefficientsQ12[i] = (word16_t)SATURATE(PSHR(LPCoefficients[i+1], 15), MAXINT16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeLP : As described in spec 3.2.1 and 3.2.2 : Windowing, */
|
||||
/* Autocorrelation and Levinson-Durbin algorithm */
|
||||
/* parameters: */
|
||||
/* -(i) signal: 240 samples in Q0, the last 40 are from next frame */
|
||||
/* -(o) LPCoefficientsQ12: 10 LP coefficients in Q12 */
|
||||
/* -(o) reflectionCoefficient: 10 values Q31, k generated by Levinson */
|
||||
/* Durbin LP coefficient generation and needed for VAD and RFC3389 */
|
||||
/* -(o) reflectionCoefficient: in Q31, k[1] generated during Levinson */
|
||||
/* Durbin LP coefficient generation and needed for VAD */
|
||||
/* -(o) autoCorrelationCoefficients : used internally but needed by VAD */
|
||||
/* scale is variable */
|
||||
/* -(o) noLagautoCorrelationCoefficients : needed by DTX */
|
||||
/* scale is variable */
|
||||
/* -(o) autoCorrelationCoefficientsScale : scale factor of previous buf */
|
||||
/* -(i) autoCorrelationCoefficientsNumber number of coeff to be computed*/
|
||||
/* 13 if we are using them for VAD, only 11 otherwise */
|
||||
/*****************************************************************************/
|
||||
void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[], word32_t reflectionCoefficients[], word32_t autoCorrelationCoefficients[], word32_t noLagAutocorrelationCoefficients[], int8_t *autoCorrelationCoefficientsScale, uint8_t autoCorrelationCoefficientsNumber)
|
||||
{
|
||||
int i,j;
|
||||
word16_t windowedSignal[L_LP_ANALYSIS_WINDOW];
|
||||
word64_t acc64=0; /* acc on 64 bits */
|
||||
int rightShiftToNormalise=0;
|
||||
word32_t residualEnergy; /* interally compute by autoCorrelation2LP and extracted for DTX only, useless here */
|
||||
|
||||
/*********************************************************************/
|
||||
/* Compute the windowed signal according to spec 3.2.1 eq4 */
|
||||
/*********************************************************************/
|
||||
for (i=0; i<L_LP_ANALYSIS_WINDOW; i++) {
|
||||
windowedSignal[i] = MULT16_16_P15(signal[i], wlp[i]); /* signal in Q0, wlp in Q0.15, windowedSignal in Q0 */
|
||||
}
|
||||
|
||||
/*********************************************************************************/
|
||||
/* Compute the autoCorrelation coefficients r[0..10] according to spec 3.2.1 eq5 */
|
||||
/*********************************************************************************/
|
||||
/* Compute autoCorrelationCoefficients[0] first as it is the highest number and normalise it on 32 bits then apply the same normalisation to the other coefficients */
|
||||
/* autoCorrelationCoefficients are normalised on 32 bits and then considered as Q31 in range [-1,1[ */
|
||||
/* autoCorrelationCoefficients[0] is computed on 64 bits as it is likely to overflow 32 bits */
|
||||
for (i=0; i<L_LP_ANALYSIS_WINDOW; i++) {
|
||||
acc64 = MAC64(acc64, windowedSignal[i], windowedSignal[i]);
|
||||
}
|
||||
if (acc64==0) {
|
||||
acc64 = 1; /* spec 3.2.1: To avoid arithmetic problems for low-level input signals the value of r(0) has a lower boundary of r(0) = 1.0 */
|
||||
}
|
||||
/* normalise the acc64 on 32 bits */
|
||||
if (acc64>MAXINT32) {
|
||||
do {
|
||||
acc64 = SHR(acc64,1);
|
||||
rightShiftToNormalise++;
|
||||
} while (acc64>MAXINT32);
|
||||
autoCorrelationCoefficients[0] = acc64;
|
||||
} else {
|
||||
rightShiftToNormalise = -countLeadingZeros((word32_t)acc64);
|
||||
autoCorrelationCoefficients[0] = SSHL((word32_t)acc64, -rightShiftToNormalise);
|
||||
}
|
||||
|
||||
/* give current autoCorrelation coefficients scale to the output */
|
||||
*autoCorrelationCoefficientsScale = -rightShiftToNormalise;
|
||||
|
||||
/* compute autoCorrelationCoefficients 1 to requested number (10 - no VAD - or 12 if VAD is enabled */
|
||||
if (rightShiftToNormalise>0) { /* acc64 was not fitting on 32 bits so compute the other sum on 64 bits too */
|
||||
for (i=1; i<autoCorrelationCoefficientsNumber; i++) {
|
||||
/* compute the sum in the 64 bits acc*/
|
||||
acc64=0;
|
||||
for (j=i; j<L_LP_ANALYSIS_WINDOW; j++) {
|
||||
acc64 = ADD64_32(acc64, MULT16_16(windowedSignal[j], windowedSignal[j-i]));
|
||||
}
|
||||
/* normalise it */
|
||||
autoCorrelationCoefficients[i] = SHR(acc64 ,rightShiftToNormalise);
|
||||
}
|
||||
} else { /* acc64 was fitting on 32 bits, compute the other sum on 32 bits only as it is faster */
|
||||
for (i=1; i<autoCorrelationCoefficientsNumber; i++) {
|
||||
/* compute the sum in the 64 bits acc*/
|
||||
word32_t acc32=0;
|
||||
for (j=i; j<L_LP_ANALYSIS_WINDOW; j++) {
|
||||
acc32 = MAC16_16(acc32, windowedSignal[j], windowedSignal[j-i]);
|
||||
}
|
||||
/* normalise it */
|
||||
autoCorrelationCoefficients[i] = SSHL(acc32, -rightShiftToNormalise);
|
||||
}
|
||||
}
|
||||
|
||||
/* save autocorrelation before applying lag window as they are requested like this for DTX */
|
||||
for (i=0; i<autoCorrelationCoefficientsNumber; i++) {
|
||||
noLagAutocorrelationCoefficients[i] = autoCorrelationCoefficients[i];
|
||||
}
|
||||
|
||||
/* apply lag window on the autocorrelation coefficients spec 3.2.1 eq7 */
|
||||
/* this check shall be useless but it makes some compiler happy */
|
||||
if (autoCorrelationCoefficientsNumber>NB_LSP_COEFF+3) {
|
||||
autoCorrelationCoefficientsNumber = NB_LSP_COEFF+3;
|
||||
}
|
||||
|
||||
for (i=1; i<autoCorrelationCoefficientsNumber; i++) {
|
||||
autoCorrelationCoefficients[i] = MULT16_32_P15(wlag[i], autoCorrelationCoefficients[i]); /* wlag in Q15 */
|
||||
//autoCorrelationCoefficients[i] = MULT32_32_Q31(wlag[i], autoCorrelationCoefficients[i]); /* wlag in Q31 */
|
||||
}
|
||||
|
||||
/* convert to LP using Levinson-Durbin algo described in sepc 3.2.2 */
|
||||
autoCorrelation2LP(autoCorrelationCoefficients, LPCoefficientsQ12, reflectionCoefficients, &residualEnergy);
|
||||
|
||||
return;
|
||||
}
|
56
bcg729/src/computeLP.h
Normal file
56
bcg729/src/computeLP.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef COMPUTELP_H
|
||||
#define COMPUTELP_H
|
||||
/*****************************************************************************/
|
||||
/* autoCorrelation2LP: convert autocorrelation coefficients to LP using */
|
||||
/* Levinson-Durbin algo described in spec 3.2.2 */
|
||||
/* parameters : */
|
||||
/* -(i) autoCorrelationCoefficients : 11 values in variable scale */
|
||||
/* scale is not needed here as a division cancel it */
|
||||
/* -(o) LPCoefficientsQ12: 10 LP coefficients in Q12 */
|
||||
/* -(o) reflectionCoefficients: 10 values Q31, k generated during Levinson*/
|
||||
/* Durbin LP coefficient generation and needed for VAD and RFC3389 */
|
||||
/* -(o) residualEnergy : with the same scale factor as input */
|
||||
/* autoCorrelationCoefficients, needed by DTX */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void autoCorrelation2LP(word32_t autoCorrelationCoefficients[], word16_t LPCoefficientsQ12[], word32_t reflectionCoefficients[], word32_t *residualEnergy);
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeLP : As described in spec 3.2.1 and 3.2.2 : Windowing, */
|
||||
/* Autocorrelation and Levinson-Durbin algorithm */
|
||||
/* parameters: */
|
||||
/* -(i) signal: 240 samples in Q0, the last 40 are from next frame */
|
||||
/* -(o) LPCoefficientsQ12: 10 LP coefficients in Q12 */
|
||||
/* -(o) reflectionCoefficient: 10 values Q31, k generated by Levinson */
|
||||
/* Durbin LP coefficient generation and needed for VAD and RFC3389 */
|
||||
/* -(o) reflectionCoefficient: in Q31, k[1] generated during Levinson */
|
||||
/* Durbin LP coefficient generation and needed for VAD */
|
||||
/* -(o) autoCorrelationCoefficients : used internally but needed by VAD */
|
||||
/* scale is variable */
|
||||
/* -(o) noLagautoCorrelationCoefficients : needed by DTX */
|
||||
/* scale is variable */
|
||||
/* -(o) autoCorrelationCoefficientsScale : scale factor of previous buf */
|
||||
/* -(i) autoCorrelationCoefficientsNumber number of coeff to be computed*/
|
||||
/* 13 if we are using them for VAD, only 11 otherwise */
|
||||
/*****************************************************************************/
|
||||
void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[], word32_t reflectionCoefficients[], word32_t autoCorrelationCoefficients[], word32_t noLagAutocorrelationCoefficients[], int8_t *autoCorrelationCoefficientsScale, uint8_t autoCorrelationCoefficientsNumber);
|
||||
#endif /* ifndef COMPUTELP_H */
|
87
bcg729/src/computeWeightedSpeech.c
Normal file
87
bcg729/src/computeWeightedSpeech.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "computeWeightedSpeech.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeWeightedSpeech: compute wieghted speech according to spec A3.3.3 */
|
||||
/* parameters: */
|
||||
/* -(i) inputSignal : 90 values buffer accessed in range [-10, 79] in Q0*/
|
||||
/* -(i) qLPCoefficients: 20 coefficients(10 for each subframe) in Q12 */
|
||||
/* -(i) weightedqLPCoefficients: 20 coefficients(10 for each subframe) */
|
||||
/* in Q12 */
|
||||
/* -(i/o) weightedInputSignal: 90 values in Q0: [-10, -1] as input */
|
||||
/* [0,79] as output in Q0 */
|
||||
/* -(o) LPResidualSignal: 80 values of residual signal in Q0 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void computeWeightedSpeech(word16_t inputSignal[], word16_t qLPCoefficients[], word16_t weightedqLPCoefficients[], word16_t weightedInputSignal[], word16_t LPResidualSignal[])
|
||||
{
|
||||
/* algo as specified in A3.3.3: */
|
||||
/* first compute LPResidualSignal[n] = inputSignal[n] + ∑(i=1..10)qLP[i]*inputSignal[n-i] specA3.3.3 eqA.3 */
|
||||
/* then compute qLP' coefficients as qLP'[i] = weightedqLP[i] - 0.7*weightedqLP[i-1] */
|
||||
|
||||
/* finally get the weightedInputSignal[n] = LPResidualSignal[n] - ∑(i=1..10)qLP'[i]*weightedInputSignal[n-i] spec A3.3.3 eqA.2 */
|
||||
|
||||
int i,j;
|
||||
word16_t weightedqLPLowPassCoefficients[NB_LSP_COEFF]; /* in Q12 */
|
||||
|
||||
/*** compute LPResisualSignal (spec A3.3.3 eqA.3) in Q0 ***/
|
||||
/* compute residual signal for the first subframe: use the first 10 qLPCoefficients */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
word32_t acc = SSHL((word32_t)inputSignal[i], 12); /* inputSignal in Q0 is shifted to set acc in Q12 */
|
||||
for (j=0; j<NB_LSP_COEFF; j++) {
|
||||
acc = MAC16_16(acc, qLPCoefficients[j],inputSignal[i-j-1]); /* qLPCoefficients in Q12, inputSignal in Q0 -> acc in Q12 */
|
||||
}
|
||||
LPResidualSignal[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* shift back acc to Q0 and saturate it to avoid overflow when going back to 16 bits */
|
||||
}
|
||||
/* compute residual signal for the second subframe: use the second part of qLPCoefficients */
|
||||
for (i=L_SUBFRAME; i<L_FRAME; i++) {
|
||||
word32_t acc = SSHL((word32_t)inputSignal[i], 12); /* inputSignal in Q0 is shifted to set acc in Q12 */
|
||||
for (j=0; j<NB_LSP_COEFF; j++) {
|
||||
acc = MAC16_16(acc, qLPCoefficients[NB_LSP_COEFF+j],inputSignal[i-j-1]); /* qLPCoefficients in Q12, inputSignal in Q0 -> acc in Q12 */
|
||||
}
|
||||
LPResidualSignal[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* shift back acc to Q0 and saturate it to avoid overflow when going back to 16 bits */
|
||||
}
|
||||
|
||||
/*** compute weightedqLPLowPassCoefficients and weightedInputSignal for first subframe ***/
|
||||
/* spec A3.3.3 a' = weightedqLPLowPassCoefficients[i] = weightedqLP[i] - 0.7*weightedqLP[i-1] */
|
||||
weightedqLPLowPassCoefficients[0] = SUB16(weightedqLPCoefficients[0],O7_IN_Q12); /* weightedqLP[-1] = 1 -> weightedqLPLowPassCoefficients[0] = weightedqLPCoefficients[0] - 0.7 */
|
||||
for (i=1; i<NB_LSP_COEFF; i++) {
|
||||
weightedqLPLowPassCoefficients[i] = SUB16(weightedqLPCoefficients[i], MULT16_16_Q12(weightedqLPCoefficients[i-1], O7_IN_Q12));
|
||||
}
|
||||
|
||||
/* weightedInputSignal for the first subframe: synthesis filter 1/[A'(z)] */
|
||||
synthesisFilter(LPResidualSignal, weightedqLPLowPassCoefficients, weightedInputSignal);
|
||||
|
||||
/*** compute weightedqLPLowPassCoefficients and weightedInputSignal for second subframe ***/
|
||||
/* spec A3.3.3 a' = weightedqLPLowPassCoefficients[i] = weightedqLP[i] - 0.7*weightedqLP[i-1] */
|
||||
weightedqLPLowPassCoefficients[0] = SUB16(weightedqLPCoefficients[NB_LSP_COEFF],O7_IN_Q12); /* weightedqLP[-1] = 1 -> weightedqLPLowPassCoefficients[0] = weightedqLPCoefficients[0] - 0.7 */
|
||||
for (i=1; i<NB_LSP_COEFF; i++) {
|
||||
weightedqLPLowPassCoefficients[i] = SUB16(weightedqLPCoefficients[NB_LSP_COEFF+i], MULT16_16_Q12(weightedqLPCoefficients[NB_LSP_COEFF+i-1], O7_IN_Q12));
|
||||
}
|
||||
|
||||
/* weightedInputSignal for the second subframe: synthesis filter 1/[A'(z)] */
|
||||
synthesisFilter(&(LPResidualSignal[L_SUBFRAME]), weightedqLPLowPassCoefficients, &(weightedInputSignal[L_SUBFRAME]));
|
||||
}
|
35
bcg729/src/computeWeightedSpeech.h
Normal file
35
bcg729/src/computeWeightedSpeech.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef COMPUTEWEIGHTEDSPEECH
|
||||
#define COMPUTEWEIGHTEDSPEECH
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeWeightedSpeech: compute wieghted speech according to spec A3.3.3 */
|
||||
/* parameters: */
|
||||
/* -(i) inputSignal : 90 values buffer accessed in range [-10, 79] in Q0*/
|
||||
/* -(i) qLPCoefficients: 20 coefficients(10 for each subframe) in Q12 */
|
||||
/* -(i) weightedqLPCoefficients: 20 coefficients(10 for each subframe) */
|
||||
/* in Q12 */
|
||||
/* -(i/o) weightedInputSignal: 90 values in Q0: [-10, -1] as input */
|
||||
/* [0,79] as output in Q0 */
|
||||
/* -(o) LPResidualSignal: 80 values of residual signal in Q0 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void computeWeightedSpeech(word16_t inputSignal[], word16_t qLPCoefficients[], word16_t weightedqLPCoefficients[], word16_t weightedInputSignal[], word16_t LPResidualSignal[]);
|
||||
#endif /* ifndef COMPUTEWEIGHTEDSPEECH */
|
159
bcg729/src/decodeAdaptativeCodeVector.c
Normal file
159
bcg729/src/decodeAdaptativeCodeVector.c
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "codebooks.h"
|
||||
|
||||
#include "decodeAdaptativeCodeVector.h"
|
||||
|
||||
/* init function */
|
||||
void initDecodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChannelContext)
|
||||
{
|
||||
decoderChannelContext->previousIntPitchDelay = 60;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeAdaptativeCodeVector : as in spec 4.1.3 */
|
||||
/* parameters: */
|
||||
/* -(i/o) excitationVector : in Q0 excitation accessed from */
|
||||
/* [-MAXIMUM_INT_PITCH_DELAY(143), -1] as input */
|
||||
/* and [0, L_SUBFRAME[ as output to store the adaptative */
|
||||
/* codebook vector */
|
||||
/* -(i/o) fracPitchDelay : the fractionnal part of Pitch Delay. */
|
||||
/* -(i/o) intPitchDelay : the integer part of Pitch Delay. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void computeAdaptativeCodebookVector(word16_t *excitationVector, int16_t fracPitchDelay, int16_t intPitchDelay) {
|
||||
word16_t *excitationVectorMinusK; /* pointer to u(-k) */
|
||||
int n;
|
||||
/* compute the adaptative codebook vector using the pitch delay and the past excitation vector */
|
||||
/* from spec 4.1.3 and 3.7.1 */
|
||||
/* shall compute v(n ) = ∑ u (n - k + i )b30 (t + 3i ) + ∑ u (n - k + 1 + i )b30 (3 - t + 3i ) for i=0,...,9 and n = 0,...,39 (t in 0, 1, 2) */
|
||||
/* with k = intPitchDelay and t = fracPitchDelay wich must be converted from range -1,0,1 to 0,1,2 */
|
||||
/* u the past excitation vector */
|
||||
/* v the adaptative codebook vector */
|
||||
/* b30 an interpolation filter */
|
||||
|
||||
/* scale fracPichDelay from -1,0.1 to 0,1,2 */
|
||||
if (fracPitchDelay==1) {
|
||||
excitationVectorMinusK = &(excitationVector[-(intPitchDelay+1)]); /* fracPitchDelay being positive -> increase by one the integer part and set to 2 the fractional part : -(k+1/3) -> -(k+1)+2/3 */
|
||||
fracPitchDelay = 2;
|
||||
} else {
|
||||
fracPitchDelay = -fracPitchDelay; /* 0 unchanged, -1 -> +1 */
|
||||
excitationVectorMinusK = &(excitationVector[-intPitchDelay]); /* -(k-1/3) -> -k+1/3 or -(k) -> -k*/
|
||||
}
|
||||
|
||||
for (n=0; n<L_SUBFRAME; n++) { /* loop over the whole subframe */
|
||||
word16_t *excitationVectorNMinusK = &(excitationVectorMinusK[n]); /* point to u(n-k), unscaled value, full range */
|
||||
word16_t *excitationVectorNMinusKPlusOne = &(excitationVectorMinusK[n+1]); /* point to u(n-k+1), unscaled value, full range */
|
||||
|
||||
word16_t *b301 = &(b30[fracPitchDelay]); /* point to b30(t) in Q0.15 : sums of all b30 coeffs is < 2, no overflow possible on 32 bits */
|
||||
word16_t *b302 = &(b30[3-fracPitchDelay]); /* point to b30(3-t) in Q0.15*/
|
||||
int i,j; /* j will store 3i */
|
||||
word32_t acc = 0; /* in Q15 */
|
||||
for (i=0, j=0; i<10; i++, j+=3) {
|
||||
acc = MAC16_16(acc, excitationVectorNMinusK[-i], b301[j]); /* Note : the spec says: u(n−k+i)b30(t+3i) but the ITU code do (and here too) u(n-k-i )b30(t+3i) */
|
||||
acc = MAC16_16(acc, excitationVectorNMinusKPlusOne[i], b302[j]); /* u(n-k+1+i)b30(3-t+3i) */
|
||||
}
|
||||
excitationVector[n] = SATURATE(PSHR(acc, 15), MAXINT16); /* acc in Q15, shift/round to unscaled value and check overflow on 16 bits */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* decodeAdaptativeCodeVector : as in spec 4.1.3 */
|
||||
/* parameters: */
|
||||
/* -(i/o) decoderChannelContext : the channel context data */
|
||||
/* -(i) subFrameIndex : 0 or 40 for subframe 1 or subframe 2 */
|
||||
/* -(i) adaptativeCodebookIndex : parameter P1 or P2 */
|
||||
/* -(i) parityFlag : based on P1 parity flag : set if parity error */
|
||||
/* -(i) frameErasureFlag : set in case of frame erasure */
|
||||
/* -(i/o) intPitchDelay : the integer part of Pitch Delay. Computed from*/
|
||||
/* P1 on subframe 1. On Subframe 2, contains the intPitchDelay */
|
||||
/* computed on Subframe 1. */
|
||||
/* -(i/o) excitationVector : in Q0 excitation accessed from */
|
||||
/* [-MAXIMUM_INT_PITCH_DELAY(143), -1] as input */
|
||||
/* and [0, L_SUBFRAME[ as output to store the adaptative */
|
||||
/* codebook vector */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void decodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChannelContext, int subFrameIndex, uint16_t adaptativeCodebookIndex, uint8_t parityFlag, uint8_t frameErasureFlag,
|
||||
int16_t *intPitchDelay, word16_t *excitationVector)
|
||||
{
|
||||
int16_t fracPitchDelay;
|
||||
|
||||
/*** Compute the Pitch Delay from the Codebook index ***/
|
||||
/* fracPitchDelay is computed in the range -1,0,1 */
|
||||
if (subFrameIndex == 0 ) { /* first subframe */
|
||||
if (parityFlag|frameErasureFlag) { /* there is an error (either parity or frame erased) */
|
||||
*intPitchDelay = decoderChannelContext->previousIntPitchDelay; /* set the integer part of Pitch Delay to the last second subframe Pitch Delay computed spec: 4.1.2 */
|
||||
/* Note: unable to find anything regarding this part in the spec, just copied it from the ITU source code */
|
||||
fracPitchDelay = 0;
|
||||
decoderChannelContext->previousIntPitchDelay++;
|
||||
if (decoderChannelContext->previousIntPitchDelay>MAXIMUM_INT_PITCH_DELAY) decoderChannelContext->previousIntPitchDelay=MAXIMUM_INT_PITCH_DELAY;
|
||||
} else { /* parity and frameErasure flags are off, do the normal computation (doc 4.1.3) */
|
||||
if (adaptativeCodebookIndex<197) {
|
||||
/* *intPitchDelay = (P1 + 2 )/ 3 + 19 */
|
||||
*intPitchDelay = ADD16(MULT16_16_Q15(ADD16(adaptativeCodebookIndex,2), 10923), 19); /* MULT in Q15: 1/3 in Q15: 10923 */
|
||||
/* fracPitchDelay = P1 − 3*intPitchDelay + 58 : fracPitchDelay in -1, 0, 1 */
|
||||
fracPitchDelay = ADD16(SUB16(adaptativeCodebookIndex, MULT16_16(*intPitchDelay, 3)), 58);
|
||||
} else {/* adaptativeCodebookIndex>= 197 */
|
||||
*intPitchDelay = SUB16(adaptativeCodebookIndex, 112);
|
||||
fracPitchDelay = 0;
|
||||
}
|
||||
|
||||
/* backup the intPitchDelay */
|
||||
decoderChannelContext->previousIntPitchDelay = *intPitchDelay;
|
||||
}
|
||||
} else { /* second subframe */
|
||||
if (frameErasureFlag) { /* there is an error : frame erased, in case of parity error, it has been taken in account at first subframe */
|
||||
/* unable to find anything regarding this part in the spec, just copied it from the ITU source code */
|
||||
*intPitchDelay = decoderChannelContext->previousIntPitchDelay;
|
||||
fracPitchDelay = 0;
|
||||
decoderChannelContext->previousIntPitchDelay++;
|
||||
if (decoderChannelContext->previousIntPitchDelay>MAXIMUM_INT_PITCH_DELAY) decoderChannelContext->previousIntPitchDelay=MAXIMUM_INT_PITCH_DELAY;
|
||||
} else { /* frameErasure flags are off, do the normal computation (doc 4.1.3) */
|
||||
int16_t tMin = SUB16(*intPitchDelay,5); /* intPitchDelay contains the intPitch computed for subframe one */
|
||||
if (tMin<20) {
|
||||
tMin = 20;
|
||||
}
|
||||
if (tMin>134) {
|
||||
tMin = 134;
|
||||
}
|
||||
/* intPitchDelay = (P2 + 2 )/ 3 − 1 */
|
||||
*intPitchDelay = SUB16(MULT16_16_Q15(ADD16(adaptativeCodebookIndex, 2), 10923), 1);
|
||||
/* fracPitchDelay = P2 − 2 − 3((P 2 + 2 )/ 3 − 1) */
|
||||
fracPitchDelay = SUB16(SUB16(adaptativeCodebookIndex, MULT16_16(*intPitchDelay, 3)), 2);
|
||||
/* *intPitchDelay = (P2 + 2 )/ 3 − 1 + tMin */
|
||||
*intPitchDelay = ADD16(*intPitchDelay,tMin);
|
||||
|
||||
/* backup the intPitchDelay */
|
||||
decoderChannelContext->previousIntPitchDelay = *intPitchDelay;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute the adaptative codebook vector using the pitch delay we just get and the past excitation vector */
|
||||
computeAdaptativeCodebookVector(excitationVector, fracPitchDelay, *intPitchDelay);
|
||||
|
||||
return;
|
||||
}
|
||||
|
56
bcg729/src/decodeAdaptativeCodeVector.h
Normal file
56
bcg729/src/decodeAdaptativeCodeVector.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef DECODEADAPTATIVECODEVECTOR_H
|
||||
#define DECODEADAPTATIVECODEVECTOR_H
|
||||
/* init function */
|
||||
void initDecodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChannelContext);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeAdaptativeCodeVector : as in spec 4.1.3 */
|
||||
/* parameters: */
|
||||
/* -(i/o) excitationVector : in Q0 excitation accessed from */
|
||||
/* [-MAXIMUM_INT_PITCH_DELAY(143), -1] as input */
|
||||
/* and [0, L_SUBFRAME[ as output to store the adaptative */
|
||||
/* codebook vector */
|
||||
/* -(i/o) fracPitchDelay : the fractionnal part of Pitch Delay. */
|
||||
/* -(i/o) intPitchDelay : the integer part of Pitch Delay. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void computeAdaptativeCodebookVector(word16_t *excitationVector, int16_t fracPitchDelay, int16_t intPitchDelay);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* decodeAdaptativeCodeVector : as in spec 4.1.3 */
|
||||
/* parameters: */
|
||||
/* -(i/o) decoderChannelContext : the channel context data */
|
||||
/* -(i) subFrameIndex : 0 or 40 for subframe 1 or subframe 2 */
|
||||
/* -(i) adaptativeCodebookIndex : parameter P1 or P2 */
|
||||
/* -(i) parityFlag : based on P1 parity flag : set if parity error */
|
||||
/* -(i) frameErasureFlag : set in case of frame erasure */
|
||||
/* -(i/o) intPitchDelay : the integer part of Pitch Delay. Computed from*/
|
||||
/* P1 on subframe 1. On Subframe 2, contains the intPitchDelay */
|
||||
/* computed on Subframe 1. */
|
||||
/* -(i/o) excitationVector : in Q0 excitation accessed from */
|
||||
/* [-MAXIMUM_INT_PITCH_DELAY(143), -1] as input */
|
||||
/* and [0, L_SUBFRAME[ as output to store the adaptative */
|
||||
/* codebook vector */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void decodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChannelContext, int subFrameIndex, uint16_t adaptativeCodebookIndex, uint8_t parityFlag, uint8_t frameErasureFlag,
|
||||
int16_t *intPitchDelay, word16_t *excitationVector);
|
||||
#endif /* ifndef DECODEADAPTATIVECODEVECTOR_H */
|
72
bcg729/src/decodeFixedCodeVector.c
Normal file
72
bcg729/src/decodeFixedCodeVector.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* decodeFixedCodeVector : compute the fixed codebook vector as in spec 4.1.4*/
|
||||
/* parameters: */
|
||||
/* -(i) signs: parameter S(4 signs bit) eq61 */
|
||||
/* -(i) positions: parameter C(4 3bits position and jx bit) eq62 */
|
||||
/* -(i) intPitchDelay: integer part of pitch Delay (T) */
|
||||
/* -(i) boundedPitchGain: Beta in eq47 and eq48, in Q14 */
|
||||
/* -(o) fixedCodebookVector: 40 values in Q13, range: [-1.8,+1.8] */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void decodeFixedCodeVector(uint16_t signs, uint16_t positions, int16_t intPitchDelay, word16_t boundedPitchGain,
|
||||
word16_t *fixedCodebookVector)
|
||||
{
|
||||
uint16_t positionsArray[4];
|
||||
uint16_t jx;
|
||||
int i;
|
||||
|
||||
/* get the positions into an array: mapping according to eq62 and table7 in spec 3.8 */
|
||||
positionsArray[0] = (positions&(uint16_t)7)*5; /* m0 = 5*C, do not use macro here as whatever fixed or floating point computation we use, these are integers */
|
||||
positions = SHR(positions, 3); /* shift right by 3 to get the 3 next bits(m1/5) as LSB */
|
||||
positionsArray[1] = ((positions&(uint16_t)7)*5) + 1; /* m1 = 5*C + 1, do not use macro here as whatever fixed or floating point computation we use, these are integers */
|
||||
positions = SHR(positions, 3); /* shift right by 3 to get the 3 next bits(m2/5) as LSB */
|
||||
positionsArray[2] = ((positions&(uint16_t)7)*5) + 2; /* m2 = 5*C + 2, do not use macro here as whatever fixed or floating point computation we use, these are integers */
|
||||
positions = SHR(positions, 3); /* shift right by 3 to get the last 4 bits(m3/5 and jx) as LSB */
|
||||
jx = positions&(uint16_t)1; /* jx from eq62 is the last bit */
|
||||
positions = SHR(positions, 1); /* shift right by 1 to get the last 3 bits as LSB */
|
||||
positionsArray[3] = ((positions&(uint16_t)7)*5) + 3 + jx; /* m3 = 5*C + 3 + jx, do not use macro here as whatever fixed or floating point computation we use, these are integers */
|
||||
|
||||
/* initialise the output Vector */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
fixedCodebookVector[i]=0;
|
||||
}
|
||||
|
||||
/* get the signs and compute the fixedCodebookVector */
|
||||
for (i=0; i<4; i++) {
|
||||
if ((signs&(uint16_t)1) != 0) { /* sign bit is 1 */
|
||||
fixedCodebookVector[positionsArray[i]] = 8192; /* +1 in Q13 */
|
||||
} else {
|
||||
fixedCodebookVector[positionsArray[i]] = -8192; /* -1 in Q13 */
|
||||
}
|
||||
signs = SHR(signs, 1); /* shift signs right by one to get the next sign bit at next loop */
|
||||
}
|
||||
|
||||
/* if intPitchDelay is smaller than subframe length, give some correction using boundedPitchGain according to eq48 */
|
||||
for (i=intPitchDelay; i<L_SUBFRAME; i++) {
|
||||
/* fixedCodebookVector[i] = fixedCodebookVector[i] + fixedCodebookVector[i-intPitchDelay]*boundedPitchGain */
|
||||
fixedCodebookVector[i] = ADD16(fixedCodebookVector[i], MULT16_16_P14(fixedCodebookVector[i-intPitchDelay], boundedPitchGain));
|
||||
}
|
||||
}
|
33
bcg729/src/decodeFixedCodeVector.h
Normal file
33
bcg729/src/decodeFixedCodeVector.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef DECODEFIXEDCODEVECTOR_H
|
||||
#define DECODEFIXEDCODEVECTOR_H
|
||||
/*****************************************************************************/
|
||||
/* decodeFixedCodeVector : compute the fixed codebook vector as in spec 4.1.4*/
|
||||
/* parameters: */
|
||||
/* -(i) signs: parameter S(4 signs bit) eq61 */
|
||||
/* -(i) positions: parameter C(4 3bits position and jx bit) eq62 */
|
||||
/* -(i) intPitchDelay: integer part of pitch Delay (T) */
|
||||
/* -(i) boundedPitchGain: Beta in eq47 and eq48, in Q14 */
|
||||
/* -(o) fixedCodebookVector: 40 values in Q13, range: [-1.8,+1.8] */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void decodeFixedCodeVector(uint16_t signs, uint16_t positions, int16_t intPitchDelay, word16_t boundedPitchGain,
|
||||
word16_t *fixedCodebookVector);
|
||||
#endif /* ifndef DECODEFIXEDCODEVECTOR_H */
|
113
bcg729/src/decodeGains.c
Normal file
113
bcg729/src/decodeGains.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "codebooks.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "decodeGains.h"
|
||||
|
||||
/* init function */
|
||||
void initDecodeGains(bcg729DecoderChannelContextStruct *decoderChannelContext)
|
||||
{
|
||||
/*init previousGainPredictionError to -14 in Q10 */
|
||||
decoderChannelContext->previousGainPredictionError[0] = -14336;
|
||||
decoderChannelContext->previousGainPredictionError[1] = -14336;
|
||||
decoderChannelContext->previousGainPredictionError[2] = -14336;
|
||||
decoderChannelContext->previousGainPredictionError[3] = -14336;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* decodeGains : decode adaptive and fixed codebooks gains as in spec 4.1.5 */
|
||||
/* parameters: */
|
||||
/* -(i/o) decoderChannelContext : the channel context data */
|
||||
/* -(i) GA : parameter GA: Gain Codebook Stage 1 (3 bits) */
|
||||
/* -(i) GB : paremeter GB: Gain Codebook Stage 2 (4 bits) */
|
||||
/* -(i) fixedCodebookVector: 40 values current fixed Codebook vector */
|
||||
/* in Q1.13. */
|
||||
/* -(i) frameErasureFlag : set in case of frame erasure */
|
||||
/* -(i/o) adaptativeCodebookGain : input previous/output current */
|
||||
/* subframe Pitch Gain in Q14 */
|
||||
/* -(i/o) fixedCodebookGain : input previous/output current Fixed */
|
||||
/* Codebook Gain in Q1 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void decodeGains (bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_t GA, uint16_t GB, word16_t *fixedCodebookVector, uint8_t frameErasureFlag,
|
||||
word16_t *adaptativeCodebookGain, word16_t *fixedCodebookGain)
|
||||
{
|
||||
word32_t predictedFixedCodebookGain;
|
||||
word16_t fixedCodebookGainCorrectionFactor;
|
||||
|
||||
/* check the erasure flag */
|
||||
if (frameErasureFlag != 0) { /* we have a frame erasure, proceed as described in spec 4.4.2 */
|
||||
int i;
|
||||
word32_t currentGainPredictionError =0;
|
||||
|
||||
/* adaptativeCodebookGain as in eq94 */
|
||||
if (*adaptativeCodebookGain < 16384) { /* last subframe gain < 1 in Q14 */
|
||||
*adaptativeCodebookGain = MULT16_16_Q15(*adaptativeCodebookGain, 29491 ); /* *0.9 in Q15 */
|
||||
} else { /* bound current subframe gain to 0.9 (14746 in Q14) */
|
||||
*adaptativeCodebookGain = 14746;
|
||||
}
|
||||
/* fixedCodebookGain as in eq93 */
|
||||
*fixedCodebookGain = MULT16_16_Q15(*fixedCodebookGain, 32113 ); /* *0.98 in Q15 */
|
||||
|
||||
/* And update the previousGainPredictionError according to spec 4.4.3 */
|
||||
for (i=0; i<4; i++) {
|
||||
currentGainPredictionError = ADD32(currentGainPredictionError, decoderChannelContext->previousGainPredictionError[i]); /* previousGainPredictionError in Q3.10-> Sum in Q5.10 (on 32 bits) */
|
||||
}
|
||||
currentGainPredictionError = PSHR(currentGainPredictionError,2); /* /4 -> Q3.10 */
|
||||
|
||||
if (currentGainPredictionError < -10240) { /* final result is low bounded by -14, so check before doing -4 if it's over -10(-10240 in Q10) or not */
|
||||
currentGainPredictionError = -14336; /* set to -14 in Q10 */
|
||||
} else { /* substract 4 */
|
||||
currentGainPredictionError = SUB32(currentGainPredictionError,4096); /* in Q10 */
|
||||
}
|
||||
|
||||
/* shift the array and insert the current Prediction Error */
|
||||
decoderChannelContext->previousGainPredictionError[3] = decoderChannelContext->previousGainPredictionError[2];
|
||||
decoderChannelContext->previousGainPredictionError[2] = decoderChannelContext->previousGainPredictionError[1];
|
||||
decoderChannelContext->previousGainPredictionError[1] = decoderChannelContext->previousGainPredictionError[0];
|
||||
decoderChannelContext->previousGainPredictionError[0] = (word16_t)currentGainPredictionError;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* First recover the GA and GB real index from their mapping tables(spec 3.9.3) */
|
||||
GA = reverseIndexMappingGA[GA];
|
||||
GB = reverseIndexMappingGB[GB];
|
||||
|
||||
/* Compute the adaptativeCodebookGain from the tables according to eq73 in spec3.9.2 */
|
||||
/* adaptativeCodebookGain = GACodebook[GA][0] + GBCodebook[GB][0] */
|
||||
*adaptativeCodebookGain = ADD16(GACodebook[GA][0], GBCodebook[GB][0]); /* result in Q1.14 */
|
||||
|
||||
/* Fixed Codebook: MA code-gain prediction */
|
||||
predictedFixedCodebookGain = MACodeGainPrediction(decoderChannelContext->previousGainPredictionError, fixedCodebookVector); /* predictedFixedCodebookGain on 32 bits in Q11.16 */
|
||||
|
||||
/* get fixed codebook gain correction factor(gama) from the codebooks GA and GB according to eq74 */
|
||||
fixedCodebookGainCorrectionFactor = ADD16(GACodebook[GA][1], GBCodebook[GB][1]); /* result in Q3.12 (range [0.185, 5.05])*/
|
||||
|
||||
/* compute fixedCodebookGain according to eq74 */
|
||||
*fixedCodebookGain = (word16_t)PSHR(MULT16_32_Q12(fixedCodebookGainCorrectionFactor, predictedFixedCodebookGain), 15); /* Q11.16*Q3.12 -> Q14.16, shift by 15 to get a Q14.1 which fits on 16 bits */
|
||||
|
||||
/* use eq72 to compute current prediction error in order to update the previousGainPredictionError array */
|
||||
computeGainPredictionError(fixedCodebookGainCorrectionFactor, decoderChannelContext->previousGainPredictionError);
|
||||
}
|
41
bcg729/src/decodeGains.h
Normal file
41
bcg729/src/decodeGains.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef DECODEGAINS_H
|
||||
#define DECODEGAINS_H
|
||||
/* init function */
|
||||
void initDecodeGains(bcg729DecoderChannelContextStruct *decoderChannelContext);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* decodeGains : decode adaptive and fixed codebooks gains as in spec 4.1.5 */
|
||||
/* parameters: */
|
||||
/* -(i/o) decoderChannelContext : the channel context data */
|
||||
/* -(i) GA : parameter GA: Gain Codebook Stage 1 (3 bits) */
|
||||
/* -(i) GB : paremeter GB: Gain Codebook Stage 2 (4 bits) */
|
||||
/* -(i) fixedCodebookVector: 40 values current fixed Codebook vector */
|
||||
/* in Q1.13. */
|
||||
/* -(i) frameErasureFlag : set in case of frame erasure */
|
||||
/* -(i/o) adaptativeCodebookGain : input previous/output current */
|
||||
/* subframe Pitch Gain in Q14 */
|
||||
/* -(i/o) fixedCodebookGain : input previous/output current Fixed */
|
||||
/* Codebook Gain in Q1 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void decodeGains (bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_t GA, uint16_t GB, word16_t *fixedCodebookVector, uint8_t frameErasureFlag,
|
||||
word16_t *adaptativeCodebookGain, word16_t *fixedCodebookGain);
|
||||
#endif /* ifndef DECODEGAINS_H */
|
185
bcg729/src/decodeLSP.c
Normal file
185
bcg729/src/decodeLSP.c
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "codebooks.h"
|
||||
#include "utils.h"
|
||||
#include "g729FixedPointMath.h"
|
||||
|
||||
/* define the initialisation vector for qLSP */
|
||||
/* previous L Code Word initial values (Pi/11 steps) in Q2.13 */
|
||||
static word16_t previousLCodeWordInit[NB_LSP_COEFF] = {2339, 4679, 7018, 9358, 11698, 14037, 16377, 18717, 21056, 23396};
|
||||
|
||||
/* initialisations */
|
||||
void initDecodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext)
|
||||
{
|
||||
int i,j;
|
||||
/* init the previousLCodeWord buffer according to doc 3.2.4 -> pi/11 steps */
|
||||
for (i=0; i<MA_MAX_K; i++) {
|
||||
for (j=0; j<NB_LSP_COEFF; j++) {
|
||||
decoderChannelContext->previousLCodeWord[i][j] = previousLCodeWordInit[j];
|
||||
}
|
||||
}
|
||||
|
||||
/* init the last valid values just to avoid problem in case the first frame is a lost one */
|
||||
decoderChannelContext->lastValidL0 = 0;
|
||||
for (j=0; j<NB_LSP_COEFF; j++) {
|
||||
decoderChannelContext->lastqLSF[j] = previousLCodeWordInit[j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//[MA_MAX_K][NB_LSP_COEFF]; /* in Q2.13, buffer to store the last 4 frames codewords, used to compute the current qLSF */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeqLSF : get qLSF extracted from codebooks and process them */
|
||||
/* according to spec 3.2.4 */
|
||||
/* parameters: */
|
||||
/* -(i/o) codebookqLSF : 10 values i Q2.13 to be updated */
|
||||
/* -(i/o) previousCodeWord : codewords for the last 4 subframes in Q2.13*/
|
||||
/* is updated by this function */
|
||||
/* -(i) L0: the Switched MA predictor retrieved from bitstream */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void computeqLSF(word16_t *codebookqLSF, word16_t previousLCodeWord[MA_MAX_K][NB_LSP_COEFF], uint8_t L0, word16_t currentMAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF], word16_t currentMAPredictorSum[L0_RANGE][NB_LSP_COEFF]) {
|
||||
int i,j;
|
||||
word32_t acc; /* Accumulator in Q2.28 */
|
||||
|
||||
/*** rearrange in order to have a minimum distance between two consecutives coefficients ***/
|
||||
rearrangeCoefficients(codebookqLSF, GAP1);
|
||||
rearrangeCoefficients(codebookqLSF, GAP2); /* codebookqLSF still in Q2.13 */
|
||||
|
||||
/*** doc 3.2.4 eq(20) ***/
|
||||
/* compute the qLSF as a weighted sum(weighted by MA coefficient selected according to L0 value) of previous and current frame L codewords coefficients */
|
||||
|
||||
/* L0 is the Switched MA predictor of LSP quantizer(1 bit) */
|
||||
/* codebookqLSF and previousLCodeWord in Q2.13 */
|
||||
/* MAPredictor and MAPredictorSum in Q0.15 with MAPredictorSum[MA switch][i]+Sum[j=0-3](MAPredictor[MA switch][j][i])=1 -> acc will end up being in Q2.28*/
|
||||
/* Note : previousLCodeWord array containing the last 4 code words is updated during this phase */
|
||||
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
acc = MULT16_16(currentMAPredictorSum[L0][i], codebookqLSF[i]);
|
||||
for (j=MA_MAX_K-1; j>=0; j--) {
|
||||
acc = MAC16_16(acc, currentMAPredictor[L0][j][i], previousLCodeWord[j][i]);
|
||||
previousLCodeWord[j][i] = (j>0)?previousLCodeWord[j-1][i]:codebookqLSF[i]; /* update the previousqLCodeWord array: row[0] = current code word and row[j]=row[j-1] */
|
||||
}
|
||||
/* acc in Q2.28, shift back the acc to a Q2.13 with rounding */
|
||||
codebookqLSF[i] = (word16_t)PSHR(acc, 15); /* codebookqLSF in Q2.13 */
|
||||
}
|
||||
/* Note : codebookqLSF buffer now contains qLSF */
|
||||
|
||||
/*** doc 3.2.4 qLSF stability ***/
|
||||
/* qLSF in Q2.13 as are qLSF_MIN and qLSF_MAX and MIN_qLSF_DISTANCE */
|
||||
|
||||
/* sort the codebookqLSF array */
|
||||
insertionSort(codebookqLSF, NB_LSP_COEFF);
|
||||
|
||||
/* check for low limit on qLSF[0] */
|
||||
if (codebookqLSF[0]<qLSF_MIN) {
|
||||
codebookqLSF[0] = qLSF_MIN;
|
||||
}
|
||||
|
||||
/* check and rectify minimum distance between two consecutive qLSF */
|
||||
for (i=0; i<NB_LSP_COEFF-1; i++) {
|
||||
if (SUB16(codebookqLSF[i+1],codebookqLSF[i])<MIN_qLSF_DISTANCE) {
|
||||
codebookqLSF[i+1] = codebookqLSF[i]+MIN_qLSF_DISTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for upper limit on qLSF[NB_LSP_COEFF-1] */
|
||||
if (codebookqLSF[NB_LSP_COEFF-1]>qLSF_MAX) {
|
||||
codebookqLSF[NB_LSP_COEFF-1] = qLSF_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* decodeLSP : decode LSP coefficients as in spec 4.1.1/3.2.4 */
|
||||
/* parameters: */
|
||||
/* -(i/o) decoderChannelContext : the channel context data */
|
||||
/* -(i) L: 4 elements array containing L[0-3] the first and */
|
||||
/* second stage vector of LSP quantizer */
|
||||
/* -(i) frameErased : a boolean, when true, frame has been erased */
|
||||
/* -(o) qLSP: 10 quantized LSP coefficients in Q15 in range [-1,+1[ */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void decodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_t L[], word16_t qLSP[], uint8_t frameErased)
|
||||
{
|
||||
int i,j;
|
||||
word16_t currentqLSF[NB_LSP_COEFF]; /* buffer to the current qLSF in Q2.13 */
|
||||
|
||||
|
||||
if (frameErased == 0) { /* frame is ok, proceed according to 3.2.4 section of the doc */
|
||||
|
||||
/*** doc 3.2.4 eq(19) ***/
|
||||
/* get the L codewords from the codebooks L1, L2 and L3 */
|
||||
/* for easier implementation, L2 and L3 5 dimensional codebooks have been stored in one 10 dimensional L2L3 codebook */
|
||||
/* get the 5 first coefficient from the L1 and L2 codebooks */
|
||||
/* Note : currentqLSF buffer contains L codewords and not qLSF */
|
||||
for (i=0; i<NB_LSP_COEFF/2; i++) {
|
||||
currentqLSF[i] = ADD16(L1[L[1]][i], L2L3[L[2]][i]); /* codebooks are in Q2.13 for L1 and Q0.13 for L2L3, due to actual values stored in the codebooks, result in Q2.13 */
|
||||
}
|
||||
|
||||
/* get the 5 last coefficient from L1 and L3 codebooks */
|
||||
for ( i=NB_LSP_COEFF/2; i<NB_LSP_COEFF; i++) {
|
||||
currentqLSF[i] = ADD16(L1[L[1]][i], L2L3[L[3]][i]); /* same as previous, output in Q2.13 */
|
||||
}
|
||||
|
||||
computeqLSF(currentqLSF, decoderChannelContext->previousLCodeWord, L[0], MAPredictor, MAPredictorSum); /* use regular MAPredictor as this function is not called on SID frame decoding */
|
||||
|
||||
/* backup the qLSF and L0 to restore them in case of frame erased */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
decoderChannelContext->lastqLSF[i] = currentqLSF[i];
|
||||
}
|
||||
decoderChannelContext->lastValidL0 = L[0];
|
||||
|
||||
|
||||
} else { /* frame erased indicator is set, proceed according to section 4.4 of the specs */
|
||||
word32_t acc; /* acc in Q2.28 */
|
||||
|
||||
/* restore the qLSF of last valid frame */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
currentqLSF[i] = decoderChannelContext->lastqLSF[i];
|
||||
}
|
||||
|
||||
/* compute back the codewords from the qLSF and store them in the previousLCodeWord buffer */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) { /* currentqLSF and previousLCodeWord in Q2.13, MAPredictor in Q0.15 and invMAPredictorSum in Q3.12 */
|
||||
acc = SHL(decoderChannelContext->lastqLSF[i],15); /* Q2.13 -> Q2.28 */
|
||||
for (j=0; j<MA_MAX_K; j++) {
|
||||
acc = MSU16_16(acc, MAPredictor[decoderChannelContext->lastValidL0][j][i], decoderChannelContext->previousLCodeWord[j][i]); /* acc in Q2.28 - MAPredictor in Q0.15 * previousLCodeWord in Q2.13 -> acc in Q2.28 (because 1-Sum(MAPred) < 0.6) */
|
||||
}
|
||||
acc = MULT16_32_Q12(invMAPredictorSum[decoderChannelContext->lastValidL0][i], acc); /* Q3.12*Q2.28 >>12 -> Q2.28 because invMAPredictor is 1/(1 - Sum(MAPred))*/
|
||||
|
||||
/* update the array of previoux Code Words */
|
||||
for (j=MA_MAX_K-1; j>=0; j--) {
|
||||
/* acc in Q2.28, shift back the acc to a Q2.13 with rounding */
|
||||
decoderChannelContext->previousLCodeWord[j][i] = (j>0)?decoderChannelContext->previousLCodeWord[j-1][i]:(word16_t)PSHR(acc, 15); /* update the previousqLSF array: row[0] = computed code word and row[j]=row[j-1] */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* convert qLSF to qLSP: qLSP = cos(qLSF) */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
qLSP[i] = g729Cos_Q13Q15(currentqLSF[i]); /* ouput in Q0.15 */
|
||||
}
|
||||
|
||||
/* output: the qLSP buffer in Q0.15 */
|
||||
return;
|
||||
}
|
55
bcg729/src/decodeLSP.h
Normal file
55
bcg729/src/decodeLSP.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef DECODELSP_H
|
||||
#define DECODELSP_H
|
||||
|
||||
/*****************************************************************************/
|
||||
/* initDecodeLSP : */
|
||||
/* Initialise the decodeLSP previousqLSP buffer */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void initDecodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeqLSF : get qLSF extracted from codebooks and process them */
|
||||
/* according to spec 3.2.4 */
|
||||
/* parameters: */
|
||||
/* -(i/o) codebookqLSF : 10 values i Q2.13 to be updated */
|
||||
/* -(i/o) previousCodeWord : codewords for the last 4 subframes in Q2.13*/
|
||||
/* is updated by this function */
|
||||
/* -(i) L0: the Switched MA predictor retrieved from bitstream */
|
||||
/* -(i) currentMAPredictor : MAPredictor to use, noise or voice frame */
|
||||
/* -(i) currentMAPredictorSum : same as previous */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void computeqLSF(word16_t *codebookqLSF, word16_t previousLCodeWord[MA_MAX_K][NB_LSP_COEFF], uint8_t L0, word16_t currentMAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF], word16_t currentMAPredictorSum[L0_RANGE][NB_LSP_COEFF]);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* decodeLSP : decode LSP coefficients as in spec 4.1.1/3.2.4 */
|
||||
/* parameters: */
|
||||
/* -(i/o) decoderChannelContext : the channel context data */
|
||||
/* -(i) L: 4 elements array containing L[0-3] the first and */
|
||||
/* second stage vector of LSP quantizer */
|
||||
/* -(i) frameErased : a boolean, when true, frame has been erased */
|
||||
/* -(o) qLSP: 10 quantized LSP coefficients in Q15 in range [-1,+1[ */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void decodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_t L[], word16_t qLSP[], uint8_t frameErased);
|
||||
|
||||
#endif /* ifndef DECODELSP_H */
|
311
bcg729/src/decoder.c
Normal file
311
bcg729/src/decoder.c
Normal file
|
@ -0,0 +1,311 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "bcg729/decoder.h"
|
||||
#include "decodeLSP.h"
|
||||
#include "interpolateqLSP.h"
|
||||
#include "qLSP2LP.h"
|
||||
#include "decodeAdaptativeCodeVector.h"
|
||||
#include "decodeFixedCodeVector.h"
|
||||
#include "decodeGains.h"
|
||||
#include "LPSynthesisFilter.h"
|
||||
#include "postFilter.h"
|
||||
#include "postProcessing.h"
|
||||
#include "cng.h"
|
||||
|
||||
/* buffers allocation */
|
||||
static const word16_t previousqLSPInitialValues[NB_LSP_COEFF] = {30000, 26000, 21000, 15000, 8000, 0, -8000,-15000,-21000,-26000}; /* in Q0.15 the initials values for the previous qLSP buffer */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* initBcg729DecoderChannel : create context structure and initialise it */
|
||||
/* return value : */
|
||||
/* - the decoder channel context data */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
bcg729DecoderChannelContextStruct *initBcg729DecoderChannel()
|
||||
{
|
||||
/* create the context structure */
|
||||
bcg729DecoderChannelContextStruct *decoderChannelContext = malloc(sizeof(bcg729DecoderChannelContextStruct));
|
||||
memset(decoderChannelContext, 0, sizeof(bcg729DecoderChannelContextStruct));
|
||||
|
||||
/* intialise statics buffers and variables */
|
||||
memcpy(decoderChannelContext->previousqLSP, previousqLSPInitialValues, NB_LSP_COEFF*sizeof(word16_t)); /* initialise the previousqLSP buffer */
|
||||
memset(decoderChannelContext->excitationVector, 0, L_PAST_EXCITATION*sizeof(word16_t)); /* initialise the part of the excitationVector containing the past excitation */
|
||||
decoderChannelContext->boundedAdaptativeCodebookGain = BOUNDED_PITCH_GAIN_MIN;
|
||||
decoderChannelContext->pseudoRandomSeed = 21845; /* initialise pseudo Random seed according to spec 4.4.4 */
|
||||
decoderChannelContext->CNGpseudoRandomSeed = CNG_DTX_RANDOM_SEED_INIT; /* initialise CNG pseudo Random seed according to ITU code */
|
||||
decoderChannelContext->adaptativeCodebookGain = 0; /* gains are initialised at 0 */
|
||||
decoderChannelContext->fixedCodebookGain = 0;
|
||||
memset(decoderChannelContext->reconstructedSpeech, 0, NB_LSP_COEFF*sizeof(word16_t)); /* initialise to zero all the values used from previous frame to get the current frame reconstructed speech */
|
||||
decoderChannelContext->previousFrameIsActiveFlag = 1;
|
||||
decoderChannelContext->CNGChannelContext = initBcg729CNGChannel();
|
||||
|
||||
|
||||
/* initialisation of the differents blocs which need to be initialised */
|
||||
initDecodeLSP(decoderChannelContext);
|
||||
initDecodeAdaptativeCodeVector(decoderChannelContext);
|
||||
initDecodeGains(decoderChannelContext);
|
||||
initPostFilter(decoderChannelContext);
|
||||
initPostProcessing(decoderChannelContext);
|
||||
|
||||
return decoderChannelContext;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* closeBcg729DecoderChannel : free memory of context structure */
|
||||
/* parameters: */
|
||||
/* -(i) decoderChannelContext : the channel context data */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void closeBcg729DecoderChannel(bcg729DecoderChannelContextStruct *decoderChannelContext)
|
||||
{
|
||||
if (decoderChannelContext) {
|
||||
if (decoderChannelContext->CNGChannelContext) {
|
||||
free(decoderChannelContext->CNGChannelContext);
|
||||
}
|
||||
free(decoderChannelContext);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* bcg729Decoder : */
|
||||
/* parameters: */
|
||||
/* -(i) decoderChannelContext : the channel context data */
|
||||
/* -(i) bitStream : 15 parameters on 80 bits */
|
||||
/* -(i): bitStreamLength : in bytes, length of previous buffer */
|
||||
/* -(i) frameErased: flag: true, frame has been erased */
|
||||
/* -(i) SIDFrameFlag: flag: true, frame is a SID one */
|
||||
/* -(i) rfc3389PayloadFlag: true when CN payload follow rfc3389 */
|
||||
/* -(o) signal : a decoded frame 80 samples (16 bits PCM) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, const uint8_t bitStream[], uint8_t bitStreamLength, uint8_t frameErasureFlag, uint8_t SIDFrameFlag, uint8_t rfc3389PayloadFlag, int16_t signal[])
|
||||
{
|
||||
int i;
|
||||
uint16_t parameters[NB_PARAMETERS];
|
||||
/* internal buffers which we do not need to keep between calls */
|
||||
word16_t qLSP[NB_LSP_COEFF]; /* store the qLSP coefficients in Q0.15 */
|
||||
word16_t interpolatedqLSP[NB_LSP_COEFF]; /* store the interpolated qLSP coefficient in Q0.15 */
|
||||
word16_t LP[2*NB_LSP_COEFF]; /* store the 2 sets of LP coefficients in Q12 */
|
||||
int16_t intPitchDelay; /* store the Pitch Delay in and out of decodeAdaptativeCodeVector, in for decodeFixedCodeVector */
|
||||
word16_t fixedCodebookVector[L_SUBFRAME]; /* the fixed Codebook Vector in Q1.13*/
|
||||
word16_t postFilteredSignal[L_SUBFRAME]; /* store the postfiltered signal in Q0 */
|
||||
|
||||
uint8_t parityErrorFlag;
|
||||
int subframeIndex;
|
||||
int parametersIndex = 4; /* this is used to select the right parameter according to the subframe currently computed, start pointing to P1 */
|
||||
int LPCoefficientsIndex = 0; /* this is used to select the right LP Coefficients according to the subframe currently computed */
|
||||
|
||||
/*** parse the bitstream and get all parameter into an array as in spec 4 - Table 8 ***/
|
||||
/* parameters buffer mapping : */
|
||||
/* 0 -> L0 (1 bit) */
|
||||
/* 1 -> L1 (7 bits) */
|
||||
/* 2 -> L2 (5 bits) */
|
||||
/* 3 -> L3 (5 bits) */
|
||||
/* 4 -> P1 (8 bit) */
|
||||
/* 5 -> P0 (1 bits) */
|
||||
/* 6 -> C1 (13 bits) */
|
||||
/* 7 -> S1 (4 bits) */
|
||||
/* 8 -> GA1(3 bits) */
|
||||
/* 9 -> GB1(4 bits) */
|
||||
/* 10 -> P2 (5 bits) */
|
||||
/* 11 -> C2 (13 bits) */
|
||||
/* 12 -> S2 (4 bits) */
|
||||
/* 13 -> GA2(3 bits) */
|
||||
/* 14 -> GB2(4 bits) */
|
||||
/* in case of SID frame : params are decoded in the decodeSIDframe functions */
|
||||
/* 0-> L0 (1 bit) */
|
||||
/* 1-> L1 (5 bits) */
|
||||
/* 2-> L2 (4 bits) */
|
||||
/* 3-> Gain (5 bits) */
|
||||
if (bitStream!=NULL) { /* bitStream might be null in case of frameErased (which shall be set in the appropriated flag)*/
|
||||
if (SIDFrameFlag == 0) {
|
||||
parametersBitStream2Array(bitStream, parameters);
|
||||
}
|
||||
} else { /* avoid compiler complaining for non inizialazed use of variable */
|
||||
for (i=0; i<NB_PARAMETERS; i++) {
|
||||
parameters[i]=0;
|
||||
}
|
||||
}
|
||||
|
||||
/* manage frameErasure and CNG as specified in B.27 */
|
||||
if (frameErasureFlag) {
|
||||
if (decoderChannelContext->previousFrameIsActiveFlag) {
|
||||
SIDFrameFlag = 0;
|
||||
} else {
|
||||
SIDFrameFlag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* this is a SID frame, process it using the dedicated function */
|
||||
if (SIDFrameFlag == 1) {
|
||||
decodeSIDframe(decoderChannelContext->CNGChannelContext, decoderChannelContext->previousFrameIsActiveFlag, bitStream, bitStreamLength, &(decoderChannelContext->excitationVector[L_PAST_EXCITATION]), decoderChannelContext->previousqLSP, LP, &(decoderChannelContext->CNGpseudoRandomSeed), decoderChannelContext->previousLCodeWord, rfc3389PayloadFlag);
|
||||
decoderChannelContext->previousFrameIsActiveFlag = 0;
|
||||
|
||||
/* loop over the two subframes */
|
||||
for (subframeIndex=0; subframeIndex<L_FRAME; subframeIndex+=L_SUBFRAME) {
|
||||
/* reconstruct speech using LP synthesis filter spec 4.1.6 eq77 */
|
||||
/* excitationVector in Q0, LP in Q12, recontructedSpeech in Q0 -> +NB_LSP_COEFF on the index of this one because the first NB_LSP_COEFF elements store the previous frame filter output */
|
||||
LPSynthesisFilter(&(decoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex]), &(LP[LPCoefficientsIndex]), &(decoderChannelContext->reconstructedSpeech[NB_LSP_COEFF+subframeIndex]) );
|
||||
|
||||
/* NOTE: ITU code check for overflow after LP Synthesis Filter computation and if it happened, divide excitation buffer by 2 and recompute the LP Synthesis Filter */
|
||||
/* here, possible overflows are managed directly inside the Filter by saturation at MAXINT16 on each result */
|
||||
|
||||
/* postFilter */
|
||||
postFilter(decoderChannelContext, &(LP[LPCoefficientsIndex]), /* select the LP coefficients for this subframe, use last frame intPitchDelay */
|
||||
&(decoderChannelContext->reconstructedSpeech[NB_LSP_COEFF+subframeIndex]), decoderChannelContext->previousIntPitchDelay, subframeIndex, postFilteredSignal);
|
||||
|
||||
/* postProcessing */
|
||||
postProcessing(decoderChannelContext, postFilteredSignal);
|
||||
|
||||
/* copy postProcessing Output to the signal output buffer */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
signal[subframeIndex+i] = postFilteredSignal[i];
|
||||
}
|
||||
|
||||
/* increase LPCoefficient Indexes */
|
||||
LPCoefficientsIndex+=NB_LSP_COEFF;
|
||||
}
|
||||
|
||||
decoderChannelContext->boundedAdaptativeCodebookGain = BOUNDED_PITCH_GAIN_MIN;
|
||||
|
||||
/* Shift Excitation Vector by L_FRAME left */
|
||||
memmove(decoderChannelContext->excitationVector, &(decoderChannelContext->excitationVector[L_FRAME]), L_PAST_EXCITATION*sizeof(word16_t));
|
||||
/* Copy the last 10 words of reconstructed Speech to the begining of the array for next frame computation */
|
||||
memcpy(decoderChannelContext->reconstructedSpeech, &(decoderChannelContext->reconstructedSpeech[L_FRAME]), NB_LSP_COEFF*sizeof(word16_t));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
decoderChannelContext->previousFrameIsActiveFlag = 1;
|
||||
/* re-init the CNG pseudo random seed at each active frame spec B.4 */
|
||||
decoderChannelContext->CNGpseudoRandomSeed = CNG_DTX_RANDOM_SEED_INIT; /* re-initialise CNG pseudo Random seed to 11111 according to ITU code */
|
||||
|
||||
|
||||
/*****************************************************************************************/
|
||||
/*** on frame basis : decodeLSP, interpolate them with previous ones and convert to LP ***/
|
||||
decodeLSP(decoderChannelContext, parameters, qLSP, frameErasureFlag); /* decodeLSP need the first 4 parameters: L0-L3 */
|
||||
|
||||
|
||||
interpolateqLSP(decoderChannelContext->previousqLSP, qLSP, interpolatedqLSP);
|
||||
/* copy the currentqLSP to previousqLSP buffer */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
decoderChannelContext->previousqLSP[i] = qLSP[i];
|
||||
}
|
||||
|
||||
/* call the qLSP2LP function for first subframe */
|
||||
qLSP2LP(interpolatedqLSP, LP);
|
||||
/* call the qLSP2LP function for second subframe */
|
||||
qLSP2LP(qLSP, &(LP[NB_LSP_COEFF]));
|
||||
|
||||
/* check the parity on the adaptativeCodebookIndexSubframe1(P1) with the received one (P0)*/
|
||||
parityErrorFlag = (uint8_t)(computeParity(parameters[4]) ^ parameters[5]);
|
||||
|
||||
/* loop over the two subframes */
|
||||
for (subframeIndex=0; subframeIndex<L_FRAME; subframeIndex+=L_SUBFRAME) {
|
||||
/* decode the adaptative Code Vector */
|
||||
decodeAdaptativeCodeVector( decoderChannelContext,
|
||||
subframeIndex,
|
||||
parameters[parametersIndex],
|
||||
parityErrorFlag,
|
||||
frameErasureFlag,
|
||||
&intPitchDelay,
|
||||
|
||||
&(decoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex]));
|
||||
if (subframeIndex==0) { /* at first subframe we have P0 between P1 and C1 */
|
||||
parametersIndex+=2;
|
||||
} else {
|
||||
parametersIndex++;
|
||||
}
|
||||
|
||||
/* in case of frame erasure we shall generate pseudoRandom signs and index for fixed code vector decoding according to spec 4.4.4 */
|
||||
if (frameErasureFlag) {
|
||||
parameters[parametersIndex] = pseudoRandom(&(decoderChannelContext->pseudoRandomSeed))&(uint16_t)0x1fff; /* signs are set to the 13 LSB of the first pseudoRandom number */
|
||||
parameters[parametersIndex+1] = pseudoRandom(&(decoderChannelContext->pseudoRandomSeed))&(uint16_t)0x000f; /* signs are set to the 4 LSB of the second pseudoRandom number */
|
||||
}
|
||||
|
||||
/* decode the fixed Code Vector */
|
||||
decodeFixedCodeVector(parameters[parametersIndex+1], parameters[parametersIndex], intPitchDelay, decoderChannelContext->boundedAdaptativeCodebookGain, fixedCodebookVector);
|
||||
parametersIndex+=2;
|
||||
|
||||
/* decode gains */
|
||||
decodeGains(decoderChannelContext, parameters[parametersIndex], parameters[parametersIndex+1], fixedCodebookVector, frameErasureFlag,
|
||||
&(decoderChannelContext->adaptativeCodebookGain), &(decoderChannelContext->fixedCodebookGain));
|
||||
parametersIndex+=2;
|
||||
|
||||
/* update bounded Adaptative Codebook Gain (in Q14) according to eq47 */
|
||||
decoderChannelContext->boundedAdaptativeCodebookGain = decoderChannelContext->adaptativeCodebookGain;
|
||||
if (decoderChannelContext->boundedAdaptativeCodebookGain>BOUNDED_PITCH_GAIN_MAX) {
|
||||
decoderChannelContext->boundedAdaptativeCodebookGain = BOUNDED_PITCH_GAIN_MAX;
|
||||
}
|
||||
if (decoderChannelContext->boundedAdaptativeCodebookGain<BOUNDED_PITCH_GAIN_MIN) {
|
||||
decoderChannelContext->boundedAdaptativeCodebookGain = BOUNDED_PITCH_GAIN_MIN;
|
||||
}
|
||||
|
||||
/* compute excitation vector according to eq75 */
|
||||
/* excitationVector = adaptative Codebook Vector * adaptativeCodebookGain + fixed Codebook Vector * fixedCodebookGain */
|
||||
/* the adaptative Codebook Vector is in the excitationVector buffer [L_PAST_EXCITATION + subframeIndex] */
|
||||
/* with adaptative Codebook Vector in Q0, adaptativeCodebookGain in Q14, fixed Codebook Vector in Q1.13 and fixedCodebookGain in Q14.1 -> result in Q14 on 32 bits */
|
||||
/* -> shift right 14 bits and store the value in Q0 in a 16 bits type */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
decoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex + i] = (word16_t)(SATURATE(PSHR(
|
||||
ADD32(
|
||||
MULT16_16(decoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex + i], decoderChannelContext->adaptativeCodebookGain),
|
||||
MULT16_16(fixedCodebookVector[i], decoderChannelContext->fixedCodebookGain)
|
||||
), 14), MAXINT16));
|
||||
}
|
||||
|
||||
/* reconstruct speech using LP synthesis filter spec 4.1.6 eq77 */
|
||||
/* excitationVector in Q0, LP in Q12, recontructedSpeech in Q0 -> +NB_LSP_COEFF on the index of this one because the first NB_LSP_COEFF elements store the previous frame filter output */
|
||||
LPSynthesisFilter(&(decoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex]), &(LP[LPCoefficientsIndex]), &(decoderChannelContext->reconstructedSpeech[NB_LSP_COEFF+subframeIndex]) );
|
||||
|
||||
/* NOTE: ITU code check for overflow after LP Synthesis Filter computation and if it happened, divide excitation buffer by 2 and recompute the LP Synthesis Filter */
|
||||
/* here, possible overflows are managed directly inside the Filter by saturation at MAXINT16 on each result */
|
||||
|
||||
/* postFilter */
|
||||
postFilter(decoderChannelContext, &(LP[LPCoefficientsIndex]), /* select the LP coefficients for this subframe */
|
||||
&(decoderChannelContext->reconstructedSpeech[NB_LSP_COEFF+subframeIndex]), intPitchDelay, subframeIndex, postFilteredSignal);
|
||||
|
||||
/* postProcessing */
|
||||
postProcessing(decoderChannelContext, postFilteredSignal);
|
||||
|
||||
/* copy postProcessing Output to the signal output buffer */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
signal[subframeIndex+i] = postFilteredSignal[i];
|
||||
}
|
||||
|
||||
/* increase LPCoefficient Indexes */
|
||||
LPCoefficientsIndex+=NB_LSP_COEFF;
|
||||
}
|
||||
|
||||
/* Shift Excitation Vector by L_FRAME left */
|
||||
memmove(decoderChannelContext->excitationVector, &(decoderChannelContext->excitationVector[L_FRAME]), L_PAST_EXCITATION*sizeof(word16_t));
|
||||
/* Copy the last 10 words of reconstructed Speech to the begining of the array for next frame computation */
|
||||
memcpy(decoderChannelContext->reconstructedSpeech, &(decoderChannelContext->reconstructedSpeech[L_FRAME]), NB_LSP_COEFF*sizeof(word16_t));
|
||||
|
||||
return;
|
||||
}
|
438
bcg729/src/dtx.c
Normal file
438
bcg729/src/dtx.c
Normal file
|
@ -0,0 +1,438 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "dtx.h"
|
||||
#include "computeLP.h"
|
||||
#include "g729FixedPointMath.h"
|
||||
#include "LP2LSPConversion.h"
|
||||
#include "LSPQuantization.h"
|
||||
#include "codebooks.h"
|
||||
#include "cng.h"
|
||||
#include "interpolateqLSP.h"
|
||||
#include "qLSP2LP.h"
|
||||
|
||||
#define SID_FRAME 2
|
||||
#define UNTRANSMITTED_FRAME 0
|
||||
/*** local functions ***/
|
||||
static void sumAutocorrelationCoefficients(word32_t autoCorrelationCoefficients[][NB_LSP_COEFF+1], int8_t *autocorrelationCoefficientsScale, uint8_t nbElements,
|
||||
word32_t *autoCorrelationCoefficientsResult, int8_t *autocorrelationCoefficientsScaleResults) {
|
||||
|
||||
int i,j;
|
||||
word64_t autoCorrelationSumBuffer[NB_LSP_COEFF+1]; /* used to temporary store sum on 64 bits */
|
||||
word64_t max=0;
|
||||
word32_t rescaledAutocorrelationCoefficients[7][NB_LSP_COEFF+1]; /* used to temporary stored rescaled elements */
|
||||
int8_t rightShiftToNormalise = 0;
|
||||
|
||||
/* get lowest scale */
|
||||
int8_t minScale = autocorrelationCoefficientsScale[0];
|
||||
for (i=1; i<nbElements; i++) {
|
||||
if (autocorrelationCoefficientsScale[i]<minScale) {
|
||||
minScale=autocorrelationCoefficientsScale[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* rescale the coefficients */
|
||||
for (j=0; j<nbElements; j++) {
|
||||
int8_t rescaling = autocorrelationCoefficientsScale[j] - minScale;
|
||||
for (i=0; i<NB_LSP_COEFF+1; i++) {
|
||||
rescaledAutocorrelationCoefficients[j][i] = SHR32(autoCorrelationCoefficients[j][i], rescaling);
|
||||
}
|
||||
}
|
||||
|
||||
/* sum them on 64 bits and get the maximum value reached */
|
||||
for (i=0; i<NB_LSP_COEFF+1; i++) {
|
||||
autoCorrelationSumBuffer[i] = rescaledAutocorrelationCoefficients[0][i];
|
||||
for (j=1; j<nbElements; j++) {
|
||||
autoCorrelationSumBuffer[i] = ADD64(autoCorrelationSumBuffer[i], rescaledAutocorrelationCoefficients[j][i]);
|
||||
}
|
||||
if (ABS(autoCorrelationSumBuffer[i])>max) max = ABS(autoCorrelationSumBuffer[i]);
|
||||
}
|
||||
|
||||
/* normalise result on 32 bits */
|
||||
if (max>MAXINT32) {
|
||||
do {
|
||||
max = SHR(max,1);
|
||||
rightShiftToNormalise++;
|
||||
} while (max>MAXINT32);
|
||||
|
||||
for (i=0; i<NB_LSP_COEFF+1; i++) {
|
||||
autoCorrelationCoefficientsResult[i] = (word32_t)SHR64(autoCorrelationSumBuffer[i], rightShiftToNormalise);
|
||||
}
|
||||
} else {
|
||||
for (i=0; i<NB_LSP_COEFF+1; i++) {
|
||||
autoCorrelationCoefficientsResult[i] = (word32_t)(autoCorrelationSumBuffer[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* adjust output scale according to possible right shift */
|
||||
*autocorrelationCoefficientsScaleResults = minScale - rightShiftToNormalise;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* residual Energy quantization according to spec B4.2.1 */
|
||||
/* parameters: */
|
||||
/* -(i) residualEnergy : to be quantized in variable scale */
|
||||
/* -(i) residualEnergyScale : scale of previous parameter */
|
||||
/* -(o) decodedLogEnergy : decode the quantized energy into a 10Log(E) */
|
||||
/* returns the quantized residual energy parameterR(on 5 bits) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static uint8_t residualEnergyQuantization(word32_t residualEnergy, int8_t residualEnergyScale, int8_t *decodedLogEnergy) {
|
||||
word32_t acc;
|
||||
acc = SUB32(g729Log2_Q0Q16(residualEnergy), ADD32(479849, (int32_t)(residualEnergyScale<<16))); /* -479849 is log2(aw/(NCur*80)) acc is log2(E') in Q16 aw = 1 as we use unlagged autocorrelation coefficients */
|
||||
acc = SHR32(acc,1); /* acc = log2(E') in Q15 */
|
||||
acc = MULT16_32_Q15(INV_LOG2_10_Q15, acc); /* acc log10(E') in Q15 */
|
||||
|
||||
/* quantization acc contains value to be quantized/10 so all constant / 10 respect what is in the spec */
|
||||
if (acc < - 26214) { /* -0.8 in Q15 */
|
||||
*decodedLogEnergy = -12;
|
||||
return 0; /* first step by 8 */
|
||||
} else if (acc < 45875 ) { /* 1,4 in Q15 */
|
||||
uint8_t steps;
|
||||
acc = (acc+19661); /* up to 14, step by 0.4*/
|
||||
if (acc<0) {
|
||||
acc= 0;
|
||||
} else {
|
||||
acc = MULT16_32_Q13(20480, acc); /* step by 0.4, 20480 is 1/0.4 in Q13 -> acc still in Q15 */
|
||||
}
|
||||
steps = SHR(acc,15);
|
||||
*decodedLogEnergy = -2 +4*steps;
|
||||
return 1+steps;
|
||||
} else if (acc<216268) { /* check that log(E') is not > 66dB (216268 is 6.6 in Q15) */
|
||||
uint8_t steps;
|
||||
acc = (acc-49152); /* -1.5 in Q15 */
|
||||
if (acc<0) {
|
||||
acc = 0;
|
||||
} else {
|
||||
acc = MULT16_32_Q12(20480, acc); /* step by 0.2, 20480 is 1/0.2 in Q12 -> acc still in Q15 */
|
||||
}
|
||||
steps = SHR(acc,15);
|
||||
*decodedLogEnergy = 16 +2*steps;
|
||||
return 6+steps;
|
||||
} else { /* quantized energy support up to 66dB */
|
||||
*decodedLogEnergy = 66;
|
||||
return 31;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* compute LP Coefficients auto correlation as in eq B.13 */
|
||||
/* parameters: */
|
||||
/* -(i) LPCoefficients : in Q12, 10 values, 1 LP Coeff is always 1 and not*/
|
||||
/* stored in this buffer */
|
||||
/* -(o) LPCautocorrelation : 11 values in Q20 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static void computeLPCoefficientAutocorrelation(word16_t *LPCoefficients, word32_t *LPCautocorrelation) {
|
||||
int j,k;
|
||||
/* first compute Ra0 */
|
||||
LPCautocorrelation[0] = 4096*4096>>4; /* LPCoefficients are in Q12 -> acc in Q24, init: acc = LP(0)*LP(0) -> 1 in Q20 as LP(0) is not stored because always 1 */
|
||||
for (k=0; k<NB_LSP_COEFF; k++) {
|
||||
LPCautocorrelation[0] = MAC16_16_Q4(LPCautocorrelation[0], LPCoefficients[k], LPCoefficients[k]); /* LPCoefficients in Q12*Q12 -> Q24 >> Q4: result in Q20 */
|
||||
}
|
||||
|
||||
/* and the rest */
|
||||
for (j=1; j<NB_LSP_COEFF+1; j++) {
|
||||
LPCautocorrelation[j] = SHL(LPCoefficients[j-1],9); /* LPCoeff[0] is not stored always 1, so LPCoeff index is -1 respect LPCautocorrelation, SHL(9) to make *2 and get it in Q20 from Q12 */
|
||||
for (k=0; k<10-j; k++) {
|
||||
LPCautocorrelation[j] = MAC16_16_Q3(LPCautocorrelation[j], LPCoefficients[k], LPCoefficients[k+j]); /* this k is actually k-1 respect to eq B.13 Q12*Q12 -> Q24 >> 3 : *2 and result in Q20 */
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************/
|
||||
/* compare LPC filters: as in spec B.4.1.3 eq B.12 */
|
||||
/* parameters: */
|
||||
/* -(i) LPCoefficientsAutocorrelation: 11 values in Q20, Ra in spec */
|
||||
/* -(i) autocorrelationCoefficients: 11 values in variable scale, Rt in spec */
|
||||
/* -(i) residualEnergy : in the same scale as previous value, Et in spec */
|
||||
/* -(i) threshold : in Q20 */
|
||||
/* return 1 if the filter significantly differs (eq B.12 is true) */
|
||||
/* */
|
||||
/********************************************************************************/
|
||||
static uint8_t compareLPCFilters(word32_t *LPCoefficientsAutocorrelation, word32_t *autocorrelationCoefficients, word32_t residualEnergy, word32_t threshold) {
|
||||
/* on the left term of the comparison we have Ra in Q20 an Rt in variable scale */
|
||||
/* on the right term of the comparison we have Threshold in Q20 an Et in variable scale but same as Rt */
|
||||
word64_t acc = 0;
|
||||
int i;
|
||||
for (i=0; i<NB_LSP_COEFF+1; i++) {
|
||||
acc = MAC64(acc, LPCoefficientsAutocorrelation[i], autocorrelationCoefficients[i]);
|
||||
}
|
||||
|
||||
if (acc >= MULT32_32(residualEnergy, threshold)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/* initBcg729DTXChannel : create context structure and initialise it */
|
||||
/* return value : */
|
||||
/* - the DTX channel context data */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
bcg729DTXChannelContextStruct *initBcg729DTXChannel() {
|
||||
int i;
|
||||
/* create the context structure */
|
||||
bcg729DTXChannelContextStruct *DTXChannelContext = malloc(sizeof(bcg729DTXChannelContextStruct));
|
||||
memset(DTXChannelContext, 0, sizeof(*DTXChannelContext)); /* set autocorrelation buffers to 0 */
|
||||
/* avoid arithmetics problem: set past autocorrelation[0] to 1 */
|
||||
for (i=0; i<7; i++) {
|
||||
DTXChannelContext->autocorrelationCoefficients[i][0] = ONE_IN_Q30;
|
||||
DTXChannelContext->autocorrelationCoefficientsScale[i] = 30;
|
||||
}
|
||||
|
||||
DTXChannelContext->previousVADflag = 1; /* previous VAD flag must be initialised to VOICE */
|
||||
DTXChannelContext->pseudoRandomSeed = CNG_DTX_RANDOM_SEED_INIT;
|
||||
return DTXChannelContext;
|
||||
}
|
||||
|
||||
/*******************************************************************************************/
|
||||
/* updateDTXContext : save autocorrelation value in DTX context as requested in B4.1.1 */
|
||||
/* parameters: */
|
||||
/* -(i/o) DTXChannelContext : the DTX context to be updated */
|
||||
/* -(i) autocorrelationsCoefficients : 11 values of variable scale, values are copied */
|
||||
/* in DTX context */
|
||||
/* -(i) autocorrelationCoefficientsScale : the scale of previous buffer(can be <0) */
|
||||
/* */
|
||||
/*******************************************************************************************/
|
||||
void updateDTXContext(bcg729DTXChannelContextStruct *DTXChannelContext, word32_t *autocorrelationCoefficients, int8_t autocorrelationCoefficientsScale) {
|
||||
/* move previous autocorrelation coefficients and store the new one */
|
||||
/* TODO: optimise it buy using rolling index */
|
||||
memcpy(DTXChannelContext->autocorrelationCoefficients[6], DTXChannelContext->autocorrelationCoefficients[5], (NB_LSP_COEFF+1)*sizeof(word32_t));
|
||||
DTXChannelContext->autocorrelationCoefficientsScale[6] = DTXChannelContext->autocorrelationCoefficientsScale[5];
|
||||
memcpy(DTXChannelContext->autocorrelationCoefficients[5], DTXChannelContext->autocorrelationCoefficients[4], (NB_LSP_COEFF+1)*sizeof(word32_t));
|
||||
DTXChannelContext->autocorrelationCoefficientsScale[5] = DTXChannelContext->autocorrelationCoefficientsScale[4];
|
||||
memcpy(DTXChannelContext->autocorrelationCoefficients[4], DTXChannelContext->autocorrelationCoefficients[3], (NB_LSP_COEFF+1)*sizeof(word32_t));
|
||||
DTXChannelContext->autocorrelationCoefficientsScale[4] = DTXChannelContext->autocorrelationCoefficientsScale[3];
|
||||
memcpy(DTXChannelContext->autocorrelationCoefficients[3], DTXChannelContext->autocorrelationCoefficients[2], (NB_LSP_COEFF+1)*sizeof(word32_t));
|
||||
DTXChannelContext->autocorrelationCoefficientsScale[3] = DTXChannelContext->autocorrelationCoefficientsScale[2];
|
||||
memcpy(DTXChannelContext->autocorrelationCoefficients[2], DTXChannelContext->autocorrelationCoefficients[1], (NB_LSP_COEFF+1)*sizeof(word32_t));
|
||||
DTXChannelContext->autocorrelationCoefficientsScale[2] = DTXChannelContext->autocorrelationCoefficientsScale[1];
|
||||
memcpy(DTXChannelContext->autocorrelationCoefficients[1], DTXChannelContext->autocorrelationCoefficients[0], (NB_LSP_COEFF+1)*sizeof(word32_t));
|
||||
DTXChannelContext->autocorrelationCoefficientsScale[1] = DTXChannelContext->autocorrelationCoefficientsScale[0];
|
||||
memcpy(DTXChannelContext->autocorrelationCoefficients[0], autocorrelationCoefficients, (NB_LSP_COEFF+1)*sizeof(word32_t));
|
||||
DTXChannelContext->autocorrelationCoefficientsScale[0] = autocorrelationCoefficientsScale;
|
||||
}
|
||||
|
||||
/*******************************************************************************************/
|
||||
/* encodeSIDFrame: called at eache frame even if VADflag is set to active speech */
|
||||
/* Update the previousVADflag and if curent is set to NOISE, compute the SID params */
|
||||
/* parameters: */
|
||||
/* -(i/o) DTXChannelContext: current DTX context, is updated by this function */
|
||||
/* -(o) previousLSPCoefficients : 10 values in Q15, is updated by this function */
|
||||
/* -(i/o) previousqLSPCoefficients : 10 values in Q15, is updated by this function */
|
||||
/* -(i) VADflag : 1 active voice frame, 0 noise frame */
|
||||
/* -(i/o) previousqLSF : set of 4 last frames qLSF in Q2.13, is updated */
|
||||
/* -(i/o) excicationVector : in Q0, accessed in range [-L_PAST_EXCITATION,L_FRAME-1] */
|
||||
/* -(o) qLPCoefficients : 20 values in Q3.12 the quantized LP coefficients */
|
||||
/* -(o) bitStream : SID frame parameters on 2 bytes, may be null if no frame is to be */
|
||||
/* transmitted */
|
||||
/* -(o) bitStreamLength : length of bitStream buffer to be transmitted (2 for SID, 0 for */
|
||||
/* untransmitted frame) */
|
||||
/* */
|
||||
/*******************************************************************************************/
|
||||
void encodeSIDFrame(bcg729DTXChannelContextStruct *DTXChannelContext, word16_t *previousLSPCoefficients, word16_t *previousqLSPCoefficients, uint8_t VADflag, word16_t previousqLSF[MA_MAX_K][NB_LSP_COEFF], word16_t *excitationVector, word16_t *qLPCoefficients, uint8_t *bitStream, uint8_t *bitStreamLength) {
|
||||
|
||||
int i;
|
||||
word32_t summedAutocorrelationCoefficients[NB_LSP_COEFF+1];
|
||||
word16_t LPCoefficients[NB_LSP_COEFF]; /* in Q12 */
|
||||
word16_t LSPCoefficients[NB_LSP_COEFF]; /* in Q15 */
|
||||
word32_t reflectionCoefficients[NB_LSP_COEFF]; /* product of LP Computation, may be used if we need to generate the RFC3389 payload */
|
||||
word32_t residualEnergy; /* in variable scale(summedAutocorrelationCoefficientsScale) computed together with LP coefficients */
|
||||
int8_t summedAutocorrelationCoefficientsScale;
|
||||
uint8_t frameType;
|
||||
word32_t meanEnergy;
|
||||
int8_t meanEnergyScale;
|
||||
uint8_t quantizedResidualEnergy;
|
||||
int8_t decodedLogEnergy;
|
||||
uint8_t parameters[3]; /* array of the first 3 output parameters, 4th is in quantizedResidualEnergy */
|
||||
word16_t interpolatedqLSP[NB_LSP_COEFF]; /* the interpolated qLSP used for first subframe in Q15 */
|
||||
|
||||
|
||||
if (VADflag == 1) {/* this is a voice frame, just update the VADflag history and return */
|
||||
DTXChannelContext->pseudoRandomSeed = CNG_DTX_RANDOM_SEED_INIT; /* re-init pseudo random seed at each active frame to keep CNG and DTX in sync */
|
||||
DTXChannelContext->previousVADflag = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* NOISE frame */
|
||||
/* compute the autocorrelation coefficients sum on the current and previous frame */
|
||||
sumAutocorrelationCoefficients((DTXChannelContext->autocorrelationCoefficients), DTXChannelContext->autocorrelationCoefficientsScale, 2,
|
||||
summedAutocorrelationCoefficients, &summedAutocorrelationCoefficientsScale);
|
||||
|
||||
/* compute LP filter coefficients */
|
||||
autoCorrelation2LP(summedAutocorrelationCoefficients, LPCoefficients, reflectionCoefficients, &residualEnergy); /* output residualEnergy with the same scale of input summedAutocorrelationCoefficients */
|
||||
|
||||
/* determine type of frame SID or untrasmitted */
|
||||
if (DTXChannelContext->previousVADflag == 1) { /* if previous frame was active : we must generate a SID frame spec B.10 */
|
||||
frameType = SID_FRAME;
|
||||
meanEnergy = residualEnergy;
|
||||
meanEnergyScale = summedAutocorrelationCoefficientsScale;
|
||||
quantizedResidualEnergy = residualEnergyQuantization(meanEnergy, meanEnergyScale, &decodedLogEnergy);
|
||||
} else { /* previous frame was already non active, check if we have to generate a new SID frame according to spec 4.1.2-4.1.4 */
|
||||
int8_t flag_chang = 0;
|
||||
|
||||
/* update meanEnergy using current and previous frame Energy : meanE = current+previous/2 : rescale both of them dividing by 2 and sum */
|
||||
/* eqB14 doesn't divide by KE but it's done in eqB15, do it now */
|
||||
if (summedAutocorrelationCoefficientsScale<DTXChannelContext->previousResidualEnergyScale) {
|
||||
meanEnergyScale = summedAutocorrelationCoefficientsScale;
|
||||
meanEnergy = ADD32(SHR(residualEnergy,1), VSHR32(DTXChannelContext->previousResidualEnergy, DTXChannelContext->previousResidualEnergyScale - summedAutocorrelationCoefficientsScale + 1));
|
||||
|
||||
} else {
|
||||
meanEnergyScale = DTXChannelContext->previousResidualEnergyScale;
|
||||
meanEnergy = ADD32(VSHR32(residualEnergy,summedAutocorrelationCoefficientsScale - DTXChannelContext->previousResidualEnergyScale + 1), SHR(DTXChannelContext->previousResidualEnergy, 1));
|
||||
}
|
||||
quantizedResidualEnergy = residualEnergyQuantization(meanEnergy, meanEnergyScale, &decodedLogEnergy);
|
||||
|
||||
/* comparison of LPC filters B4.1.3 : DTXChannelContext->SIDLPCoefficientAutocorrelation contains the last used filter LP coeffecients autocorrelation in Q20 */
|
||||
if (compareLPCFilters(DTXChannelContext->SIDLPCoefficientAutocorrelation, summedAutocorrelationCoefficients, residualEnergy, THRESHOLD1_IN_Q20) != 0) {
|
||||
flag_chang = 1;
|
||||
}
|
||||
|
||||
/* comparison of the energies B4.1.4 */
|
||||
if (ABS(DTXChannelContext->previousDecodedLogEnergy - decodedLogEnergy)>2) {
|
||||
flag_chang = 1;
|
||||
}
|
||||
|
||||
/* check if we have to transmit a SID frame eq B.11 */
|
||||
DTXChannelContext->count_fr++;
|
||||
if (DTXChannelContext->count_fr<3) { /* min 3 frames between 2 consecutive SID frames */
|
||||
frameType = UNTRANSMITTED_FRAME;
|
||||
} else {
|
||||
if (flag_chang == 1) {
|
||||
frameType = SID_FRAME;
|
||||
} else {
|
||||
frameType = UNTRANSMITTED_FRAME;
|
||||
}
|
||||
DTXChannelContext->count_fr = 3; /* counter on 8 bits, keep value low, we just need to know if it is > 3 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* generate the SID frame */
|
||||
if (frameType == SID_FRAME) {
|
||||
word32_t SIDLPCAutocorrelationCoefficients[NB_LSP_COEFF+1];
|
||||
int8_t SIDLPCAutocorrelationCoefficientsScale;
|
||||
word16_t pastAverageLPCoefficients[NB_LSP_COEFF]; /* in Q12 */
|
||||
word32_t pastAverageReflectionCoefficients[NB_LSP_COEFF]; /* produced by LP computation, may be used if we have to generate RFC3389 payload */
|
||||
word32_t pastAverageResidualEnergy; /* not used here, by-product of LP coefficients computation */
|
||||
|
||||
/* reset frame count */
|
||||
DTXChannelContext->count_fr = 0;
|
||||
|
||||
/*** compute the past average filter on the last 6 past frames ***/
|
||||
sumAutocorrelationCoefficients(&(DTXChannelContext->autocorrelationCoefficients[1]), &(DTXChannelContext->autocorrelationCoefficientsScale[1]), 6,
|
||||
SIDLPCAutocorrelationCoefficients, &SIDLPCAutocorrelationCoefficientsScale);
|
||||
|
||||
/* compute past average LP filter coefficients Ap in B4.2.2 */
|
||||
autoCorrelation2LP(SIDLPCAutocorrelationCoefficients, pastAverageLPCoefficients, pastAverageReflectionCoefficients, &pastAverageResidualEnergy); /* output residualEnergy with the same scale of input summedAutocorrelationCoefficients */
|
||||
|
||||
/* select coefficients according to eq B.17 we have Ap in SIDLPCoefficients and At in LPCoefficients, store result, in Q12 in SIDLPCoefficients */
|
||||
/* check distance beetwen currently used filter and past filter : compute LPCoefficentAutocorrelation for the past average filter */
|
||||
computeLPCoefficientAutocorrelation(pastAverageLPCoefficients, DTXChannelContext->SIDLPCoefficientAutocorrelation);
|
||||
|
||||
DTXChannelContext->decodedLogEnergy = decodedLogEnergy; /* store frame mean energy for RFC3389 payload generation */
|
||||
|
||||
if (compareLPCFilters(DTXChannelContext->SIDLPCoefficientAutocorrelation, summedAutocorrelationCoefficients, residualEnergy, THRESHOLD3_IN_Q20) == 0) { /* use the past average filter */
|
||||
/* generate LSP coefficient using the past LP coefficients */
|
||||
if (!LP2LSPConversion(pastAverageLPCoefficients, LSPCoefficients)) {
|
||||
/* unable to find the 10 roots repeat previous LSP */
|
||||
memcpy(LSPCoefficients, previousqLSPCoefficients, NB_LSP_COEFF*sizeof(word16_t));
|
||||
}
|
||||
/* LPCoefficientAutocorrelation are already in DTXChannelContext */
|
||||
/* save the reflection coefficients in the DTX context as they will be requested to generate RFC3389 payload */
|
||||
memcpy(DTXChannelContext->reflectionCoefficients, pastAverageReflectionCoefficients, NB_LSP_COEFF*sizeof(word32_t));
|
||||
} else { /* use filter computed on current and previous frame */
|
||||
/* compute the LPCoefficientAutocorrelation for this filter and store them in DTXChannel */
|
||||
computeLPCoefficientAutocorrelation(LPCoefficients, DTXChannelContext->SIDLPCoefficientAutocorrelation);
|
||||
/* generate LSP coefficient current LP coefficients */
|
||||
if (!LP2LSPConversion(LPCoefficients, LSPCoefficients)) {
|
||||
/* unable to find the 10 roots repeat previous LSP */
|
||||
memcpy(LSPCoefficients, previousqLSPCoefficients, NB_LSP_COEFF*sizeof(word16_t));
|
||||
}
|
||||
/* save the reflection coefficients in the DTX context as they will be requested to generate RFC3389 payload */
|
||||
memcpy(DTXChannelContext->reflectionCoefficients, reflectionCoefficients, NB_LSP_COEFF*sizeof(word32_t));
|
||||
}
|
||||
|
||||
/* update previousLSP coefficient buffer */
|
||||
memcpy(previousLSPCoefficients, LSPCoefficients, NB_LSP_COEFF*sizeof(word16_t));
|
||||
|
||||
/* LSP quantization */
|
||||
noiseLSPQuantization(previousqLSF, LSPCoefficients, DTXChannelContext->qLSPCoefficients, parameters);
|
||||
|
||||
/* update previousDecodedLogEnergy and SIDGain */
|
||||
DTXChannelContext->previousDecodedLogEnergy = decodedLogEnergy;
|
||||
DTXChannelContext->currentSIDGain = SIDGainCodebook[quantizedResidualEnergy];
|
||||
}
|
||||
|
||||
/* save current Frame Energy */
|
||||
DTXChannelContext->previousResidualEnergy = residualEnergy;
|
||||
DTXChannelContext->previousResidualEnergyScale = summedAutocorrelationCoefficientsScale;
|
||||
|
||||
/* apply target gain smoothing eq B.19 */
|
||||
if(DTXChannelContext->previousVADflag == 1) {
|
||||
DTXChannelContext->smoothedSIDGain = DTXChannelContext->currentSIDGain;
|
||||
} else {
|
||||
DTXChannelContext->smoothedSIDGain = SUB16(DTXChannelContext->smoothedSIDGain, (DTXChannelContext->smoothedSIDGain>>3));
|
||||
DTXChannelContext->smoothedSIDGain = ADD16(DTXChannelContext->smoothedSIDGain, (DTXChannelContext->currentSIDGain>>3));
|
||||
}
|
||||
|
||||
/* update excitation vector */
|
||||
computeComfortNoiseExcitationVector(DTXChannelContext->smoothedSIDGain, &(DTXChannelContext->pseudoRandomSeed), excitationVector);
|
||||
|
||||
/* Interpolate qLSP and update the previousqLSP buffer */
|
||||
interpolateqLSP(previousqLSPCoefficients, DTXChannelContext->qLSPCoefficients, interpolatedqLSP); /* in case of untransmitted frame, use qLSP generated for the last transmitted one */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
previousqLSPCoefficients[i] = DTXChannelContext->qLSPCoefficients[i];
|
||||
}
|
||||
|
||||
/* first subframe */
|
||||
qLSP2LP(interpolatedqLSP, qLPCoefficients);
|
||||
/* second subframe */
|
||||
qLSP2LP(DTXChannelContext->qLSPCoefficients, &(qLPCoefficients[NB_LSP_COEFF]));
|
||||
|
||||
/* set parameters into the bitStream if a frame must be transmitted */
|
||||
if (frameType == SID_FRAME) {
|
||||
*bitStreamLength = 2;
|
||||
bitStream[0] = (((parameters[0]&0x01)<<7) /* L0 1 bit */
|
||||
| ((parameters[1]&0x1F)<<2) /* L1 5 bits */
|
||||
| ((parameters[2]>>2)%0x03)); /* L2 is 4 bits 2 MSB in this byte */
|
||||
bitStream[1] = (((parameters[2]&0x03)<<6) /* 2 LSB of 4 bits L2 */
|
||||
| ((quantizedResidualEnergy&0x1F)<<1)); /* Gain 5 bits, last bit is left to 0 */
|
||||
} else {
|
||||
*bitStreamLength = 0;
|
||||
}
|
||||
|
||||
/* update the previousVADflag in context */
|
||||
DTXChannelContext->previousVADflag = 0;
|
||||
|
||||
}
|
59
bcg729/src/dtx.h
Normal file
59
bcg729/src/dtx.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef DTX_H
|
||||
#define DTX_H
|
||||
|
||||
/*****************************************************************************/
|
||||
/* initBcg729DTXChannel : create context structure and initialise it */
|
||||
/* return value : */
|
||||
/* - the DTX channel context data */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
bcg729DTXChannelContextStruct *initBcg729DTXChannel();
|
||||
|
||||
/*******************************************************************************************/
|
||||
/* updateDTXContext : save autocorrelation value in DTX context as requested in B4.1.1 */
|
||||
/* parameters: */
|
||||
/* -(i/o) DTXChannelContext : the DTX context to be updated */
|
||||
/* -(i) autocorrelationsCoefficients : 11 values of variable scale, values are copied */
|
||||
/* in DTX context */
|
||||
/* -(i) autocorrelationCoefficientsScale : the scale of previous buffer(can be <0) */
|
||||
/* */
|
||||
/*******************************************************************************************/
|
||||
void updateDTXContext(bcg729DTXChannelContextStruct *DTXChannelContext, word32_t *autocorrelationCoefficients, int8_t autocorrelationCoefficientsScale);
|
||||
|
||||
/*******************************************************************************************/
|
||||
/* encodeSIDFrame: called at eache frame even if VADflag is set to active speech */
|
||||
/* Update the previousVADflag and if curent is set to NOISE, compute the SID params */
|
||||
/* parameters: */
|
||||
/* -(i/o) DTXChannelContext: current DTX context, is updated by this function */
|
||||
/* -(o) previousLSPCoefficients : 10 values in Q15, is updated by this function */
|
||||
/* -(i/o) previousqLSPCoefficients : 10 values in Q15, is updated by this function */
|
||||
/* -(i) VADflag : 1 active voice frame, 0 noise frame */
|
||||
/* -(i/o) previousqLSF : set of 4 last frames qLSF in Q2.13, is updated */
|
||||
/* -(i/o) excicationVector : in Q0, accessed in range [-L_PAST_EXCITATION,L_FRAME-1] */
|
||||
/* -(o) qLPCoefficients : 20 values in Q3.12 the quantized LP coefficients */
|
||||
/* -(o) bitStream : SID frame parameters on 2 bytes, may be null if no frame is to be */
|
||||
/* transmitted */
|
||||
/* -(o) bitStreamLength : length of bitStream buffer to be transmitted (2 for SID, 0 for */
|
||||
/* untransmitted frame) */
|
||||
/* */
|
||||
/*******************************************************************************************/
|
||||
void encodeSIDFrame(bcg729DTXChannelContextStruct *DTXChannelContext, word16_t *previousLSPCoefficients, word16_t *previousqLSPCoefficients, uint8_t VADflag, word16_t previousqLSF[MA_MAX_K][NB_LSP_COEFF], word16_t *excitationVector, word16_t *qLPCoefficients, uint8_t *bitStream, uint8_t *bitStreamLength);
|
||||
#endif /* ifndef DTX_H */
|
405
bcg729/src/encoder.c
Normal file
405
bcg729/src/encoder.c
Normal file
|
@ -0,0 +1,405 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "bcg729/encoder.h"
|
||||
|
||||
#include "interpolateqLSP.h"
|
||||
#include "qLSP2LP.h"
|
||||
|
||||
#include "preProcessing.h"
|
||||
#include "computeLP.h"
|
||||
#include "LP2LSPConversion.h"
|
||||
#include "LSPQuantization.h"
|
||||
#include "computeWeightedSpeech.h"
|
||||
#include "findOpenLoopPitchDelay.h"
|
||||
#include "adaptativeCodebookSearch.h"
|
||||
#include "computeAdaptativeCodebookGain.h"
|
||||
#include "fixedCodebookSearch.h"
|
||||
#include "gainQuantization.h"
|
||||
#include "g729FixedPointMath.h"
|
||||
#include "vad.h"
|
||||
#include "dtx.h"
|
||||
|
||||
/* buffers allocation */
|
||||
static const word16_t previousLSPInitialValues[NB_LSP_COEFF] = {30000, 26000, 21000, 15000, 8000, 0, -8000,-15000,-21000,-26000}; /* in Q0.15 the initials values for the previous LSP buffer */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* initBcg729EncoderChannel : create context structure and initialise it */
|
||||
/* return value : */
|
||||
/* - the encoder channel context data */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
bcg729EncoderChannelContextStruct *initBcg729EncoderChannel(uint8_t enableVAD)
|
||||
{
|
||||
/* create the context structure */
|
||||
bcg729EncoderChannelContextStruct *encoderChannelContext = malloc(sizeof(bcg729EncoderChannelContextStruct));
|
||||
memset(encoderChannelContext, 0, sizeof(bcg729EncoderChannelContextStruct));
|
||||
|
||||
/* initialise statics buffers and variables */
|
||||
memset(encoderChannelContext->signalBuffer, 0, (L_LP_ANALYSIS_WINDOW-L_FRAME)*sizeof(word16_t)); /* set to zero all the past signal */
|
||||
encoderChannelContext->signalLastInputFrame = &(encoderChannelContext->signalBuffer[L_LP_ANALYSIS_WINDOW-L_FRAME]); /* point to the last frame in the signal buffer */
|
||||
encoderChannelContext->signalCurrentFrame = &(encoderChannelContext->signalBuffer[L_LP_ANALYSIS_WINDOW-L_SUBFRAME-L_FRAME]); /* point to the current frame */
|
||||
memcpy(encoderChannelContext->previousLSPCoefficients, previousLSPInitialValues, NB_LSP_COEFF*sizeof(word16_t)); /* reset the previous quantized and unquantized LSP vector with the same value */
|
||||
memcpy(encoderChannelContext->previousqLSPCoefficients, previousLSPInitialValues, NB_LSP_COEFF*sizeof(word16_t));
|
||||
memset(encoderChannelContext->weightedInputSignal, 0, MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t)); /* set to zero values of previous weighted signal */
|
||||
memset(encoderChannelContext->excitationVector, 0, L_PAST_EXCITATION*sizeof(word16_t)); /* set to zero values of previous excitation vector */
|
||||
memset(encoderChannelContext->targetSignal, 0, NB_LSP_COEFF*sizeof(word16_t)); /* set to zero values filter memory for the targetSignal computation */
|
||||
encoderChannelContext->lastQuantizedAdaptativeCodebookGain = O2_IN_Q14; /* quantized gain is initialized at his minimum value: 0.2 */
|
||||
if (enableVAD == 1) {
|
||||
encoderChannelContext->VADChannelContext = initBcg729VADChannel();
|
||||
encoderChannelContext->DTXChannelContext = initBcg729DTXChannel();
|
||||
} else {
|
||||
encoderChannelContext->VADChannelContext = NULL;
|
||||
encoderChannelContext->DTXChannelContext = NULL;
|
||||
}
|
||||
|
||||
/* initialisation of the differents blocs which need to be initialised */
|
||||
initPreProcessing(encoderChannelContext);
|
||||
initLSPQuantization(encoderChannelContext);
|
||||
initGainQuantization(encoderChannelContext);
|
||||
|
||||
return encoderChannelContext;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* closeBcg729EncoderChannel : free memory of context structure */
|
||||
/* parameters: */
|
||||
/* -(i) encoderChannelContext : the channel context data */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void closeBcg729EncoderChannel(bcg729EncoderChannelContextStruct *encoderChannelContext)
|
||||
{
|
||||
if (encoderChannelContext) {
|
||||
if (encoderChannelContext->VADChannelContext) {
|
||||
free(encoderChannelContext->VADChannelContext);
|
||||
}
|
||||
if (encoderChannelContext->DTXChannelContext) {
|
||||
free(encoderChannelContext->DTXChannelContext);
|
||||
}
|
||||
free(encoderChannelContext);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* bcg729Encoder : */
|
||||
/* parameters: */
|
||||
/* -(i) encoderChannelContext : context for this encoder channel */
|
||||
/* -(i) inputFrame : 80 samples (16 bits PCM) */
|
||||
/* -(o) bitStream : The 15 parameters for a frame on 80 bits */
|
||||
/* on 80 bits (10 8bits words) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, const int16_t inputFrame[], uint8_t bitStream[], uint8_t *bitStreamLength)
|
||||
{
|
||||
int i;
|
||||
uint16_t parameters[NB_PARAMETERS]; /* the output parameters in an array */
|
||||
|
||||
/* internal buffers which we do not need to keep between calls */
|
||||
word16_t LPCoefficients[NB_LSP_COEFF]; /* the LP coefficients in Q3.12 */
|
||||
word16_t LSFCoefficients[NB_LSP_COEFF]; /* the LSF coefficients in Q3.12 */
|
||||
word16_t qLPCoefficients[2*NB_LSP_COEFF]; /* the quantized LP coefficients in Q3.12 computed from the qLSP one after interpolation: two sets, one for each subframe */
|
||||
word16_t weightedqLPCoefficients[2*NB_LSP_COEFF]; /* the qLP coefficients in Q3.12 weighted according to spec A3.3.3 */
|
||||
word16_t LSPCoefficients[NB_LSP_COEFF]; /* the LSP coefficients in Q15 */
|
||||
word16_t qLSPCoefficients[NB_LSP_COEFF]; /* the quantized LSP coefficients in Q15 */
|
||||
word16_t interpolatedqLSP[NB_LSP_COEFF]; /* the interpolated qLSP used for first subframe in Q15 */
|
||||
|
||||
uint16_t openLoopPitchDelay;
|
||||
int16_t intPitchDelayMin;
|
||||
int16_t intPitchDelayMax;
|
||||
int subframeIndex;
|
||||
int LPCoefficientsIndex = 0;
|
||||
int parametersIndex = 4; /* index to insert parameters in the parameters output array */
|
||||
word16_t impulseResponseInput[L_SUBFRAME]; /* input buffer for the impulse response computation: in Q12, 1 followed by all zeros see spec A3.5*/
|
||||
|
||||
/* used for VAD */
|
||||
word32_t reflectionCoefficients[NB_LSP_COEFF]; /* in Q31, computed during LP generation, reflectionCoefficients[1] is requested by VAD, the others are stored in context if we cover RFC3389 payload generation */
|
||||
word32_t autoCorrelationCoefficients[NB_LSP_COEFF+3]; /* if VAD is enabled we must compute 13 coefficients, 11 otherwise but used only internally by computeLP function in that case */
|
||||
word32_t noLagAutoCorrelationCoefficients[NB_LSP_COEFF+3]; /* DTX must have access to autocorrelation Coefficients on which lag windowing as not been applied */
|
||||
int8_t autoCorrelationCoefficientsScale; /* autocorrelation coefficients are normalised by computeLP, must get their scaling factor */
|
||||
|
||||
/*****************************************************************************************/
|
||||
/*** on frame basis : preProcessing, LP Analysis, Open-loop pitch search ***/
|
||||
preProcessing(encoderChannelContext, inputFrame, encoderChannelContext->signalLastInputFrame); /* output of the function in the signal buffer */
|
||||
|
||||
/* use the whole signal Buffer for windowing and autocorrelation */
|
||||
/* autoCorrelation Coefficients are computed and used internally, in case of VAD we must compute and retrieve 13 coefficients, compute only 11 when VAD is disabled */
|
||||
computeLP(encoderChannelContext->signalBuffer, LPCoefficients, reflectionCoefficients, autoCorrelationCoefficients, noLagAutoCorrelationCoefficients, &autoCorrelationCoefficientsScale, (encoderChannelContext->VADChannelContext != NULL)?(NB_LSP_COEFF+3):(NB_LSP_COEFF+1));
|
||||
/*** compute LSP: it might fail, get the previous one in this case ***/
|
||||
if (!LP2LSPConversion(LPCoefficients, LSPCoefficients)) {
|
||||
/* unable to find the 10 roots repeat previous LSP */
|
||||
memcpy(LSPCoefficients, encoderChannelContext->previousLSPCoefficients, NB_LSP_COEFF*sizeof(word16_t));
|
||||
}
|
||||
|
||||
/*********** VAD *****************/
|
||||
if (encoderChannelContext->VADChannelContext != NULL) { /* if VAD is not enable, no context */
|
||||
uint8_t VADflag = 1;
|
||||
/* update DTX context */
|
||||
updateDTXContext(encoderChannelContext->DTXChannelContext, noLagAutoCorrelationCoefficients, autoCorrelationCoefficientsScale);
|
||||
|
||||
/*** compute LSF in Q2.13 : lsf = arcos(lsp) range [0, Pi[ spec 3.2.4 eq18 ***/
|
||||
/* TODO : remove it from LSPQuantizationFunction and perform it out of enableVAD test */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
LSFCoefficients[i] = g729Acos_Q15Q13(LSPCoefficients[i]);
|
||||
}
|
||||
|
||||
VADflag = bcg729_vad(encoderChannelContext->VADChannelContext, reflectionCoefficients[1], LSFCoefficients, autoCorrelationCoefficients, autoCorrelationCoefficientsScale, encoderChannelContext->signalCurrentFrame);
|
||||
|
||||
/* call encodeSIDFrame even if it is a voice frame as it will update DTXContext with current VADflag : TODO : move updateDTXContext in the encodeSIDFrame as part of the update is performed in it anyway */
|
||||
encodeSIDFrame(encoderChannelContext->DTXChannelContext, encoderChannelContext->previousLSPCoefficients, encoderChannelContext->previousqLSPCoefficients, VADflag, encoderChannelContext->previousqLSF, &(encoderChannelContext->excitationVector[L_PAST_EXCITATION]), qLPCoefficients, bitStream, bitStreamLength);
|
||||
|
||||
if (VADflag == 0 ) { /* NOISE frame has been encoded */
|
||||
word16_t residualSignal[L_FRAME];
|
||||
/* update encoder context : generate weighted signal */
|
||||
/*** Compute the weighted Quantized LP Coefficients according to spec A3.3.3 ***/
|
||||
/* weightedqLPCoefficients[0] = qLPCoefficients[0]*Gamma^(i+1) (i=0..9) with Gamma = 0.75 in Q15 */
|
||||
weightedqLPCoefficients[0] = MULT16_16_P15(qLPCoefficients[0], GAMMA_E1);
|
||||
weightedqLPCoefficients[1] = MULT16_16_P15(qLPCoefficients[1], GAMMA_E2);
|
||||
weightedqLPCoefficients[2] = MULT16_16_P15(qLPCoefficients[2], GAMMA_E3);
|
||||
weightedqLPCoefficients[3] = MULT16_16_P15(qLPCoefficients[3], GAMMA_E4);
|
||||
weightedqLPCoefficients[4] = MULT16_16_P15(qLPCoefficients[4], GAMMA_E5);
|
||||
weightedqLPCoefficients[5] = MULT16_16_P15(qLPCoefficients[5], GAMMA_E6);
|
||||
weightedqLPCoefficients[6] = MULT16_16_P15(qLPCoefficients[6], GAMMA_E7);
|
||||
weightedqLPCoefficients[7] = MULT16_16_P15(qLPCoefficients[7], GAMMA_E8);
|
||||
weightedqLPCoefficients[8] = MULT16_16_P15(qLPCoefficients[8], GAMMA_E9);
|
||||
weightedqLPCoefficients[9] = MULT16_16_P15(qLPCoefficients[9], GAMMA_E10);
|
||||
weightedqLPCoefficients[10] = MULT16_16_P15(qLPCoefficients[10], GAMMA_E1);
|
||||
weightedqLPCoefficients[11] = MULT16_16_P15(qLPCoefficients[11], GAMMA_E2);
|
||||
weightedqLPCoefficients[12] = MULT16_16_P15(qLPCoefficients[12], GAMMA_E3);
|
||||
weightedqLPCoefficients[13] = MULT16_16_P15(qLPCoefficients[13], GAMMA_E4);
|
||||
weightedqLPCoefficients[14] = MULT16_16_P15(qLPCoefficients[14], GAMMA_E5);
|
||||
weightedqLPCoefficients[15] = MULT16_16_P15(qLPCoefficients[15], GAMMA_E6);
|
||||
weightedqLPCoefficients[16] = MULT16_16_P15(qLPCoefficients[16], GAMMA_E7);
|
||||
weightedqLPCoefficients[17] = MULT16_16_P15(qLPCoefficients[17], GAMMA_E8);
|
||||
weightedqLPCoefficients[18] = MULT16_16_P15(qLPCoefficients[18], GAMMA_E9);
|
||||
weightedqLPCoefficients[19] = MULT16_16_P15(qLPCoefficients[19], GAMMA_E10);
|
||||
|
||||
/*** Compute weighted signal according to spec A3.3.3, this function also compute LPResidualSignal(entire frame values) as specified in eq A.3 ***/
|
||||
computeWeightedSpeech(encoderChannelContext->signalCurrentFrame, qLPCoefficients, weightedqLPCoefficients, &(encoderChannelContext->weightedInputSignal[MAXIMUM_INT_PITCH_DELAY]), residualSignal); /* weightedInputSignal contains MAXIMUM_INT_PITCH_DELAY values from previous frame, points to current frame */
|
||||
|
||||
/* update the target Signal : targetSignal = residualSignal - excitationVector */
|
||||
for (subframeIndex=0; subframeIndex<L_FRAME; subframeIndex+=L_SUBFRAME) {
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
encoderChannelContext->targetSignal[NB_LSP_COEFF+i] = SUB16(residualSignal[subframeIndex+i], encoderChannelContext->excitationVector[L_PAST_EXCITATION+subframeIndex+i]);
|
||||
}
|
||||
synthesisFilter(&(encoderChannelContext->targetSignal[NB_LSP_COEFF]), &(weightedqLPCoefficients[LPCoefficientsIndex]), &(encoderChannelContext->targetSignal[NB_LSP_COEFF]));
|
||||
LPCoefficientsIndex+= NB_LSP_COEFF;
|
||||
}
|
||||
|
||||
/*** memory updates ***/
|
||||
/* shift left by L_FRAME the signal buffer */
|
||||
memmove(encoderChannelContext->signalBuffer, &(encoderChannelContext->signalBuffer[L_FRAME]), (L_LP_ANALYSIS_WINDOW-L_FRAME)*sizeof(word16_t));
|
||||
/* shift left by L_FRAME the weightedInputSignal buffer */
|
||||
memmove(encoderChannelContext->weightedInputSignal, &(encoderChannelContext->weightedInputSignal[L_FRAME]), MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t));
|
||||
/* shift left by L_FRAME the excitationVector */
|
||||
memmove(encoderChannelContext->excitationVector, &(encoderChannelContext->excitationVector[L_FRAME]), L_PAST_EXCITATION*sizeof(word16_t));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* set generated bitStream length: active voice is compressed into 80 bits */
|
||||
*bitStreamLength = 10;
|
||||
|
||||
/*********** VAD *****************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*** LSPQuantization and compute L0, L1, L2, L3: the first four parameters ***/
|
||||
LSPQuantization(encoderChannelContext, LSPCoefficients, qLSPCoefficients, parameters);
|
||||
|
||||
/*** interpolate qLSP and convert to LP ***/
|
||||
interpolateqLSP(encoderChannelContext->previousqLSPCoefficients, qLSPCoefficients, interpolatedqLSP);
|
||||
/* copy the currentqLSP to previousqLSP buffer */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
encoderChannelContext->previousqLSPCoefficients[i] = qLSPCoefficients[i];
|
||||
}
|
||||
|
||||
/* first subframe */
|
||||
qLSP2LP(interpolatedqLSP, qLPCoefficients);
|
||||
/* second subframe */
|
||||
qLSP2LP(qLSPCoefficients, &(qLPCoefficients[NB_LSP_COEFF]));
|
||||
|
||||
/*** Compute the weighted Quantized LP Coefficients according to spec A3.3.3 ***/
|
||||
/* weightedqLPCoefficients[0] = qLPCoefficients[0]*Gamma^(i+1) (i=0..9) with Gamma = 0.75 in Q15 */
|
||||
weightedqLPCoefficients[0] = MULT16_16_P15(qLPCoefficients[0], GAMMA_E1);
|
||||
weightedqLPCoefficients[1] = MULT16_16_P15(qLPCoefficients[1], GAMMA_E2);
|
||||
weightedqLPCoefficients[2] = MULT16_16_P15(qLPCoefficients[2], GAMMA_E3);
|
||||
weightedqLPCoefficients[3] = MULT16_16_P15(qLPCoefficients[3], GAMMA_E4);
|
||||
weightedqLPCoefficients[4] = MULT16_16_P15(qLPCoefficients[4], GAMMA_E5);
|
||||
weightedqLPCoefficients[5] = MULT16_16_P15(qLPCoefficients[5], GAMMA_E6);
|
||||
weightedqLPCoefficients[6] = MULT16_16_P15(qLPCoefficients[6], GAMMA_E7);
|
||||
weightedqLPCoefficients[7] = MULT16_16_P15(qLPCoefficients[7], GAMMA_E8);
|
||||
weightedqLPCoefficients[8] = MULT16_16_P15(qLPCoefficients[8], GAMMA_E9);
|
||||
weightedqLPCoefficients[9] = MULT16_16_P15(qLPCoefficients[9], GAMMA_E10);
|
||||
weightedqLPCoefficients[10] = MULT16_16_P15(qLPCoefficients[10], GAMMA_E1);
|
||||
weightedqLPCoefficients[11] = MULT16_16_P15(qLPCoefficients[11], GAMMA_E2);
|
||||
weightedqLPCoefficients[12] = MULT16_16_P15(qLPCoefficients[12], GAMMA_E3);
|
||||
weightedqLPCoefficients[13] = MULT16_16_P15(qLPCoefficients[13], GAMMA_E4);
|
||||
weightedqLPCoefficients[14] = MULT16_16_P15(qLPCoefficients[14], GAMMA_E5);
|
||||
weightedqLPCoefficients[15] = MULT16_16_P15(qLPCoefficients[15], GAMMA_E6);
|
||||
weightedqLPCoefficients[16] = MULT16_16_P15(qLPCoefficients[16], GAMMA_E7);
|
||||
weightedqLPCoefficients[17] = MULT16_16_P15(qLPCoefficients[17], GAMMA_E8);
|
||||
weightedqLPCoefficients[18] = MULT16_16_P15(qLPCoefficients[18], GAMMA_E9);
|
||||
weightedqLPCoefficients[19] = MULT16_16_P15(qLPCoefficients[19], GAMMA_E10);
|
||||
|
||||
/*** Compute weighted signal according to spec A3.3.3, this function also set LPResidualSignal(entire frame values) as specified in eq A.3 in excitationVector[L_PAST_EXCITATION] ***/
|
||||
computeWeightedSpeech(encoderChannelContext->signalCurrentFrame, qLPCoefficients, weightedqLPCoefficients, &(encoderChannelContext->weightedInputSignal[MAXIMUM_INT_PITCH_DELAY]), &(encoderChannelContext->excitationVector[L_PAST_EXCITATION])); /* weightedInputSignal contains MAXIMUM_INT_PITCH_DELAY values from previous frame, points to current frame */
|
||||
|
||||
/*** find the open loop pitch delay ***/
|
||||
openLoopPitchDelay = findOpenLoopPitchDelay(&(encoderChannelContext->weightedInputSignal[MAXIMUM_INT_PITCH_DELAY]));
|
||||
|
||||
/* define boundaries for closed loop pitch delay search as specified in 3.7 */
|
||||
intPitchDelayMin = openLoopPitchDelay-3;
|
||||
if (intPitchDelayMin < 20) {
|
||||
intPitchDelayMin = 20;
|
||||
}
|
||||
intPitchDelayMax = intPitchDelayMin + 6;
|
||||
if (intPitchDelayMax > MAXIMUM_INT_PITCH_DELAY) {
|
||||
intPitchDelayMax = MAXIMUM_INT_PITCH_DELAY;
|
||||
intPitchDelayMin = MAXIMUM_INT_PITCH_DELAY - 6;
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
/* loop over the two subframes: Closed-loop pitch search(adaptative codebook), fixed codebook, memory update */
|
||||
/* set index and buffers */
|
||||
impulseResponseInput[0] = ONE_IN_Q12;
|
||||
memset(&(impulseResponseInput[1]), 0, (L_SUBFRAME-1)*sizeof(word16_t));
|
||||
|
||||
for (subframeIndex=0; subframeIndex<L_FRAME; subframeIndex+=L_SUBFRAME) {
|
||||
int16_t intPitchDelay, fracPitchDelay;
|
||||
word16_t adaptativeCodebookGain;
|
||||
/*** Compute the impulse response : filter a subframe long buffer filled with unit and only zero through the 1/weightedqLPCoefficients as in spec A.3.5 ***/
|
||||
word16_t impulseResponseBuffer[NB_LSP_COEFF+L_SUBFRAME]; /* impulseResponseBuffer in Q12, need NB_LSP_COEFF as past value to go through filtering function */
|
||||
word16_t filteredAdaptativeCodebookVector[NB_LSP_COEFF+L_SUBFRAME]; /* in Q0, the first NB_LSP_COEFF words are set to zero and used by filter only */
|
||||
word64_t gainQuantizationXy, gainQuantizationYy; /* used to store in Q0 values reused in gain quantization */
|
||||
word16_t fixedCodebookVector[L_SUBFRAME]; /* in Q13 */
|
||||
word16_t convolvedFixedCodebookVector[L_SUBFRAME]; /* in Q12 */
|
||||
word16_t quantizedAdaptativeCodebookGain; /* in Q14 */
|
||||
word16_t quantizedFixedCodebookGain; /* in Q1 */
|
||||
|
||||
memset(impulseResponseBuffer, 0, (NB_LSP_COEFF)*sizeof(word16_t)); /* set the past values to zero */
|
||||
synthesisFilter(impulseResponseInput, &(weightedqLPCoefficients[LPCoefficientsIndex]), &(impulseResponseBuffer[NB_LSP_COEFF]));
|
||||
|
||||
/*** Compute the target signal (x[n]) as in spec A.3.6 in Q0 ***/
|
||||
/* excitationVector[L_PAST_EXCITATION+subframeIndex] currently store in Q0 the LPResidualSignal as in spec A.3.3 eq A.3*/
|
||||
synthesisFilter( &(encoderChannelContext->excitationVector[L_PAST_EXCITATION+subframeIndex]), &(weightedqLPCoefficients[LPCoefficientsIndex]), &(encoderChannelContext->targetSignal[NB_LSP_COEFF]));
|
||||
|
||||
/*** Adaptative Codebook search : compute the intPitchDelay, fracPitchDelay and associated parameter, compute also the adaptative codebook vector used to generate the excitation ***/
|
||||
/* after this call, the excitationVector[L_PAST_EXCITATION + subFrameIndex] contains the adaptative codebook vector as in spec 3.7.1 */
|
||||
adaptativeCodebookSearch(&(encoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex]), &intPitchDelayMin, &intPitchDelayMax, &(impulseResponseBuffer[NB_LSP_COEFF]), &(encoderChannelContext->targetSignal[NB_LSP_COEFF]),
|
||||
&intPitchDelay, &fracPitchDelay, &(parameters[parametersIndex]), subframeIndex);
|
||||
|
||||
/*** Compute adaptative codebook gain spec 3.7.3, result in Q14 ***/
|
||||
/* compute the filtered adaptative codebook vector spec 3.7.3 */
|
||||
/* this computation makes use of two partial results used for gainQuantization too (yy and xy in eq63), they are part of the function output */
|
||||
/* note spec 3.7.3 eq44 make use of convolution of impulseResponse and adaptative codebook vector to compute the filtered version */
|
||||
/* in the Annex A, the filter being simpler, it's faster to directly filter the the vector using the weightedqLPCoefficients */
|
||||
memset(filteredAdaptativeCodebookVector, 0, NB_LSP_COEFF*sizeof(word16_t));
|
||||
synthesisFilter(&(encoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex]), &(weightedqLPCoefficients[LPCoefficientsIndex]), &(filteredAdaptativeCodebookVector[NB_LSP_COEFF]));
|
||||
|
||||
adaptativeCodebookGain = computeAdaptativeCodebookGain(&(encoderChannelContext->targetSignal[NB_LSP_COEFF]), &(filteredAdaptativeCodebookVector[NB_LSP_COEFF]), &gainQuantizationXy, &gainQuantizationYy); /* gain in Q14 */
|
||||
|
||||
/* increase parameters index and compute P0 if needed */
|
||||
parametersIndex++;
|
||||
if (subframeIndex==0) { /* first subframe compute P0, the parity bit of P1 */
|
||||
parameters[parametersIndex] = computeParity(parameters[parametersIndex-1]);
|
||||
parametersIndex++;
|
||||
}
|
||||
|
||||
/*** Fixed Codebook Search : compute the parameters for fixed codebook and the regular and convolved version of the fixed codebook vector ***/
|
||||
fixedCodebookSearch(&(encoderChannelContext->targetSignal[NB_LSP_COEFF]), &(impulseResponseBuffer[NB_LSP_COEFF]), intPitchDelay, encoderChannelContext->lastQuantizedAdaptativeCodebookGain, &(filteredAdaptativeCodebookVector[NB_LSP_COEFF]), adaptativeCodebookGain,
|
||||
&(parameters[parametersIndex]), &(parameters[parametersIndex+1]), fixedCodebookVector, convolvedFixedCodebookVector);
|
||||
parametersIndex+=2;
|
||||
|
||||
/*** gains Quantization ***/
|
||||
gainQuantization(encoderChannelContext, &(encoderChannelContext->targetSignal[NB_LSP_COEFF]), &(filteredAdaptativeCodebookVector[NB_LSP_COEFF]), convolvedFixedCodebookVector, fixedCodebookVector, gainQuantizationXy, gainQuantizationYy,
|
||||
&quantizedAdaptativeCodebookGain, &quantizedFixedCodebookGain, &(parameters[parametersIndex]), &(parameters[parametersIndex+1]));
|
||||
parametersIndex+=2;
|
||||
|
||||
/*** subframe basis indexes and memory updates ***/
|
||||
LPCoefficientsIndex+= NB_LSP_COEFF;
|
||||
encoderChannelContext->lastQuantizedAdaptativeCodebookGain = quantizedAdaptativeCodebookGain;
|
||||
if (encoderChannelContext->lastQuantizedAdaptativeCodebookGain>ONE_POINT_2_IN_Q14) encoderChannelContext->lastQuantizedAdaptativeCodebookGain = ONE_POINT_2_IN_Q14;
|
||||
if (encoderChannelContext->lastQuantizedAdaptativeCodebookGain<O2_IN_Q14) encoderChannelContext->lastQuantizedAdaptativeCodebookGain = O2_IN_Q14;
|
||||
/* compute excitation for current subframe as in spec A.3.10 */
|
||||
/* excitationVector[L_PAST_EXCITATION + subframeIndex] currently contains in Q0 the adaptative codebook vector, quantizedAdaptativeCodebookGain in Q14 */
|
||||
/* fixedCodebookVector in Q13, quantizedFixedCodebookGain in Q1 */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
encoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex + i] = (word16_t)(SATURATE(PSHR(ADD32(MULT16_16(encoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex + i], quantizedAdaptativeCodebookGain),
|
||||
MULT16_16(fixedCodebookVector[i], quantizedFixedCodebookGain)), 14), MAXINT16)); /* result in Q0 */
|
||||
}
|
||||
|
||||
/* update targetSignal memory as in spec A.3.10 */
|
||||
quantizedAdaptativeCodebookGain = PSHR(quantizedAdaptativeCodebookGain, 1); /* quantizedAdaptativeCodebookGain in Q13 */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
/* targetSignal[i] = targetSignal[L_SUBFRAME+i] - quantizedAdaptativeCodebookGain*filteredAdaptativeCodebookVector[L_SUBFRAME+i] - quantizedFixedCodebookGain*convolvedFixedCodebookVector[L_SUBFRAME-NB_LSP_COEFF+i]*/
|
||||
word32_t acc = MAC16_16(MULT16_16(quantizedAdaptativeCodebookGain, filteredAdaptativeCodebookVector[L_SUBFRAME+i]), quantizedFixedCodebookGain, convolvedFixedCodebookVector[L_SUBFRAME-NB_LSP_COEFF+i]); /* acc in Q13 */
|
||||
encoderChannelContext->targetSignal[i] = (word16_t)(SATURATE(SUB32(encoderChannelContext->targetSignal[L_SUBFRAME+i], PSHR(acc, 13)), MAXINT16));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
/*** frame basis memory updates ***/
|
||||
/* shift left by L_FRAME the signal buffer */
|
||||
memmove(encoderChannelContext->signalBuffer, &(encoderChannelContext->signalBuffer[L_FRAME]), (L_LP_ANALYSIS_WINDOW-L_FRAME)*sizeof(word16_t));
|
||||
/* update previousLSP coefficient buffer */
|
||||
memcpy(encoderChannelContext->previousLSPCoefficients, LSPCoefficients, NB_LSP_COEFF*sizeof(word16_t));
|
||||
memcpy(encoderChannelContext->previousqLSPCoefficients, qLSPCoefficients, NB_LSP_COEFF*sizeof(word16_t));
|
||||
/* shift left by L_FRAME the weightedInputSignal buffer */
|
||||
memmove(encoderChannelContext->weightedInputSignal, &(encoderChannelContext->weightedInputSignal[L_FRAME]), MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t));
|
||||
/* shift left by L_FRAME the excitationVector */
|
||||
memmove(encoderChannelContext->excitationVector, &(encoderChannelContext->excitationVector[L_FRAME]), L_PAST_EXCITATION*sizeof(word16_t));
|
||||
|
||||
/*** Convert array of parameters into bitStream ***/
|
||||
parametersArray2BitStream(parameters, bitStream);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* bcg729GetRFC3389Payload : return the comfort noise payload according to */
|
||||
/* RFC3389 for the last CN frame generated by encoder */
|
||||
/* */
|
||||
/* parameters: */
|
||||
/* -(i) encoderChannelContext : retrieve the last CN frame encoded */
|
||||
/* using this context */
|
||||
/* -(o) payload : 11 parameters following RFC3389 with filter order 10 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void bcg729GetRFC3389Payload(bcg729EncoderChannelContextStruct *encoderChannelContext, uint8_t payload[]) {
|
||||
int i;
|
||||
|
||||
/* decodedLogEnergy is the frame mean energy, range [-12,66[, RFC3389 ask for DBov value, max mean energy would be 10log10(2^15*2^15) -> 90 so -90 to switch to DBov */
|
||||
payload[0] = -(encoderChannelContext->DTXChannelContext->decodedLogEnergy - 90);
|
||||
|
||||
/* use last reflection coefficients stored in DTX context and convert them as specified in RFC3389 : Ni = (ki in Q15)/258 + 127 */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
payload[i+1] = (uint8_t)ADD16((word16_t)SHR(MULT16_32_Q15(127/* 1/258 in Q15 */, -encoderChannelContext->DTXChannelContext->reflectionCoefficients[i]), 16), 127); /* ki in Q31 * (1/258 in Q15) -> result in Q31, shift right by 16 -> Q15 */
|
||||
}
|
||||
}
|
207
bcg729/src/findOpenLoopPitchDelay.c
Normal file
207
bcg729/src/findOpenLoopPitchDelay.c
Normal file
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
#include "g729FixedPointMath.h"
|
||||
|
||||
/* local functions prototypes */
|
||||
/* compute eqA.4 from spec A3.4 on the given range and step(1 compute all the correlation in range, 2 only the even ones) return the maximum and set the index giving it in the first parameter */
|
||||
word32_t getCorrelationMax(uint16_t *index, word16_t inputSignal[], uint16_t rangeOpen, uint16_t rangeClose, uint16_t step);
|
||||
/* compute eqA.4 from spec3.4 */
|
||||
word32_t getCorrelation(word16_t inputSignal[], uint16_t index);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* findOpenLoopPitchDelay : as specified in specA3.4 */
|
||||
/* paremeters: */
|
||||
/* -(i) weightedInputSignal: 223 values in Q0, buffer */
|
||||
/* accessed in range [-MAXIMUM_INT_PITCH_DELAY(143), L_FRAME(80)[ */
|
||||
/* return value: */
|
||||
/* - the openLoopIntegerPitchDelay in Q0 range [20, 143] */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
uint16_t findOpenLoopPitchDelay(word16_t weightedInputSignal[])
|
||||
{
|
||||
int i;
|
||||
/*** scale the signal to avoid overflows ***/
|
||||
word16_t scaledWeightedInputSignalBuffer[MAXIMUM_INT_PITCH_DELAY+L_FRAME]; /* this buffer might store the scaled version of input Signal, if scaling is not needed, it is not used */
|
||||
word16_t *scaledWeightedInputSignal; /* points to the begining of present frame either scaled or directly the input signal */
|
||||
word64_t autocorrelation = 0;
|
||||
uint16_t indexRange1=0, indexRange2=0, indexRange3Even=0, indexRange3;
|
||||
word32_t correlationMaxRange1;
|
||||
word32_t correlationMaxRange2;
|
||||
word32_t correlationMaxRange3;
|
||||
word32_t correlationMaxRange3Odd;
|
||||
word32_t autoCorrelationRange1;
|
||||
word32_t autoCorrelationRange2;
|
||||
word32_t autoCorrelationRange3;
|
||||
word32_t normalisedCorrelationMaxRange1;
|
||||
word32_t normalisedCorrelationMaxRange2;
|
||||
word32_t normalisedCorrelationMaxRange3;
|
||||
uint16_t indexMultiple;
|
||||
|
||||
/* compute on 64 bits the autocorrelation on the input signal and if needed scale to have it on 32 bits */
|
||||
for (i=-MAXIMUM_INT_PITCH_DELAY; i<L_FRAME; i++) {
|
||||
autocorrelation = MAC64(autocorrelation, weightedInputSignal[i], weightedInputSignal[i]);
|
||||
}
|
||||
if (autocorrelation>MAXINT32) {
|
||||
int overflowScale;
|
||||
scaledWeightedInputSignal = &(scaledWeightedInputSignalBuffer[MAXIMUM_INT_PITCH_DELAY]);
|
||||
overflowScale = PSHR(31-countLeadingZeros((word32_t)(autocorrelation>>31)),1); /* count number of bits needed over the 31 bits allowed and divide by 2 to get the right scaling for the signal */
|
||||
for (i=-MAXIMUM_INT_PITCH_DELAY; i<L_FRAME; i++) {
|
||||
scaledWeightedInputSignal[i] = SHR(weightedInputSignal[i], overflowScale);
|
||||
}
|
||||
|
||||
} else { /* scaledWeightedInputSignal points directly to weightedInputSignal */
|
||||
scaledWeightedInputSignal = weightedInputSignal;
|
||||
}
|
||||
|
||||
|
||||
/*** compute the correlationMax in the different ranges ***/
|
||||
correlationMaxRange1 = getCorrelationMax(&indexRange1, scaledWeightedInputSignal, 20, 39, 1);
|
||||
correlationMaxRange2 = getCorrelationMax(&indexRange2, scaledWeightedInputSignal, 40, 79, 1);
|
||||
correlationMaxRange3 = getCorrelationMax(&indexRange3Even, scaledWeightedInputSignal, 80, 143, 2);
|
||||
indexRange3 = indexRange3Even;
|
||||
/* for the third range, correlationMax shall be computed at +1 and -1 around the maximum found as described in spec A3.4 */
|
||||
if (indexRange3>80) { /* don't test value out of range [80, 143] */
|
||||
correlationMaxRange3Odd = getCorrelation(scaledWeightedInputSignal, indexRange3-1);
|
||||
if (correlationMaxRange3Odd>correlationMaxRange3) {
|
||||
correlationMaxRange3 = correlationMaxRange3Odd;
|
||||
indexRange3 = indexRange3Even-1;
|
||||
}
|
||||
}
|
||||
correlationMaxRange3Odd = getCorrelation(scaledWeightedInputSignal, indexRange3+1);
|
||||
if (correlationMaxRange3Odd>correlationMaxRange3) {
|
||||
correlationMaxRange3 = correlationMaxRange3Odd;
|
||||
indexRange3 = indexRange3Even+1;
|
||||
}
|
||||
|
||||
/*** normalise the correlations ***/
|
||||
autoCorrelationRange1 = getCorrelation(&(scaledWeightedInputSignal[-indexRange1]), 0);
|
||||
autoCorrelationRange2 = getCorrelation(&(scaledWeightedInputSignal[-indexRange2]), 0);
|
||||
autoCorrelationRange3 = getCorrelation(&(scaledWeightedInputSignal[-indexRange3]), 0);
|
||||
if (autoCorrelationRange1==0) {
|
||||
autoCorrelationRange1 = 1; /* avoid division by 0 */
|
||||
}
|
||||
if (autoCorrelationRange2==0) {
|
||||
autoCorrelationRange2 = 1; /* avoid division by 0 */
|
||||
}
|
||||
if (autoCorrelationRange3==0) {
|
||||
autoCorrelationRange3 = 1; /* avoid division by 0 */
|
||||
}
|
||||
|
||||
/* according to ITU code comments, the normalisedCorrelationMax values fit on 16 bits when in Q0, so keep them in Q8 on 32 bits shall not give any overflow */
|
||||
normalisedCorrelationMaxRange1 = MULT32_32_Q23(correlationMaxRange1, g729InvSqrt_Q0Q31(autoCorrelationRange1));
|
||||
normalisedCorrelationMaxRange2 = MULT32_32_Q23(correlationMaxRange2, g729InvSqrt_Q0Q31(autoCorrelationRange2));
|
||||
normalisedCorrelationMaxRange3 = MULT32_32_Q23(correlationMaxRange3, g729InvSqrt_Q0Q31(autoCorrelationRange3));
|
||||
|
||||
|
||||
|
||||
/*** Favouring the delays with the values in the lower range ***/
|
||||
/* not clearly documented in spec A3.4, algo from the ITU code */
|
||||
indexMultiple = SHL(indexRange2,1); /* indexMultiple = 2*indexRange2 */
|
||||
if( abs(indexMultiple - indexRange3) < 5) { /* 2*indexRange2 - indexRange3 < 5 */
|
||||
normalisedCorrelationMaxRange2 = ADD32(normalisedCorrelationMaxRange2, SHR(normalisedCorrelationMaxRange3,2)); /* Max2 += Max3*0.25 */
|
||||
}
|
||||
|
||||
if( abs(indexMultiple + indexRange2 - indexRange3) < 7) { /* 3*indexRange2 - indexRange3 < 5 */
|
||||
normalisedCorrelationMaxRange2 = ADD32(normalisedCorrelationMaxRange2, SHR(normalisedCorrelationMaxRange3,2)); /* Max2 += Max3*0.25 */
|
||||
}
|
||||
|
||||
indexMultiple = SHL(indexRange1,1); /* indexMultiple = 2*indexRange1 */
|
||||
if( abs(indexMultiple - indexRange2) < 5) { /* 2*indexRange1 - indexRange2 < 5 */
|
||||
normalisedCorrelationMaxRange1 = MAC16_32_P15(normalisedCorrelationMaxRange1, O2_IN_Q15, normalisedCorrelationMaxRange2); /* Max1 += Max2*0.2 */
|
||||
}
|
||||
|
||||
if( abs(indexMultiple + indexRange1 - indexRange2) < 7) { /* 3*indexRange1 - indexRange2 < 7 */
|
||||
normalisedCorrelationMaxRange1 = MAC16_32_P15(normalisedCorrelationMaxRange1, O2_IN_Q15, normalisedCorrelationMaxRange2); /* Max1 += Max2*0.2 */
|
||||
}
|
||||
|
||||
/*** return the index corresponding to the greatest normalised Correlation */
|
||||
if (normalisedCorrelationMaxRange1<normalisedCorrelationMaxRange2) {
|
||||
normalisedCorrelationMaxRange1 = normalisedCorrelationMaxRange2;
|
||||
indexRange1 = indexRange2;
|
||||
}
|
||||
if (normalisedCorrelationMaxRange1<normalisedCorrelationMaxRange3) {
|
||||
indexRange1 = indexRange3;
|
||||
}
|
||||
return indexRange1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* getCorrelation : as specified in specA3.4 eqA.4 */
|
||||
/* correlation = ∑(i=0..39)inputSignal[2*i]*inputSignal[2*i-index] */
|
||||
/* paremeters: */
|
||||
/* -(i) inputSignal: 223 values in Q0, buffer accessed in range */
|
||||
/* [-index, L_FRAME[ */
|
||||
/* -(i) index: integer value in range [20,143] */
|
||||
/* return value: */
|
||||
/* -the correlation in Q0 on 32 bits */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
word32_t getCorrelation(word16_t inputSignal[], uint16_t index)
|
||||
{
|
||||
int i,j=-index; /* i will be the [2*i] index and j the [2*i-index] in eqA.4 */
|
||||
|
||||
word32_t correlation = 0;
|
||||
|
||||
for (i=0; i<L_FRAME; i+=2,j+=2) {
|
||||
correlation = MAC16_16(correlation, inputSignal[i], inputSignal[j]);
|
||||
}
|
||||
|
||||
return correlation;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* getCorrelation : compute eqA.4 from spec A3.4 on the given range and */
|
||||
/* step(1 compute all the correlation in range, 2 only the even ones) */
|
||||
/* then return the maximum as specified in specA3.4 eqA.4 */
|
||||
/* paremeters: */
|
||||
/* -(o) index : the index giving the maximum of correlation on the */
|
||||
/* considered range */
|
||||
/* -(i) inputSignal: signal used to compute the correlation, in Q0 */
|
||||
/* accessed in range [-rangeClose, L_FRAME[ */
|
||||
/* -(i) rangeOpen and rangeClose : the index range in which looking for */
|
||||
/* the correlation max */
|
||||
/* -(i) step : incrementing step for the index */
|
||||
/* return value : */
|
||||
/* - the correlation maximum found on the given range in Q0 on 32 bits */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
word32_t getCorrelationMax(uint16_t *index, word16_t inputSignal[], uint16_t rangeOpen, uint16_t rangeClose, uint16_t step)
|
||||
{
|
||||
int i;
|
||||
word32_t correlationMax = MININT32;
|
||||
|
||||
for (i=rangeOpen; i<=rangeClose; i+=step) {
|
||||
word32_t correlation = getCorrelation(inputSignal, i);
|
||||
if (correlation>correlationMax) {
|
||||
*index = i;
|
||||
correlationMax = correlation;
|
||||
}
|
||||
}
|
||||
|
||||
return correlationMax;
|
||||
}
|
31
bcg729/src/findOpenLoopPitchDelay.h
Normal file
31
bcg729/src/findOpenLoopPitchDelay.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef FINDOPENLOOPPITCHDELAY_H
|
||||
#define FINDOPENLOOPPITCHDELAY_H
|
||||
/*****************************************************************************/
|
||||
/* findOpenLoopPitchDelay : as specified in specA3.4 */
|
||||
/* paremeters: */
|
||||
/* -(i) weightedInputSignal: 223 values in Q0, buffer */
|
||||
/* accessed in range [-MAXIMUM_INT_PITCH_DELAY(143), L_FRAME(80)[ */
|
||||
/* return value: */
|
||||
/* - the openLoopIntegerPitchDelay in Q0 range [20, 143] */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
uint16_t findOpenLoopPitchDelay(word16_t weightedInputSignal[]);
|
||||
#endif /* ifndef FINDOPENLOOPPITCHDELAY_H */
|
398
bcg729/src/fixedCodebookSearch.c
Normal file
398
bcg729/src/fixedCodebookSearch.c
Normal file
|
@ -0,0 +1,398 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "fixedCodebookSearch.h"
|
||||
|
||||
/*** local functions ***/
|
||||
void computeImpulseResponseCorrelationMatrix(word16_t impulseResponse[], word16_t correlationSignal[], int correlationSignalSign[], word32_t Phi[L_SUBFRAME][L_SUBFRAME]);
|
||||
void computePhiDiagonal(int j, word16_t impulseResponse[], word32_t Phi[L_SUBFRAME][L_SUBFRAME], uint16_t PhiScaling);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* fixedCodebookSearch: compute fixed codebook parameters (codeword and sign)*/
|
||||
/* compute also fixed codebook vector as in spec 3.8.1 */
|
||||
/* parameters: */
|
||||
/* -(i) targetSignal: 40 values as in spec A.3.6 in Q0 */
|
||||
/* -(i) impulseResponse: 40 values as in spec A.3.5 in Q12 */
|
||||
/* -(i) intPitchDelay: current integer pitch delay */
|
||||
/* -(i) lastQuantizedAdaptativeCodebookGain: previous subframe pitch */
|
||||
/* gain quantized in Q14 */
|
||||
/* -(i) filteredAdaptativeCodebookVector : 40 values in Q0 */
|
||||
/* -(i) adaptativeCodebookGain : in Q14 */
|
||||
/* -(o) fixedCodebookParameter */
|
||||
/* -(o) fixedCodebookPulsesSigns */
|
||||
/* -(o) fixedCodebookVector : 40 values as in spec 3.8, eq45 in Q13 */
|
||||
/* -(o) fixedCodebookVectorConvolved : 40 values as in spec 3.9, eq64 */
|
||||
/* in Q12. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void fixedCodebookSearch(word16_t targetSignal[], word16_t impulseResponse[], int16_t intPitchDelay, word16_t lastQuantizedAdaptativeCodebookGain, word16_t filteredAdaptativeCodebookVector[], word16_t adaptativeCodebookGain,
|
||||
uint16_t *fixedCodebookParameter, uint16_t *fixedCodebookPulsesSigns, word16_t fixedCodebookVector[], word16_t fixedCodebookVectorConvolved[])
|
||||
{
|
||||
int i,j,n;
|
||||
word16_t fixedCodebookTargetSignal[L_SUBFRAME];
|
||||
word32_t correlationSignal32[L_SUBFRAME]; /* on 32 bits in Q12 */
|
||||
word16_t correlationSignal[L_SUBFRAME]; /* normalised to fit on 13 bits */
|
||||
word32_t correlationSignalMax = 0;
|
||||
word32_t abscCrrelationSignal32;
|
||||
uint16_t correlationSignalMaxNorm;
|
||||
int correlationSignalSign[L_SUBFRAME]; /* to store the sign of each correlationSignal element */
|
||||
/* build the matrix Ф' : impulseResponse correlation matrix spec 3.8.1 eq51, eq56 and eq57 */
|
||||
/* correlationSignal turns to absolute values and sign of elements is stored in correlationSignalSign */
|
||||
word32_t Phi[L_SUBFRAME][L_SUBFRAME] = {{0}};
|
||||
int m3Base;
|
||||
int i0=0, i1=0, i2=0, i3=0;
|
||||
word32_t correlationSquareMax = -1;
|
||||
word32_t energyMax = 1;
|
||||
int m0=0, m1=0, m2=0, m3=0;
|
||||
int mSwitch[2][4] = {{2,3,0,1},{3,0,1,2}};
|
||||
int mIndex;
|
||||
int jx = 0;
|
||||
|
||||
/* compute the target signal for fixed codebook spec 3.8.1 eq50 : fixedCodebookTargetSignal[i] = targetSignal[i] - (adaptativeCodebookGain * filteredAdaptativeCodebookVector[i]) */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
fixedCodebookTargetSignal[i] = MSU16_16_Q14(targetSignal[i], filteredAdaptativeCodebookVector[i], adaptativeCodebookGain); /* adaptativeCodebookGain in Q14, other values in Q0 */
|
||||
}
|
||||
|
||||
/* update impulse vector as in spec 3.8 eq49 */
|
||||
for (i=intPitchDelay; i<L_SUBFRAME; i++) {
|
||||
impulseResponse[i] = MAC16_16_Q14(impulseResponse[i], impulseResponse[i-intPitchDelay], lastQuantizedAdaptativeCodebookGain); /* h[n] = h[n] + β*h[n-T], impulseResponse in Q12, lastQuantizedAdaptativeCodebookGain in Q14 */
|
||||
}
|
||||
|
||||
/* compute the correlation signal as in spec 3.8.1 eq52 */
|
||||
/* compute on 32 bits and get the maximum */
|
||||
for (n=0; n<L_SUBFRAME; n++) {
|
||||
correlationSignal32[n] = 0;
|
||||
for (i=n; i<L_SUBFRAME; i++) {
|
||||
correlationSignal32[n] = MAC16_16(correlationSignal32[n], fixedCodebookTargetSignal[i], impulseResponse[i-n]);
|
||||
}
|
||||
abscCrrelationSignal32 = correlationSignal32[n]>=0?correlationSignal32[n]:-correlationSignal32[n];
|
||||
if (abscCrrelationSignal32>correlationSignalMax) {
|
||||
correlationSignalMax = abscCrrelationSignal32;
|
||||
}
|
||||
}
|
||||
/* normalise on 13 bits */
|
||||
correlationSignalMaxNorm = countLeadingZeros(correlationSignalMax);
|
||||
if (correlationSignalMaxNorm<18) { /* if it doesn't already fit on 13 bits */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
correlationSignal[i] = (word16_t)(SHR(correlationSignal32[i], 18-correlationSignalMaxNorm));
|
||||
}
|
||||
} else { /* it fits on 13 bits, just copy it to the 16 bits buffer */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
correlationSignal[i] = (word16_t)correlationSignal32[i];
|
||||
}
|
||||
}
|
||||
|
||||
computeImpulseResponseCorrelationMatrix(impulseResponse, correlationSignal, correlationSignalSign, Phi);
|
||||
|
||||
/* search for impulses leading to a max in C^2/E : spec 3.8.1 eq53 */
|
||||
/* algorithm, not described in spec, retrieved from ITU code */
|
||||
/* by tracks are intended series of index m0 track is 0,5,10,...35. m1 is 1,6,11,..,36. m2 is 2,7,12,..,37. m3 is 3,8,13,..,38. m4 is 4,9,14,..,39 */
|
||||
/* note index m3 will follow track m3 and m4 */
|
||||
/* The following search is performed twice: first with m3 index following m3 track, and then m3 index follow m4 track */
|
||||
/* The following operation are performed twice, first using indexes m2, m3, m0, m1 and then m3, m0, m1, m2 as following */
|
||||
/* description is made for the first run, for the second one, juste substitute m2 by m3, m3 by m0, m0 by m1 and m1 by m2 */
|
||||
/* - search in m2 track two maxima for the correlation Signal. For each of this maximum : */
|
||||
/* -- compute for the whole m3 track (8 values) the values C^2 and E (see eq58 and 59) and keep the one giving the best ratio */
|
||||
/* - compute for the whole tracks m0 and m1 (64 values) the values C^2 and E (keeping the m2 and m3 previously computed) and save the one giving the best ratio */
|
||||
for (m3Base=3; m3Base<5; m3Base++) {
|
||||
for(mIndex=0; mIndex<2; mIndex++) {
|
||||
/* define for this loop on m3 track the Correlation and Energy giving the maximum of eq53 */
|
||||
word32_t m3TrackCorrelationSquare = -1;
|
||||
word32_t m3TrackEnergy = 1;
|
||||
|
||||
/* Loop on the two maxima of correlation in the m2 index */
|
||||
int firstM2 = 0; /* save the first maximum index to not select it again */
|
||||
word16_t correlationM2M3Max = 0; /* stores the contribution of m2 and m3 impulses to the correlation for the maximum selected */
|
||||
word32_t energyM2M3Max = 0; /* same thing but for the energy */
|
||||
for (i=0; i<2; i++) {
|
||||
word16_t correlationM2 = -1;
|
||||
int currentM2=0;
|
||||
word32_t energyM2;
|
||||
for (j=mSwitch[mIndex][0]; j<L_SUBFRAME; j+=5) { /* in the m2 range, find the correlation Max -> select m2 */
|
||||
if (correlationSignal[j]>correlationM2 && j!=firstM2) {
|
||||
currentM2 = j;
|
||||
correlationM2=correlationSignal[j];
|
||||
}
|
||||
}
|
||||
firstM2 = currentM2; /* to avoid selecting the same maximum at next iteration */
|
||||
|
||||
energyM2 = Phi[currentM2][currentM2]; /* compute the energy with terms of eq55 using m2 only: Phi'(m2,m2) */
|
||||
|
||||
/* with selected m2, test the 8 m3 possibilities for the current m3 track */
|
||||
for (j=mSwitch[mIndex][1]; j<L_SUBFRAME; j+=5) {
|
||||
word16_t correlationM2M3 = ADD16(correlationM2, correlationSignal[j]); /* compute the correlation sum due to m2 and m3 pulses */
|
||||
word32_t energyM2M3 = ADD32(energyM2, ADD32(Phi[currentM2][j], Phi[j][j])); /* compute the energy if eq55 using term including m2 and m3: Phi'(m2,m2) is already in energyM2 + Phi'(m2,m3) + Phi'(m3,m3) */
|
||||
word32_t correlationM2M3Square = MULT16_16(correlationM2M3, correlationM2M3);
|
||||
/* check if the current correlation/energy couple gives better results than the stored one : maximise C^2/E -> C^2/E > C^2max/Emax => Emax*C^2 > C^2max*E */
|
||||
if (MULT32_32(m3TrackEnergy,correlationM2M3Square) > MULT32_32(energyM2M3, m3TrackCorrelationSquare)) {
|
||||
m3TrackCorrelationSquare = correlationM2M3Square;
|
||||
m3TrackEnergy = energyM2M3;
|
||||
correlationM2M3Max = correlationM2M3;
|
||||
m3 = j;
|
||||
m2 = currentM2;
|
||||
}
|
||||
}
|
||||
}
|
||||
energyM2M3Max = m3TrackEnergy;
|
||||
|
||||
/* reset the current m3 track correlationSquare and energy */
|
||||
m3TrackCorrelationSquare = -1;
|
||||
m3TrackEnergy = 1;
|
||||
|
||||
for (i=mSwitch[mIndex][2]; i<L_SUBFRAME; i+=5) { /* test the 8 possibilities for m0 track */
|
||||
word16_t correlationM2M3M0 = ADD16(correlationM2M3Max, correlationSignal[i]); /* compute correlation with current m0 taking in account the previously selected m2 and m3 */
|
||||
word32_t energyM2M3M0 = ADD32(energyM2M3Max, ADD32(Phi[i][i], ADD32(Phi[i][m2], Phi[i][m3]))); /* add to the previously computed energy the terms of eq59 we can compute with the selected m0: Phi'(m0,m0) + Phi'(m0,m2) + Phi'(m0,m3) */
|
||||
for (j=mSwitch[mIndex][3]; j<L_SUBFRAME; j+=5) { /* test the 8 possibilities for m1 track */
|
||||
word16_t correlationM2M3M0M1 = ADD16(correlationM2M3M0, correlationSignal[j]); /* compute correlation with current m1 taking in account the previously selected m2, m3 and m0 */
|
||||
word32_t energyM2M3M0M1 = ADD32(energyM2M3M0, ADD32(Phi[j][i], ADD32(Phi[j][j], ADD32(Phi[j][m2], Phi[j][m3])))); /* add to the previously computed energy the terms of eq59 we can compute with the selected m1: Phi'(m1,m0) + Phi'(m1,m1) + Phi'(m1,m2) + Phi'(m1,m3) */
|
||||
word32_t correlationM2M3M0M1Square = MULT16_16(correlationM2M3M0M1, correlationM2M3M0M1);
|
||||
/* check if the current correlation/energy couple gives better results than the stored one : maximise C^2/E -> C^2/E > C^2max/Emax => Emax*C^2 > C^2max*E */
|
||||
if (MULT32_32(m3TrackEnergy,correlationM2M3M0M1Square) > MULT32_32(energyM2M3M0M1, m3TrackCorrelationSquare)) {
|
||||
m3TrackCorrelationSquare = correlationM2M3M0M1Square;
|
||||
m3TrackEnergy = energyM2M3M0M1;
|
||||
m1 = j;
|
||||
m0 = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check with currently selected indexes if this one is better */
|
||||
if (MULT32_32(energyMax,m3TrackCorrelationSquare) > MULT32_32(m3TrackEnergy, correlationSquareMax)) {
|
||||
correlationSquareMax = m3TrackCorrelationSquare;
|
||||
energyMax = m3TrackEnergy;
|
||||
if (mIndex==0) {
|
||||
i0 = m0;
|
||||
i1 = m1;
|
||||
i2 = m2;
|
||||
i3 = m3;
|
||||
} else {
|
||||
i0 = m3;
|
||||
i1 = m0;
|
||||
i2 = m1;
|
||||
i3 = m2;
|
||||
}
|
||||
jx = m3Base - 3; /* needed for parameter computation apec 3.8.2 eq62 */
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
mSwitch[0][1]++; mSwitch[1][0]++; /*increment the m3Base into the mSwitch */
|
||||
}
|
||||
|
||||
/* compute the fixedCodebookVector */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
fixedCodebookVector[i] = 0; /* reset the vector */
|
||||
}
|
||||
|
||||
/* set the four pulses, in Q13 */
|
||||
fixedCodebookVector[i0] = SSHL((word16_t)correlationSignalSign[i0], 13);
|
||||
fixedCodebookVector[i1] = SSHL((word16_t)correlationSignalSign[i1], 13);
|
||||
fixedCodebookVector[i2] = SSHL((word16_t)correlationSignalSign[i2], 13);
|
||||
fixedCodebookVector[i3] = SSHL((word16_t)correlationSignalSign[i3], 13);
|
||||
|
||||
/* adapt it according to eq48 */
|
||||
for (i=intPitchDelay; i<L_SUBFRAME; i++) {
|
||||
fixedCodebookVector[i] = MAC16_16_Q14(fixedCodebookVector[i], fixedCodebookVector[i-intPitchDelay], lastQuantizedAdaptativeCodebookGain); /* h[n] = h[n] + β*h[n-T], fixedCodebookVector in Q13, lastQuantizedAdaptativeCodebookGain in Q14 */
|
||||
}
|
||||
|
||||
/* compute the parameters */
|
||||
*fixedCodebookParameter = (uint16_t)( MULT16_16_Q15((word16_t)i0, O2_IN_Q15)
|
||||
+ ((MULT16_16_Q15((word16_t)i1, O2_IN_Q15))<<3)
|
||||
+ ((MULT16_16_Q15((word16_t)i2, O2_IN_Q15))<<6)
|
||||
+ ((((MULT16_16_Q15((word16_t)i3, O2_IN_Q15))<<1)+jx)<<9)
|
||||
);
|
||||
*fixedCodebookPulsesSigns = (uint16_t)((correlationSignalSign[i0]+1)>>1) | /* as in spec 3.8.2 eq61 */
|
||||
(uint16_t)(((correlationSignalSign[i1]+1)>>1)<<1) |
|
||||
(uint16_t)(((correlationSignalSign[i2]+1)>>1)<<2) |
|
||||
(uint16_t)(((correlationSignalSign[i3]+1)>>1)<<3);
|
||||
|
||||
/* compute the fixedCodebook vector convolved with impulse response spec 3.9 eq64 */
|
||||
/* this vector is used in gain quantization but computed here because it's faster doing it having directly the impulses positions */
|
||||
/* eq64 make use of fixedCodebook vector adapted by eq48, using the impulse position(and thus fixed codebook vector before the adaptation) but */
|
||||
/* the impulse response adapted as in eq49 gives the same output */
|
||||
/* reset the vector */
|
||||
for (i=0; i<i0; i++) fixedCodebookVectorConvolved[i] = 0;
|
||||
|
||||
if(correlationSignalSign[i0] > 0) {
|
||||
for(i=i0, j=0; i<L_SUBFRAME; i++, j++) {
|
||||
fixedCodebookVectorConvolved[i] = impulseResponse[j];
|
||||
}
|
||||
} else {
|
||||
for(i=i0, j=0; i<L_SUBFRAME; i++, j++) {
|
||||
fixedCodebookVectorConvolved[i] = -impulseResponse[j];
|
||||
}
|
||||
}
|
||||
|
||||
if(correlationSignalSign[i1] > 0) {
|
||||
for(i=i1, j=0; i<L_SUBFRAME; i++, j++) {
|
||||
fixedCodebookVectorConvolved[i] = ADD16(fixedCodebookVectorConvolved[i], impulseResponse[j]);
|
||||
}
|
||||
} else {
|
||||
for(i=i1, j=0; i<L_SUBFRAME; i++, j++) {
|
||||
fixedCodebookVectorConvolved[i] = SUB16(fixedCodebookVectorConvolved[i], impulseResponse[j]);
|
||||
}
|
||||
}
|
||||
|
||||
if(correlationSignalSign[i2] > 0) {
|
||||
for(i=i2, j=0; i<L_SUBFRAME; i++, j++) {
|
||||
fixedCodebookVectorConvolved[i] = ADD16(fixedCodebookVectorConvolved[i], impulseResponse[j]);
|
||||
}
|
||||
} else {
|
||||
for(i=i2, j=0; i<L_SUBFRAME; i++, j++) {
|
||||
fixedCodebookVectorConvolved[i] = SUB16(fixedCodebookVectorConvolved[i], impulseResponse[j]);
|
||||
}
|
||||
}
|
||||
|
||||
if(correlationSignalSign[i3] > 0) {
|
||||
for(i=i3, j=0; i<L_SUBFRAME; i++, j++) {
|
||||
fixedCodebookVectorConvolved[i] = ADD16(fixedCodebookVectorConvolved[i], impulseResponse[j]);
|
||||
}
|
||||
} else {
|
||||
for(i=i3, j=0; i<L_SUBFRAME; i++, j++) {
|
||||
fixedCodebookVectorConvolved[i] = SUB16(fixedCodebookVectorConvolved[i], impulseResponse[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeImpulseResponseCorrelationMatrix: as in spec 3.8.1 eq51, eq56, eq57*/
|
||||
/* parameters: */
|
||||
/* -(i) impulseResponse : 40 values in Q12 */
|
||||
/* -(i/o) correlationSignal: 40 values in Q12 get absolute value of */
|
||||
/* input as output as specified in spec 3.8.1 */
|
||||
/* -(o) correlationSignalSign : 40 values of -1 or 1 : the sign of */
|
||||
/* the input correlationSignal elements */
|
||||
/* */
|
||||
/* return value: a triangular matrix composed of Phi(i,j) in Q24 */
|
||||
/* where Phi(i,j) = ∑h(n-i)*h(n-j) n in i..39 */
|
||||
/* The matrix is then modified as decribed in eq56 and eq 57 */
|
||||
/* */
|
||||
/* Algorithm : the matrix elements are computed for j<=i */
|
||||
/* due to matrix element definition we have */
|
||||
/* Phi(i,j) = Phi(i+1,j+1) + h(39-i)*h(39-j) */
|
||||
/* - The matrix is computed starting from element Phi(39,x)=h(0)*h(39-x) */
|
||||
/* and adding terms h(39-i)*h(39-j) give all the element of the diagonal */
|
||||
/* up to Phi(39-x,0) */
|
||||
/* - Some diagonals are not computed because not needed : */
|
||||
/* Phi(39,34), Phi(39,29), Phi(39,24), .. Phi(39,4) */
|
||||
/* - The matrix elements signs are then adjusted according to eq56 */
|
||||
/* - The correlationSignal is modified to get absolute values of each */
|
||||
/* element in it. */
|
||||
/* - Matrix elements are then duplicated to make access to them easier */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void computeImpulseResponseCorrelationMatrix(word16_t impulseResponse[], word16_t correlationSignal[], int correlationSignalSign[], word32_t Phi[L_SUBFRAME][L_SUBFRAME])
|
||||
{
|
||||
int i,j,iComp;
|
||||
word32_t acc = 0;
|
||||
uint16_t PhiScaling = 0;
|
||||
int correlationSignalSignInv[L_SUBFRAME];
|
||||
|
||||
/* first compute the diagonal Phi(x,x) : Phi(39,39) = h[0]^2 # Phi(38,38) = Phi(39,39)+h[1]^2 */
|
||||
/* this diagonal must be divided by 2 according to spec 3.8.1 eq57 */
|
||||
for (i=0, iComp=L_SUBFRAME-1; i<L_SUBFRAME; i++, iComp--) { /* i in [0..39], iComp in [39..0] */
|
||||
acc = MAC16_16(acc, impulseResponse[i], impulseResponse[i]); /* impulseResponse in Q12 -> acc in Q24 */
|
||||
Phi[iComp][iComp] = SHR(acc,1); /* divide by 2: eq57*/
|
||||
}
|
||||
|
||||
/* check for possible overflow: Phi will be summed 10 times, so max Phi (by construction Phi[0][0]*2 is the max of Phi-> 2*Phi[0][0]*10 must be < 0x7fff ffff -> Phi[0][0]< 0x06666666 - otherwise scale Phi)*/
|
||||
if (Phi[0][0]>0x6666666) {
|
||||
PhiScaling = 3 - countLeadingZeros((Phi[0][0]<<1) + 0x3333333); /* complement 0xccccccc adding 0x3333333 to shift by one when max(2*Phi[0][0]) is in 0x0fffffff < max < 0xcccccc */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
Phi[i][i] = SHR(Phi[i][i],PhiScaling);
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute all diagonals but the 34, 29, 24, 19, 14, 9 and 4*/
|
||||
for (i=0; i<8; i++) {
|
||||
for (j=0; j<4; j++) {
|
||||
computePhiDiagonal(5*i+j, impulseResponse, Phi, PhiScaling);
|
||||
}
|
||||
}
|
||||
|
||||
/* correlationSignal -> absolute value and get sign (and his inverse in an array) */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
if (correlationSignal[i] >= 0) {
|
||||
correlationSignalSign[i] = 1;
|
||||
correlationSignalSignInv[i] = -1;
|
||||
} else { /* correlationSignal < 0 */
|
||||
correlationSignalSign[i] = -1;
|
||||
correlationSignalSignInv[i] = 1;
|
||||
correlationSignal[i] = -correlationSignal[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* modify the signs according to eq56 */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
int *signOfCorrelationSignalJ;
|
||||
|
||||
if (correlationSignalSign[i]>0) { /* is sign(correlationSignal[i]) is positive, use the correlationSignalSign otherwise the inverted one */
|
||||
signOfCorrelationSignalJ = correlationSignalSign;
|
||||
} else {
|
||||
signOfCorrelationSignalJ = correlationSignalSignInv;
|
||||
}
|
||||
for (j=0; j<=i; j++) { /* multiply by the selected sign the matrix element */
|
||||
/* Note : even the not needed and thus not computed elements are multiplicated... might found other way to do this sign stuff to be more efficient */
|
||||
Phi[i][j] = Phi[i][j] * signOfCorrelationSignalJ[j];
|
||||
}
|
||||
}
|
||||
|
||||
/* duplicate the usefull values to their symetric part to get easier acces to the matrix elements */
|
||||
for (i=0; i<8; i++) {
|
||||
for (j=0; j<4; j++) {
|
||||
int k;
|
||||
int startIndex = 5*i+j;
|
||||
for(k=0; k<=startIndex; k++) {
|
||||
Phi[startIndex-k][L_SUBFRAME-1-k] = Phi[L_SUBFRAME-1-k][startIndex-k];
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute a diagonal of Phi values: start from Phi(39,j) and step Phi(38, j-1) down to Phi(39-j, 0) */
|
||||
/* Phi(i,j) = Phi(i+1,j+1) + h(39-i)*h(39-j) */
|
||||
void computePhiDiagonal(int j, word16_t impulseResponse[], word32_t Phi[L_SUBFRAME][L_SUBFRAME], uint16_t PhiScaling)
|
||||
{
|
||||
word32_t acc = 0;
|
||||
int i=L_SUBFRAME -1;
|
||||
int iComp = 0;
|
||||
int jComp = L_SUBFRAME - 1 - j;
|
||||
|
||||
if (PhiScaling == 0) {
|
||||
for (; j>=0; j--, i--, jComp++, iComp++) {
|
||||
acc = MAC16_16(acc, impulseResponse[iComp], impulseResponse[jComp]);
|
||||
Phi[i][j] = acc;
|
||||
}
|
||||
} else {
|
||||
for (; j>=0; j--, i--, jComp++, iComp++) {
|
||||
acc = MAC16_16(acc, impulseResponse[iComp], impulseResponse[jComp]);
|
||||
Phi[i][j] = SHR(acc,PhiScaling);
|
||||
}
|
||||
}
|
||||
}
|
41
bcg729/src/fixedCodebookSearch.h
Normal file
41
bcg729/src/fixedCodebookSearch.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef FIXEDCODEBOOKSEARCH_H
|
||||
#define FIXEDCODEBOOKSEARCH_H
|
||||
/*****************************************************************************/
|
||||
/* fixedCodebookSearch: compute fixed codebook parameters (codeword and sign)*/
|
||||
/* compute also fixed codebook vector as in spec 3.8.1 */
|
||||
/* parameters: */
|
||||
/* -(i) targetSignal: 40 values as in spec A.3.6 in Q0 */
|
||||
/* -(i) impulseResponse: 40 values as in spec A.3.5 in Q12 */
|
||||
/* -(i) intPitchDelay: current integer pitch delay */
|
||||
/* -(i) lastQuantizedAdaptativeCodebookGain: previous subframe pitch */
|
||||
/* gain quantized in Q14 */
|
||||
/* -(i) filteredAdaptativeCodebookVector : 40 values in Q0 */
|
||||
/* -(i) adaptativeCodebookGain : in Q14 */
|
||||
/* -(o) fixedCodebookParameter */
|
||||
/* -(o) fixedCodebookPulsesSigns */
|
||||
/* -(o) fixedCodebookVector : 40 values as in spec 3.8, eq45 in Q13 */
|
||||
/* -(o) fixedCodebookVectorConvolved : 40 values as in spec 3.9, eq64 */
|
||||
/* in Q12. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void fixedCodebookSearch(word16_t targetSignal[], word16_t impulseResponse[], int16_t intPitchDelay, word16_t lastQuantizedAdaptativeCodebookGain, word16_t filteredAdaptativeCodebookVector[], word16_t adaptativeCodebookGain,
|
||||
uint16_t *fixedCodebookParameter, uint16_t *fixedCodebookPulsesSigns, word16_t fixedCodebookVector[], word16_t fixedCodebookVectorConvolved[]);
|
||||
#endif /* ifndef FIXEDCODEBOOKSEARCH_H */
|
138
bcg729/src/fixedPointMacros.h
Normal file
138
bcg729/src/fixedPointMacros.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef FIXEDPOINTMACROS_H
|
||||
#define FIXEDPOINTMACROS_H
|
||||
|
||||
#define EXTEND32(x) ((word32_t)(x))
|
||||
#define NEG16(x) (-(x))
|
||||
#define NEG32(x) (-(x))
|
||||
#define NEG64(x) (-(x))
|
||||
|
||||
/*** shifts ***/
|
||||
#define SHR(a,shift) ((a) >> (shift))
|
||||
#define SHL(a,shift) ((word32_t)(a) << (shift))
|
||||
/* Signed shift left, C standard claims shifting left a negative value lead to undetermined status,
|
||||
* recent compiler shall not have any problem, but just in case, shift a positive value and back */
|
||||
#define SSHL(a,shift) ((a < 0)?(NEG32((word32_t)(NEG32(a)) << (shift))):((word32_t)(a) << (shift)))
|
||||
#define USHL(a,shift) ((uword32_t)(a) << (shift))
|
||||
/* shift right with rounding: used to extract the integer value of a Qa number */
|
||||
#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
|
||||
/* shift right with checking on sign of shift value */
|
||||
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
|
||||
#define SVSHR32(a, shift) (((shift)>0) ? SHR32((word32_t)(a), shift) : SSHL((word32_t)(a), -(shift)))
|
||||
#define SHR16(a,shift) ((a) >> (shift))
|
||||
#define SHL16(a,shift) ((a) << (shift))
|
||||
#define SHR32(a,shift) ((a) >> (shift))
|
||||
#define SHL32(a,shift) ((a) << (shift))
|
||||
#define SHR64(a,shift) ((a) >> (shift))
|
||||
#define SHL64(a,shift) ((a) << (shift))
|
||||
#define SSHL64(a,shift) ((a < 0)?(NEG64((word64_t)(NEG64(a)) << (shift))):((word64_t)(a) << (shift)))
|
||||
|
||||
/* avoid overflows: a+1 is used to check on negative value because range of a 2n signed bits int is -2pow(n) - 2pow(n)-1 */
|
||||
/* SATURATE Macro shall be called with MAXINT(nbits). Ex: SATURATE(x,MAXINT16) with MAXINT16 defined to 2pow(16) - 1 */
|
||||
#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a+1) ? -(a+1) : (x)))
|
||||
/* same but for unsigned values only */
|
||||
#define USATURATE(x,a) ((x)>(a) ? (a) : (x))
|
||||
|
||||
/* absolute value */
|
||||
#define ABS(a) (((a)>0) ? (a) : -(a))
|
||||
|
||||
/*** add and sub ***/
|
||||
#define ADD16(a,b) ((word16_t)((word16_t)(a)+(word16_t)(b)))
|
||||
#define SUB16(a,b) ((word16_t)(a)-(word16_t)(b))
|
||||
#define ADD32(a,b) ((word32_t)(a)+(word32_t)(b))
|
||||
#define UADD32(a,b) ((uword32_t)(a)+(uword32_t)(b))
|
||||
#define SUB32(a,b) ((word32_t)(a)-(word32_t)(b))
|
||||
|
||||
/*** Multiplications/Accumulations ***/
|
||||
/* WARNING: MULT16_32_QX use MULT16_16 macro but the first multiplication must actually be a 16bits * 32bits with result on 32 bits and not a 16*16 */
|
||||
/* MULT16_16 is then implemented here as a 32*32 bits giving result on 32 bits */
|
||||
#define MULT16_16(a,b) ((word32_t)((word32_t)(a))*((word32_t)(b)))
|
||||
#define MULT16_32(a,b) ((word32_t)((word16_t)(a))*((word32_t)(b)))
|
||||
#define UMULT16_16(a,b) ((uword32_t)((word32_t)(a))*((word32_t)(b)))
|
||||
#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
|
||||
#define UMAC16_16(c,a,b) (UADD32((c),UMULT16_16((a),(b))))
|
||||
#define MSU16_16(c,a,b) (SUB32((c),MULT16_16((a),(b))))
|
||||
#define DIV32(a,b) (((word32_t)(a))/((word32_t)(b)))
|
||||
#define UDIV32(a,b) (((uword32_t)(a))/((uword32_t)(b)))
|
||||
|
||||
/* Q3 operations */
|
||||
#define MULT16_16_Q3(a,b) (SHR(MULT16_16((a),(b)),3))
|
||||
#define MULT16_32_Q3(a,b) ADD32(MULT16_16((a),SHR((b),3)), SHR(MULT16_16((a),((b)&0x00000007)),3))
|
||||
#define MAC16_16_Q3(c,a,b) ADD32(c,MULT16_16_Q3(a,b))
|
||||
|
||||
/* Q4 operations */
|
||||
#define MULT16_16_Q4(a,b) (SHR(MULT16_16((a),(b)),4))
|
||||
#define UMULT16_16_Q4(a,b) (SHR(UMULT16_16((a),(b)),4))
|
||||
#define UMAC16_16_Q4(c,a,b) ADD32(c,UMULT16_16_Q4(a,b))
|
||||
#define MAC16_16_Q4(c,a,b) ADD32(c,MULT16_16_Q4(a,b))
|
||||
|
||||
/* Q11 operations */
|
||||
#define MULT16_16_Q11(a,b) (SHR(MULT16_16((a),(b)),11))
|
||||
#define MULT16_16_P11(a,b) (SHR(ADD32(1024,MULT16_16((a),(b))),11))
|
||||
|
||||
/* Q12 operations */
|
||||
#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12))
|
||||
#define MAC16_32_Q12(c,a,b) ADD32(c,MULT16_32_Q12(a,b))
|
||||
#define MULT16_16_Q12(a,b) (SHR(MULT16_16((a),(b)),12))
|
||||
#define MAC16_16_Q12(c,a,b) ADD32(c,MULT16_16_Q12(a,b))
|
||||
#define MSU16_16_Q12(c,a,b) SUB32(c,MULT16_16_Q12(a,b))
|
||||
|
||||
/* Q13 operations */
|
||||
#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13))
|
||||
#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13))
|
||||
#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13))
|
||||
#define MAC16_16_Q13(c,a,b) ADD32(c,MULT16_16_Q13(a,b))
|
||||
#define MAC16_32_Q13(c,a,b) ADD32(c,MULT16_32_Q13(a,b))
|
||||
|
||||
/* Q14 operations */
|
||||
#define MULT16_32_P14(a,b) ADD32(MULT16_16((a),SHR((b),14)), PSHR(MULT16_16((a),((b)&0x00003fff)),14))
|
||||
#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14))
|
||||
#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14))
|
||||
#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14))
|
||||
#define MAC16_16_Q14(c,a,b) ADD32(c,MULT16_16_Q14(a,b))
|
||||
#define MSU16_16_Q14(c,a,b) SUB32(c,MULT16_16_Q14(a,b))
|
||||
#define MAC16_32_Q14(c,a,b) ADD32(c,MULT16_32_Q14(a,b))
|
||||
|
||||
/* Q15 operations */
|
||||
#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15))
|
||||
#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15))
|
||||
#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
|
||||
#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))
|
||||
#define MAC16_32_P15(c,a,b) ADD32(c,MULT16_32_P15(a,b))
|
||||
|
||||
/* 64 bits operations */
|
||||
#define ADD64(a,b) ((word64_t)(a)+(word64_t)(b))
|
||||
#define SUB64(a,b) ((word64_t)(a)-(word32_t)(b))
|
||||
#define ADD64_32(a,b) ((word64_t)(a)+(word32_t)(b))
|
||||
#define MULT32_32(a,b) ((word64_t)((word64_t)(a)*((word64_t)(b))))
|
||||
#define DIV64(a,b) ((word64_t)(a)/(word64_t)(b))
|
||||
#define MAC64(c,a,b) ((word64_t)c+(word64_t)((word64_t)a*(word64_t)b))
|
||||
|
||||
/* Divisions: input numbers with similar scale(Q) output according to operation. Warning: Make use of 64 bits variables */
|
||||
#define DIV32_32_Q24(a,b) (((word64_t)(a)<<24)/((word32_t)(b)))
|
||||
#define DIV32_32_Q27(a,b) ((SSHL64((word64_t)(a),27))/((word32_t)(b)))
|
||||
#define DIV32_32_Q31(a,b) ((SSHL64((word64_t)(a),31))/((word32_t)(b)))
|
||||
|
||||
#define MULT32_32_Q23(a,b) ((word32_t)(SHR64(((word64_t)a*(word64_t)b),23)))
|
||||
|
||||
#define MULT32_32_Q31(a,b) ((word32_t)(SHR64(((word64_t)a*(word64_t)b),31)))
|
||||
#define MAC32_32_Q31(c,a,b) ADD32(c,MULT32_32_Q31(a,b))
|
||||
|
||||
#endif /* ifndef FIXEDPOINTMACROS_H */
|
50
bcg729/src/floatingPointMacros.h
Normal file
50
bcg729/src/floatingPointMacros.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef FLOATINGPOINTMACROS_H
|
||||
#define FLOATINGPOINTMACROS_H
|
||||
|
||||
#define EXTEND32(x) (x)
|
||||
|
||||
/* shifts */
|
||||
#define SHR(a,shift) (a)
|
||||
#define SHL(a,shift) (a)
|
||||
#define PSHR(a,shift) (a)
|
||||
|
||||
/* avoid overflows: nothing to do for floats */
|
||||
#define SATURATE(x,a) (x)
|
||||
|
||||
/* add and sub */
|
||||
#define ADD16(a,b) ((a)+(b))
|
||||
#define SUB16(a,b) ((a)-(b))
|
||||
#define ADD32(a,b) ((a)+(b))
|
||||
#define SUB32(a,b) ((a)-(b))
|
||||
|
||||
|
||||
/* Multiplications/Accumulations */
|
||||
#define MULT16_16(a,b) ((word32_t)(a)*(word32_t)(b))
|
||||
#define MAC16_16(c,a,b) ((c)+MULT16_16((a),(b)))
|
||||
#define MULT16_32(a,b) ((a)*(b))
|
||||
#define MAC16_32(c,a,b) ((c)+(a)*(b))
|
||||
|
||||
/* Q12 operations */
|
||||
#define MULT16_32_Q12(a,b) MULT16_32(a,b)
|
||||
#define MAC16_32_Q12(c,a,b) MAC16_32(c,a,b)
|
||||
|
||||
|
||||
#endif /* ifndef FLOATINGPOINTMACROS_H */
|
314
bcg729/src/g729FixedPointMath.h
Normal file
314
bcg729/src/g729FixedPointMath.h
Normal file
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef G729FIXEDPOINTMATH_H
|
||||
#define G729FIXEDPOINTMATH_H
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* This library provides the following functions */
|
||||
/* */
|
||||
/* g729Log2_Q0Q16 : Logarithm base 2 */
|
||||
/* g729Exp2_Q11Q16 : Exponentiel base 2 */
|
||||
/* g729Sqrt_Q0Q7 : Square Root */
|
||||
/* g729Cos_Q13Q15 : Cosine */
|
||||
/* g729Atan_Q15Q13 : Arc Tangent */
|
||||
/* g729Asin_Q15Q13 : Arc Sine */
|
||||
/* g729Acos_Q15Q13 : Arc Cosine */
|
||||
/* */
|
||||
/* Extention QxxQyy stands for input in Qxx output in Qyy */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
|
||||
/* constants defined in Q16: actual values:
|
||||
KL0 = -2.059978
|
||||
KL1 = 5.770780
|
||||
KL2 = -3.847187
|
||||
KL3 = 1.139907
|
||||
*/
|
||||
#define KL0 -135003
|
||||
#define KL1 378194
|
||||
#define KL2 -252129
|
||||
#define KL3 74705
|
||||
/*****************************************************************************/
|
||||
/* g729Log2_Q0Q16 : logarithm base 2, frac part computed from Taylor serie */
|
||||
/* paremeters: */
|
||||
/* -(i) x : 32 bits integer in Q0, expected to be>0(not checked here) */
|
||||
/* return value: */
|
||||
/* - the log2(x) in Q16 on 32 bits */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static BCG729_INLINE word32_t g729Log2_Q0Q16(word32_t x)
|
||||
{
|
||||
/* first get the integer part and put it in the 16 MSB of return value (in Q16) */
|
||||
uint16_t leadingZeros = countLeadingZeros(x); /* note: MSB is excluded as considered as sign bit */
|
||||
word32_t retValue = SHL32(SUB16(30,leadingZeros), 16);
|
||||
|
||||
/* now shift the number to have it on this form 01XX XXXX XXXX XXXX, and keep only 16 bits -> consider it as a number in range [0.5, 1[ in Q0.15 */
|
||||
word16_t acc = (word16_t)VSHR32(x, 16-leadingZeros);
|
||||
/* So calling int the integer part of the log2, we have: */
|
||||
/* int = 30 - leadingZeros */
|
||||
/* acc = x*2^(leadingZeros - 16) */
|
||||
/* acc = x*2^(14 - int) */
|
||||
/* considering the content of acc as a Q15 number eq *2^-15*/
|
||||
/* acc = x*2^(14 -int)*2^-15 */
|
||||
/* acc = x*2^(-1 -int) */
|
||||
/* log2(acc) = log2(x) -1 - int */
|
||||
/* log2(x) ~= -3.059978 + 5.770780*x - 3.847187*x^2 + 1.139907*x^3 (for .5 < x < 1) Taylor Serie log2(x) at x near 0.75 */
|
||||
/* log2(x) + 1 = -2.059978 + x*(5.770780 +x(-3.847187 + 1.139907*x)) */
|
||||
/* with coeff in Q16 : */
|
||||
/* log2(acc) +1 = log2(x) - int = */
|
||||
/* log2(acc) +1 = -135003 +acc*(378194 +acc*(-252129 + acc*74705)) acc in Q15 and constants in Q16 -> final result will be log2(x) -int in Q16(on 32 bits) */
|
||||
word32_t acc32 = ADD32(KL0, MULT16_32_Q15(acc, ADD32(KL1, MULT16_32_Q15(acc, ADD32(KL2, MULT16_32_Q15(acc, KL3))))));
|
||||
|
||||
return ADD32(retValue,acc32);
|
||||
}
|
||||
|
||||
/* constants defined in Q15: actual values:
|
||||
E0 = 1
|
||||
E1 = log(2)
|
||||
E2 = 3-4*log(2)
|
||||
E3 = 3*log(2) - 2
|
||||
*/
|
||||
#define E0 16384
|
||||
#define E1 11356
|
||||
#define E2 3726
|
||||
#define E3 1301
|
||||
/*****************************************************************************/
|
||||
/* g729Exp2_Q11Q16 : Exponentielle base 2 */
|
||||
/* paremeters: */
|
||||
/* -(i) x : 16 bits integer in Q11 */
|
||||
/* return value: */
|
||||
/* - exp2(x) in Q16 on 32 bits */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static BCG729_INLINE word32_t g729Exp2_Q11Q16(word16_t x)
|
||||
{
|
||||
int integer;
|
||||
word16_t frac;
|
||||
integer = SHR16(x,11);
|
||||
if (integer>14) {
|
||||
return 0x7fffffff;
|
||||
} else {
|
||||
if (integer < -15) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
frac = SHL16(x-SHL16(integer,11),3);
|
||||
frac = ADD16(E0, MULT16_16_Q14(frac, ADD16(E1, MULT16_16_Q14(frac, ADD16(E2 , MULT16_16_Q14(E3,frac))))));
|
||||
return VSHR32(EXTEND32(frac), -integer-2);
|
||||
}
|
||||
|
||||
/* constants in Q14 */
|
||||
#define C0 3634
|
||||
#define C1 21173
|
||||
#define C2 -12627
|
||||
#define C3 4204
|
||||
/*****************************************************************************/
|
||||
/* g729Sqrt_Q0Q7 : Square root */
|
||||
/* paremeters: */
|
||||
/* -(i) x : 32 bits unsigned integer in Q0 */
|
||||
/* return value: */
|
||||
/* - sqrt(x) in Q7 on 32 bits signed integer */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static BCG729_INLINE word32_t g729Sqrt_Q0Q7(uword32_t x)
|
||||
{
|
||||
int k;
|
||||
word32_t rt;
|
||||
|
||||
if (x==0) return 0;
|
||||
/* set x in Q14 in range [0.25,1[ */
|
||||
k = (19-unsignedCountLeadingZeros(x))>>1;
|
||||
x = VSHR32(x, k*2); /* x = x.2^-2k */
|
||||
|
||||
/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25659*x^3 (for .25 < x < 1) */
|
||||
/* consider x as in Q14: y = x.2^(-2k-14) -> and give sqrt(y).2^14 = sqrt(x).2^(-k-7).2^14 */
|
||||
rt = ADD16(C0, MULT16_16_Q14(x, ADD16(C1, MULT16_16_Q14(x, ADD16(C2, MULT16_16_Q14(x, (C3))))))); /* rt = sqrt(x).2^(7-k)*/
|
||||
rt = VSHR32(rt,-k); /* rt = sqrt(x).2^7 */
|
||||
return rt;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* g729InvSqrt_Q0Q31 : Inverse Square root(1/Sqrt(x) */
|
||||
/* x is not tested to be >=1, shall be done by caller function */
|
||||
/* paremeters: */
|
||||
/* -(i) x : 32 bits integer in Q0 in range [1, MAXINT32] */
|
||||
/* return value: */
|
||||
/* - 1/sqrt(x) in Q31 on 32 bits in range [43341/2^31, MAXINT32] */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static BCG729_INLINE word32_t g729InvSqrt_Q0Q31(word32_t x)
|
||||
{
|
||||
if (x==1) return MAXINT32;
|
||||
return (word32_t)(DIV32_32_Q24(g729Sqrt_Q0Q7(x),x)); /* sqrt(x) in Q7 + Q24 -> Q31 */
|
||||
}
|
||||
|
||||
/* constants Q0.15 */
|
||||
#define Kcos1 32768
|
||||
#define Kcos2 -16384
|
||||
#define Kcos3 1365
|
||||
#define Kcos4 -46
|
||||
|
||||
#define Ksin1 32768
|
||||
#define Ksin2 -5461
|
||||
#define Ksin3 273
|
||||
#define Ksin4 -7
|
||||
|
||||
/*****************************************************************************/
|
||||
/* g729Cos_Q13Q15 : Cosine fonction in [0, Pi] */
|
||||
/* x is not tested to be in correct range */
|
||||
/* paremeters: */
|
||||
/* -(i) x : 16 bits integer in Q13 in range [0, Pi(25736)] */
|
||||
/* return value: */
|
||||
/* - cos(x) in Q0.15 on 16 bits in range [-1, 1[ */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static BCG729_INLINE word16_t g729Cos_Q13Q15(word16_t x)
|
||||
{
|
||||
/* input var x in Q2.13 and in ]0, Pi[ */
|
||||
word16_t x2,xScaled;
|
||||
if (x<12868) {
|
||||
if (x<6434) { /* x in ]0, Pi/4[ */
|
||||
x2 = MULT16_16_P11(x,x); /* in Q0.15 */
|
||||
return SATURATE(ADD32(Kcos1, MULT16_16_P15(x2, ADD32(Kcos2, MULT16_16_P15(x2, ADD32(Kcos3, MULT16_16_P15(Kcos4, x2)))))), MAXINT16); /* return cos x, must saturate if return value is +1 */
|
||||
} else {/* x in [Pi/4, Pi/2[ */
|
||||
x = SUB16(12868,x); /* x = pi/2 -x, x in [0, Pi/4] in Q0.13 */
|
||||
x2 = MULT16_16_P11(x,x); /* in Q0.15 */
|
||||
return (MULT16_16_P13(x,ADD32(Ksin1, MULT16_16_P15(x2, ADD32(Ksin2, MULT16_16_P15(x2, ADD32(Ksin3, MULT16_16_P15(Ksin4, x2)))))))); /* return cos x as sin(pi/2 -x) */
|
||||
}
|
||||
} else { /* x in [Pi/2, Pi[ */
|
||||
xScaled = SUB16(25736,x); /* xScaled = Pi - x -> in [0,Pi/2] with cos(Pi-x) = -cos(x) and sin(Pi-x) = */
|
||||
if (x<19302) { /* x in [Pi/2, 3Pi/4], xScaled in [Pi/4, Pi/2] */
|
||||
xScaled = SUB16(12868,xScaled); /* xScaled = pi/2 - xScaled = x - Pi/2, xScaled in [0, Pi/4] in Q0.13 */
|
||||
x2 = MULT16_16_P11(xScaled,xScaled); /* in Q0.15 */
|
||||
return (MULT16_16_P13(-xScaled,ADD32(Ksin1, MULT16_16_P15(x2, ADD32(Ksin2, MULT16_16_P15(x2, ADD32(Ksin3, MULT16_16_P15(Ksin4, x2)))))))); /* return cos x as -sin(x - Pi/2) */
|
||||
} else { /* x in [3Pi/4, Pi[ -> xScaled in [0, Pi/4], cos(xScaled) = -cos(x) */
|
||||
x2 = MULT16_16_P11(xScaled,xScaled); /* in Q0.15 */
|
||||
return (SUB32(-Kcos1, MULT16_16_P15(x2, ADD32(Kcos2, MULT16_16_P15(x2, ADD32(Kcos3, MULT16_16_P15(Kcos4, x2))))))); /* return cos x as -cos(Pi -x) */
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/* KPI6 = pi/6 in Q15 */
|
||||
#define KPI6 17157
|
||||
/* KtanPI6 = tan(pi/6) in Q15 */
|
||||
#define KtanPI6 18919
|
||||
/* KtanPI12 = tan(pi/12) in Q15 */
|
||||
#define KtanPI12 8780
|
||||
|
||||
/* B = 0.257977658811405 in Q15 */
|
||||
#define atanB 8453
|
||||
/* C = 0.59120450521312 in Q15 */
|
||||
#define atanC 19373
|
||||
|
||||
/*****************************************************************************/
|
||||
/* g729Atan_Q15Q13: ArcTangent fonction in [-2^16, 2^16[ */
|
||||
/* paremeters: */
|
||||
/* -(i) x : 32 bits integer in Q15 in range [-2^16, 2^16[ */
|
||||
/* return value: */
|
||||
/* - atan(x) in Q2.13 on 16 bits in range ]-Pi/2(12868), Pi/2(12868)[ */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static BCG729_INLINE word16_t g729Atan_Q15Q13(word32_t x)
|
||||
{
|
||||
/* constants for rational polynomial */
|
||||
word32_t angle;
|
||||
word16_t x2;
|
||||
int highSegment = 0;
|
||||
int sign = 0;
|
||||
int complement = 0;
|
||||
|
||||
/* make argument positive */
|
||||
if (x < 0) {
|
||||
x = NEG16(x);
|
||||
sign = 1;
|
||||
}
|
||||
|
||||
/* limit argument to 0..1 */
|
||||
if(x > ONE_IN_Q15){
|
||||
complement = 1;
|
||||
x = DIV32(ONE_IN_Q30, x); /* 1/x in Q15 */
|
||||
}
|
||||
|
||||
/* determine segmentation */
|
||||
if(x > KtanPI12){
|
||||
highSegment = 1;
|
||||
/* x = (x - k)/(1 + k*x); */
|
||||
x = DIV32(SSHL(SUB32(x, KtanPI6), 15), ADD32(MULT16_16_Q15(KtanPI6, x), ONE_IN_Q15));
|
||||
}
|
||||
|
||||
/* argument is now < tan(15 degrees) */
|
||||
/* approximate the function */
|
||||
x2 = MULT16_16_Q15(x,x);
|
||||
angle = DIV32(MULT16_16(x, ADD32(ONE_IN_Q15, MULT16_16_Q15(atanB, x2))), ADD32(ONE_IN_Q15, MULT16_16_Q15(atanC, x2))); /* ang = x*(1 + B*x2)/(1 + C*x2) */
|
||||
|
||||
/* now restore offset if needed */
|
||||
if(highSegment) {
|
||||
angle += KPI6;
|
||||
}
|
||||
|
||||
/* restore complement if needed */
|
||||
if(complement) {
|
||||
angle = SUB32(HALF_PI_Q15, angle);
|
||||
}
|
||||
|
||||
/* set result in Q13 */
|
||||
angle = PSHR(angle, 2);
|
||||
|
||||
/* restore sign if needed */
|
||||
if(sign) {
|
||||
return NEG16(angle);
|
||||
} else {
|
||||
return angle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* g729Asin_Q15Q13: ArcSine fonction */
|
||||
/* paremeters: */
|
||||
/* -(i) x : 16 bits integer in Q15 in range ]-1, 1[ */
|
||||
/* return value: */
|
||||
/* - asin(x) in Q2.13 on 16 bits in range ]-Pi/2(12868), Pi/2(12868)[ */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static BCG729_INLINE word16_t g729Asin_Q15Q13(word16_t x)
|
||||
{
|
||||
return g729Atan_Q15Q13(DIV32(SSHL(x,15), PSHR(g729Sqrt_Q0Q7(SUB32(ONE_IN_Q30, MULT16_16(x,x))),7))); /* atan(x/sqrt(1.0 - x*x)) */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* g729Acos_Q15Q13: ArcCosine fonction */
|
||||
/* paremeters: */
|
||||
/* -(i) x : 16 bits integer in Q15 in range ]-1, 1[ */
|
||||
/* return value: */
|
||||
/* - acos(x) in Q2.13 on 16 bits in range ]0, Pi(25736)[ */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static BCG729_INLINE word16_t g729Acos_Q15Q13(word16_t x)
|
||||
{
|
||||
return(HALF_PI_Q13 - g729Asin_Q15Q13(x));
|
||||
}
|
||||
|
||||
#endif /* ifndef G729FIXEDPOINTMATH_H */
|
229
bcg729/src/gainQuantization.c
Normal file
229
bcg729/src/gainQuantization.c
Normal file
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
#include "codebooks.h"
|
||||
|
||||
#include "gainQuantization.h"
|
||||
|
||||
void initGainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext)
|
||||
{
|
||||
/*init previousGainPredictionError to -14 in Q10 */
|
||||
encoderChannelContext->previousGainPredictionError[0] = -14336;
|
||||
encoderChannelContext->previousGainPredictionError[1] = -14336;
|
||||
encoderChannelContext->previousGainPredictionError[2] = -14336;
|
||||
encoderChannelContext->previousGainPredictionError[3] = -14336;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* gainQuantization : compute quantized adaptative and fixed codebooks gains */
|
||||
/* spec 3.9 */
|
||||
/* parameters: */
|
||||
/* -(i/o) encoderChannelContext : the channel context data */
|
||||
/* -(i) targetSignal: 40 values in Q0, x in eq63 */
|
||||
/* -(i) filteredAdaptativeCodebookVector: 40 values in Q0, y in eq63 */
|
||||
/* -(i) convolvedFixedCodebookVector: 40 values in Q12, z in eq63 */
|
||||
/* -(i) fixedCodebookVector: 40 values in Q13 */
|
||||
/* -(i) xy in Q0 on 64 bits term of eq63 computed previously */
|
||||
/* -(i) yy in Q0 on 64 bits term of eq63 computed previously */
|
||||
/* -(o) quantizedAdaptativeCodebookGain : in Q14 */
|
||||
/* -(o) quantizedFixedCodebookGain : in Q1 */
|
||||
/* -(o) gainCodebookStage1 : GA parameter value (3 bits) */
|
||||
/* -(o) gainCodebookStage2 : GB parameter value (4 bits) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void gainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, word16_t targetSignal[], word16_t filteredAdaptativeCodebookVector[], word16_t convolvedFixedCodebookVector[], word16_t fixedCodebookVector[], word64_t xy64, word64_t yy64,
|
||||
word16_t *quantizedAdaptativeCodebookGain, word16_t *quantizedFixedCodebookGain, uint16_t *gainCodebookStage1, uint16_t *gainCodebookStage2)
|
||||
{
|
||||
int i,j;
|
||||
word64_t xz64=0, yz64=0, zz64=0;
|
||||
word32_t xy;
|
||||
word32_t yy;
|
||||
word32_t xz;
|
||||
word32_t yz;
|
||||
word32_t zz;
|
||||
uint16_t minNormalization = 31;
|
||||
uint16_t currentNormalization;
|
||||
word32_t bestAdaptativeCodebookGain, bestFixedCodebookGain;
|
||||
word64_t denominator;
|
||||
word16_t predictedFixedCodebookGain;
|
||||
uint16_t indexBaseGa=0;
|
||||
uint16_t indexBaseGb=0;
|
||||
uint16_t indexGa=0, indexGb=0;
|
||||
word64_t distanceMin = MAXINT64;
|
||||
|
||||
/*** compute spec 3.9 eq63 terms first on 64 bits and then scale them if needed to fit on 32 ***/
|
||||
/* Xy64 and Yy64 already computed during adaptativeCodebookGain computation */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
xz64 = MAC64(xz64, targetSignal[i], convolvedFixedCodebookVector[i]); /* in Q12 */
|
||||
yz64 = MAC64(yz64, filteredAdaptativeCodebookVector[i], convolvedFixedCodebookVector[i]); /* in Q12 */
|
||||
zz64 = MAC64(zz64, convolvedFixedCodebookVector[i], convolvedFixedCodebookVector[i]); /* in Q24 */
|
||||
}
|
||||
|
||||
/* now scale this terms to have them fit on 32 bits - terms Xy, Xz and Yz shall fit on 31 bits because used in eq63 with a factor 2 */
|
||||
xy = SHR64(((xy64<0)?-xy64:xy64),30);
|
||||
yy = SHR64(yy64,31);
|
||||
xz = SHR64(((xz64<0)?-xz64:xz64),30);
|
||||
yz = SHR64(((yz64<0)?-yz64:yz64),30);
|
||||
zz = SHR64(zz64,31);
|
||||
|
||||
currentNormalization = countLeadingZeros(xy);
|
||||
if (currentNormalization<minNormalization) {
|
||||
minNormalization = currentNormalization;
|
||||
}
|
||||
currentNormalization = countLeadingZeros(xz);
|
||||
if (currentNormalization<minNormalization) {
|
||||
minNormalization = currentNormalization;
|
||||
}
|
||||
currentNormalization = countLeadingZeros(yz);
|
||||
if (currentNormalization<minNormalization) {
|
||||
minNormalization = currentNormalization;
|
||||
}
|
||||
currentNormalization = countLeadingZeros(yy);
|
||||
if (currentNormalization<minNormalization) {
|
||||
minNormalization = currentNormalization;
|
||||
}
|
||||
currentNormalization = countLeadingZeros(zz);
|
||||
if (currentNormalization<minNormalization) {
|
||||
minNormalization = currentNormalization;
|
||||
}
|
||||
|
||||
if (minNormalization<31) { /* we shall normalise, values are over 32 bits */
|
||||
minNormalization = 31 - minNormalization;
|
||||
xy = (word32_t)SHR64(xy64, minNormalization);
|
||||
yy = (word32_t)SHR64(yy64, minNormalization);
|
||||
xz = (word32_t)SHR64(xz64, minNormalization);
|
||||
yz = (word32_t)SHR64(yz64, minNormalization);
|
||||
zz = (word32_t)SHR64(zz64, minNormalization);
|
||||
|
||||
} else { /* no need to normalise, values already fit on 32 bits, just cast them */
|
||||
xy = (word32_t)xy64; /* in Q0 */
|
||||
yy = (word32_t)yy64; /* in Q0 */
|
||||
xz = (word32_t)xz64; /* in Q12 */
|
||||
yz = (word32_t)yz64; /* in Q12 */
|
||||
zz = (word32_t)zz64; /* in Q24 */
|
||||
}
|
||||
|
||||
/*** compute the best gains minimizinq eq63 ***/
|
||||
/* Note this bestgain computation is not at all described in the spec, got it from ITU code */
|
||||
/* bestAdaptativeCodebookGain = (zz.xy - xz.yz) / (yy*zz) - yz^2) */
|
||||
/* bestfixedCodebookGain = (yy*xz - xy*yz) / (yy*zz) - yz^2) */
|
||||
/* best gain are computed in Q9 and Q2 and fits on 16 bits */
|
||||
denominator = MAC64(MULT32_32(yy, zz), -yz, yz); /* (yy*zz) - yz^2) in Q24 (always >= 0)*/
|
||||
/* avoid division by zero */
|
||||
if (denominator==0) { /* consider it to be one */
|
||||
bestAdaptativeCodebookGain = (word32_t)(SHR64(MAC64(MULT32_32(zz, xy), -xz, yz), 15)); /* MAC in Q24 -> Q9 */
|
||||
bestFixedCodebookGain = (word32_t)(SHR64(MAC64(MULT32_32(yy, xz), -xy, yz), 10)); /* MAC in Q12 -> Q2 */
|
||||
} else {
|
||||
/* bestAdaptativeCodebookGain in Q9 */
|
||||
uint16_t numeratorNorm;
|
||||
word64_t numerator = MAC64(MULT32_32(zz, xy), -xz, yz); /* in Q24 */
|
||||
/* check if we can shift it by 9 without overflow as the bestAdaptativeCodebookGain in computed in Q9 */
|
||||
word32_t numeratorH = (word32_t)(SHR64(numerator,32));
|
||||
numeratorH = (numeratorH>0)?numeratorH:-numeratorH;
|
||||
numeratorNorm = countLeadingZeros(numeratorH);
|
||||
if (numeratorNorm >= 9) {
|
||||
bestAdaptativeCodebookGain = (word32_t)(DIV64(SSHL64(numerator,9), denominator)); /* bestAdaptativeCodebookGain in Q9 */
|
||||
} else {
|
||||
word64_t shiftedDenominator = SHR64(denominator, 9-numeratorNorm);
|
||||
if (shiftedDenominator>0) { /* can't shift left by 9 the numerator, can we shift right by 9-numeratorNorm the denominator without hiting 0 */
|
||||
bestAdaptativeCodebookGain = (word32_t)(DIV64(SHL64(numerator, numeratorNorm),shiftedDenominator)); /* bestAdaptativeCodebookGain in Q9 */
|
||||
} else {
|
||||
bestAdaptativeCodebookGain = SHL((word32_t)(DIV64(SHL64(numerator, numeratorNorm), denominator)), 9-numeratorNorm); /* shift left the division result to reach Q9 */
|
||||
}
|
||||
}
|
||||
|
||||
numerator = MAC64(MULT32_32(yy, xz), -xy, yz); /* in Q12 */
|
||||
/* check if we can shift it by 14(it's in Q12 and denominator in Q24) without overflow as the bestFixedCodebookGain in computed in Q2 */
|
||||
numeratorH = (word32_t)(SHR64(numerator,32));
|
||||
numeratorH = (numeratorH>0)?numeratorH:-numeratorH;
|
||||
numeratorNorm = countLeadingZeros(numeratorH);
|
||||
|
||||
if (numeratorNorm >= 14) {
|
||||
bestFixedCodebookGain = (word32_t)(DIV64(SSHL64(numerator,14), denominator));
|
||||
} else {
|
||||
word64_t shiftedDenominator = SHR64(denominator, 14-numeratorNorm); /* bestFixedCodebookGain in Q14 */
|
||||
if (shiftedDenominator>0) { /* can't shift left by 9 the numerator, can we shift right by 9-numeratorNorm the denominator without hiting 0 */
|
||||
bestFixedCodebookGain = (word32_t)(DIV64(SHL64(numerator, numeratorNorm),shiftedDenominator)); /* bestFixedCodebookGain in Q14 */
|
||||
} else {
|
||||
bestFixedCodebookGain = SHL((word32_t)(DIV64(SHL64(numerator, numeratorNorm), denominator)), 14-numeratorNorm); /* shift left the division result to reach Q14 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*** Compute the predicted gain as in spec 3.9.1 eq71 in Q6 ***/
|
||||
predictedFixedCodebookGain = (word16_t)(SHR32(MACodeGainPrediction(encoderChannelContext->previousGainPredictionError, fixedCodebookVector), 12)); /* in Q16 -> Q4 range [3,1830] */
|
||||
|
||||
/*** preselection spec 3.9.2 ***/
|
||||
/* Note: spec just says to select the best 50% of each vector, ITU code go through magical constant computation to select the begining of a continuous range */
|
||||
/* much more simple here : vector are ordened in growing order so just select 2 (4 for Gb) indexes before the first value to be superior to the best gain previously computed */
|
||||
while (indexBaseGa<6 && bestFixedCodebookGain>(MULT16_16_Q14(GACodebook[indexBaseGa][1],predictedFixedCodebookGain))) { /* bestFixedCodebookGain> in Q2, GACodebook in Q12 *predictedFixedCodebookGain in Q4 -> Q16-14 */
|
||||
indexBaseGa++;
|
||||
}
|
||||
if (indexBaseGa>0) indexBaseGa--;
|
||||
if (indexBaseGa>0) indexBaseGa--;
|
||||
while (indexBaseGb<12 && bestAdaptativeCodebookGain>(SHR(GBCodebook[indexBaseGb][0],5))) {
|
||||
indexBaseGb++;
|
||||
}
|
||||
if (indexBaseGb>0) indexBaseGb--;
|
||||
if (indexBaseGb>0) indexBaseGb--;
|
||||
if (indexBaseGb>0) indexBaseGb--;
|
||||
if (indexBaseGb>0) indexBaseGb--;
|
||||
|
||||
/*** test all possibilities of Ga and Gb indexes and select the best one ***/
|
||||
xy = -SSHL(xy,1); /* xy term is always used with a -2 factor */
|
||||
xz = -SSHL(xz,1); /* xz term is always used with a -2 factor */
|
||||
yz = SSHL(yz,1); /* yz term is always used with a 2 factor */
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
for (j=0; j<8; j++) {
|
||||
/* compute gamma->gc and gp */
|
||||
word16_t gp = ADD16(GACodebook[i+indexBaseGa][0], GBCodebook[j+indexBaseGb][0]); /* result in Q14 */
|
||||
word16_t gamma = ADD16(GACodebook[i+indexBaseGa][1], GBCodebook[j+indexBaseGb][1]); /* result in Q3.12 (range [0.185, 5.05])*/
|
||||
word32_t gc = MULT16_16_Q14(gamma, predictedFixedCodebookGain); /* gamma in Q12, predictedFixedCodebookGain in Q4 -> Q16 -14 -> Q2 */
|
||||
|
||||
/* compute E as in eq63 (first term excluded) */
|
||||
word64_t acc = MULT32_32(MULT16_16(gp, gp), yy); /* acc = gp^2*yy gp in Q14, yy in Q0 -> acc in Q28 */
|
||||
acc = MAC64(acc, MULT16_16(gc, gc), zz); /* gc in Q2, zz in Q24 -> acc in Q28, note gc is on 32 bits but in a range making gc^2 fitting on 32 bits */
|
||||
acc = MAC64(acc, SHL32((word32_t)gp, 14), xy); /* gp in Q14 shifted to Q28, xy in Q0 -> acc in Q28 */
|
||||
acc = MAC64(acc, SHL32(gc, 14), xz); /* gc in Q2 shifted to Q16, xz in Q12 -> acc in Q28 */
|
||||
acc = MAC64(acc, MULT16_16(gp,gc), yz); /* gp in Q14, gc in Q2 yz in Q12 -> acc in Q28 */
|
||||
|
||||
if (acc<distanceMin) {
|
||||
distanceMin = acc;
|
||||
indexGa = i+indexBaseGa;
|
||||
indexGb = j+indexBaseGb;
|
||||
*quantizedAdaptativeCodebookGain = gp;
|
||||
*quantizedFixedCodebookGain = (word16_t)SHR(gc, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* update the previous gain prediction error */
|
||||
computeGainPredictionError(ADD16(GACodebook[indexGa][1], GBCodebook[indexGb][1]), encoderChannelContext->previousGainPredictionError);
|
||||
|
||||
/* mapping of indexes */
|
||||
*gainCodebookStage1 = indexMappingGA[indexGa];
|
||||
*gainCodebookStage2 = indexMappingGB[indexGb];
|
||||
|
||||
return;
|
||||
}
|
42
bcg729/src/gainQuantization.h
Normal file
42
bcg729/src/gainQuantization.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef GAINQUANTIZATION_H
|
||||
#define GAINQUANTIZATION_H
|
||||
void initGainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext);
|
||||
/*****************************************************************************/
|
||||
/* gainQuantization : compute quantized adaptative and fixed codebooks gains */
|
||||
/* spec 3.9 */
|
||||
/* parameters: */
|
||||
/* -(i/o) encoderChannelContext : the channel context data */
|
||||
/* -(i) targetSignal: 40 values in Q0, x in eq63 */
|
||||
/* -(i) filteredAdaptativeCodebookVector: 40 values in Q0, y in eq63 */
|
||||
/* -(i) convolvedFixedCodebookVector: 40 values in Q12, z in eq63 */
|
||||
/* -(i) fixedCodebookVector: 40 values in Q13 */
|
||||
/* -(i) xy in Q0 on 64 bits term of eq63 computed previously */
|
||||
/* -(i) yy in Q0 on 64 bits term of eq63 computed previously */
|
||||
/* -(o) quantizedAdaptativeCodebookGain : in Q14 */
|
||||
/* -(o) quantizedFixedCodebookGain : in Q1 */
|
||||
/* -(o) gainCodebookStage1 : GA parameter value (3 bits) */
|
||||
/* -(o) gainCodebookStage2 : GB parameter value (4 bits) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void gainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, word16_t targetSignal[], word16_t filteredAdaptativeCodebookVector[], word16_t convolvedFixedCodebookVector[], word16_t fixedCodebookVector[], word64_t Xy64, word64_t Yy64,
|
||||
word16_t *quantizedAdaptativeCodebookGain, word16_t *quantizedFixedCodebookGain, uint16_t *gainCodebookStage1, uint16_t *gainCodebookStage2);
|
||||
|
||||
#endif /* ifndef GAINQUANTIZATION_H */
|
39
bcg729/src/interpolateqLSP.c
Normal file
39
bcg729/src/interpolateqLSP.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* interpolateqLSP : interpolate previous and current qLSP according to */
|
||||
/* spec. 3.2.5 : interpolated = (current+previous)/2 */
|
||||
/* parameters: */
|
||||
/* -(i) previousqLSP : 10 values in Q0.15: the qLSP of previous frame */
|
||||
/* -(i) currentqLSP : 10 values in Q0.15: the qLSP of current frame */
|
||||
/* -(o) interpolatedqLSP : 10 values in Q0.15 : the interpolated qLSP */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void interpolateqLSP(word16_t previousqLSP[], word16_t currentqLSP[], word16_t interpolatedqLSP[])
|
||||
{ /* interpolate previous and current qLSP according to spec. 3.2.5 : interpolated = (current+previous)/2 */
|
||||
int i;
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
interpolatedqLSP[i] = (word16_t)PSHR(ADD32(previousqLSP[i], currentqLSP[i]),1);
|
||||
}
|
||||
}
|
31
bcg729/src/interpolateqLSP.h
Normal file
31
bcg729/src/interpolateqLSP.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef INTERPOLATATEQLSP_H
|
||||
#define INTERPOLATATEQLSP_H
|
||||
/*****************************************************************************/
|
||||
/* interpolateqLSP : interpolate previous and current qLSP according to */
|
||||
/* spec. 3.2.5 : interpolated = (current+previous)/2 */
|
||||
/* parameters: */
|
||||
/* -(i) previousqLSP : 10 values in Q0.15: the qLSP of previous frame */
|
||||
/* -(i) currentqLSP : 10 values in Q0.15: the qLSP of current frame */
|
||||
/* -(o) interpolatedqLSP : 10 values in Q0.15 : the interpolated qLSP */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void interpolateqLSP(word16_t previousqLSP[], word16_t currentqLSP[], word16_t interpolatedqLSP[]);
|
||||
#endif /* ifndef INTERPOLATATEQLSP_H */
|
344
bcg729/src/postFilter.c
Normal file
344
bcg729/src/postFilter.c
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
#include "g729FixedPointMath.h"
|
||||
|
||||
/* init function */
|
||||
void initPostFilter(bcg729DecoderChannelContextStruct *decoderChannelContext)
|
||||
{
|
||||
/* set to zero the residual signal memory */
|
||||
memset(decoderChannelContext->residualSignalBuffer, 0, MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t));
|
||||
memset(decoderChannelContext->scaledResidualSignalBuffer, 0, MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t));
|
||||
/* set to zero the one word of longTermFilteredResidualSignal needed as memory for tilt compensation filter */
|
||||
decoderChannelContext->longTermFilteredResidualSignalBuffer[0] = 0;
|
||||
decoderChannelContext->longTermFilteredResidualSignal = &(decoderChannelContext->longTermFilteredResidualSignalBuffer[1]); /* init the pointer to the begining of longTermFilteredResidualSignal current subframe */
|
||||
/* intialise the shortTermFilteredResidualSignal filter memory and pointer*/
|
||||
memset(decoderChannelContext->shortTermFilteredResidualSignalBuffer, 0, NB_LSP_COEFF*sizeof(word16_t));
|
||||
decoderChannelContext->shortTermFilteredResidualSignal = &(decoderChannelContext->shortTermFilteredResidualSignalBuffer[NB_LSP_COEFF]);
|
||||
/* initialise the previous Gain for adaptative gain control */
|
||||
decoderChannelContext->previousAdaptativeGain = 4096; /* 1 in Q12 */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* postFilter: filter the reconstructed speech according to spec A.4.2 */
|
||||
/* parameters: */
|
||||
/* -(i/o) decoderChannelContext : the channel context data */
|
||||
/* -(i) LPCoefficients: 10 LP coeff for current subframe in Q12 */
|
||||
/* -(i) reconstructedSpeech: output of LP Synthesis, 50 values in Q0 */
|
||||
/* 10 values of previous subframe, accessed in range [-10, 39] */
|
||||
/* -(i) intPitchDelay: the integer part of Pitch Delay in Q0 */
|
||||
/* -(i) subframeIndex: 0 or L_SUBFRAME for subframe 0 or 1 */
|
||||
/* -(o) postFilteredSignal: 40 values in Q0 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16_t *LPCoefficients, word16_t *reconstructedSpeech, int16_t intPitchDelay, int subframeIndex,
|
||||
word16_t *postFilteredSignal)
|
||||
{
|
||||
int i,j;
|
||||
word16_t LPGammaNCoefficients[NB_LSP_COEFF]; /* in Q12 */
|
||||
word16_t *residualSignal;
|
||||
word16_t *scaledResidualSignal;
|
||||
word32_t correlationMax = (word32_t)MININT32;
|
||||
int16_t bestIntPitchDelay = 0;
|
||||
word16_t *delayedResidualSignal;
|
||||
word32_t residualSignalEnergy = 0; /* in Q-4 */
|
||||
word32_t delayedResidualSignalEnergy = 0; /* in Q-4 */
|
||||
word32_t maximumThree;
|
||||
int16_t leadingZeros = 0;
|
||||
word16_t correlationMaxWord16 = 0;
|
||||
word16_t residualSignalEnergyWord16 = 0;
|
||||
word16_t delayedResidualSignalEnergyWord16 = 0;
|
||||
word16_t LPGammaDCoefficients[NB_LSP_COEFF]; /* in Q12 */
|
||||
word16_t hf[22]; /* the truncated impulse response to short term filter Hf in Q12 */
|
||||
word32_t rh1;
|
||||
word16_t tiltCompensatedSignal[L_SUBFRAME]; /* in Q0 */
|
||||
word16_t gainScalingFactor; /* in Q12 */
|
||||
uword32_t shortTermFilteredResidualSignalSquareSum = 0;
|
||||
|
||||
/********************************************************************/
|
||||
/* Long Term Post Filter */
|
||||
/********************************************************************/
|
||||
/*** Compute LPGammaN and LPGammaD coefficients : LPGamma[0] = LP[0]*Gamma^(i+1) (i=0..9) ***/
|
||||
/* GAMMA_XX constants are in Q15 */
|
||||
LPGammaNCoefficients[0] = MULT16_16_P15(LPCoefficients[0], GAMMA_N1);
|
||||
LPGammaNCoefficients[1] = MULT16_16_P15(LPCoefficients[1], GAMMA_N2);
|
||||
LPGammaNCoefficients[2] = MULT16_16_P15(LPCoefficients[2], GAMMA_N3);
|
||||
LPGammaNCoefficients[3] = MULT16_16_P15(LPCoefficients[3], GAMMA_N4);
|
||||
LPGammaNCoefficients[4] = MULT16_16_P15(LPCoefficients[4], GAMMA_N5);
|
||||
LPGammaNCoefficients[5] = MULT16_16_P15(LPCoefficients[5], GAMMA_N6);
|
||||
LPGammaNCoefficients[6] = MULT16_16_P15(LPCoefficients[6], GAMMA_N7);
|
||||
LPGammaNCoefficients[7] = MULT16_16_P15(LPCoefficients[7], GAMMA_N8);
|
||||
LPGammaNCoefficients[8] = MULT16_16_P15(LPCoefficients[8], GAMMA_N9);
|
||||
LPGammaNCoefficients[9] = MULT16_16_P15(LPCoefficients[9], GAMMA_N10);
|
||||
|
||||
/*** Compute the residual signal as described in spec 4.2.1 eq79 ***/
|
||||
/* Compute also a scaled residual signal: shift right by 2 to avoid overflows on 32 bits when computing correlation and energy */
|
||||
|
||||
/* pointers to current subframe beginning */
|
||||
residualSignal = &(decoderChannelContext->residualSignalBuffer[MAXIMUM_INT_PITCH_DELAY+subframeIndex]);
|
||||
scaledResidualSignal = &(decoderChannelContext->scaledResidualSignalBuffer[MAXIMUM_INT_PITCH_DELAY+subframeIndex]);
|
||||
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
word32_t acc = SSHL((word32_t)reconstructedSpeech[i], 12); /* reconstructedSpeech in Q0 shifted to set acc in Q12 */
|
||||
for (j=0; j<NB_LSP_COEFF; j++) {
|
||||
acc = MAC16_16(acc, LPGammaNCoefficients[j],reconstructedSpeech[i-j-1]); /* LPGammaNCoefficients in Q12, reconstructedSpeech in Q0 -> acc in Q12 */
|
||||
}
|
||||
residualSignal[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* shift back acc to Q0 and saturate it to avoid overflow when going back to 16 bits */
|
||||
scaledResidualSignal[i] = PSHR(residualSignal[i], 2); /* shift acc to Q-2 and saturate it to get the scaled version of the signal */
|
||||
}
|
||||
|
||||
/*** Compute the maximum correlation on scaledResidualSignal delayed by intPitchDelay +/- 3 to get the best delay. Spec 4.2.1 eq80 ***/
|
||||
/* using a scaled(Q-2) signals gives correlation in Q-4. */
|
||||
if (intPitchDelay>MAXIMUM_INT_PITCH_DELAY-3) { /* intPitchDelay shall be < MAXIMUM_INT_PITCH_DELAY-3 (140) */
|
||||
intPitchDelay = MAXIMUM_INT_PITCH_DELAY-3;
|
||||
}
|
||||
|
||||
for (i=intPitchDelay-3; i<=intPitchDelay+3; i++) {
|
||||
word32_t correlation = 0;
|
||||
delayedResidualSignal = &(scaledResidualSignal[-i]); /* delayedResidualSignal points to scaledResidualSignal[-i] */
|
||||
|
||||
/* compute correlation: ∑r(n)*rk(n) */
|
||||
for (j=0; j<L_SUBFRAME; j++) {
|
||||
correlation = MAC16_16(correlation, delayedResidualSignal[j], scaledResidualSignal[j]);
|
||||
}
|
||||
/* if we have a maximum correlation */
|
||||
if (correlation>correlationMax) {
|
||||
correlationMax = correlation;
|
||||
bestIntPitchDelay = i; /* get the intPitchDelay */
|
||||
}
|
||||
}
|
||||
|
||||
/* saturate correlation to a positive integer */
|
||||
if (correlationMax<0) {
|
||||
correlationMax = 0;
|
||||
}
|
||||
|
||||
/*** Compute the signal energy ∑r(n)*r(n) and delayed signal energy ∑rk(n)*rk(n) which shall be used to compute gl spec 4.2.1 eq81, eq 82 and eq83 ***/
|
||||
delayedResidualSignal = &(scaledResidualSignal[-bestIntPitchDelay]); /* in Q-2, points to the residual signal delayed to give the higher correlation: rk(n) */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
residualSignalEnergy = MAC16_16(residualSignalEnergy, scaledResidualSignal[i], scaledResidualSignal[i]);
|
||||
delayedResidualSignalEnergy = MAC16_16(delayedResidualSignalEnergy, delayedResidualSignal[i], delayedResidualSignal[i]);
|
||||
}
|
||||
|
||||
/*** Scale correlationMax, residualSignalEnergy and delayedResidualSignalEnergy to the best fit on 16 bits ***/
|
||||
/* these variables must fit on 16bits for the following computation, to avoid loosing information, scale them */
|
||||
/* at best fit: scale the higher of three to get the value over 2^14 and shift the other two from the same amount */
|
||||
/* Note: all three value are >= 0 */
|
||||
maximumThree = correlationMax;
|
||||
if (maximumThree<residualSignalEnergy) {
|
||||
maximumThree = residualSignalEnergy;
|
||||
}
|
||||
if (maximumThree<delayedResidualSignalEnergy) {
|
||||
maximumThree = delayedResidualSignalEnergy;
|
||||
}
|
||||
|
||||
if (maximumThree>0) { /* if all of them a null, just do nothing otherwise shift right to get the max number in range [0x4000,0x8000[ */
|
||||
leadingZeros = countLeadingZeros(maximumThree);
|
||||
if (leadingZeros<16) {
|
||||
correlationMaxWord16 = (word16_t)SHR32(correlationMax, 16-leadingZeros);
|
||||
residualSignalEnergyWord16 = (word16_t)SHR32(residualSignalEnergy, 16-leadingZeros);
|
||||
delayedResidualSignalEnergyWord16 = (word16_t)SHR32(delayedResidualSignalEnergy, 16-leadingZeros);
|
||||
} else { /* if the values already fit on 16 bits, no need to shift */
|
||||
correlationMaxWord16 = (word16_t)correlationMax;
|
||||
residualSignalEnergyWord16 = (word16_t)residualSignalEnergy;
|
||||
delayedResidualSignalEnergyWord16 = (word16_t)delayedResidualSignalEnergy;
|
||||
}
|
||||
}
|
||||
|
||||
/* eq78: Hp(z)=(1 + γp*gl*z(−T))/(1 + γp*gl) -> (with g=γp*gl) Hp(z)=1/(1+g) + (g/(1+g))*z(-T) = g0 + g1*z(-T) */
|
||||
/* g = gl/2 (as γp=0.5)= (eq83) correlationMax/(2*delayedResidualSignalEnergy) */
|
||||
/* compute g0 = 1/(1+g)= delayedResidualSignalEnergy/(delayedResidualSignalEnergy+correlationMax/2) = 1-g1*/
|
||||
/* compute g1 = g/(1+g) = correlationMax/(2*delayedResidualSignalEnergy+correlationMax) = 1-g0 */
|
||||
|
||||
/*** eq82 -> (correlationMax^2)/(residualSignalEnergy*delayedResidualSignalEnergy)<0.5 ***/
|
||||
/* (correlationMax^2) < (residualSignalEnergy*delayedResidualSignalEnergy)*0.5 */
|
||||
if ((MULT16_16(correlationMaxWord16, correlationMaxWord16) < SHR(MULT16_16(residualSignalEnergyWord16, delayedResidualSignalEnergyWord16), 1)) /* eq82 */
|
||||
|| ((correlationMaxWord16==0) && (delayedResidualSignalEnergyWord16==0))) { /* correlationMax and delayedResidualSignalEnergy values are 0 -> unable to compute g0 and g1 -> disable filter */
|
||||
/* long term post filter disabled */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
decoderChannelContext->longTermFilteredResidualSignal[i] = residualSignal[i];
|
||||
}
|
||||
} else { /* eq82 gives long term filter enabled, */
|
||||
word16_t g0, g1;
|
||||
/* eq83: gl = correlationMax/delayedResidualSignalEnergy bounded in ]0,1] */
|
||||
/* check if gl > 1 -> gl=1 -> g=1/2 -> g0=2/3 and g1=1/3 */
|
||||
if (correlationMax > delayedResidualSignalEnergy) {
|
||||
g0 = 21845; /* 2/3 in Q15 */
|
||||
g1 = 10923; /* 1/3 in Q15 */
|
||||
} else {
|
||||
/* g1 = correlationMax/(2*delayedResidualSignalEnergy+correlationMax) */
|
||||
g1 = DIV32((word32_t)SHL32(correlationMaxWord16,15),(word32_t)ADD32(SHL32(delayedResidualSignalEnergyWord16,1), correlationMaxWord16)); /* g1 in Q15 */
|
||||
g0 = SUB16(32767, g1); /* g0 = 1 - g1 in Q15 */
|
||||
}
|
||||
|
||||
/* longTermFilteredResidualSignal[i] = g0*residualSignal[i] + g1*delayedResidualSignal[i]*/
|
||||
delayedResidualSignal = &(residualSignal[-bestIntPitchDelay]);
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
decoderChannelContext->longTermFilteredResidualSignal[i] = (word16_t)SATURATE(PSHR(ADD32(MULT16_16(g0, residualSignal[i]), MULT16_16(g1, delayedResidualSignal[i])), 15), MAXINT16);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/* Tilt Compensation Filter */
|
||||
/********************************************************************/
|
||||
|
||||
/* compute hf the truncated (to 22 coefficients) impulse response of the filter A(z/γn)/A(z/γd) described in spec 4.2.2 eq84 */
|
||||
/* hf(i) = LPGammaNCoeff[i] - ∑[j:0..9]LPGammaDCoeff[j]*hf[i-j-1]) */
|
||||
/* GAMMA_XX constants are in Q15 */
|
||||
LPGammaDCoefficients[0] = MULT16_16_P15(LPCoefficients[0], GAMMA_D1);
|
||||
LPGammaDCoefficients[1] = MULT16_16_P15(LPCoefficients[1], GAMMA_D2);
|
||||
LPGammaDCoefficients[2] = MULT16_16_P15(LPCoefficients[2], GAMMA_D3);
|
||||
LPGammaDCoefficients[3] = MULT16_16_P15(LPCoefficients[3], GAMMA_D4);
|
||||
LPGammaDCoefficients[4] = MULT16_16_P15(LPCoefficients[4], GAMMA_D5);
|
||||
LPGammaDCoefficients[5] = MULT16_16_P15(LPCoefficients[5], GAMMA_D6);
|
||||
LPGammaDCoefficients[6] = MULT16_16_P15(LPCoefficients[6], GAMMA_D7);
|
||||
LPGammaDCoefficients[7] = MULT16_16_P15(LPCoefficients[7], GAMMA_D8);
|
||||
LPGammaDCoefficients[8] = MULT16_16_P15(LPCoefficients[8], GAMMA_D9);
|
||||
LPGammaDCoefficients[9] = MULT16_16_P15(LPCoefficients[9], GAMMA_D10);
|
||||
|
||||
hf[0] = 4096; /* 1 in Q12 as LPGammaNCoefficients and LPGammaDCoefficient doesn't contain the first element which is 1 and past values of hf are 0 */
|
||||
for (i=1; i<11; i++) {
|
||||
word32_t acc = (word32_t)SSHL(LPGammaNCoefficients[i-1],12); /* LPGammaNCoefficients in Q12 -> acc in Q24 */
|
||||
for (j=0; j<NB_LSP_COEFF && j<i; j++) { /* j<i to avoid access to negative index of hf(past values are 0 anyway) */
|
||||
acc = MSU16_16(acc, LPGammaDCoefficients[j], hf[i-j-1]); /* LPGammaDCoefficient in Q12, hf in Q12 -> Q24 TODO: Possible overflow?? */
|
||||
}
|
||||
hf[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* get result back in Q12 and saturate on 16 bits */
|
||||
}
|
||||
for (i=11; i<22; i++) {
|
||||
word32_t acc = 0;
|
||||
for (j=0; j<NB_LSP_COEFF; j++) { /* j<i to avoid access to negative index of hf(past values are 0 anyway) */
|
||||
acc = MSU16_16(acc, LPGammaDCoefficients[j], hf[i-j-1]); /* LPGammaDCoefficient in Q12, hf in Q12 -> Q24 TODO: Possible overflow?? */
|
||||
}
|
||||
hf[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* get result back in Q12 and saturate on 16 bits */
|
||||
}
|
||||
|
||||
/* hf is then used to compute k'1 spec 4.2.3 eq87: k'1 = -rh1/rh0 */
|
||||
/* rh0 = ∑[i:0..21]hf[i]*hf[i] */
|
||||
/* rh1 = ∑[i:0..20]hf[i]*hf[i+1] */
|
||||
rh1 = MULT16_16(hf[0], hf[1]);
|
||||
for (i=1; i<21; i++) {
|
||||
rh1 = MAC16_16(rh1, hf[i], hf[i+1]); /* rh1 in Q24 */
|
||||
}
|
||||
|
||||
/* tiltCompensationGain is set to 0 if k'1>0 -> rh1<0 (as rh0 is always>0) */
|
||||
if (rh1<0) { /* tiltCompensationGain = 0 -> no gain filter is off, just copy the input */
|
||||
memcpy(tiltCompensatedSignal, decoderChannelContext->longTermFilteredResidualSignal, L_SUBFRAME*sizeof(word16_t));
|
||||
} else { /*compute tiltCompensationGain = k'1*γt */
|
||||
word16_t tiltCompensationGain;
|
||||
word32_t rh0 = MULT16_16(hf[0], hf[0]);
|
||||
for (i=1; i<22; i++) {
|
||||
rh0 = MAC16_16(rh0, hf[i], hf[i]); /* rh0 in Q24 */
|
||||
}
|
||||
rh1 = MULT16_32_Q15(GAMMA_T, rh1); /* GAMMA_T in Q15, rh1 in Q24*/
|
||||
tiltCompensationGain = (word16_t)SATURATE((word32_t)(DIV32(rh1,PSHR(rh0,12))), MAXINT16); /* rh1 in Q24, PSHR(rh0,12) in Q12 -> tiltCompensationGain in Q12 */
|
||||
|
||||
/* compute filter Ht (spec A.4.2.3 eqA14) = 1 + gain*z(-1) */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
tiltCompensatedSignal[i] = MSU16_16_Q12(decoderChannelContext->longTermFilteredResidualSignal[i], tiltCompensationGain, decoderChannelContext->longTermFilteredResidualSignal[i-1]);
|
||||
}
|
||||
}
|
||||
/* update memory word of longTermFilteredResidualSignal for next subframe */
|
||||
decoderChannelContext->longTermFilteredResidualSignal[-1] = decoderChannelContext->longTermFilteredResidualSignal[L_SUBFRAME-1];
|
||||
|
||||
/********************************************************************/
|
||||
/* synthesis filter 1/[Â(z /γd)] spec A.4.2.2 */
|
||||
/* */
|
||||
/* Note: Â(z/γn) was done before when computing residual signal */
|
||||
/********************************************************************/
|
||||
/* shortTermFilteredResidualSignal is accessed in range [-NB_LSP_COEFF,L_SUBFRAME[ */
|
||||
synthesisFilter(tiltCompensatedSignal, LPGammaDCoefficients, decoderChannelContext->shortTermFilteredResidualSignal);
|
||||
/* get the last NB_LSP_COEFF of shortTermFilteredResidualSignal and set them as memory for next subframe(they do not overlap so use memcpy) */
|
||||
memcpy(decoderChannelContext->shortTermFilteredResidualSignalBuffer, &(decoderChannelContext->shortTermFilteredResidualSignalBuffer[L_SUBFRAME]), NB_LSP_COEFF*sizeof(word16_t));
|
||||
|
||||
/********************************************************************/
|
||||
/* Adaptive Gain Control spec A.4.2.4 */
|
||||
/* */
|
||||
/********************************************************************/
|
||||
|
||||
/*** compute G(gain scaling factor) according to eqA15 : G = Sqrt((∑s(n)^2)/∑sf(n)^2 ) ***/
|
||||
/* compute ∑sf(n)^2, scale the signal shifting right by 4 to avoid possible overflow on 32 bits sum */
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
shortTermFilteredResidualSignalSquareSum = UMAC16_16_Q4(shortTermFilteredResidualSignalSquareSum, decoderChannelContext->shortTermFilteredResidualSignal[i], decoderChannelContext->shortTermFilteredResidualSignal[i]); /* inputs are both in Q0, output is in Q-4 */
|
||||
}
|
||||
|
||||
/* if the sum is null we can't compute gain -> output of postfiltering is the output of shortTermFilter and previousAdaptativeGain is set to 0 */
|
||||
/* the reset of previousAdaptativeGain is not mentionned in the spec but in ITU code only */
|
||||
if (shortTermFilteredResidualSignalSquareSum == 0) {
|
||||
decoderChannelContext->previousAdaptativeGain = 0;
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
postFilteredSignal[i] = decoderChannelContext->shortTermFilteredResidualSignal[i];
|
||||
}
|
||||
} else { /* we can compute adaptativeGain and output signal */
|
||||
word16_t currentAdaptativeGain;
|
||||
/* compute ∑s(n)^2 scale the signal shifting right by 4 to avoid possible overflow on 32 bits sum, same shift was applied at denominator */
|
||||
uword32_t reconstructedSpeechSquareSum = 0;
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
reconstructedSpeechSquareSum = UMAC16_16_Q4(reconstructedSpeechSquareSum, reconstructedSpeech[i], reconstructedSpeech[i]); /* inputs are both in Q0, output is in Q-4 */
|
||||
}
|
||||
|
||||
if (reconstructedSpeechSquareSum==0) { /* numerator is null -> current gain is null */
|
||||
gainScalingFactor = 0;
|
||||
} else {
|
||||
uword32_t fractionResult; /* stores ∑s(n)^2)/∑sf(n)^2 in Q10 on a 32 bit unsigned */
|
||||
word32_t scaledShortTermFilteredResidualSignalSquareSum;
|
||||
/* Compute ∑s(n)^2)/∑sf(n)^2 result shall be in Q10 */
|
||||
/* normalise the numerator on 32 bits */
|
||||
word16_t numeratorShift = unsignedCountLeadingZeros(reconstructedSpeechSquareSum);
|
||||
reconstructedSpeechSquareSum = USHL(reconstructedSpeechSquareSum, numeratorShift); /* reconstructedSpeechSquareSum*2^numeratorShift */
|
||||
|
||||
/* normalise denominator to get the result directly in Q10 if possible */
|
||||
scaledShortTermFilteredResidualSignalSquareSum = VSHR32(shortTermFilteredResidualSignalSquareSum, 10-numeratorShift); /* shortTermFilteredResidualSignalSquareSum*2^(numeratorShift-10)*/
|
||||
|
||||
if (scaledShortTermFilteredResidualSignalSquareSum==0) {/* shift might have sent to zero the denominator */
|
||||
fractionResult = UDIV32(reconstructedSpeechSquareSum, shortTermFilteredResidualSignalSquareSum); /* result in QnumeratorShift */
|
||||
fractionResult = VSHR32(fractionResult, numeratorShift-10); /* result in Q10 */
|
||||
} else { /* ok denominator is still > 0 */
|
||||
fractionResult = UDIV32(reconstructedSpeechSquareSum, scaledShortTermFilteredResidualSignalSquareSum); /* result in Q10 */
|
||||
}
|
||||
/* now compute current Gain = Sqrt((∑s(n)^2)/∑sf(n)^2 ) */
|
||||
/* g729Sqrt_Q0Q7(Q0)->Q7, by giving a Q10 as input, output is in Q12 */
|
||||
gainScalingFactor = (word16_t)SATURATE(g729Sqrt_Q0Q7(fractionResult), MAXINT16);
|
||||
|
||||
/* multiply by 0.1 as described in spec A.4.2.4 */
|
||||
gainScalingFactor = MULT16_16_P15(gainScalingFactor, 3277); /* in Q12, 3277 = 0.1 in Q15*/
|
||||
}
|
||||
/* Compute the signal according to eq89 (spec 4.2.4 and section A4.2.4) */
|
||||
/* currentGain = 0.9*previousGain + 0.1*gainScalingFactor the 0.1 factor has already been integrated in the variable gainScalingFactor */
|
||||
/* outputsignal = currentGain*shortTermFilteredResidualSignal */
|
||||
currentAdaptativeGain = decoderChannelContext->previousAdaptativeGain;
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
currentAdaptativeGain = ADD16(gainScalingFactor, MULT16_16_P15(currentAdaptativeGain, 29491)); /* 29492 = 0.9 in Q15, result in Q12 */
|
||||
postFilteredSignal[i] = MULT16_16_Q12(currentAdaptativeGain, decoderChannelContext->shortTermFilteredResidualSignal[i]);
|
||||
}
|
||||
decoderChannelContext->previousAdaptativeGain = currentAdaptativeGain;
|
||||
}
|
||||
|
||||
/* shift buffers if needed */
|
||||
if (subframeIndex>0) { /* only after 2nd subframe treatment */
|
||||
/* shift left by L_FRAME the residualSignal and scaledResidualSignal buffers */
|
||||
memmove(decoderChannelContext->residualSignalBuffer, &(decoderChannelContext->residualSignalBuffer[L_FRAME]), MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t));
|
||||
memmove(decoderChannelContext->scaledResidualSignalBuffer, &(decoderChannelContext->scaledResidualSignalBuffer[L_FRAME]), MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t));
|
||||
}
|
||||
return;
|
||||
}
|
38
bcg729/src/postFilter.h
Normal file
38
bcg729/src/postFilter.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef POSTFILTER_H
|
||||
#define POSTFILTER_H
|
||||
/* init function */
|
||||
void initPostFilter(bcg729DecoderChannelContextStruct *decoderChannelContext);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* postFilter: filter the reconstructed speech according to spec A.4.2 */
|
||||
/* parameters: */
|
||||
/* -(i/o) decoderChannelContext : the channel context data */
|
||||
/* -(i) LPCoefficients: 10 LP coeff for current subframe in Q12 */
|
||||
/* -(i) reconstructedSpeech: output of LP Synthesis, 50 values in Q0 */
|
||||
/* 10 values of previous subframe, accessed in range [-10, 39] */
|
||||
/* -(i) intPitchDelay: the integer part of Pitch Delay in Q0 */
|
||||
/* -(i) subframeIndex: 0 or L_SUBFRAME for subframe 0 or 1 */
|
||||
/* -(o) postFilteredSignal: 40 values in Q0 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16_t *LPCoefficients, word16_t *reconstructedSpeech, int16_t intPitchDelay, int subframeIndex,
|
||||
word16_t *postFilteredSignal);
|
||||
#endif /* ifndef POSTFILTER_H */
|
89
bcg729/src/postProcessing.c
Normal file
89
bcg729/src/postProcessing.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
|
||||
#include "preProcessing.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Define filter coefficients */
|
||||
/* Coefficient are given by the filter transfert function : */
|
||||
/* */
|
||||
/* 0.46363718 - 0.92724705z(-1) + 0.46363718z(-2) */
|
||||
/* H(z) = −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− */
|
||||
/* 1 - 1.9059465z(-1) + 0.9114024z(-2) */
|
||||
/* */
|
||||
/* giving: */
|
||||
/* y[i] = B0*x[i] + B1*x[i-1] + B2*x[i-2] */
|
||||
/* + A1*y[i-1] + A2*y[i-2] */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* coefficients are stored in Q1.13 */
|
||||
#define A1 ((word16_t)(15836))
|
||||
#define A2 ((word16_t)(-7667))
|
||||
#define B0 ((word16_t)(7699))
|
||||
#define B1 ((word16_t)(-15398))
|
||||
#define B2 ((word16_t)(7699))
|
||||
|
||||
/* Initialization of context values */
|
||||
void initPostProcessing(bcg729DecoderChannelContextStruct *decoderChannelContext) {
|
||||
decoderChannelContext->outputY2 = 0;
|
||||
decoderChannelContext->outputY1 = 0;
|
||||
decoderChannelContext->inputX0 = 0;
|
||||
decoderChannelContext->inputX1 = 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* postProcessing : high pass filtering and upscaling Spec 4.2.5 */
|
||||
/* Algorithm: */
|
||||
/* y[i] = BO*x[i] + B1*x[i-1] + B2*x[i-2] + A1*y[i-1] + A2*y[i-2] */
|
||||
/* parameters: */
|
||||
/* -(i/o) decoderChannelContext : the channel context data */
|
||||
/* -(i/o) signal : 40 values in Q0, reconstructed speech, output */
|
||||
/* replaces the input in buffer */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void postProcessing(bcg729DecoderChannelContextStruct *decoderChannelContext, word16_t signal[]) {
|
||||
int i;
|
||||
word16_t inputX2;
|
||||
word32_t acc; /* in Q13 */
|
||||
|
||||
for(i=0; i<L_SUBFRAME; i++) {
|
||||
inputX2 = decoderChannelContext->inputX1;
|
||||
decoderChannelContext->inputX1 = decoderChannelContext->inputX0;
|
||||
decoderChannelContext->inputX0 = signal[i];
|
||||
|
||||
/* compute with acc and coefficients in Q13 */
|
||||
acc = MULT16_32_Q13(A1, decoderChannelContext->outputY1); /* Y1 in Q14.13 * A1 in Q1.13 -> acc in Q17.13*/
|
||||
acc = MAC16_32_Q13(acc, A2, decoderChannelContext->outputY2); /* Y2 in Q14.13 * A2 in Q0.13 -> Q15.13 + acc in Q17.13 -> acc in Q18.12 */
|
||||
/* 3*(Xi in Q15.0 * Bi in Q0.13)->Q17.13 + acc in Q18.13 -> acc in 19.13(Overflow??) */
|
||||
acc = MAC16_16(acc, decoderChannelContext->inputX0, B0);
|
||||
acc = MAC16_16(acc, decoderChannelContext->inputX1, B1);
|
||||
acc = SATURATE(MAC16_16(acc, inputX2, B2), MAXINT29); /* saturate the acc to keep in Q15.13 */
|
||||
|
||||
signal[i] = SATURATE(PSHR(acc,12), MAXINT16); /* acc in Q13 -> *2 and scale back to Q0 */
|
||||
decoderChannelContext->outputY2 = decoderChannelContext->outputY1;
|
||||
decoderChannelContext->outputY1 = acc;
|
||||
}
|
||||
return;
|
||||
}
|
33
bcg729/src/postProcessing.h
Normal file
33
bcg729/src/postProcessing.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef POSTPROCESSING_H
|
||||
#define POSTPROCESSING_H
|
||||
void initPostProcessing(bcg729DecoderChannelContextStruct *decoderChannelContext);
|
||||
/*****************************************************************************/
|
||||
/* postProcessing : high pass filtering and upscaling Spec 4.2.5 */
|
||||
/* Algorithm: */
|
||||
/* y[i] = BO*x[i] + B1*x[i-1] + B2*x[i-2] + A1*y[i-1] + A2*y[i-2] */
|
||||
/* parameters: */
|
||||
/* -(i/o) decoderChannelContext : the channel context data */
|
||||
/* -(i/o) signal : 40 values in Q0, reconstructed speech, output */
|
||||
/* replaces the input in buffer */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void postProcessing(bcg729DecoderChannelContextStruct *decoderChannelContext, word16_t signal[]);
|
||||
#endif /* ifndef POSTPROCESSING_H */
|
94
bcg729/src/preProcessing.c
Normal file
94
bcg729/src/preProcessing.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
|
||||
#include "preProcessing.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Define filter coefficients */
|
||||
/* Coefficient are given by the filter transfert function : */
|
||||
/* */
|
||||
/* 0.46363718 - 0.92724705z(-1) + 0.46363718z(-2) */
|
||||
/* H(z) = −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− */
|
||||
/* 1 - 1.9059465z(-1) + 0.9114024z(-2) */
|
||||
/* */
|
||||
/* giving: */
|
||||
/* y[i] = B0*x[i] + B1*x[i-1] + B2*x[i-2] */
|
||||
/* + A1*y[i-1] + A2*y[i-2] */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* coefficients a stored in Q1.12 for A1 (the only one having a float value > 1) and Q0.12 for all the others */
|
||||
#define A1 ((word16_t)(7807))
|
||||
#define A2 ((word16_t)(-3733))
|
||||
#define B0 ((word16_t)(1899))
|
||||
#define B1 ((word16_t)(-3798))
|
||||
#define B2 ((word16_t)(1899))
|
||||
|
||||
/* Initialization of context values */
|
||||
void initPreProcessing(bcg729EncoderChannelContextStruct *encoderChannelContext) {
|
||||
encoderChannelContext->outputY2 = 0;
|
||||
encoderChannelContext->outputY1 = 0;
|
||||
encoderChannelContext->inputX0 = 0;
|
||||
encoderChannelContext->inputX1 = 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* preProcessing : 2nd order highpass filter with cut off frequency at 140Hz */
|
||||
/* Algorithm: */
|
||||
/* y[i] = BO*x[i] + B1*x[i-1] + B2*x[i-2] + A1*y[i-1] + A2*y[i-2] */
|
||||
/* parameters : */
|
||||
/* -(i/o) encoderChannelContext : the channel context data */
|
||||
/* -(i) signal : 80 values in Q0 */
|
||||
/* -(o) preProcessedSignal : 80 values in Q0 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void preProcessing(bcg729EncoderChannelContextStruct *encoderChannelContext, const word16_t signal[], word16_t preProcessedSignal[]) {
|
||||
int i;
|
||||
word16_t inputX2;
|
||||
word32_t acc; /* in Q12 */
|
||||
|
||||
for(i=0; i<L_FRAME; i++) {
|
||||
inputX2 = encoderChannelContext->inputX1;
|
||||
encoderChannelContext->inputX1 = encoderChannelContext->inputX0;
|
||||
encoderChannelContext->inputX0 = signal[i];
|
||||
|
||||
/* compute with acc and coefficients in Q12 */
|
||||
acc = MULT16_32_Q12(A1, encoderChannelContext->outputY1); /* Y1 in Q15.12 * A1 in Q1.12 -> acc in Q17.12*/
|
||||
acc = MAC16_32_Q12(acc, A2, encoderChannelContext->outputY2); /* Y2 in Q15.12 * A2 in Q0.12 -> Q15.12 + acc in Q17.12 -> acc in Q18.12 */
|
||||
/* 3*(Xi in Q15.0 * Bi in Q0.12)->Q17.12 + acc in Q18.12 -> acc in 19.12 */
|
||||
acc = MAC16_16(acc, encoderChannelContext->inputX0, B0);
|
||||
acc = MAC16_16(acc, encoderChannelContext->inputX1, B1);
|
||||
acc = MAC16_16(acc, inputX2, B2);
|
||||
/* acc in Q19.12 : We must check it won't overflow
|
||||
- the Q15.12 of Y
|
||||
- the Q15.0 extracted from it by shifting 12 right
|
||||
-> saturate to 28 bits -> acc in Q15.12 */
|
||||
acc = SATURATE(acc, MAXINT28);
|
||||
|
||||
preProcessedSignal[i] = PSHR(acc,12); /* extract integer value of the Q15.12 representation */
|
||||
encoderChannelContext->outputY2 = encoderChannelContext->outputY1;
|
||||
encoderChannelContext->outputY1 = acc;
|
||||
}
|
||||
return;
|
||||
}
|
35
bcg729/src/preProcessing.h
Normal file
35
bcg729/src/preProcessing.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef PREPROCESSING_H
|
||||
#define PREPROCESSING_H
|
||||
/* internal variable initialisations */
|
||||
void initPreProcessing(bcg729EncoderChannelContextStruct *encoderChannelContext);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* preProcessing : 2nd order highpass filter with cut off frequency at 140Hz */
|
||||
/* Algorithm: */
|
||||
/* y[i] = BO*x[i] + B1*x[i-1] + B2*x[i-2] + A1*y[i-1] + A2*y[i-2] */
|
||||
/* parameters : */
|
||||
/* -(i/o) encoderChannelContext : the channel context data */
|
||||
/* -(i) signal : 80 values in Q0 */
|
||||
/* -(o) preProcessedSignal : 80 values in Q0 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void preProcessing(bcg729EncoderChannelContextStruct *encoderChannelContext, const word16_t signal[], word16_t preProcessedSignal[]);
|
||||
#endif /* ifndef PREPROCESSING_H */
|
94
bcg729/src/qLSP2LP.c
Normal file
94
bcg729/src/qLSP2LP.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
|
||||
/* local function */
|
||||
void computePolynomialCoefficients(word16_t qLSP[], word32_t f[]);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* qLSP2LP : convert qLSP into LP parameters according to spec. 3.2.6 */
|
||||
/* parameters: */
|
||||
/* -(i) qLSP : 10 LSP to be converted in Q0.15 range [-1, +1[ */
|
||||
/* -(o) LP : 10 LP coefficients in Q12 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void qLSP2LP(word16_t qLSP[], word16_t LP[])
|
||||
{
|
||||
int i;
|
||||
word32_t f1[6], f2[6]; /* define two buffer to store the polynomials coefficients (size is 6 for 5 coefficient because fx[0] is used during computation as a buffer) */
|
||||
/* pointers to access directly the elements 1 of f1 and f2 */
|
||||
word32_t *fp1=&(f1[1]);
|
||||
word32_t *fp2=&(f2[1]);
|
||||
computePolynomialCoefficients(qLSP, f1);
|
||||
|
||||
computePolynomialCoefficients(&(qLSP[1]), f2);
|
||||
|
||||
/* convert f coefficient in f' coefficient f'1[i] = f1[i]+f[i-1] and f'2[i] = f2[i] - f2[i-1] */
|
||||
for (i=5; i>0; i--) {
|
||||
f1[i] = ADD32(f1[i], f1[i-1]); /* f1 is still in Q24 */
|
||||
f2[i] = SUB32(f2[i], f2[i-1]); /* f1 is still in Q24 */
|
||||
}
|
||||
|
||||
/* compute the LP coefficients */
|
||||
/* fx[0] is not needed anymore, acces the f1 and f2 buffers via the fp1 and fp2 pointers */
|
||||
for (i=0; i<5; i++) {
|
||||
/* i in [0,5[ : LP[i] = (f1[i] + f2[i])/2 */
|
||||
LP[i] = PSHR(ADD32(fp1[i], fp2[i]),13); /* f1 and f2 in Q24, LP in Q12 */
|
||||
/* i in [5,9[ : LP[i] = (f1[9-i] - f2[9-i])/2 */
|
||||
LP[9-i] = PSHR(SUB32(fp1[i], fp2[i]),13); /* f1 and f2 in Q24, LP in Q12 */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computePolynomialCoefficients : according to spec. 3.2.6 */
|
||||
/* parameters: */
|
||||
/* -(i) qLSP : 10 LSP to be converted in Q0.15 range [-1, +1[ */
|
||||
/* -(o) f : 6 values in Q24 : polynomial coefficients on 32 bits */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void computePolynomialCoefficients(word16_t qLSP[], word32_t f[])
|
||||
{
|
||||
int i,j;
|
||||
|
||||
/* init values */
|
||||
/* f[-1] which is not available is to be egal at 0, it is directly removed in the following when used as a factor */
|
||||
f[0] = 16777216; /* 1 in Q24, f[0] is used only for the other coefficient computation */
|
||||
|
||||
/* correspont to i=1 in the algorithm description in spec. 3.2.6 */
|
||||
f[1] = MULT16_16(qLSP[0], -1024); /* f[1] = -2*qLSP[0], with qLSP in Q0.15 * -2*2^9(-1024) -> f[1] in Q1.24 */
|
||||
|
||||
/* so we start with i=2 */
|
||||
/* Note : index of qLSP are -1 respect of what is in the spec because qLSP array is indexed from 0-9 and not 1-10 */
|
||||
for (i=2; i<6; i++) {
|
||||
/* spec: f[i] = 2(f[i-2] - qLSP[2i-1]*f[i-1]) */
|
||||
f[i] = SSHL(SUB32(f[i-2], MULT16_32_P15(qLSP[2*i-2], f[i-1])),1); /* with qLSP in Q0.15 and f in Q24 */
|
||||
for (j=i-1; j>1; j--) { /* case of j=1 is just doing f[1] -= 2*qLSP[2i-1], done after the loop in order to avoid reference to f[-1] */
|
||||
/* spec: f[j] = f[j] -2*qLSP[2i-i]*f[j-1] + f[j-2] (all right terms refer to the value at the previous iteration on i indexed loop) */
|
||||
f[j] = ADD32(f[j], SUB32(f[j-2], MULT16_32_P14(qLSP[2*i-2], f[j-1]))); /* qLPS in Q0.15 and f in Q24, using MULT16_32_P14 instead of P15 does the *2 on qLSP. Result in Q24 */
|
||||
}
|
||||
/* f[1] -= 2*qLSP[2i-1] */
|
||||
f[1] = SUB32(f[1], SSHL(qLSP[2*i-2],10)); /* qLSP in Q0.15, must be shift by 9 to get in Q24 and one more to be *2 */
|
||||
}
|
||||
return;
|
||||
}
|
29
bcg729/src/qLSP2LP.h
Normal file
29
bcg729/src/qLSP2LP.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef QLSP2LP_H
|
||||
#define QLSP2LP_H
|
||||
/*****************************************************************************/
|
||||
/* qLSP2LP : convert qLSP into LP parameters according to spec. 3.2.6 */
|
||||
/* parameters: */
|
||||
/* -(i) qLSP : 10 LSP to be converted in Q0.15 range [-1, +1[ */
|
||||
/* -(o) LP : 10 LP coefficients in Q12 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void qLSP2LP(word16_t qLSP[], word16_t LP[]);
|
||||
#endif /* ifndef QLSP2LP_H */
|
213
bcg729/src/typedef.h
Normal file
213
bcg729/src/typedef.h
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TYPEDEF_H
|
||||
#define TYPEDEF_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "codecParameters.h"
|
||||
#include "bcg729/encoder.h"
|
||||
#include "bcg729/decoder.h"
|
||||
|
||||
typedef int16_t word16_t;
|
||||
typedef uint16_t uword16_t;
|
||||
typedef int32_t word32_t;
|
||||
typedef uint32_t uword32_t;
|
||||
typedef int64_t word64_t;
|
||||
|
||||
struct bcg729VADChannelContextStruct_struct {
|
||||
/* buffer used during the init period - first N0(32) frames */
|
||||
word32_t initEfSum;
|
||||
word32_t initZCSum;
|
||||
word32_t initLSFSum[NB_LSP_COEFF];
|
||||
uint8_t nbValidInitFrame; /* VAD init needs 32 frames to be completed but we must use only frame with Ef > 15dB so we must count them */
|
||||
|
||||
|
||||
word16_t meanZC; /* in Q15 */
|
||||
word16_t meanEf; /* in Q11 */
|
||||
word16_t meanEl; /* in Q11 */
|
||||
word16_t meanLSF[NB_LSP_COEFF]; /* in Q2.13 */
|
||||
uint32_t frameCount; /* number of frame processed, used to close the initialisation period */
|
||||
uint32_t updateCount; /* number of frame leading to an update of running averages */
|
||||
word16_t EfBuffer[N0]; /* store the last N0 Ef values to be able to retrieve the min */
|
||||
uint8_t SVDm1; /* smoothed voice activity decision on last frame */
|
||||
uint8_t SVDm2; /* smoothed voice activity decision on 2 frames ago */
|
||||
uint32_t Count_inert; /* defined in appendix II, used to implement hysteresis on VOICE->NOISE switching */
|
||||
uint8_t secondStageVADSmoothingFlag; /* flag defined as FVD-1 in spec B3.6 */
|
||||
uint32_t smoothingCounter; /* counter Ce defined in spec B3.6 */
|
||||
word16_t previousFrameEf; /* in Q11 */
|
||||
word32_t noiseContinuityCounter; /* counter Cs defined in spec B3.6 */
|
||||
};
|
||||
typedef struct bcg729VADChannelContextStruct_struct bcg729VADChannelContextStruct;
|
||||
|
||||
struct bcg729DTXChannelContextStruct_struct {
|
||||
/* store past autocorrelations coefficients for 6 past frames and current one(at index 0) spec B4.1.1 */
|
||||
word32_t autocorrelationCoefficients[7][NB_LSP_COEFF+1];
|
||||
int8_t autocorrelationCoefficientsScale[7];
|
||||
|
||||
uint8_t previousVADflag; /* previous frame VAD : 1 VOICE 0 NOISE */
|
||||
word32_t previousResidualEnergy;
|
||||
uint8_t previousResidualEnergyScale;
|
||||
int8_t previousDecodedLogEnergy; /* store the last decodedLog energy sent in a SID frame */
|
||||
uint8_t count_fr; /* count the number of noise frame since last SID frame was sent */
|
||||
word32_t SIDLPCoefficientAutocorrelation[NB_LSP_COEFF+1]; /* the autocorrelation of LP coefficients as described in eq B.13 in Q20 */
|
||||
word16_t currentSIDGain; /* gain in Q3 */
|
||||
word16_t smoothedSIDGain; /* gain in Q3 */
|
||||
uint16_t pseudoRandomSeed; /* seed used in the pseudo random number generator for excitation generation */
|
||||
word16_t qLSPCoefficients[NB_LSP_COEFF]; /* current Quantized LSP coefficient in Q15, saved to be re-used in case of untransmitted frame */
|
||||
word32_t reflectionCoefficients[NB_LSP_COEFF]; /* used to generate the RFC3389 payload, generated during LP computation */
|
||||
int8_t decodedLogEnergy; /* log10(frame residual energy), used to generate noise level for RFC3389 paylaod */
|
||||
};
|
||||
typedef struct bcg729DTXChannelContextStruct_struct bcg729DTXChannelContextStruct;
|
||||
|
||||
struct bcg729CNGChannelContextStruct_struct {
|
||||
word16_t receivedSIDGain; /* gain in Q3 */
|
||||
word16_t smoothedSIDGain; /* gain in Q3 */
|
||||
word16_t qLSP[NB_LSP_COEFF]; /* qLSP in Q0.15 */
|
||||
word64_t lastFrameEnergy; /* in Q0 */
|
||||
};
|
||||
|
||||
typedef struct bcg729CNGChannelContextStruct_struct bcg729CNGChannelContextStruct;
|
||||
|
||||
/* define the context structure to store all static data for a decoder channel */
|
||||
struct bcg729DecoderChannelContextStruct_struct {
|
||||
/*** buffers used in decoder bloc ***/
|
||||
word16_t previousqLSP[NB_LSP_COEFF]; /* previous quantised LSP in Q0.15 */
|
||||
word16_t excitationVector[L_PAST_EXCITATION + L_FRAME]; /* in Q0 this vector contains:
|
||||
0->153 : the past excitation vector.(length is Max Pitch Delay: 144 + interpolation window size : 10)
|
||||
154-> 154+L_FRAME-1 : the current frame adaptative Code Vector first used to compute then the excitation vector */
|
||||
word16_t boundedAdaptativeCodebookGain; /* the pitch gain from last subframe bounded in range [0.2,0.8] in Q0.14 */
|
||||
word16_t adaptativeCodebookGain; /* the gains needs to be stored in case of frame erasure in Q14 */
|
||||
word16_t fixedCodebookGain; /* in Q14.1 */
|
||||
word16_t reconstructedSpeech[NB_LSP_COEFF+L_FRAME]; /* in Q0, output of the LP synthesis filter, the first 10 words store the previous frame output */
|
||||
uint16_t pseudoRandomSeed; /* seed used in the pseudo random number generator */
|
||||
uint16_t CNGpseudoRandomSeed; /* seed used in the pseudo random number generator for CNG */
|
||||
|
||||
/*** buffers used in decodeLSP bloc ***/
|
||||
word16_t lastqLSF[NB_LSP_COEFF]; /* this buffer stores the last qLSF to be used in case of frame lost in Q2.13 */
|
||||
/* buffer to store the last 4 frames codewords, used to compute the current qLSF */
|
||||
word16_t previousLCodeWord[MA_MAX_K][NB_LSP_COEFF]; /* in Q2.13, buffer to store the last 4 frames codewords, used to compute the current qLSF */
|
||||
/* the values stored are the codewords computed from the codebooks and rearranged */
|
||||
word16_t lastValidL0; /* this one store the L0 of last valid frame to be used in case of frame erased */
|
||||
|
||||
/*** buffer used in decodeAdaptativeCodeVector bloc ***/
|
||||
uint16_t previousIntPitchDelay; /* store the last valid Integer Pitch Delay computed, used in case of parity error or frame erased */
|
||||
|
||||
/*** buffer used in decodeGains bloc ***/
|
||||
word16_t previousGainPredictionError[4]; /* the last four gain prediction error U(m) eq69 and eq72, spec3.9.1 in Q10*/
|
||||
|
||||
/*** buffers used in postFilter bloc ***/
|
||||
word16_t residualSignalBuffer[MAXIMUM_INT_PITCH_DELAY+L_FRAME]; /* store the residual signal (current subframe and MAXIMUM_INT_PITCH_DELAY of previous values) in Q0 */
|
||||
word16_t scaledResidualSignalBuffer[MAXIMUM_INT_PITCH_DELAY+L_FRAME]; /* same as previous but in Q-2 */
|
||||
word16_t longTermFilteredResidualSignalBuffer[1+L_SUBFRAME]; /* the output of long term filter in Q0, need 1 word from previous subframe for tilt compensation filter */
|
||||
word16_t *longTermFilteredResidualSignal; /* points to the beginning of current subframe longTermFilteredResidualSignal */
|
||||
word16_t shortTermFilteredResidualSignalBuffer[NB_LSP_COEFF+L_SUBFRAME]; /* the output of short term filter(synthesis filter) in Q0, need NB_LSP_COEFF word from previous subframe as filter memory */
|
||||
word16_t *shortTermFilteredResidualSignal; /* points to the beginning of current subframe shortTermFilteredResidualSignal */
|
||||
word16_t previousAdaptativeGain; /* previous gain for adaptative gain control */
|
||||
|
||||
/*** buffers used in postProcessing bloc ***/
|
||||
word16_t inputX0;
|
||||
word16_t inputX1;
|
||||
word32_t outputY2;
|
||||
word32_t outputY1;
|
||||
|
||||
/* SID frame management */
|
||||
bcg729CNGChannelContextStruct *CNGChannelContext; /* store informations specific to CNG */
|
||||
uint8_t previousFrameIsActiveFlag; /* store last processed frame type */
|
||||
|
||||
};
|
||||
|
||||
/* define the context structure to store all static data for an encoder channel */
|
||||
struct bcg729EncoderChannelContextStruct_struct {
|
||||
/*** buffers used in decoder bloc ***/
|
||||
/* Signal buffer mapping : 240 word16_t length */
|
||||
/* <---- 120 word16_t -->|<---- 80 word16_t ---->|<---- 40 word16_t --->| */
|
||||
/* |----- old signal -----|----------- current frame -------------------|-----next subframe 1 ------------| */
|
||||
/* |----- subframe 1 -----|----- subframe 2 -----| */
|
||||
/* |--------------- last input frame -----------------------| */
|
||||
/* ^ ^ ^ */
|
||||
/* | | | */
|
||||
/* signalBuffer signalCurrentFrame signalLastInputFrame */
|
||||
word16_t signalBuffer[L_LP_ANALYSIS_WINDOW]; /* this buffer stores the input signal */
|
||||
word16_t *signalLastInputFrame; /* point to the beginning of the last frame in the signal buffer */
|
||||
word16_t *signalCurrentFrame; /* point to the beginning of the current frame in the signal buffer */
|
||||
word16_t previousLSPCoefficients[NB_LSP_COEFF]; /* LSP coefficient of previous frame */
|
||||
word16_t previousqLSPCoefficients[NB_LSP_COEFF]; /* Quantized LSP coefficient of previous frame */
|
||||
word16_t weightedInputSignal[MAXIMUM_INT_PITCH_DELAY+L_FRAME]; /* buffer storing the weightedInputSignal on current frame and MAXIMUM_INT_PITCH_DELAY of previous values */
|
||||
word16_t excitationVector[L_PAST_EXCITATION + L_FRAME]; /* in Q0 this vector contains:
|
||||
0->153 : the past excitation vector.(length is Max Pitch Delay: 144 + interpolation window size : 10)
|
||||
154-> 154+L_FRAME-1 : the current frame adaptative Code Vector first used to compute then the excitation vector */
|
||||
word16_t targetSignal[NB_LSP_COEFF+L_SUBFRAME]; /* in Q0, buffer holding the target signal (x[n]) as in spec A.3.6, the first NB_LSP_COEFF values are memory from previous subframe used in filtering(computed according to spec A.3.10), the following values are the target signal for current subframe */
|
||||
word16_t lastQuantizedAdaptativeCodebookGain; /* in Q14, the quantized adaptive codebook gain from previous subframe */
|
||||
|
||||
/*** buffer used in preProcessing ***/
|
||||
word16_t inputX0, inputX1;
|
||||
word32_t outputY2, outputY1;
|
||||
|
||||
/*** buffer used in LSPQuantization ***/
|
||||
word16_t previousqLSF[MA_MAX_K][NB_LSP_COEFF]; /* previousqLSF of the last 4(MA pred buffer size) frames in Q13, contains actually quantizer output (l) and not LSF (w)*/
|
||||
|
||||
/*** buffer used in gainQuantization ***/
|
||||
word16_t previousGainPredictionError[4]; /* the last four gain prediction error U(m) eq69 and eq72, spec3.9.1 in Q10*/
|
||||
|
||||
/*** VAD management ***/
|
||||
bcg729VADChannelContextStruct *VADChannelContext;
|
||||
bcg729DTXChannelContextStruct *DTXChannelContext;
|
||||
};
|
||||
|
||||
/* MAXINTXX define the maximum signed integer value on XX bits(2^(XX-1) - 1) */
|
||||
/* used to check on overflows in fixed point mode */
|
||||
#define MAXINT16 0x7fff
|
||||
#define MAXUINT16 0xffff
|
||||
#define MAXINT17 0xffff
|
||||
#define MAXINT28 0x7ffffff
|
||||
#define MAXINT29 0xfffffff
|
||||
#define MININT32 0x80000000
|
||||
#define MAXINT32 0x7fffffff
|
||||
#define MAXINT64 0x7fffffffffffffffLL
|
||||
|
||||
/* several values used for inits */
|
||||
#define ONE_IN_Q31 0x7FFFFFFF
|
||||
#define ONE_IN_Q30 0x40000000
|
||||
#define ONE_IN_Q27 0x08000000
|
||||
#define ONE_IN_Q15 0x00008000
|
||||
#define ONE_IN_Q13 0x00002000
|
||||
#define ONE_IN_Q12 0x00001000
|
||||
#define ONE_IN_Q11 0x00000800
|
||||
|
||||
#define HALF_PI_Q13 12868
|
||||
#define HALF_PI_Q15 51472
|
||||
|
||||
/* 0.04*Pi + 1 and 0.92*Pi - 1 used by LSPQuantization */
|
||||
#define OO4PIPLUS1_IN_Q13 9221
|
||||
#define O92PIMINUS1_IN_Q13 15485
|
||||
/* 1.2 in Q14 */
|
||||
#define ONE_POINT_2_IN_Q14 19661
|
||||
/* 0.7 in Q12 */
|
||||
#define O7_IN_Q12 2867
|
||||
/* 0.2 in Q14 */
|
||||
#define O2_IN_Q14 3277
|
||||
/* 0.2 in Q15 */
|
||||
#define O2_IN_Q15 6554
|
||||
|
||||
#endif /* ifndef TYPEDEF_H */
|
383
bcg729/src/utils.c
Normal file
383
bcg729/src/utils.c
Normal file
|
@ -0,0 +1,383 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "typedef.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "codecParameters.h"
|
||||
#include "g729FixedPointMath.h"
|
||||
#include "codebooks.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* insertionSort : sort an array in growing order using insertion algorithm */
|
||||
/* parameters : */
|
||||
/* -(i/o) x: the array to be sorted */
|
||||
/* -(i) length: the array length */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void insertionSort(word16_t x[], int length)
|
||||
{
|
||||
int i, j;
|
||||
word16_t currentValue;
|
||||
|
||||
for (i=1; i<length; i++) {
|
||||
currentValue = x[i];
|
||||
|
||||
j = i-1;
|
||||
while ((j>=0) && (x[j]>currentValue)) {
|
||||
x[j+1] = x[j];
|
||||
j--;
|
||||
}
|
||||
|
||||
x[j+1] = currentValue;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* getMinInArray : get the minimum value from an array */
|
||||
/* parameters : */
|
||||
/* -(i) x: the array to be searched */
|
||||
/* -(i) length: the array length */
|
||||
/* returns : the minimum value found in the array */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
word16_t getMinInArray(word16_t x[], int length) {
|
||||
word16_t min = MAXINT16;
|
||||
int i;
|
||||
for (i=0; i<length; i++) {
|
||||
if (x[i]<min) min = x[i];
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeParity : compute parity for pitch delay adaptative codebook index */
|
||||
/* XOR of the 6 MSB (pitchDelay on 8 bits) */
|
||||
/* parameters : */
|
||||
/* -(i) adaptativeCodebookIndex: the pitch delay on 8 bits */
|
||||
/* return value : */
|
||||
/* the parity bit */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
uint16_t computeParity(uint16_t adaptativeCodebookIndex)
|
||||
{
|
||||
int i;
|
||||
uint16_t parity = 1;
|
||||
adaptativeCodebookIndex = SHR(adaptativeCodebookIndex,2); /* ignore the two LSB */
|
||||
|
||||
for (i=0; i<6; i++) {
|
||||
parity ^= adaptativeCodebookIndex&(uint16_t)1; /* XOR with the LSB */
|
||||
adaptativeCodebookIndex = SHR(adaptativeCodebookIndex,1);
|
||||
}
|
||||
|
||||
return parity;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* rearrangeCoefficients: rearrange coefficients according to spec 3.2.4 */
|
||||
/* Have a minimum distance of J beetwen two consecutive coefficients */
|
||||
/* parameters: */
|
||||
/* -(i/o) qLSP: 10 ordered coefficients in Q13 replaced by new values */
|
||||
/* if needed */
|
||||
/* -(i) J: minimum distance between coefficients in Q0.13 (10 or 5) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void rearrangeCoefficients(word16_t qLSP[], word16_t J)
|
||||
{ /* qLSP in Q2.13 and J in Q0.13(fitting on 4 bits: possible values 10 and 5) */
|
||||
int i=1;
|
||||
word16_t delta; /* in Q0.13 */
|
||||
|
||||
for (i=1; i<NB_LSP_COEFF; i++) {
|
||||
delta = (ADD16(SUB16(qLSP[i-1],qLSP[i]),J))/2; /* delta = (l[i-1] - l[i] +J)/2 */
|
||||
if (delta > 0) {
|
||||
qLSP[i-1] = SUB16(qLSP[i-1], delta); /* qLSP still in Q2.13 */
|
||||
qLSP[i] = ADD16(qLSP[i], delta);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* synthesisFilter : compute 1/[A(z)] using the following algorithm */
|
||||
/* filteredSignal[n] = inputSignal[n] */
|
||||
/* - Sum(i=1..10)filterCoefficients[i]*filteredSignal[n-i] */
|
||||
/* for n in [0, L_SUBFRAME[ */
|
||||
/* parameters: */
|
||||
/* -(i) inputSignal: 40 values in Q0 */
|
||||
/* -(i) filterCoefficients: 10 coefficients in Q12 */
|
||||
/* -(i/o) filteredSignal: 50 values in Q0 accessed in ranges [-10,-1] */
|
||||
/* as input and [0, 39] as output. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void synthesisFilter(word16_t inputSignal[], word16_t filterCoefficients[], word16_t filteredSignal[])
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
word32_t acc = SSHL(inputSignal[i],12); /* acc get the first term of the sum, in Q12 (inputSignal is in Q0)*/
|
||||
int j;
|
||||
for (j=0; j<NB_LSP_COEFF; j++) {
|
||||
acc = MSU16_16(acc, filterCoefficients[j], filteredSignal[i-j-1]); /* filterCoefficients in Q12 and signal in Q0 -> acc in Q12 */
|
||||
}
|
||||
filteredSignal[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* shift right acc to get it back in Q0 and check overflow on 16 bits */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* correlateVectors : compute the correlations between two vectors of */
|
||||
/* L_SUBFRAME length: c[i] = Sum(x[j]*y[j-i]) j in [i, L_SUBFRAME[ */
|
||||
/* parameters: */
|
||||
/* -(i) x : L_SUBFRAME length input vector on 16 bits */
|
||||
/* -(i) y : L_SUBFRAME length input vector on 16 bits */
|
||||
/* -(o) c : L_SUBFRAME length output vector on 32 bits */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void correlateVectors (word16_t x[], word16_t y[], word32_t c[])
|
||||
{
|
||||
int i,j;
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
c[i] = 0;
|
||||
for (j=i; j<L_SUBFRAME; j++) {
|
||||
c[i] = MAC16_16(c[i], x[j], y[j-i]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*** gain related functions ***/
|
||||
/*****************************************************************************/
|
||||
/* MACodeGainPrediction : spec 3.9.1 */
|
||||
/* parameters: */
|
||||
/* -(i) previousGainPredictionError: qU(m) in eq69 4 values in Q10 */
|
||||
/* -(i) fixedCodebookVector: the current subframe fixed codebook vector */
|
||||
/* 40 values in Q1.13 */
|
||||
/* return value : */
|
||||
/* - predicted Fixed Codebook gain on 32 bits in Q16 range [3, 1830] */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
word32_t MACodeGainPrediction(word16_t *previousGainPredictionError, word16_t *fixedCodebookVector)
|
||||
{
|
||||
|
||||
/***** algorithm described in spec 3.9.1 *****/
|
||||
/*** first compute eq66: E = 10log10((Sum0-39(fixedCodebookVector^2))/40) ***/
|
||||
/*** directly used in eq71 in E| - E = 30 - 10log10((Sum0-39(fixedCodebookVector^2))/40) */
|
||||
/* = 30 - 10log10((Sum*2^26)/(40*2^26)) */
|
||||
/* = 30 + 10log10(40*2^26) - (10/log2(10))*log2(Sum*2^26) [The Sum is computed in Q26] */
|
||||
/* = 30 + 94.2884 - 3.0103*log2(Sum*2^26) */
|
||||
/* = 124.2884 - 3.0103*log2(Sum*2^26) = E| - E as used in eq71 */
|
||||
|
||||
/* compute the sum of squares of fixedCodebookVector in Q26 */
|
||||
int i;
|
||||
word32_t fixedCodebookVectorSquaresSum = 0;
|
||||
word32_t acc;
|
||||
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
if (fixedCodebookVector[i] != 0) { /* as most of the codebook vector is egal to 0, it worth checking it to avoid useless multiplications */
|
||||
/* fixedCodebookVector in Q1.13 and final sum in range [4, 8.48] (4 values filled with abs values: 1,1,1.8 and 1.8 in the vector give max value of sum) */
|
||||
/* fixedCodebookVectorSquaresSum is then in Q4.26 */
|
||||
fixedCodebookVectorSquaresSum = MAC16_16(fixedCodebookVectorSquaresSum, fixedCodebookVector[i], fixedCodebookVector[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* compute E| - E as in eq71, result in Q16 */
|
||||
/* acc = 124.2884 - 3.0103*log2(Sum) */
|
||||
/* acc = 8145364[32 bits Q16] - 24660[16 bits Q2.13]*log2(Sum)[32 bits Q16] */
|
||||
acc = MAC16_32_Q13(8145364, -24660, g729Log2_Q0Q16(fixedCodebookVectorSquaresSum)); /* acc in Q16 */
|
||||
|
||||
/* accumulate the MA prediction described in eq69 to the previous Sum, result will be in E~(m) + E| -E as used in eq71 */
|
||||
/* acc in Q16->Q24, previousGainPredictionError in Q10 and MAPredictionCoefficients in Q0.14*/
|
||||
acc = SHL(acc,8); /* acc in Q24 to match the fixed point of next accumulations */
|
||||
for (i=0; i<4; i++) {
|
||||
acc = MAC16_16(acc, previousGainPredictionError[i], MAPredictionCoefficients[i]);
|
||||
}
|
||||
/* acc range [10, 65] -> Q6.24 */
|
||||
|
||||
|
||||
/* compute eq71, we already have the exposant in acc so */
|
||||
/* g'c = 10^(acc/20) */
|
||||
/* = 2^((acc*ln(10))/(20*ln(2))) */
|
||||
/* = 2^(0,1661*acc) */
|
||||
acc = SHR(acc,2); /* Q24->Q22 */
|
||||
acc = MULT16_32_Q15(5442, acc); /* 5442 is 0.1661 in Q15 -> acc now in Q4.22 range [1.6, 10.8] */
|
||||
acc = PSHR(acc,11); /* get acc in Q4.11 */
|
||||
|
||||
return g729Exp2_Q11Q16((word16_t)acc); /* acc fits on 16 bits, cast it to word16_t to send it to the exp2 function, output in Q16*/
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeGainPredictionError : apply eq72 to compute current fixed Codebook */
|
||||
/* gain prediction error and store the result in the adhoc array */
|
||||
/* parameters : */
|
||||
/* -(i) fixedCodebookGainCorrectionFactor: gamma in eq72 in Q3.12 */
|
||||
/* -(i/o) previousGainPredictionError: array to be updated in Q10 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void computeGainPredictionError(word16_t fixedCodebookGainCorrectionFactor, word16_t *previousGainPredictionError)
|
||||
{
|
||||
/* need to compute eq72: 20log10(fixedCodebookGainCorrectionFactor) */
|
||||
/* = (20/log2(10))*log2(fixedCodebookGainCorrectionFactor) */
|
||||
/* = 6.0206*log2(fixedCodebookGainCorrectionFactor) */
|
||||
/* log2 input in Q0, output in Q16,fixedCodebookGainCorrectionFactor being in Q12, we shall substract 12 in Q16(786432) to the result of log2 function -> final result in Q2.16 */
|
||||
word32_t currentGainPredictionError = SUB32(g729Log2_Q0Q16(fixedCodebookGainCorrectionFactor), 786432);
|
||||
currentGainPredictionError = PSHR(MULT16_32_Q12(24660, currentGainPredictionError),6); /* 24660 = 6.0206 in Q3.12 -> mult result in Q16, precise shift right to get it in Q4.10 */
|
||||
|
||||
/* shift the array and insert the current Prediction Error */
|
||||
previousGainPredictionError[3] = previousGainPredictionError[2];
|
||||
previousGainPredictionError[2] = previousGainPredictionError[1];
|
||||
previousGainPredictionError[1] = previousGainPredictionError[0];
|
||||
previousGainPredictionError[0] = (word16_t)currentGainPredictionError;
|
||||
}
|
||||
|
||||
|
||||
/*** bitStream to parameters Array conversions functions ***/
|
||||
/* Note: these functions are in utils.c because used by test source code too */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* parametersArray2BitStream : convert array of parameters to bitStream */
|
||||
/* according to spec 4 - Table 8 and following mapping of values */
|
||||
/* 0 -> L0 (1 bit) */
|
||||
/* 1 -> L1 (7 bits) */
|
||||
/* 2 -> L2 (5 bits) */
|
||||
/* 3 -> L3 (5 bits) */
|
||||
/* 4 -> P1 (8 bit) */
|
||||
/* 5 -> P0 (1 bits) */
|
||||
/* 6 -> C1 (13 bits) */
|
||||
/* 7 -> S1 (4 bits) */
|
||||
/* 8 -> GA1(3 bits) */
|
||||
/* 9 -> GB1(4 bits) */
|
||||
/* 10 -> P2 (5 bits) */
|
||||
/* 11 -> C2 (13 bits) */
|
||||
/* 12 -> S2 (4 bits) */
|
||||
/* 13 -> GA2(3 bits) */
|
||||
/* 14 -> GB2(4 bits) */
|
||||
/* parameters: */
|
||||
/* -(i) parameters : 16 values parameters array */
|
||||
/* -(o) bitStream : the 16 values streamed on 80 bits in a */
|
||||
/* 10*8bits values array */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void parametersArray2BitStream(uint16_t parameters[], uint8_t bitStream[])
|
||||
{
|
||||
bitStream[0] = ((parameters[0]&((uint16_t) 0x1))<<7) |
|
||||
(parameters[1]&((uint16_t) 0x7f));
|
||||
|
||||
bitStream[1] = ((parameters[2]&((uint16_t) 0x1f))<<3) |
|
||||
((parameters[3]>>2)&((uint16_t) 0x7));
|
||||
|
||||
bitStream[2] = ((parameters[3]&((uint16_t) 0x3))<<6) |
|
||||
((parameters[4]>>2)&((uint16_t) 0x3f));
|
||||
|
||||
bitStream[3] = ((parameters[4]&((uint16_t) 0x3))<<6) |
|
||||
((parameters[5]&((uint16_t) 0x1))<<5) |
|
||||
((parameters[6]>>8)&((uint16_t) 0x1f));
|
||||
|
||||
bitStream[4] = ((parameters[6])&((uint16_t) 0xff));
|
||||
|
||||
bitStream[5] = ((parameters[7]&((uint16_t) 0xf))<<4) |
|
||||
((parameters[8]&((uint16_t) 0x7))<<1) |
|
||||
((parameters[9]>>3)&((uint16_t) 0x1));
|
||||
|
||||
bitStream[6] = ((parameters[9]&((uint16_t) 0x7))<<5) |
|
||||
(parameters[10]&((uint16_t) 0x1f));
|
||||
|
||||
bitStream[7] = ((parameters[11]>>5)&((uint16_t) 0xff));
|
||||
|
||||
bitStream[8] = ((parameters[11]&((uint16_t) 0x1f))<<3) |
|
||||
((parameters[12]>>1)&((uint16_t) 0x7));
|
||||
|
||||
bitStream[9] = ((parameters[12]&((uint16_t) 0x1))<<7) |
|
||||
((parameters[13]&((uint16_t) 0x7))<<4) |
|
||||
(parameters[14]&((uint16_t) 0xf));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* CNGparametersArray2BitStream : convert array of parameters to bitStream */
|
||||
/* according to spec B4.3 - Table B2 and following mapping of values */
|
||||
/* 0 -> L0 (1 bit) */
|
||||
/* 1 -> L1 (5 bits) */
|
||||
/* 2 -> L2 (4 bits) */
|
||||
/* 3 -> Gain (5 bits) */
|
||||
/* parameters: */
|
||||
/* -(i) parameters : 4 values parameters array */
|
||||
/* -(o) bitStream : the 4 values streamed on 15 bits in a */
|
||||
/* 2*8bits values array */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
void CNGparametersArray2BitStream(uint16_t parameters[], uint8_t bitStream[]) {
|
||||
bitStream[0] = ((parameters[0]&((uint16_t) 0x1))<<7) |
|
||||
((parameters[1]&((uint16_t) 0x1f))<<2) |
|
||||
((parameters[2]>>2)&((uint16_t) 0x3));
|
||||
|
||||
bitStream[1] = ((parameters[2]&((uint16_t) 0x03))<<6) |
|
||||
((parameters[3]&((uint16_t) 0x1f))<<1);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* parametersArray2BitStream : convert bitStream to an array of parameters */
|
||||
/* reverse operation of previous funtion */
|
||||
/* parameters: */
|
||||
/* -(i) bitStream : the 16 values streamed on 80 bits in a */
|
||||
/* 10*8bits values array */
|
||||
/* -(o) parameters : 16 values parameters array */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void parametersBitStream2Array(const uint8_t bitStream[], uint16_t parameters[])
|
||||
{
|
||||
parameters[0] = (bitStream[0]>>7)&(uint16_t)0x1;
|
||||
parameters[1] = bitStream[0]&(uint16_t)0x7f;
|
||||
parameters[2] = (bitStream[1]>>3)&(uint16_t)0x1f;
|
||||
parameters[3] = (((uint16_t)bitStream[1]&(uint16_t)0x7)<<2) | ((bitStream[2]>>6)&(uint16_t)0x3);
|
||||
parameters[4] = (((uint16_t)bitStream[2])&(uint16_t)0x3f)<<2 | ((bitStream[3]>>6)&(uint16_t)0x3);;
|
||||
parameters[5] = (bitStream[3]>>5)&(uint16_t)0x1;
|
||||
parameters[6] = (((uint16_t)(bitStream[3]&(uint16_t)0x1f))<<8)| bitStream[4];
|
||||
parameters[7] = (bitStream[5]>>4)&(uint16_t)0xf;
|
||||
parameters[8] = (bitStream[5]>>1)&(uint16_t)0x7;
|
||||
parameters[9] = (((uint16_t)bitStream[5]&(uint16_t)0x1)<<3)|((bitStream[6]>>5)&(uint16_t)0x7);
|
||||
parameters[10]= (uint16_t)bitStream[6]&(uint16_t)0x1f;
|
||||
parameters[11]= (((uint16_t)bitStream[7])<<5)|((bitStream[8]>>3)&(uint16_t)0x1f);
|
||||
parameters[12]= ((bitStream[8]&(uint16_t)0x7)<<1) | ((bitStream[9]>>7)&(uint16_t)0x1);
|
||||
parameters[13]= (bitStream[9]>>4)&(uint16_t)0x7;
|
||||
parameters[14]= bitStream[9]&(uint16_t)0xf;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* pseudoRandom : generate pseudo random number as in spec 4.4.4 eq96 */
|
||||
/* parameters: */
|
||||
/* -(i/o) randomGeneratorSeed(updated by this function) */
|
||||
/* return value : */
|
||||
/* - a unsigned 16 bits pseudo random number */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
uint16_t pseudoRandom(uint16_t *randomGeneratorSeed)
|
||||
{
|
||||
/* pseudoRandomSeed is stored in an uint16_t var, we shall not worry about overflow here */
|
||||
/* pseudoRandomSeed*31821 + 13849; */
|
||||
*randomGeneratorSeed = MAC16_16(13849, (*randomGeneratorSeed), 31821);
|
||||
return *randomGeneratorSeed;
|
||||
}
|
224
bcg729/src/utils.h
Normal file
224
bcg729/src/utils.h
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define BCG729_INLINE __inline
|
||||
#else
|
||||
#define BCG729_INLINE inline
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* insertionSort : sort an array in growing order using insertion algorithm */
|
||||
/* parameters : */
|
||||
/* -(i/o) x: the array to be sorted */
|
||||
/* -(i) length: the array length */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void insertionSort(word16_t x[], int length);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* getMinInArray : get the minimum value from an array */
|
||||
/* parameters : */
|
||||
/* -(i) x: the array to be searched */
|
||||
/* -(i) length: the array length */
|
||||
/* returns : the minimum value found in the array */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
word16_t getMinInArray(word16_t x[], int length);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeParity : compute parity for pitch delay adaptative codebook index */
|
||||
/* XOR of the 6 MSB (pitchDelay on 8 bits) */
|
||||
/* parameters : */
|
||||
/* -(i) adaptativeCodebookIndex: the pitch delay on 8 bits */
|
||||
/* return value : */
|
||||
/* the parity bit */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
uint16_t computeParity(uint16_t adaptativeCodebookIndex);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* rearrangeCoefficients: rearrange coefficients according to spec 3.2.4 */
|
||||
/* Have a minimum distance of J beetwen two consecutive coefficients */
|
||||
/* parameters: */
|
||||
/* -(i/o) qLSP: 10 ordered coefficients in Q13 replaced by new values */
|
||||
/* if needed */
|
||||
/* -(i) J: minimum distance between coefficients in Q0.13 (10 or 5) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void rearrangeCoefficients(word16_t qLSP[], word16_t J);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* synthesisFilter : compute 1/[A(z)] using the following algorithm */
|
||||
/* filteredSignal[n] = inputSignal[n] */
|
||||
/* - Sum(i=1..10)filterCoefficients[i]*filteredSignal[n-i] */
|
||||
/* for n in [0, L_SUBFRAME[ */
|
||||
/* parameters: */
|
||||
/* -(i) inputSignal: 40 values in Q0 */
|
||||
/* -(i) filterCoefficients: 10 coefficients in Q12 */
|
||||
/* -(i/o) filteredSignal: 50 values in Q0 accessed in ranges [-10,-1] */
|
||||
/* as input and [0, 39] as output. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void synthesisFilter(word16_t inputSignal[], word16_t filterCoefficients[], word16_t filteredSignal[]);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* correlateVectors : compute the correlations between two vectors of */
|
||||
/* L_SUBFRAME length: c[i] = Sum(x[j]*y[j-i]) j in [i..L_SUBFRAME] */
|
||||
/* parameters: */
|
||||
/* -(i) x : L_SUBFRAME length input vector on 16 bits */
|
||||
/* -(i) y : L_SUBFRAME length input vector on 16 bits */
|
||||
/* -(o) c : L_SUBFRAME length output vector on 32 bits */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void correlateVectors (word16_t x[], word16_t y[], word32_t c[]);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* countLeadingZeros : return the number of zero heading the argument */
|
||||
/* MSB is excluded as considered sign bit. */
|
||||
/* May be replaced by one asm instruction. */
|
||||
/* parameters : */
|
||||
/* -(i) x : 32 bits values >= 0 (no checking done by this function) */
|
||||
/* return value : */
|
||||
/* - number of heading zeros(MSB excluded. Ex: 0x0080 00000 returns 7) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static BCG729_INLINE uint16_t countLeadingZeros(word32_t x)
|
||||
{
|
||||
uint16_t leadingZeros = 0;
|
||||
if (x==0) return 31;
|
||||
while (x<(word32_t)0x40000000) {
|
||||
leadingZeros++;
|
||||
x <<=1;
|
||||
}
|
||||
return leadingZeros;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* unsignedCountLeadingZeros : return the number of zero heading the argument*/
|
||||
/* May be replaced by one asm instruction. */
|
||||
/* parameters : */
|
||||
/* -(i) x : 32 bits unsigned int values */
|
||||
/* return value : */
|
||||
/* - number of heading zeros(MSB included. Ex: 0x0080 00000 returns 8) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
static BCG729_INLINE uint16_t unsignedCountLeadingZeros(uword32_t x)
|
||||
{
|
||||
uint16_t leadingZeros = 0;
|
||||
if (x==0) return 32;
|
||||
while ((x&0x80000000)!=(uword32_t)0x80000000) {
|
||||
leadingZeros++;
|
||||
x <<=1;
|
||||
}
|
||||
return leadingZeros;
|
||||
}
|
||||
|
||||
|
||||
/*** gain related functions ***/
|
||||
/*****************************************************************************/
|
||||
/* MACodeGainPrediction : spec 3.9.1 */
|
||||
/* parameters: */
|
||||
/* -(i) previousGainPredictionError: qU(m) in eq69 4 values in Q10 */
|
||||
/* -(i) fixedCodebookVector: the current subframe fixed codebook vector */
|
||||
/* 40 values in Q1.13 */
|
||||
/* return value : */
|
||||
/* - predicted Fixed Codebook gain on 32 bits in Q16 range [3, 1830] */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
word32_t MACodeGainPrediction(word16_t *previousGainPredictionError, word16_t *fixedCodebookVector);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* computeGainPredictionError : apply eq72 to compute current fixed Codebook */
|
||||
/* gain prediction error and store the result in the adhoc array */
|
||||
/* parameters : */
|
||||
/* -(i) fixedCodebookGainCorrectionFactor: gamma in eq72 in Q3.12 */
|
||||
/* -(i/o) previousGainPredictionError: array to be updated in Q10 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void computeGainPredictionError(word16_t fixedCodebookGainCorrectionFactor, word16_t *previousGainPredictionError);
|
||||
|
||||
/*** bitStream to parameters Array conversions functions ***/
|
||||
/* Note: these functions are in utils.c because used by test source code too */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* parametersArray2BitStream : convert array of parameters to bitStream */
|
||||
/* according to spec 4 - Table 8 and following mapping of values */
|
||||
/* 0 -> L0 (1 bit) */
|
||||
/* 1 -> L1 (7 bits) */
|
||||
/* 2 -> L2 (5 bits) */
|
||||
/* 3 -> L3 (5 bits) */
|
||||
/* 4 -> P1 (8 bit) */
|
||||
/* 5 -> P0 (1 bits) */
|
||||
/* 6 -> C1 (13 bits) */
|
||||
/* 7 -> S1 (4 bits) */
|
||||
/* 8 -> GA1(3 bits) */
|
||||
/* 9 -> GB1(4 bits) */
|
||||
/* 10 -> P2 (5 bits) */
|
||||
/* 11 -> C2 (13 bits) */
|
||||
/* 12 -> S2 (4 bits) */
|
||||
/* 13 -> GA2(3 bits) */
|
||||
/* 14 -> GB2(4 bits) */
|
||||
/* parameters: */
|
||||
/* -(i) parameters : 16 values parameters array */
|
||||
/* -(o) bitStream : the 16 values streamed on 80 bits in a */
|
||||
/* 10*8bits values array */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void parametersArray2BitStream(uint16_t parameters[], uint8_t bitStream[]);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* CNGparametersArray2BitStream : convert array of parameters to bitStream */
|
||||
/* according to spec B4.3 - Table B2 and following mapping of values */
|
||||
/* 0 -> L0 (1 bit) */
|
||||
/* 1 -> L1 (5 bits) */
|
||||
/* 2 -> L2 (4 bits) */
|
||||
/* 3 -> Gain (5 bits) */
|
||||
/* parameters: */
|
||||
/* -(i) parameters : 4 values parameters array */
|
||||
/* -(o) bitStream : the 4 values streamed on 15 bits in a */
|
||||
/* 2*8bits values array */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void CNGparametersArray2BitStream(uint16_t parameters[], uint8_t bitStream[]);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* parametersArray2BitStream : convert bitStream to an array of parameters */
|
||||
/* reverse operation of previous funtion */
|
||||
/* parameters: */
|
||||
/* -(i) bitStream : the 16 values streamed on 80 bits in a */
|
||||
/* 10*8bits values array */
|
||||
/* -(o) parameters : 16 values parameters array */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void parametersBitStream2Array(const uint8_t bitStream[], uint16_t parameters[]);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* pseudoRandom : generate pseudo random number as in spec 4.4.4 eq96 */
|
||||
/* parameters: */
|
||||
/* -(i/o) randomGeneratorSeed(updated by this function) */
|
||||
/* return value : */
|
||||
/* - a unsigned 16 bits pseudo random number */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
uint16_t pseudoRandom(uint16_t *randomGeneratorSeed);
|
||||
#endif /* ifndef UTILS_H */
|
422
bcg729/src/vad.c
Normal file
422
bcg729/src/vad.c
Normal file
|
@ -0,0 +1,422 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
#include "utils.h"
|
||||
#include "g729FixedPointMath.h"
|
||||
#include "codebooks.h"
|
||||
|
||||
#include "vad.h"
|
||||
|
||||
#define VOICE 1
|
||||
#define NOISE 0
|
||||
|
||||
bcg729VADChannelContextStruct *initBcg729VADChannel() {
|
||||
int i;
|
||||
/* create the context structure */
|
||||
bcg729VADChannelContextStruct *VADChannelContext = malloc(sizeof(bcg729VADChannelContextStruct));
|
||||
memset(VADChannelContext, 0, sizeof(*VADChannelContext)); /* set meanLSF buffer to 0 */
|
||||
VADChannelContext->frameCount = 0;
|
||||
VADChannelContext->updateCount = 0;
|
||||
for (i=0; i<N0; i++) {
|
||||
VADChannelContext->EfBuffer[i] = MAXINT16;
|
||||
}
|
||||
VADChannelContext->SVDm1 = VOICE;
|
||||
VADChannelContext->SVDm2 = VOICE;
|
||||
VADChannelContext->Count_inert = 0;
|
||||
VADChannelContext->secondStageVADSmoothingFlag = 1;
|
||||
VADChannelContext->smoothingCounter = 0;
|
||||
VADChannelContext->previousFrameEf = 0;
|
||||
VADChannelContext->noiseContinuityCounter = 0;
|
||||
|
||||
return VADChannelContext;
|
||||
}
|
||||
|
||||
/*******************************************************************************************/
|
||||
/* multiBoundaryInitialVoiceActivityDecision as described in B3.5 */
|
||||
/* parameters: */
|
||||
/* -(i) deltaS spectral distorsion as decribed in B3.4.1 in Q13 */
|
||||
/* -(i) deltaEf full band energy difference as described in B3.4.2 in Q11 */
|
||||
/* -(i) deltaEl low band energy difference as described in B3.4.3 in Q11 */
|
||||
/* -(i) deltaZC Zero Crossing difference as described in B3.4.4 in Q15 */
|
||||
/* returns : Ivd as specified in B3.5 : VOICE or NOISE */
|
||||
/* */
|
||||
/*******************************************************************************************/
|
||||
static uint8_t multiBoundaryInitialVoiceActivityDecision(word32_t deltaS, word16_t deltaEf, word16_t deltaEl, word16_t deltaZC) {
|
||||
//word32_t acc1, acc2;
|
||||
|
||||
/* test the 14 conditions of B3.5 */
|
||||
/* Note : the constant used in itu code are not the one in spec. Code seems erratic with comment irrelevant, use constant found in floating point version, annex C+ */
|
||||
/* static FLOAT a[14] = { 1.750000e-03, -4.545455e-03, -2.500000e+01,
|
||||
* ( 2.000000e+01, 0.000000e+00, 8.800000e+03,
|
||||
* 0.000000e+0VADChannelContext->0, 2.5e+01, -2.909091e+01,
|
||||
* 0.000000e+00, 1.400000e+04, 0.928571,
|
||||
* -1.500000e+00, 0.714285};
|
||||
*
|
||||
* static FLOAT b[14] = { 0.00085, 0.001159091, -5.0,
|
||||
* -6.0, -4.7, -12.2,
|
||||
* 0.0009, -7.0, -4.8182,
|
||||
* -5.3, -15.5, 1.14285,
|
||||
* -9.0, -2.1428571};
|
||||
* These constants are for Ef and El computed correctlVADChannelContext->y, we have Ef/10 and El/10 in buffers, and lsf normalised (/2pi)-> deltaS/4pi^2
|
||||
*/
|
||||
/* adjust input parameters */
|
||||
word32_t deltaEf32 = MULT16_16(10, deltaEf); /* in Q11 */
|
||||
word32_t deltaEl32 = MULT16_16(10, deltaEl); /* in Q11 */
|
||||
deltaS = MULT16_32(830, deltaS); /* 830 is 1/(4*pi^2) in Q15, deltaS in Q28 now */
|
||||
|
||||
/* cond 1 : deltaS > a1*deltaZC + b1 */
|
||||
if (deltaS > ADD32(MULT16_32_Q12(deltaZC, 58720), 228170)) { /* deltaS in Q28 - deltaZC in Q15*58720(1.75e-3 in Q25) >> 12 -> result in Q28 + 228170 (0.00085 in Q28) */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 2 : deltaS > a2*deltaZC + b2 */
|
||||
if (deltaS > ADD32(MULT16_32_Q12(deltaZC, -152520), 311141)) { /* deltaS in Q28 deltaZC in Q15*-152520(-4.545455e-03 in Q25) >> 12 -> result in Q28 + 311141 (0.001159091 in Q28) */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 3 : deltaEf < a3*deltaZC + b3 */
|
||||
if (deltaEf32 < ADD32(MULT16_32_Q15(deltaZC, -51200), -10240)) { /* deltaEf32 in Q11 - deltaZC in Q15*-51200(-2.50e+01 in Q11) >> 15 -> result in Q11 - 10240 (-5 in Q11) */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 4 : deltaEf < a4*deltaZC + b4 */
|
||||
if (deltaEf32 < ADD32(MULT16_32_Q15(deltaZC, 40960), -12288)) { /* deltaEf32 in Q11 - deltaZC in Q15*40960(2.0e+01 in Q11) >> 15 -> result in Q11 - 12288 (-6.0 in Q11) */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 5 : deltaEf < b5 */
|
||||
if (deltaEf32 < -9626) { /* deltaEf32 in Q11 - -4.7 in Q11 -> 9626 */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 6 : deltaEf < a6*deltaS + b6 */
|
||||
if (deltaEf32 < ADD32(MULT16_32_Q12(275,deltaS), -24986)) { /* deltaEf32 in Q11 - deltaS in Q28*275(8.8e+03 in Q-5) >> 12 -> result in Q11 - -24986 (-12.2 in Q11) */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 7 : deltaS > b7 */
|
||||
if (deltaS > 241592) { /* deltaS in Q28 - 0.0009 in Q28 -> 241592 */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 8 : deltaEf < a8*deltaZC + b8 */
|
||||
if (deltaEf32 < ADD32(MULT16_32_Q15(deltaZC, 51200), -14336)) { /* deltaEf32 in Q11 - deltaZC in Q15*51200(2.50e+01 in Q11) >> 15 -> result in Q11 - -14336 (-7 in Q11) */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 9 : deltaEf < a9*deltaZC + b9 */
|
||||
if (deltaEf32 < ADD32(MULT16_32_Q15(deltaZC, -59578), -9868)) { /* deltaEf32 in Q11 - deltaZC in Q15*59578(-2.909091e+01 in Q11) >> 15 -> result in Q11 - -9868 (-4.8182 in Q11) */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 10 : deltaEf < b10 */
|
||||
/* Note: cond 10 is totally useless : already covered by cond 5 before - skip it.*/
|
||||
if (deltaEf32 < -10854) { /* deltaEf32 in Q11 - -5.3 in Q11 -> 10854 */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 11 : deltaEl < a11*deltaS + b11 */
|
||||
if (deltaEl32 < ADD32(MULT16_32_Q13(875,deltaS), -31744)) { /* deltaEl32 in Q11 - deltaS in Q28*875(1.4000e+04 in Q-4) >> 12 -> result in Q11 - -31744 (-15.5 in Q11) */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 12 : deltaEl > a12*deltaEf + b12 */
|
||||
if (deltaEl32 > ADD32(MULT16_32_Q15(30427, deltaEl32), 2341)) { /* deltaEl32 in Q11 - deltaEl32 in Q11*30427(0.928571 in Q15) >> 15 -> result in Q11 - 2341 (1.14285 in Q11) */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 13 : deltaEl < a13*deltaEf + b13 */
|
||||
if (deltaEl32 < ADD32(MULT16_32_Q14(-24576, deltaEl32), -18432)) { /* deltaEl32 in Q11 - deltaEl32 in Q11*-24576(-1.5 in Q14) >> 15 -> result in Q11 - -18432 (-9 in Q11) */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* cond 13 : deltaEl < a14*deltaEf + b14 */
|
||||
if (deltaEl32 < ADD32(MULT16_32_Q15(23406, deltaEl32), -4389)) { /* deltaEl32 in Q11 - deltaEl32 in Q11*23406(0.714285 in Q15) >> 15 -> result in Q11 - -4389 (-2.1428571 in Q11) */
|
||||
return VOICE;
|
||||
}
|
||||
|
||||
/* no condition was true */
|
||||
return NOISE;
|
||||
}
|
||||
|
||||
/*******************************************************************************************/
|
||||
/* bcg729_vad : voice activity detection from AnnexB */
|
||||
/* parameters: */
|
||||
/* -(i/o):VADChannelContext : context containing all informations needed for VAD */
|
||||
/* -(i): reflectionCoefficient : in Q31 */
|
||||
/* -(i): LSFCoefficients :10 Coefficient in Q2.13 in range [0,Pi[ */
|
||||
/* -(i): autoCorrelationCoefficients : 13 coefficients of autoCorrelation */
|
||||
/* -(i): autoCorrelationCoefficientsScale : scaling factor of previous coeffs */
|
||||
/* -(i): signalCurrentFrame: the preprocessed signal in Q0, accessed in [-1, L_FRAME[ */
|
||||
/* */
|
||||
/* returns : 1 for active voice frame, 0 for silence frame */
|
||||
/* */
|
||||
/*******************************************************************************************/
|
||||
uint8_t bcg729_vad(bcg729VADChannelContextStruct *VADChannelContext, word32_t reflectionCoefficient, word16_t *LSFCoefficients, word32_t *autoCorrelationCoefficients, int8_t autoCorrelationCoefficientsScale, const word16_t *signalCurrentFrame) {
|
||||
|
||||
word16_t Ef, deltaEf; /* full band energy/10 in Q11 eq B1 */
|
||||
word16_t Emin; /* minimum Ef value of the last 128 frames */
|
||||
word16_t El, deltaEl; /* low band energy/10 in Q11 eqB2 */
|
||||
word16_t ZC, deltaZC; /* zero crossing rate in Q15 eq B3 */
|
||||
word32_t deltaS; /* spectral distorsion in Q12 */
|
||||
word32_t acc;
|
||||
uint8_t Ivd = VOICE; /* Initial Voice activity decision : VOICE or NOISE, flag defined in B3.5 */
|
||||
|
||||
int i;
|
||||
|
||||
/*** parameters extraction B3.1 ***/
|
||||
/* full band energy Ef (eq B1) = 10*log10(autoCorrelationCoefficient[0]/240), we compute Ef/10 in Q11 */
|
||||
acc = SUB32(g729Log2_Q0Q16(autoCorrelationCoefficients[0]+1), (((int32_t)autoCorrelationCoefficientsScale)<<16)); /* acc = log2(R(0)) in Q16 +1 is to avoid sending 0 to the log function */
|
||||
acc = SHR32(SUB32(acc, LOG2_240_Q16),1); /* acc = log2(R(0)/240) in Q15 */
|
||||
acc = MULT16_32_Q15(INV_LOG2_10_Q15, acc); /* acc Ef in Q15 */
|
||||
Ef = (word16_t)(PSHR(acc,4));
|
||||
|
||||
/* store Ef in the rolling EfBuffer at position countFrame%N0 */
|
||||
VADChannelContext->EfBuffer[(VADChannelContext->frameCount)%N0] = Ef;
|
||||
|
||||
/* low band energy El (eq B2)/10 in Q11 */
|
||||
acc=MULT16_32_Q15(lowBandFilter[0], autoCorrelationCoefficients[0]);
|
||||
for (i=1; i<NB_LSP_COEFF+3; i++) {
|
||||
acc = MAC16_32_Q14(acc, lowBandFilter[i], autoCorrelationCoefficients[i]);
|
||||
}
|
||||
if (acc<=0) { // we cannot compute the log of a negative or zero value: as done in ITU code (annex C+), set it to a tiny number(2^-16)
|
||||
acc = 1;
|
||||
}
|
||||
acc = SUB32(g729Log2_Q0Q16(acc), (((int32_t)autoCorrelationCoefficientsScale)<<16)); /* acc = log2(htRh) in Q16*/
|
||||
acc = SHR32(SUB32(acc, LOG2_240_Q16),1); /* acc = log2(htRh/240) in Q15 */
|
||||
acc = MULT16_32_Q15(INV_LOG2_10_Q15, acc); /* acc El in Q15 */
|
||||
El = (word16_t)(PSHR(acc,4));
|
||||
|
||||
/* compute zero crossing rate ZC (eq B3) in Q15 : at each zero crossing, add 410 (1/80 in Q15)*/
|
||||
ZC = 0;
|
||||
for (i=0; i<L_FRAME; i++) {
|
||||
if (MULT16_16(signalCurrentFrame[i-1], signalCurrentFrame[i])<0) {
|
||||
ZC = ADD16(ZC,410); /* add 1/80 in Q15 */
|
||||
}
|
||||
}
|
||||
|
||||
/* B3.2 Initialisation of the running averages of background noise characteristics : End of init period (32 first frames) */
|
||||
if (VADChannelContext->frameCount == Ni) { /* complete initialisations */
|
||||
word16_t meanEn = 0;
|
||||
|
||||
if (VADChannelContext->nbValidInitFrame>0) {/* check if we had a valid frame during init */
|
||||
meanEn = (word16_t)DIV32(VADChannelContext->initEfSum, VADChannelContext->nbValidInitFrame);
|
||||
VADChannelContext->meanZC = (word16_t)DIV32(VADChannelContext->initZCSum, VADChannelContext->nbValidInitFrame);
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
VADChannelContext->meanLSF[i] = (word16_t)DIV32(VADChannelContext->initLSFSum[i], VADChannelContext->nbValidInitFrame);
|
||||
}
|
||||
/* spec B3.2 describe a mechanism for initialisation of meanEl and meanEf which is not implemented in ITU code */
|
||||
/* ITU code does: meanEf = meanEn-1 and meanEl = meanEn - 1.2, just do that */
|
||||
/* it looks like the case in wich meanEn>T2 (5.5dB) is considered always true which is certainly not the case */
|
||||
VADChannelContext->meanEf = SUB16(meanEn, 2048); /* -1 in Q11 (K4 if K4 is in Q27 in the spec)*/
|
||||
VADChannelContext->meanEl = SUB16(meanEn, 2458); /* -1.2 in Q11 (K5 if K5 is in Q27 in the spec)*/
|
||||
} else {/* if we have no valid frames */
|
||||
VADChannelContext->frameCount = 0; /* as done in Appendix II : reset frameCount to restart init period */
|
||||
}
|
||||
}
|
||||
|
||||
/* B3.2 Initialisation of the running averages of background noise characteristics : during init period(32 first frames) */
|
||||
if (VADChannelContext->frameCount < Ni) { /* initialisation is still on going for running averages */
|
||||
if (Ef<3072) { /* Ef stores 1/10 of full band energy in Q11, frames are valid only when Ef>15dB, 3072 is 1.5 in Q11 */
|
||||
Ivd = NOISE;
|
||||
} else {
|
||||
Ivd = VOICE;
|
||||
VADChannelContext->nbValidInitFrame++;
|
||||
VADChannelContext->initEfSum = ADD32(VADChannelContext->initEfSum, Ef);
|
||||
VADChannelContext->initZCSum = ADD32(VADChannelContext->initZCSum, ZC);
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
VADChannelContext->initLSFSum[i] = ADD32(VADChannelContext->initLSFSum[i], LSFCoefficients[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* context updates */
|
||||
VADChannelContext->frameCount++;
|
||||
VADChannelContext->previousFrameEf = Ef;
|
||||
VADChannelContext -> SVDm2 = VADChannelContext -> SVDm1;
|
||||
VADChannelContext -> SVDm1 = Ivd;
|
||||
|
||||
return Ivd;
|
||||
}
|
||||
|
||||
/* B3.3 Generating the long term minimum energy (real computation of the minimum over the last 128 values, no trick as suggested in the spec) */
|
||||
Emin = getMinInArray(VADChannelContext->EfBuffer, N0);
|
||||
|
||||
/* B3.4.1 spectral distorsion deltaS */
|
||||
deltaS = 0;
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
word16_t acc16;
|
||||
acc16 = SUB16(LSFCoefficients[i], VADChannelContext->meanLSF[i]);
|
||||
deltaS = MAC16_16_Q13(deltaS, acc16, acc16);
|
||||
}
|
||||
|
||||
/* B3.4.2 deltaEf */
|
||||
deltaEf = SUB16(VADChannelContext->meanEf, Ef); /* in Q11 */
|
||||
|
||||
/* B3.4.3 deltaEf */
|
||||
deltaEl = SUB16(VADChannelContext->meanEl, El); /* in Q11 */
|
||||
|
||||
/* B3.4.2 deltaEf */
|
||||
deltaZC = SUB16(VADChannelContext->meanZC, ZC); /* in Q15 */
|
||||
|
||||
if (Ef<3072) { /* Ef stores 1/10 of full band energy in Q11, frames are valid only when Ef>15dB, 3072 is 1.5 in Q11 */
|
||||
Ivd = NOISE;
|
||||
} else {
|
||||
Ivd = multiBoundaryInitialVoiceActivityDecision(deltaS, deltaEf, deltaEl, deltaZC);
|
||||
}
|
||||
|
||||
/* B3.6 : Voice Activity Decision Smoothing */
|
||||
/* Appendix II hysteresis II 5.2 as implemented in ITU code, description in appendix has a test on meanEf which is not implemented in example code */
|
||||
if (Ivd == VOICE) {
|
||||
VADChannelContext->Count_inert=0;
|
||||
}
|
||||
|
||||
if ((Ivd == NOISE) && (VADChannelContext->Count_inert < 6)) {
|
||||
VADChannelContext->Count_inert++;
|
||||
Ivd = VOICE;
|
||||
}
|
||||
|
||||
/* first stage of VAD smoothing : code add a test on Ef>15 (21 in the floating version?!?) not documented */
|
||||
if ((Ivd == NOISE) && (VADChannelContext->SVDm1) && (deltaEf>410) && (Ef>3072)) { /* deltaEf is (meanEf - Ef)/10 in Q11, test is Ef > meanEf + 2, 410 is 0.2 in Q11 - 3072 is 1.5 in Q11 */
|
||||
Ivd = VOICE;
|
||||
}
|
||||
|
||||
/* second stage of VAD smoothing */
|
||||
if ((VADChannelContext->secondStageVADSmoothingFlag == 1)
|
||||
&& (Ivd == NOISE)
|
||||
&& (VADChannelContext->SVDm1 == VOICE)
|
||||
&& (VADChannelContext->SVDm2 == VOICE)
|
||||
&& (ABS(SUB16(Ef, VADChannelContext->previousFrameEf)) <= 614)) { /* |Ef - meanEf|<=3 -> 614 is 0.3 in Q11 */
|
||||
Ivd = VOICE;
|
||||
VADChannelContext->smoothingCounter++;
|
||||
if (VADChannelContext->smoothingCounter<=4) {
|
||||
VADChannelContext->secondStageVADSmoothingFlag = 1;
|
||||
} else {
|
||||
VADChannelContext->secondStageVADSmoothingFlag = 0;
|
||||
VADChannelContext->smoothingCounter = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
VADChannelContext->secondStageVADSmoothingFlag = 1;
|
||||
}
|
||||
|
||||
/* third stage of VAD smoothing */
|
||||
if (Ivd == NOISE) {
|
||||
VADChannelContext->noiseContinuityCounter++;
|
||||
}
|
||||
|
||||
if ( (Ivd == VOICE)
|
||||
&& (VADChannelContext->noiseContinuityCounter > 10) /* Cs > N2 */
|
||||
&& (SUB16(Ef, VADChannelContext->previousFrameEf) <= 614)) { /* Ef - prevEf <= T5(3.0) : 614 is 0.3 in Q11 */
|
||||
Ivd = NOISE;
|
||||
VADChannelContext->noiseContinuityCounter = 0;
|
||||
VADChannelContext->Count_inert = 6; /* added by appendix II*/
|
||||
}
|
||||
|
||||
if (Ivd == VOICE) {
|
||||
VADChannelContext->noiseContinuityCounter = 0;
|
||||
}
|
||||
|
||||
/* forth stage of VAD smoothing is not implemented in appendix II */
|
||||
|
||||
/* update the running averages B3.7 : note ITU implementation differs from spec, not only Ef < meanEf + 3dB is tested but also ReflectionCoefficient < 0.75 and deltaS < 0.002532959 */
|
||||
if ( (SUB16(Ef, 614) < VADChannelContext->meanEf) /* 614 is 0.3 in Q11 : Ef and meanEf are 1/10 of real Ef and meanEf, so 0.3 instead of 3, all in Q11 */
|
||||
&& (reflectionCoefficient < 1610612736) ) { /* in Q31, 0.75 is 1610612736 */
|
||||
/* Note : G729 Appendix II suggest that the test on deltaS is not relevant and prevent good detection in very noisy environment : remove it */
|
||||
// && (deltaS < 819)) { /* deltaS is computed using non normalised LSF so compare with 4*pi^2*0.002532959 = 819 in Q13 as ITU code normalise LSF dividing them by 2*Pi */
|
||||
/* all beta Coefficient in Q15 */
|
||||
word16_t betaE, betaZC, betaLSF; /* parameter used for first order auto-regressive update scheme, note betaEf and betaEl are the same: betaE */
|
||||
word16_t betaEComplement, betaZCComplement, betaLSFComplement; /* these are the (1 - betaXX) */
|
||||
/* update number of update performed (Cn in spec B3.7) */
|
||||
VADChannelContext->updateCount++;
|
||||
|
||||
/* according to spec, based on Cn (updateCount) value we must use a different set of coefficient, none of them is defined in the spec, all values are picked from ITU code */
|
||||
if (VADChannelContext->updateCount<20) {
|
||||
betaE = 24576; /* 0.75 */
|
||||
betaEComplement = 8192; /* 1-0.75 */
|
||||
betaZC = 26214; /* 0.8 */
|
||||
betaZCComplement = 6554; /* 1-0.8 */
|
||||
betaLSF = 19661; /* 0.6 */
|
||||
betaLSFComplement = 13107; /* 1-0.6 */
|
||||
} else if (VADChannelContext->updateCount<30) {
|
||||
betaE = 31130; /* 0.95 */
|
||||
betaEComplement = 1638; /* 1-0.95 */
|
||||
betaZC = 30147; /* 0.92 */
|
||||
betaZCComplement = 2621; /* 1-0.92 */
|
||||
betaLSF = 21299; /* 0.65 */
|
||||
betaLSFComplement = 11469; /* 1-0.65 */
|
||||
} else if (VADChannelContext->updateCount<40) {
|
||||
betaE = 31785; /* 0.97 */
|
||||
betaEComplement = 983; /* 1-0.97 */
|
||||
betaZC = 30802; /* 0.94 */
|
||||
betaZCComplement = 1966; /* 1-0.94 */
|
||||
betaLSF = 22938; /* 0.7 */
|
||||
betaLSFComplement = 9830 ; /* 1-0.7 */
|
||||
} else if (VADChannelContext->updateCount<50) {
|
||||
betaE = 32440; /* 0.99 */
|
||||
betaEComplement = 328; /* 1-0.99 */
|
||||
betaZC = 31457; /* 0.96 */
|
||||
betaZCComplement = 1311; /* 1-0.96 */
|
||||
betaLSF = 24756; /* 0.75 */
|
||||
betaLSFComplement = 8192; /* 1-0.75 */
|
||||
} else if (VADChannelContext->updateCount<60) {
|
||||
betaE = 32604; /* 0.995 */
|
||||
betaEComplement = 164; /* 1-0.995 */
|
||||
betaZC = 32440; /* 0.99 */
|
||||
betaZCComplement = 328; /* 1-0.99 */
|
||||
betaLSF = 24576; /* 0.75 */
|
||||
betaLSFComplement = 8192; /* 1-0.75 */
|
||||
} else {
|
||||
betaE = 32702; /* 0.998 */ /* note : in ITU code betaE and betaZC seems to be swaped on this last case, this implementation swap them back */
|
||||
betaEComplement = 66; /* 1-0.998 */
|
||||
betaZC = 32604; /* 0.995 */
|
||||
betaZCComplement = 164; /* 1-0.995 */
|
||||
betaLSF = 24576; /* 0.75 */
|
||||
betaLSFComplement = 8192; /* 1-0.75 */
|
||||
}
|
||||
|
||||
VADChannelContext->meanEf = ADD16(MULT16_16_Q15(VADChannelContext->meanEf, betaE), MULT16_16_Q15(Ef, betaEComplement));
|
||||
VADChannelContext->meanEl = ADD16(MULT16_16_Q15(VADChannelContext->meanEl, betaE), MULT16_16_Q15(El, betaEComplement));
|
||||
VADChannelContext->meanZC = ADD16(MULT16_16_Q15(VADChannelContext->meanZC, betaZC), MULT16_16_Q15(ZC, betaZCComplement));
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
VADChannelContext->meanLSF[i] = ADD16(MULT16_16_Q15(VADChannelContext->meanLSF[i], betaLSF), MULT16_16_Q15(LSFCoefficients[i], betaLSFComplement));
|
||||
}
|
||||
}
|
||||
|
||||
/* further update of meanEf and updatedFrame, implementation differs from spec again, stick to ITU code */
|
||||
if ( (VADChannelContext->frameCount>N0)
|
||||
&&( ((VADChannelContext->meanEf<Emin) && (deltaS < 819)) /* deltaS < 0.002532959 -> 819 is 0.002532959*4*pi^2 in Q13 */
|
||||
||(VADChannelContext->meanEf > ADD16(Emin, 2048)))) { /* meanEf > Emin + 10 : 2048 is 1 in Q11, Ef is 1/10 of real one */
|
||||
|
||||
VADChannelContext->meanEf = Emin;
|
||||
VADChannelContext->updateCount = 0;
|
||||
}
|
||||
|
||||
/* context updates */
|
||||
VADChannelContext->frameCount++;
|
||||
VADChannelContext->previousFrameEf = Ef;
|
||||
VADChannelContext -> SVDm2 = VADChannelContext -> SVDm1;
|
||||
VADChannelContext -> SVDm1 = Ivd;
|
||||
|
||||
return Ivd;
|
||||
}
|
40
bcg729/src/vad.h
Normal file
40
bcg729/src/vad.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef VAD_H
|
||||
#define VAD_H
|
||||
|
||||
/*****************************************************************************/
|
||||
/* initBcg729VADChannel : create context structure and initialise it */
|
||||
/* return value : */
|
||||
/* - the VAD channel context data */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
bcg729VADChannelContextStruct *initBcg729VADChannel();
|
||||
|
||||
/*******************************************************************************************/
|
||||
/* bcg729_vad : voice activity detection from AnnexB */
|
||||
/* parameters: */
|
||||
/* -(i/o):VADChannelContext : context containing all informations needed for VAD */
|
||||
/* */
|
||||
/* returns : 1 for active voice frame, 0 for silence frame */
|
||||
/* */
|
||||
/*******************************************************************************************/
|
||||
uint8_t bcg729_vad(bcg729VADChannelContextStruct *VADChannelContext, word32_t reflectionCoefficient, word16_t *LSFCoefficients, word32_t *autoCorrelationCoefficients, int8_t autoCorrelationCoefficientsScale, const word16_t *signalCurrentFrame);
|
||||
|
||||
#endif /* ifndef VAD_H */
|
113
bcg729/test/CMakeLists.txt
Normal file
113
bcg729/test/CMakeLists.txt
Normal file
|
@ -0,0 +1,113 @@
|
|||
############################################################################
|
||||
# CMakeLists.txt
|
||||
# Copyright (C) 2014 Belledonne Communications, Grenoble France
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
set(BCG729_LIBRARY bcg729)
|
||||
|
||||
set(UTIL_SRC src/testUtils.c src/testUtils.h)
|
||||
|
||||
include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_BINARY_DIR})
|
||||
|
||||
add_executable(adaptativeCodebookSearchTest src/adaptativeCodebookSearchTest.c ${UTIL_SRC})
|
||||
target_link_libraries(adaptativeCodebookSearchTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(computeAdaptativeCodebookGainTest src/computeAdaptativeCodebookGainTest.c ${UTIL_SRC})
|
||||
target_link_libraries(computeAdaptativeCodebookGainTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(computeLPTest src/computeLPTest.c ${UTIL_SRC})
|
||||
target_link_libraries(computeLPTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(computeWeightedSpeechTest src/computeWeightedSpeechTest.c ${UTIL_SRC})
|
||||
target_link_libraries(computeWeightedSpeechTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(decodeAdaptativeCodeVectorTest src/decodeAdaptativeCodeVectorTest.c ${UTIL_SRC})
|
||||
target_link_libraries(decodeAdaptativeCodeVectorTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(decodeFixedCodeVectorTest src/decodeFixedCodeVectorTest.c ${UTIL_SRC})
|
||||
target_link_libraries(decodeFixedCodeVectorTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(decodeGainsTest src/decodeGainsTest.c ${UTIL_SRC})
|
||||
target_link_libraries(decodeGainsTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(decodeLSPTest src/decodeLSPTest.c ${UTIL_SRC})
|
||||
target_link_libraries(decodeLSPTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(decoderTest src/decoderTest.c ${UTIL_SRC})
|
||||
target_link_libraries(decoderTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(CNGRFC3389decoderTest src/CNGRFC3389decoderTest.c ${UTIL_SRC})
|
||||
target_link_libraries(CNGRFC3389decoderTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(CNGdecoderTest src/CNGdecoderTest.c ${UTIL_SRC})
|
||||
target_link_libraries(CNGdecoderTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(decoderMultiChannelTest src/decoderMultiChannelTest.c ${UTIL_SRC})
|
||||
target_link_libraries(decoderMultiChannelTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(encoderTest src/encoderTest.c ${UTIL_SRC})
|
||||
target_link_libraries(encoderTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(encoderMultiChannelTest src/encoderMultiChannelTest.c ${UTIL_SRC})
|
||||
target_link_libraries(encoderMultiChannelTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(findOpenLoopPitchDelayTest src/findOpenLoopPitchDelayTest.c ${UTIL_SRC})
|
||||
target_link_libraries(findOpenLoopPitchDelayTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(fixedCodebookSearchTest src/fixedCodebookSearchTest.c ${UTIL_SRC})
|
||||
target_link_libraries(fixedCodebookSearchTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(g729FixedPointMathTest src/g729FixedPointMathTest.c ${UTIL_SRC})
|
||||
target_link_libraries(g729FixedPointMathTest ${BCG729_LIBRARY} m)
|
||||
|
||||
add_executable(gainQuantizationTest src/gainQuantizationTest.c ${UTIL_SRC})
|
||||
target_link_libraries(gainQuantizationTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(interpolateqLSPAndConvert2LPTest src/interpolateqLSPAndConvert2LPTest.c ${UTIL_SRC})
|
||||
target_link_libraries(interpolateqLSPAndConvert2LPTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(LP2LSPConversionTest src/LP2LSPConversionTest.c ${UTIL_SRC})
|
||||
target_link_libraries(LP2LSPConversionTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(LPSynthesisFilterTest src/LPSynthesisFilterTest.c ${UTIL_SRC})
|
||||
target_link_libraries(LPSynthesisFilterTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(LSPQuantizationTest src/LSPQuantizationTest.c ${UTIL_SRC})
|
||||
target_link_libraries(LSPQuantizationTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(postFilterTest src/postFilterTest.c ${UTIL_SRC})
|
||||
target_link_libraries(postFilterTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(postProcessingTest src/postProcessingTest.c ${UTIL_SRC})
|
||||
target_link_libraries(postProcessingTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(preProcessingTest src/preProcessingTest.c ${UTIL_SRC})
|
||||
target_link_libraries(preProcessingTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(computeNoiseExcitationTest src/computeNoiseExcitationTest.c ${UTIL_SRC})
|
||||
target_link_libraries(computeNoiseExcitationTest ${BCG729_LIBRARY})
|
||||
|
||||
add_executable(encoderVADTest src/encoderVADTest.c ${UTIL_SRC})
|
||||
target_link_libraries(encoderVADTest ${BCG729_LIBRARY})
|
||||
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/testCampaign.cmake DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/ )
|
||||
file(RENAME ${CMAKE_CURRENT_BINARY_DIR}/testCampaign.cmake ${CMAKE_CURRENT_BINARY_DIR}/testCampaign )
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testCampaignAll.cmake ${CMAKE_CURRENT_BINARY_DIR}/testCampaignAll)
|
||||
|
15
bcg729/test/Makefile.am
Normal file
15
bcg729/test/Makefile.am
Normal file
|
@ -0,0 +1,15 @@
|
|||
SUBDIRS = bin
|
||||
|
||||
testCampaignAll-exec: $(srcdir)/testCampaignAll $(srcdir)/testCampaign
|
||||
cp -f $(srcdir)/testCampaignAll testCampaignAll-exec
|
||||
cp -f $(srcdir)/testCampaign testCampaign-exec
|
||||
|
||||
|
||||
TESTS = testCampaignAll-exec
|
||||
|
||||
EXTRA_DIST=testCampaignAll testCampaign
|
||||
|
||||
CLEANFILES=testCampaignAll-exec testCampaign-exec
|
||||
|
||||
clean-local:
|
||||
rm -rf patterns
|
39
bcg729/test/bin/Makefile.am
Normal file
39
bcg729/test/bin/Makefile.am
Normal file
|
@ -0,0 +1,39 @@
|
|||
check_PROGRAMS=adaptativeCodebookSearchTest computeAdaptativeCodebookGainTest computeLPTest computeWeightedSpeechTest decodeAdaptativeCodeVectorTest decodeFixedCodeVectorTest decodeGainsTest decodeLSPTest \
|
||||
decoderTest encoderTest decoderMultiChannelTest encoderMultiChannelTest findOpenLoopPitchDelayTest fixedCodebookSearchTest g729FixedPointMathTest gainQuantizationTest interpolateqLSPAndConvert2LPTest \
|
||||
LP2LSPConversionTest LPSynthesisFilterTest LSPQuantizationTest postFilterTest postProcessingTest preProcessingTest computeNoiseExcitationTest CNGdecoderTest CNGRFC3389decoderTest encoderVADTest
|
||||
util_src= \
|
||||
$(top_srcdir)/test/src/testUtils.c \
|
||||
$(top_srcdir)/test/src/testUtils.h
|
||||
|
||||
adaptativeCodebookSearchTest_SOURCES=$(top_srcdir)/test/src/adaptativeCodebookSearchTest.c $(util_src)
|
||||
computeAdaptativeCodebookGainTest_SOURCES=$(top_srcdir)/test/src/computeAdaptativeCodebookGainTest.c $(util_src)
|
||||
computeLPTest_SOURCES=$(top_srcdir)/test/src/computeLPTest.c $(util_src)
|
||||
computeWeightedSpeechTest_SOURCES=$(top_srcdir)/test/src/computeWeightedSpeechTest.c $(util_src)
|
||||
decodeAdaptativeCodeVectorTest_SOURCES=$(top_srcdir)/test/src/decodeAdaptativeCodeVectorTest.c $(util_src)
|
||||
decodeFixedCodeVectorTest_SOURCES=$(top_srcdir)/test/src/decodeFixedCodeVectorTest.c $(util_src)
|
||||
decodeGainsTest_SOURCES=$(top_srcdir)/test/src/decodeGainsTest.c $(util_src)
|
||||
decodeLSPTest_SOURCES=$(top_srcdir)/test/src/decodeLSPTest.c $(util_src)
|
||||
decoderTest_SOURCES=$(top_srcdir)/test/src/decoderTest.c $(util_src)
|
||||
CNGRFC3389decoderTest_SOURCES=$(top_srcdir)/test/src/CNGRFC3389decoderTest.c $(util_src)
|
||||
CNGdecoderTest_SOURCES=$(top_srcdir)/test/src/CNGdecoderTest.c $(util_src)
|
||||
decoderMultiChannelTest_SOURCES=$(top_srcdir)/test/src/decoderMultiChannelTest.c $(util_src)
|
||||
encoderTest_SOURCES=$(top_srcdir)/test/src/encoderTest.c $(util_src)
|
||||
encoderMultiChannelTest_SOURCES=$(top_srcdir)/test/src/encoderMultiChannelTest.c $(util_src)
|
||||
findOpenLoopPitchDelayTest_SOURCES=$(top_srcdir)/test/src/findOpenLoopPitchDelayTest.c $(util_src)
|
||||
fixedCodebookSearchTest_SOURCES=$(top_srcdir)/test/src/fixedCodebookSearchTest.c $(util_src)
|
||||
g729FixedPointMathTest_SOURCES=$(top_srcdir)/test/src/g729FixedPointMathTest.c $(util_src)
|
||||
g729FixedPointMathTest_LDADD=-lm
|
||||
gainQuantizationTest_SOURCES=$(top_srcdir)/test/src/gainQuantizationTest.c $(util_src)
|
||||
interpolateqLSPAndConvert2LPTest_SOURCES=$(top_srcdir)/test/src/interpolateqLSPAndConvert2LPTest.c $(util_src)
|
||||
LP2LSPConversionTest_SOURCES=$(top_srcdir)/test/src/LP2LSPConversionTest.c $(util_src)
|
||||
LPSynthesisFilterTest_SOURCES=$(top_srcdir)/test/src/LPSynthesisFilterTest.c $(util_src)
|
||||
LSPQuantizationTest_SOURCES=$(top_srcdir)/test/src/LSPQuantizationTest.c $(util_src)
|
||||
postFilterTest_SOURCES=$(top_srcdir)/test/src/postFilterTest.c $(util_src)
|
||||
postProcessingTest_SOURCES=$(top_srcdir)/test/src/postProcessingTest.c $(util_src)
|
||||
preProcessingTest_SOURCES=$(top_srcdir)/test/src/preProcessingTest.c $(util_src)
|
||||
computeNoiseExcitationTest_SOURCES=$(top_srcdir)/test/src/computeNoiseExcitationTest.c $(util_src)
|
||||
encoderVADTest_SOURCES=$(top_srcdir)/test/src/encoderVADTest.c $(util_src)
|
||||
|
||||
LDADD= $(top_builddir)/src/libbcg729.la
|
||||
AM_CPPFLAGS=-I$(top_srcdir)/include/ -I$(top_srcdir)/src/
|
||||
AM_LDFLAGS=-all-static
|
147
bcg729/test/src/CNGRFC3389decoderTest.c
Normal file
147
bcg729/test/src/CNGRFC3389decoderTest.c
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for decoder */
|
||||
/* Input: 15 parameters and the frame erasure flag on each row of a */
|
||||
/* a text CSV file. */
|
||||
/* Ouput: the reconstructed signal : each frame (80 16 bits PCM values) */
|
||||
/* on a row of a text CSV file */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "bcg729/decoder.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
FILE *fpBinOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
uint16_t inputBuffer[NB_PARAMETERS+2]; /* input buffer: an array containing the 15 parameters and the frame erasure flag and VAD flag */
|
||||
uint8_t bitStream[11]; /* binary input for the decoder */
|
||||
int16_t outputBuffer[L_FRAME]; /* output buffer: the reconstructed signal */
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
sprintf(outputFile, "%s.pcm",filePrefix);
|
||||
if ( (fpBinOutput = fopen(outputFile, "wb")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
bcg729DecoderChannelContextStruct *decoderChannelContext = initBcg729DecoderChannel();
|
||||
|
||||
/*** initialisation complete ***/
|
||||
/* perf measurement */
|
||||
clock_t start, end;
|
||||
double cpu_time_used=0.0;
|
||||
int framesNbr =0;
|
||||
/* increase LOOP_N to increase input length and perform a more accurate profiling or perf measurement */
|
||||
#define LOOP_N 1
|
||||
int j;
|
||||
for (j=0; j<LOOP_N; j++) {
|
||||
/* perf measurement */
|
||||
/*** loop over input file ***/
|
||||
while(fscanf(fpInput, "%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd", &(inputBuffer[0]), &(inputBuffer[1]), &(inputBuffer[2]), &(inputBuffer[3]), &(inputBuffer[4]), &(inputBuffer[5]), &(inputBuffer[6]), &(inputBuffer[7]), &(inputBuffer[8]), &(inputBuffer[9]), &(inputBuffer[10]), &(inputBuffer[11]), &(inputBuffer[12]), &(inputBuffer[13]), &(inputBuffer[14]), &(inputBuffer[15]), &(inputBuffer[16]))==17) /* index 4 and 5 are inverted to get P0 in 4 and P1 in 5 in the array */
|
||||
{ /* input buffer contains the parameters and in [15] the frame erasure flag */
|
||||
int i;
|
||||
uint8_t bitStreamLength;
|
||||
framesNbr++;
|
||||
|
||||
if (inputBuffer[16]==1) { /* active frame */
|
||||
parametersArray2BitStream(inputBuffer, bitStream);
|
||||
bitStreamLength = 10;
|
||||
} else { /* SID frame */
|
||||
if (inputBuffer[16]==0) {/* non transmitted frame */
|
||||
inputBuffer[15] = 1;
|
||||
bitStreamLength = 0;
|
||||
} else { /* actual SID frame */
|
||||
for (i=0; i<11; i++) {
|
||||
bitStream[i] = inputBuffer[i];
|
||||
}
|
||||
bitStreamLength = 11;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
start = clock();
|
||||
bcg729Decoder(decoderChannelContext, inputBuffer[15]==0?bitStream:NULL, bitStreamLength, inputBuffer[15], inputBuffer[16]!=1?1:0, 1, outputBuffer);
|
||||
end = clock();
|
||||
|
||||
cpu_time_used += ((double) (end - start));
|
||||
|
||||
/* write the output to the output files (only on first loop of perf measurement)*/
|
||||
if (j==0) {
|
||||
fprintf(fpOutput,"%d",outputBuffer[0]);
|
||||
for (i=1; i<L_FRAME; i++) {
|
||||
fprintf(fpOutput,",%d",outputBuffer[i]);
|
||||
}
|
||||
fprintf(fpOutput,"\n");
|
||||
/* write the ouput to raw data file */
|
||||
fwrite(outputBuffer, sizeof(int16_t), L_FRAME, fpBinOutput);
|
||||
}
|
||||
|
||||
}
|
||||
/* perf measurement */
|
||||
rewind(fpInput);
|
||||
}
|
||||
|
||||
closeBcg729DecoderChannel(decoderChannelContext);
|
||||
|
||||
/* Perf measurement: uncomment next line to print cpu usage */
|
||||
printf("Decode %d frames in %f seconds : %f us/frame\n", framesNbr, cpu_time_used/CLOCKS_PER_SEC, cpu_time_used*1000000/((double)framesNbr*CLOCKS_PER_SEC));
|
||||
/* perf measurement */
|
||||
exit (0);
|
||||
}
|
||||
|
145
bcg729/test/src/CNGdecoderTest.c
Normal file
145
bcg729/test/src/CNGdecoderTest.c
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for decoder */
|
||||
/* Input: 15 parameters and the frame erasure flag on each row of a */
|
||||
/* a text CSV file. */
|
||||
/* Ouput: the reconstructed signal : each frame (80 16 bits PCM values) */
|
||||
/* on a row of a text CSV file */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "bcg729/decoder.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
FILE *fpBinOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
uint16_t inputBuffer[NB_PARAMETERS+2]; /* input buffer: an array containing the 15 parameters and the frame erasure flag and VAD flag */
|
||||
uint8_t bitStream[10]; /* binary input for the decoder */
|
||||
int16_t outputBuffer[L_FRAME]; /* output buffer: the reconstructed signal */
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
sprintf(outputFile, "%s.pcm",filePrefix);
|
||||
if ( (fpBinOutput = fopen(outputFile, "wb")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
bcg729DecoderChannelContextStruct *decoderChannelContext = initBcg729DecoderChannel();
|
||||
|
||||
/*** initialisation complete ***/
|
||||
/* perf measurement */
|
||||
clock_t start, end;
|
||||
double cpu_time_used=0.0;
|
||||
int framesNbr =0;
|
||||
/* increase LOOP_N to increase input length and perform a more accurate profiling or perf measurement */
|
||||
#define LOOP_N 1
|
||||
int j;
|
||||
for (j=0; j<LOOP_N; j++) {
|
||||
/* perf measurement */
|
||||
/*** loop over input file ***/
|
||||
while(fscanf(fpInput, "%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd", &(inputBuffer[0]), &(inputBuffer[1]), &(inputBuffer[2]), &(inputBuffer[3]), &(inputBuffer[4]), &(inputBuffer[5]), &(inputBuffer[6]), &(inputBuffer[7]), &(inputBuffer[8]), &(inputBuffer[9]), &(inputBuffer[10]), &(inputBuffer[11]), &(inputBuffer[12]), &(inputBuffer[13]), &(inputBuffer[14]), &(inputBuffer[15]), &(inputBuffer[16]))==17) /* index 4 and 5 are inverted to get P0 in 4 and P1 in 5 in the array */
|
||||
{ /* input buffer contains the parameters and in [15] the frame erasure flag */
|
||||
int i;
|
||||
uint8_t bitStreamLength;
|
||||
framesNbr++;
|
||||
|
||||
if (inputBuffer[16]==1) { /* active frame */
|
||||
parametersArray2BitStream(inputBuffer, bitStream);
|
||||
bitStreamLength = 10;
|
||||
} else { /* SID frame */
|
||||
if (inputBuffer[16]==0) {/* non transmitted frame */
|
||||
inputBuffer[15] = 1;
|
||||
bitStreamLength = 0;
|
||||
} else { /* actual SID frame */
|
||||
CNGparametersArray2BitStream(inputBuffer, bitStream);
|
||||
bitStreamLength = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
start = clock();
|
||||
bcg729Decoder(decoderChannelContext, inputBuffer[15]==0?bitStream:NULL, bitStreamLength, inputBuffer[15], inputBuffer[16]!=1?1:0, 0, outputBuffer);
|
||||
end = clock();
|
||||
|
||||
cpu_time_used += ((double) (end - start));
|
||||
|
||||
/* write the output to the output files (only on first loop of perf measurement)*/
|
||||
if (j==0) {
|
||||
fprintf(fpOutput,"%d",outputBuffer[0]);
|
||||
for (i=1; i<L_FRAME; i++) {
|
||||
fprintf(fpOutput,",%d",outputBuffer[i]);
|
||||
}
|
||||
fprintf(fpOutput,"\n");
|
||||
/* write the ouput to raw data file */
|
||||
fwrite(outputBuffer, sizeof(int16_t), L_FRAME, fpBinOutput);
|
||||
}
|
||||
|
||||
}
|
||||
/* perf measurement */
|
||||
rewind(fpInput);
|
||||
}
|
||||
|
||||
closeBcg729DecoderChannel(decoderChannelContext);
|
||||
|
||||
/* Perf measurement: uncomment next line to print cpu usage */
|
||||
printf("Decode %d frames in %f seconds : %f us/frame\n", framesNbr, cpu_time_used/CLOCKS_PER_SEC, cpu_time_used*1000000/((double)framesNbr*CLOCKS_PER_SEC));
|
||||
/* perf measurement */
|
||||
exit (0);
|
||||
}
|
||||
|
106
bcg729/test/src/LP2LSPConversionTest.c
Normal file
106
bcg729/test/src/LP2LSPConversionTest.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for LP2LSPConversion bloc */
|
||||
/* Input: - 10 LP in Q12 */
|
||||
/* */
|
||||
/* Ouput: - 10 LSP in Q15 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "LP2LSPConversion.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
/* input file: 10 LP Coefficients(Q12) */
|
||||
word16_t LP[NB_LSP_COEFF];
|
||||
|
||||
/* output file: 10 LSP Coefficients(Q15) */
|
||||
word16_t LSP[NB_LSP_COEFF];
|
||||
word16_t previousLSP[NB_LSP_COEFF] = /* store previously computed LSP to be reused if we can't find 10 LSP from current LP */
|
||||
{30000, 26000, 21000, 15000, 8000, 0, -8000,-15000,-21000,-26000};
|
||||
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
|
||||
/* initialise buffers */
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(fscanf(fpInput,"%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd",&LP[0],&LP[1],&LP[2],&LP[3],&LP[4],&LP[5],&LP[6],&LP[7],&LP[8],&LP[9]) == 10)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* call the tested funtion */
|
||||
if (LP2LSPConversion(LP, LSP)) {
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
previousLSP[i]=LSP[i];
|
||||
}
|
||||
} else { /* unable to find the 10 roots repeat previous LSP */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
LSP[i]=previousLSP[i];
|
||||
}
|
||||
}
|
||||
/* write the output to the output file */
|
||||
fprintf(fpOutput,"%d", LSP[0]);
|
||||
for (i=1; i<NB_LSP_COEFF; i++) {
|
||||
fprintf(fpOutput,",%d", LSP[i]);
|
||||
}
|
||||
fprintf(fpOutput,"\n");
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
103
bcg729/test/src/LPSynthesisFilterTest.c
Normal file
103
bcg729/test/src/LPSynthesisFilterTest.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for LPSynthesisFilter bloc */
|
||||
/* Input: - */
|
||||
/* */
|
||||
/* Ouput: - */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "LPSynthesisFilter.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
/* input file: 10 LP Coefficients(Q12), 40 ExcitationVector(Q0), 10 past reconstructed speech(Q0) */
|
||||
word16_t LP[NB_LSP_COEFF];
|
||||
word16_t excitationVector[L_SUBFRAME]; /* this vector contains the subframe excitation vector in Q0 */
|
||||
|
||||
/* output is in the reconstruted speech: for the test purpose it's long just memory+subframe */
|
||||
word16_t reconstructedSpeech[NB_LSP_COEFF+L_SUBFRAME]; /* in Q0, output of the LP synthesis filter, the first 10 words store the previous frame output */
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
|
||||
/* initialise buffers */
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(1) /* infinite loop, escape condition is in the reading of data */
|
||||
{
|
||||
int i;
|
||||
/* read the input data until we have some */
|
||||
if (fscanf(fpInput,"%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd",&LP[0],&LP[1],&LP[2],&LP[3],&LP[4],&LP[5],&LP[6],&LP[7],&LP[8],&LP[9]) != 10) break;
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
if (fscanf(fpInput,",%hd",&(excitationVector[i])) != 1) break;
|
||||
}
|
||||
if (fscanf(fpInput,",%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd",&reconstructedSpeech[0],&reconstructedSpeech[1],&reconstructedSpeech[2],&reconstructedSpeech[3],&reconstructedSpeech[4],&reconstructedSpeech[5],&reconstructedSpeech[6],&reconstructedSpeech[7],&reconstructedSpeech[8],&reconstructedSpeech[9]) != 10) break;
|
||||
|
||||
/* call the tested funtion */
|
||||
LPSynthesisFilter(excitationVector, LP, &(reconstructedSpeech[NB_LSP_COEFF]));
|
||||
|
||||
/* write the output to the output file */
|
||||
fprintf(fpOutput,"%d",reconstructedSpeech[NB_LSP_COEFF]);
|
||||
for (i=1; i<L_SUBFRAME; i++) {
|
||||
fprintf(fpOutput,",%d", reconstructedSpeech[NB_LSP_COEFF+i]);
|
||||
}
|
||||
fprintf(fpOutput,"\n");
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
104
bcg729/test/src/LSPQuantizationTest.c
Normal file
104
bcg729/test/src/LSPQuantizationTest.c
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for LSPQuantization bloc */
|
||||
/* Input: - 10 LSP in Q15 */
|
||||
/* */
|
||||
/* Ouput: - 10 qLSP in Q15 */
|
||||
/* - 4 parameters L0, L1, L2, L3 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "LSPQuantization.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
/* input file: 10 LSP Coefficients(Q15) */
|
||||
word16_t LSP[NB_LSP_COEFF];
|
||||
|
||||
/* output file: 10 qLSP Coefficients(Q15) */
|
||||
word16_t qLSP[NB_LSP_COEFF];
|
||||
uint16_t parametersL[4];
|
||||
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
/* create the context structure */
|
||||
bcg729EncoderChannelContextStruct *encoderChannelContext = malloc(sizeof(bcg729EncoderChannelContextStruct));
|
||||
|
||||
initLSPQuantization(encoderChannelContext);
|
||||
|
||||
/* initialise buffers */
|
||||
|
||||
/*** initialisation complete ***/
|
||||
// LSPQuantization(LSP, qLSP, parametersL);
|
||||
//exit (0);
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(fscanf(fpInput,"%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd",&LSP[0],&LSP[1],&LSP[2],&LSP[3],&LSP[4],&LSP[5],&LSP[6],&LSP[7],&LSP[8],&LSP[9]) == 10)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* call the tested funtion */
|
||||
LSPQuantization(encoderChannelContext, LSP, qLSP, parametersL);
|
||||
|
||||
/* write the output to the output file */
|
||||
fprintf(fpOutput,"%d", qLSP[0]);
|
||||
for (i=1; i<NB_LSP_COEFF; i++) {
|
||||
fprintf(fpOutput,",%d", qLSP[i]);
|
||||
}
|
||||
fprintf(fpOutput,",%d,%d,%d,%d\n",parametersL[0],parametersL[1],parametersL[2],parametersL[3]);
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
111
bcg729/test/src/VADTest.c
Normal file
111
bcg729/test/src/VADTest.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for computeLP Bloc */
|
||||
/* Input: a CSV text with 107 values : */
|
||||
/* - reflectionCoefficient in Q31 */
|
||||
/* - 10 LSF in Q13 */
|
||||
/* - autocorrelation exponent */
|
||||
/* - 13 autocorrelation coefficients */
|
||||
/* - 82 values of input signal */
|
||||
/* Ouput: - VAD : 0 or 1 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "vad.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
word32_t reflectionCoefficient; /* in Q31 */
|
||||
word16_t LSFCoefficients[NB_LSP_COEFF];
|
||||
int16_t autocorrelationExponent;
|
||||
word32_t autocorrelationCoefficients[NB_LSP_COEFF+3];
|
||||
word16_t signalBuffer[82]; /* used for input and output, in Q0 */
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
bcg729VADChannelContextStruct *VADChannelContext = initBcg729VADChannel();
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(1) /* infinite loop, escape condition is in the reading of data */
|
||||
{
|
||||
int i;
|
||||
uint8_t vad;
|
||||
|
||||
/* read the input data until we have some */
|
||||
if (fscanf(fpInput,"%d",&reflectionCoefficient) != 1) break;
|
||||
for (i=0; i<10; i++) {
|
||||
if (fscanf(fpInput,",%hd",(int16_t *)&(LSFCoefficients[i])) != 1) break;
|
||||
}
|
||||
if (fscanf(fpInput,",%hd",&autocorrelationExponent) != 1) break;
|
||||
for (i=0; i<13; i++) {
|
||||
if (fscanf(fpInput,",%d",&(autocorrelationCoefficients[i])) != 1) break;
|
||||
}
|
||||
for (i=0; i<82; i++) {
|
||||
if (fscanf(fpInput,",%hd",(int16_t *)&(signalBuffer[i])) != 1) break;
|
||||
}
|
||||
|
||||
/* call the tested function: output will replace the input in the buffer */
|
||||
vad = bcg729_vad(VADChannelContext, reflectionCoefficient, LSFCoefficients, autocorrelationCoefficients, autocorrelationExponent, &(signalBuffer[1]));
|
||||
|
||||
/* write the output to the output file */
|
||||
//fprintf(fpOutput,"%d", (int16_t)randomGeneratorSeed);
|
||||
fprintf(fpOutput,"%d\n", vad);
|
||||
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
131
bcg729/test/src/adaptativeCodebookSearchTest.c
Normal file
131
bcg729/test/src/adaptativeCodebookSearchTest.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for adaptativeCodebookSearchTest bloc */
|
||||
/* Input: - the past excitation (excitationVector) : 234 values */
|
||||
/* - targetSignal : 40 values */
|
||||
/* - impulseResponse : 40 values */
|
||||
/* - intPitchDelayMin */
|
||||
/* - intPitchDelayMax */
|
||||
/* - subframeIndex (0 or 40) */
|
||||
/* */
|
||||
/* Ouput: - int Pitch Delay */
|
||||
/* - frac Pitch Delay */
|
||||
/* - intPitchDelayMin */
|
||||
/* - intPitchDelayMax */
|
||||
/* - adaptativeCodebookIndex */
|
||||
/* - adaptative codebook vector : 40 values */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "adaptativeCodebookSearch.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
/* input file: pastExcitationVector: 234 values, targetSignal: 40 values, impulseReponse: 40 values, intPitchDelayMin, intPitchDelayMax, subframeIndex */
|
||||
word16_t excitationVector[L_PAST_EXCITATION + L_FRAME]; /* this vector contains: note on second subframe we have 40 useless values of past excitation
|
||||
0->153 : the past excitation vector.(length is Max Pitch Delay: 144 + interpolation window size : 10)
|
||||
154-> 154+L_SUBFRAME-1 : the current LPResidualSignal in input
|
||||
154-> 154+L_SUBFRAME-1 : the adaptative codebook vector in Q0 as output */
|
||||
word16_t targetSignal[L_SUBFRAME];
|
||||
word16_t impulseResponse[L_SUBFRAME];
|
||||
int16_t intPitchDelayMin, intPitchDelayMax;
|
||||
int subFrameIndex;
|
||||
/* outputs : */
|
||||
int16_t intPitchDelay;
|
||||
int16_t fracPitchDelay;
|
||||
uint16_t adaptativeCodebookIndex;
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
|
||||
/* initialise buffers */
|
||||
/* actually useless init, because the complete excitation buffer is reload at each subframe from input file, but shall be done in real decoder */
|
||||
memset(excitationVector, 0, L_PAST_EXCITATION*sizeof(word16_t)); /* initialise the part of the excitationVector containing the past excitation */
|
||||
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(1) /* infinite loop, escape condition is in the reading of data */
|
||||
{
|
||||
int i;
|
||||
/* read the input data until we have some */
|
||||
for (i=0; i<234; i++) {
|
||||
if (fscanf(fpInput,"%hd,",&(excitationVector[i])) != 1) break;
|
||||
}
|
||||
for (i=0; i<40; i++) {
|
||||
if (fscanf(fpInput,"%hd,",&(targetSignal[i])) != 1) break;
|
||||
}
|
||||
for (i=0; i<40; i++) {
|
||||
if (fscanf(fpInput,"%hd,",&(impulseResponse[i])) != 1) break;
|
||||
}
|
||||
if (fscanf(fpInput,"%hd,",&intPitchDelayMin) != 1) break;
|
||||
if (fscanf(fpInput,"%hd,",&intPitchDelayMax) != 1) break;
|
||||
if (fscanf(fpInput,"%d",&subFrameIndex) != 1) break;
|
||||
|
||||
/* call the tested funtion */
|
||||
adaptativeCodebookSearch(&(excitationVector[L_PAST_EXCITATION + subFrameIndex]), &intPitchDelayMin, &intPitchDelayMax, impulseResponse, targetSignal,
|
||||
&intPitchDelay, &fracPitchDelay, &adaptativeCodebookIndex, subFrameIndex);
|
||||
|
||||
/* write the output to the output file : intPitchDelay, fracPitchDelay, intPitchDelayMin, intPitchDelayMax, adaptativeCodebookIndex, adaptative codebook vector */
|
||||
fprintf(fpOutput, "%d,%d,%d,%d,%d,%d", intPitchDelay, fracPitchDelay, intPitchDelayMin, intPitchDelayMax, adaptativeCodebookIndex, excitationVector[L_PAST_EXCITATION+subFrameIndex]);
|
||||
for (i=1; i<L_SUBFRAME; i++) {
|
||||
fprintf(fpOutput,",%d", excitationVector[L_PAST_EXCITATION+subFrameIndex+i]);
|
||||
}
|
||||
fprintf(fpOutput,"\n");
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
103
bcg729/test/src/computeAdaptativeCodebookGainTest.c
Normal file
103
bcg729/test/src/computeAdaptativeCodebookGainTest.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for computeAdaptativeCodebookGainTest bloc */
|
||||
/* Input: - targetSignal : 40 values */
|
||||
/* - filtered adaptative codebook vector : 40 values */
|
||||
/* */
|
||||
/* Ouput: - adaptative codebook gain in Q14 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "computeAdaptativeCodebookGain.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
word16_t targetSignal[L_SUBFRAME];
|
||||
word16_t filteredAdaptativeCodebookVector[L_SUBFRAME];
|
||||
/* outputs : */
|
||||
word16_t adaptativeCodebookGain;
|
||||
|
||||
/* these buffers are part of the output but not of the pattern as they aren't scaled the same way the ITU code does. */
|
||||
word64_t gainQuantizationXy, gainQuantizationYy; /* used to store in Q0 values reused in gain quantization */
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
|
||||
/* initialise buffers */
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(1) /* infinite loop, escape condition is in the reading of data */
|
||||
{
|
||||
int i;
|
||||
/* read the input data until we have some */
|
||||
if (fscanf(fpInput,"%hd",&(filteredAdaptativeCodebookVector[0])) != 1) break;
|
||||
for (i=1; i<L_SUBFRAME; i++) {
|
||||
if (fscanf(fpInput,",%hd",&(filteredAdaptativeCodebookVector[i])) != 1) break;
|
||||
}
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
if (fscanf(fpInput,",%hd",&(targetSignal[i])) != 1) break;
|
||||
}
|
||||
|
||||
/* call the tested funtion */
|
||||
adaptativeCodebookGain = computeAdaptativeCodebookGain(targetSignal, filteredAdaptativeCodebookVector, &gainQuantizationXy, &gainQuantizationYy);
|
||||
|
||||
/* write the output to the output file : adaptativeCodebookGain */
|
||||
fprintf(fpOutput,"%d\n", adaptativeCodebookGain);
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
103
bcg729/test/src/computeLPTest.c
Normal file
103
bcg729/test/src/computeLPTest.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for computeLP Bloc */
|
||||
/* Input: a CSV text with 240 values of 16 bits PCM on each row */
|
||||
/* Ouput: 10 LP values in Q12 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "basicOperationsMacros.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "computeLP.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
word16_t inputBuffer[L_LP_ANALYSIS_WINDOW];
|
||||
word16_t LPCoefficients[NB_LSP_COEFF];
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(1) /* infinite loop, escape condition is in the reading of data */
|
||||
{
|
||||
int i;
|
||||
/* by-products of computeLP used for VAD/DTX, not tested here */
|
||||
word32_t reflectionCoefficients[10];
|
||||
word32_t autoCorrelationCoefficients[11];
|
||||
word32_t noLagAutoCorrelationCoefficients[11];
|
||||
int8_t autoCorrelationCoefficientsScale;
|
||||
|
||||
/* read the input data until we have some */
|
||||
if (fscanf(fpInput,"%hd",&(inputBuffer[0])) != 1) break;
|
||||
for (i=1; i<L_LP_ANALYSIS_WINDOW; i++) {
|
||||
if (fscanf(fpInput,",%hd",&(inputBuffer[i])) != 1) break;
|
||||
}
|
||||
|
||||
/* call the preProcessing function: output will replace the input in the buffer */
|
||||
computeLP(inputBuffer, LPCoefficients, reflectionCoefficients, autoCorrelationCoefficients, noLagAutoCorrelationCoefficients, &autoCorrelationCoefficientsScale, 11);
|
||||
|
||||
/* write the output to the output file */
|
||||
fprintf(fpOutput,"%d", LPCoefficients[0]);
|
||||
for (i=1; i<NB_LSP_COEFF; i++) {
|
||||
fprintf(fpOutput,",%d", LPCoefficients[i]);
|
||||
}
|
||||
fprintf(fpOutput,"\n");
|
||||
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
103
bcg729/test/src/computeNoiseExcitationTest.c
Normal file
103
bcg729/test/src/computeNoiseExcitationTest.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for computeLP Bloc */
|
||||
/* Input: a CSV text with 236 values of 16 bits : */
|
||||
/* - target gain in Q3 */
|
||||
/* - pseudo random generator seed */
|
||||
/* - 234 values of excitation vector buffer(154 past, 80 current) */
|
||||
/* Ouput: - updated pseudo random generator seed */
|
||||
/* - 234 16 bits values of updated excitation vector */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "cng.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
word16_t inputBuffer[L_PAST_EXCITATION+L_FRAME]; /* used for input and output, in Q0 */
|
||||
word16_t targetGain; /* input in Q3 */
|
||||
uint16_t randomGeneratorSeed;
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(1) /* infinite loop, escape condition is in the reading of data */
|
||||
{
|
||||
int i;
|
||||
/* read the input data until we have some */
|
||||
if (fscanf(fpInput,"%hd",&targetGain) != 1) break;
|
||||
if (fscanf(fpInput,",%hd",&randomGeneratorSeed) != 1) break;
|
||||
for (i=0; i<L_PAST_EXCITATION+L_FRAME; i++) {
|
||||
if (fscanf(fpInput,",%hd",&(inputBuffer[i])) != 1) break;
|
||||
}
|
||||
|
||||
/* call the tested function: output will replace the input in the buffer */
|
||||
computeComfortNoiseExcitationVector(targetGain, &randomGeneratorSeed, &(inputBuffer[L_PAST_EXCITATION]));
|
||||
|
||||
/* write the output to the output file */
|
||||
//fprintf(fpOutput,"%d", (int16_t)randomGeneratorSeed);
|
||||
fprintf(fpOutput,"%d", (int16_t)inputBuffer[L_PAST_EXCITATION]);
|
||||
for (i=L_PAST_EXCITATION+1; i<L_PAST_EXCITATION+L_FRAME; i++) {
|
||||
fprintf(fpOutput,",%d", inputBuffer[i]);
|
||||
}
|
||||
fprintf(fpOutput,"\n");
|
||||
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
115
bcg729/test/src/computeWeightedSpeechTest.c
Normal file
115
bcg729/test/src/computeWeightedSpeechTest.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for computeWeightedSpeech bloc */
|
||||
/* Input: 90 values input signal, 10 values of previous weighted signal */
|
||||
/* 20 values of qLPCoefficients, 20 values of weightedqLPCoeffs */
|
||||
/* Ouput: 80 values of weightedSignal */
|
||||
/* 80 values of LP Residual Signal */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "computeWeightedSpeech.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
word16_t inputBuffer[NB_LSP_COEFF+L_FRAME]; /* buffer containing the input signal including 10 values from last frame in range [-10, 0[ */
|
||||
word16_t outputBuffer[NB_LSP_COEFF+L_FRAME]; /* same as input buffer, the values in range [-10,0[ are input */
|
||||
word16_t qLPCoefficients[2*NB_LSP_COEFF]; /* qLP coefficients in Q12: input */
|
||||
word16_t weightedqLPCoefficients[2*NB_LSP_COEFF]; /* weightedqLP coefficients in Q12: input */
|
||||
word16_t LPResidualSignal[L_FRAME]; /* LP Residual signal in Q0: ouput*/
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "rb")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "wb")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(1) /* infinite loop, escape condition is in the reading of data */
|
||||
{
|
||||
int i;
|
||||
/*** read the input data until we have some ***/
|
||||
/* read the input signal */
|
||||
if (fscanf(fpInput,"%hd",&(inputBuffer[0])) != 1) break;
|
||||
for (i=1; i<L_FRAME+NB_LSP_COEFF; i++) {
|
||||
if (fscanf(fpInput,",%hd",&(inputBuffer[i])) != 1) break;
|
||||
}
|
||||
/* read 10 values of weighted signal from previous frame */
|
||||
for (i=0; i<NB_LSP_COEFF; i++) {
|
||||
if (fscanf(fpInput,",%hd",&(outputBuffer[i])) != 1) break; /* the first 10 values of output buffer are input: weighted signal from previous frame */
|
||||
}
|
||||
/* read qLPCoefficients */
|
||||
for (i=0; i<2*NB_LSP_COEFF; i++) {
|
||||
if (fscanf(fpInput,",%hd",&(qLPCoefficients[i])) != 1) break;
|
||||
}
|
||||
/* read weightedqLPCoefficients */
|
||||
for (i=0; i<2*NB_LSP_COEFF; i++) {
|
||||
if (fscanf(fpInput,",%hd",&(weightedqLPCoefficients[i])) != 1) break;
|
||||
}
|
||||
|
||||
/* call the computeWeightedSignal function */
|
||||
computeWeightedSpeech(&(inputBuffer[NB_LSP_COEFF]), qLPCoefficients, weightedqLPCoefficients, &(outputBuffer[NB_LSP_COEFF]), LPResidualSignal); /* input and output buffer shall be accessed by the tested function in range [-NB_LSP_COEFF, LFRAME[ */
|
||||
|
||||
/* write the output to the output file */
|
||||
fprintf(fpOutput,"%d", outputBuffer[NB_LSP_COEFF]);
|
||||
for (i=1; i<L_FRAME; i++) {
|
||||
fprintf(fpOutput,",%d", outputBuffer[NB_LSP_COEFF+i]);
|
||||
}
|
||||
for (i=0; i<L_FRAME; i++) {
|
||||
fprintf(fpOutput,",%d", LPResidualSignal[i]);
|
||||
}
|
||||
fprintf(fpOutput,"\n");
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
123
bcg729/test/src/decodeAdaptativeCodeVectorTest.c
Normal file
123
bcg729/test/src/decodeAdaptativeCodeVectorTest.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for decodeAdaptativeCodeVectorTest bloc */
|
||||
/* Input: - the past excitation (excitationVector) */
|
||||
/* - subframeIndex */
|
||||
/* - frameErasureFlag */
|
||||
/* - parityFlag */
|
||||
/* - adaptative Codebook Index (P1 or P2) */
|
||||
/* */
|
||||
/* Ouput: - adaptative Codebook Vector for the current subframe */
|
||||
/* - int Pitch Delay (T) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "decodeAdaptativeCodeVector.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
/* input file: frameErasureFlag, subframeIndex, P1/2, P0, pastExcitationVector: 154 values */
|
||||
/* output is in the excitationVector */
|
||||
int16_t frameErasureFlag;
|
||||
int subFrameIndex;
|
||||
uint16_t adaptativeCodebookIndex;
|
||||
int16_t parityFlag;
|
||||
word16_t excitationVector[L_PAST_EXCITATION + L_FRAME]; /* this vector contains:
|
||||
0->153 : the past excitation vector.(length is Max Pitch Delay: 144 + interpolation window size : 10)
|
||||
154-> 154+L_FRAME-1 : the current frame adaptative Code Vector first used to compute then the excitation vector */
|
||||
int16_t intPitchDelay; /* output of the function when called for subframe wich is sent back as an input for subframe2 */
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
/* create the context structure */
|
||||
bcg729DecoderChannelContextStruct *decoderChannelContext = malloc(sizeof(bcg729DecoderChannelContextStruct));
|
||||
|
||||
initDecodeAdaptativeCodeVector(decoderChannelContext);
|
||||
|
||||
/* initialise buffers */
|
||||
/* actually useless init, because the complete excitation buffer is reload at each subframe from input file, but shall be done in real decoder */
|
||||
memset(excitationVector, 0, L_PAST_EXCITATION*sizeof(word16_t)); /* initialise the part of the excitationVector containing the past excitation */
|
||||
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(1) /* infinite loop, escape condition is in the reading of data */
|
||||
{
|
||||
int i;
|
||||
/* read the input data until we have some */
|
||||
if (fscanf(fpInput,"%hd",&frameErasureFlag) != 1) break;
|
||||
if (fscanf(fpInput,",%d",&subFrameIndex) != 1) break;
|
||||
if (fscanf(fpInput,",%hd",&adaptativeCodebookIndex) != 1) break;
|
||||
if (fscanf(fpInput,",%hd",&parityFlag) != 1) break;
|
||||
for (i=0; i<194; i++) {
|
||||
if (fscanf(fpInput,",%hd",&(excitationVector[i])) != 1) break;
|
||||
}
|
||||
|
||||
/* call the tested funtion */
|
||||
decodeAdaptativeCodeVector(decoderChannelContext, subFrameIndex, adaptativeCodebookIndex, (uint8_t)parityFlag, (uint8_t)frameErasureFlag,
|
||||
&intPitchDelay, &(excitationVector[L_PAST_EXCITATION + subFrameIndex]));
|
||||
|
||||
|
||||
/* write the output to the output file */
|
||||
fprintf(fpOutput,"%d",excitationVector[L_PAST_EXCITATION + subFrameIndex]);
|
||||
for (i=1; i<L_SUBFRAME; i++) {
|
||||
fprintf(fpOutput,",%d", excitationVector[L_PAST_EXCITATION + subFrameIndex+i]);
|
||||
}
|
||||
fprintf(fpOutput,"\n");
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
103
bcg729/test/src/decodeFixedCodeVectorTest.c
Normal file
103
bcg729/test/src/decodeFixedCodeVectorTest.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for decodeFixedCodeVectorTest bloc */
|
||||
/* Input: - signs: parameter S(4 signs bit) eq61 */
|
||||
/* - positions: parameter C(4 3bits position and jx bit) eq62 */
|
||||
/* - intPitchDelay: integer part of pitch Delay (T) */
|
||||
/* - boundedPitchGain: Beta in eq47 and eq48, in Q14 */
|
||||
/* */
|
||||
/* Ouput: - fixedCodebookVector for current subframe in Q13 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "decodeFixedCodeVector.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
/* input file: Positions(C parameter 13 bits), Signs(S parameter 4 bits), boundedPitchGain, intPitchDelay */
|
||||
/* output: fixedCodebookVector: subframe length vector in Q13 */
|
||||
int16_t signs;
|
||||
int16_t positions;
|
||||
word16_t boundedPitchGain;
|
||||
int16_t intPitchDelay;
|
||||
|
||||
word16_t fixedCodebookVector[L_SUBFRAME];
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
|
||||
/* initialise buffers */
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(fscanf(fpInput,"%hd,%hd,%hd,%hd", &positions, &signs, &boundedPitchGain, &intPitchDelay) == 4) /* loop until end of input data */
|
||||
{
|
||||
int i;
|
||||
|
||||
/* call the tested funtion */
|
||||
decodeFixedCodeVector((uint16_t)signs, (uint16_t)positions, (int16_t)intPitchDelay, (word16_t)boundedPitchGain, fixedCodebookVector);
|
||||
|
||||
|
||||
/* write the output to the output file */
|
||||
fprintf(fpOutput,"%d",fixedCodebookVector[0]);
|
||||
for (i=1; i<L_SUBFRAME; i++) {
|
||||
fprintf(fpOutput,",%d", fixedCodebookVector[i]);
|
||||
}
|
||||
fprintf(fpOutput,"\n");
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
114
bcg729/test/src/decodeGainsTest.c
Normal file
114
bcg729/test/src/decodeGainsTest.c
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for decodeGains bloc */
|
||||
/* Input: - GA parameter */
|
||||
/* - GB parameter */
|
||||
/* - frameErasureFlag */
|
||||
/* - adaptative Codebook Gain from previous frame */
|
||||
/* - fixed Codebook Gain from previous frame */
|
||||
/* - fixed Codebook Vector */
|
||||
/* */
|
||||
/* Ouput: - adaptative Codebook Gain */
|
||||
/* - fixed Codebook Gain */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "decodeGains.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
/* input file: GA, GB, frameErasureFlag, fixedCodebookVector, adaptative codebook gain, fixed codebook gain */
|
||||
/* output : adaptative codebook gain, adaptative codebook gain */
|
||||
int16_t GA, GB;
|
||||
int16_t frameErasureFlag;
|
||||
word16_t fixedCodebookVector[L_SUBFRAME];
|
||||
word16_t adaptativeCodebookGain, fixedCodebookGain;
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
/* create the context structure */
|
||||
bcg729DecoderChannelContextStruct *decoderChannelContext = malloc(sizeof(bcg729DecoderChannelContextStruct));
|
||||
|
||||
initDecodeGains(decoderChannelContext);
|
||||
|
||||
/* initialise buffers */
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(1) /* infinite loop, escape condition is in the reading of data */
|
||||
{
|
||||
int i;
|
||||
/* read the input data until we have some */
|
||||
if (fscanf(fpInput,"%hd",&GA) != 1) break;
|
||||
if (fscanf(fpInput,",%hd",&GB) != 1) break;
|
||||
if (fscanf(fpInput,",%hd",&frameErasureFlag) != 1) break;
|
||||
if (fscanf(fpInput,",%hd",&adaptativeCodebookGain) != 1) break;
|
||||
if (fscanf(fpInput,",%hd",&fixedCodebookGain) != 1) break;
|
||||
for (i=0; i<L_SUBFRAME; i++) {
|
||||
if (fscanf(fpInput,",%hd",&(fixedCodebookVector[i])) != 1) break;
|
||||
}
|
||||
|
||||
/* call the tested funtion */
|
||||
decodeGains(decoderChannelContext, GA, GB, fixedCodebookVector, (uint8_t)frameErasureFlag,
|
||||
&adaptativeCodebookGain, &fixedCodebookGain);
|
||||
|
||||
|
||||
/* write the output to the output file */
|
||||
fprintf(fpOutput,"%d,%d\n",adaptativeCodebookGain, fixedCodebookGain);
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
95
bcg729/test/src/decodeLSPTest.c
Normal file
95
bcg729/test/src/decodeLSPTest.c
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for decodeLSP bloc */
|
||||
/* Input: L coefficient files: L0, L1, L2 and L3 in word16_t format in */
|
||||
/* a text CSV file, 4 values on each row. */
|
||||
/* Ouput: the output of the decodeLSP bloc in a file: series of word16_t */
|
||||
/* 10 elements vectors in a text CSV file */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "decodeLSP.h"
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix;
|
||||
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput;
|
||||
FILE *fpOutput;
|
||||
|
||||
/*** input and output buffers ***/
|
||||
uint16_t inputBuffer[4]; /* input buffer: an array containing the 4 L coefficients */
|
||||
word16_t frameErasedIndicator; /* part of the input file */
|
||||
word16_t outputBuffer[NB_LSP_COEFF]; /* output buffer: the quantized LSF coefficients in Q0.15 */
|
||||
|
||||
/*** inits ***/
|
||||
/* open the input file */
|
||||
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the output file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out",filePrefix);
|
||||
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
/* create the context structure */
|
||||
bcg729DecoderChannelContextStruct *decoderChannelContext = malloc(sizeof(bcg729DecoderChannelContextStruct));
|
||||
initDecodeLSP(decoderChannelContext);
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
|
||||
/*** loop over input file ***/
|
||||
while(fscanf(fpInput, "%hd,%hd,%hd,%hd,%hd", &frameErasedIndicator, &(inputBuffer[0]), &(inputBuffer[1]), &(inputBuffer[2]), &(inputBuffer[3]))==5)
|
||||
{
|
||||
/* call the decodeLSP function */
|
||||
decodeLSP(decoderChannelContext, inputBuffer, outputBuffer, frameErasedIndicator);
|
||||
|
||||
/* write the output to the output file */
|
||||
fprintf(fpOutput,"%d",outputBuffer[0]);
|
||||
int i;
|
||||
for (i=1; i<NB_LSP_COEFF; i++) {
|
||||
fprintf(fpOutput,",%d",outputBuffer[i]);
|
||||
}
|
||||
fprintf(fpOutput,"\n");
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
158
bcg729/test/src/decoderMultiChannelTest.c
Normal file
158
bcg729/test/src/decoderMultiChannelTest.c
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2019 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of bcg729.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Test Program for decoder on multichannels */
|
||||
/* Input: 15 parameters and the frame erasure flag on each row of a */
|
||||
/* a text CSV file in variable number of files */
|
||||
/* Ouput: the reconstructed signal : each frame (80 16 bits PCM values) */
|
||||
/* on a row of a text CSV file in same amount of files */
|
||||
/* */
|
||||
/* All arguments shall be filenames for input file */
|
||||
/* output file keep the prefix and change the file extension to .out.multi*/
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#include "typedef.h"
|
||||
#include "codecParameters.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
#include "bcg729/decoder.h"
|
||||
|
||||
#define MAX_CHANNEL_NBR 50
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
int i;
|
||||
/*** get calling argument ***/
|
||||
char *filePrefix[MAX_CHANNEL_NBR];
|
||||
getArgumentsMultiChannel(argc, argv, filePrefix); /* check argument and set filePrefix if needed */
|
||||
|
||||
/*** input and output file pointers ***/
|
||||
FILE *fpInput[MAX_CHANNEL_NBR];
|
||||
FILE *fpOutput[MAX_CHANNEL_NBR];
|
||||
FILE *fpBinOutput[MAX_CHANNEL_NBR];
|
||||
|
||||
/*** input and output buffers ***/
|
||||
uint16_t inputBuffer[NB_PARAMETERS+1]; /* input buffer: an array containing the 15 parameters and the frame erasure flag */
|
||||
int16_t outputBuffer[L_FRAME]; /* output buffer: the reconstructed signal */
|
||||
uint8_t bitStream[10]; /* binary input for the decoder */
|
||||
bcg729DecoderChannelContextStruct *decoderChannelContext[MAX_CHANNEL_NBR]; /* context array, one per channel */
|
||||
|
||||
/*** inits ***/
|
||||
for (i=0; i<argc-1; i++) {
|
||||
/* open the inputs file */
|
||||
if ( (fpInput[i] = fopen(argv[i+1], "r")) == NULL) {
|
||||
printf("%s - Error: can't open file %s\n", argv[0], argv[i+1]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* create the outputs file(filename is the same than input file with the .out extension) */
|
||||
char *outputFile = malloc((strlen(filePrefix[i])+15)*sizeof(char));
|
||||
sprintf(outputFile, "%s.out.multi",filePrefix[i]);
|
||||
if ( (fpOutput[i] = fopen(outputFile, "w")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[i], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
sprintf(outputFile, "%s.multi.pcm",filePrefix[i]);
|
||||
if ( (fpBinOutput[i] = fopen(outputFile, "wb")) == NULL) {
|
||||
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*** init of the tested bloc ***/
|
||||
decoderChannelContext[i] = initBcg729DecoderChannel();
|
||||
}
|
||||
|
||||
|
||||
/*** initialisation complete ***/
|
||||
|
||||
/* perf measurement */
|
||||
clock_t start, end;
|
||||
double cpu_time_used=0.0;
|
||||
int framesNbr =0;
|
||||
/* increase LOOP_N to increase input length and perform a more accurate profiling or perf measurement */
|
||||
#define LOOP_N 1
|
||||
int j,k;
|
||||
for (j=0; j<LOOP_N; j++) {
|
||||
/* perf measurement */
|
||||
/*** loop over inputs file ***/
|
||||
int endedFilesNbr = 0;
|
||||
int endedFiles[MAX_CHANNEL_NBR];
|
||||
for (k=0; k<argc-1; k++) { /* reset the array of boolean containing a flag for files already read */
|
||||
endedFiles[k]=0;
|
||||
}
|
||||
while (endedFilesNbr<argc-1) { /* loop until the longest file is over */
|
||||
for (k=0; k<argc-1; k++) { /* read one frame on each not ended file */
|
||||
if (endedFiles[k]==0) { /* read only if the file is not over */
|
||||
if (fscanf(fpInput[k], "%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd", &(inputBuffer[0]), &(inputBuffer[1]), &(inputBuffer[2]), &(inputBuffer[3]), &(inputBuffer[4]), &(inputBuffer[5]), &(inputBuffer[6]), &(inputBuffer[7]), &(inputBuffer[8]), &(inputBuffer[9]), &(inputBuffer[10]), &(inputBuffer[11]), &(inputBuffer[12]), &(inputBuffer[13]), &(inputBuffer[14]), &(inputBuffer[15]))==16) /* index 4 and 5 are inverted to get P0 in 4 and P1 in 5 in the array */
|
||||
{ /* input buffer contains the parameters and in [15] the frame erasure flag */
|
||||
int i;
|
||||
framesNbr++;
|
||||
|
||||
parametersArray2BitStream(inputBuffer, bitStream);
|
||||
|
||||
start = clock();
|
||||
bcg729Decoder(decoderChannelContext[k], bitStream, 10, inputBuffer[15], 0, 0, outputBuffer);
|
||||
end = clock();
|
||||
|
||||
cpu_time_used += ((double) (end - start));
|
||||
|
||||
/* write the output to the output file */
|
||||
if (j==0) {
|
||||
fprintf(fpOutput[k],"%d",outputBuffer[0]);
|
||||
for (i=1; i<L_FRAME; i++) {
|
||||
fprintf(fpOutput[k],",%d",outputBuffer[i]);
|
||||
}
|
||||
fprintf(fpOutput[k],"\n");
|
||||
/* write the ouput to raw data file */
|
||||
fwrite(outputBuffer, sizeof(int16_t), L_FRAME, fpBinOutput[k]);
|
||||
}
|
||||
} else { /* we've reach the end of the file */
|
||||
endedFiles[k]=1;
|
||||
endedFilesNbr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* perf measurement */
|
||||
for (k=0; k<argc-1; k++) {
|
||||
rewind(fpInput[k]);
|
||||
}
|
||||
}
|
||||
|
||||
/* close decoder channels */
|
||||
for (k=0; k<argc-1; k++) {
|
||||
closeBcg729DecoderChannel(decoderChannelContext[k]);
|
||||
}
|
||||
/* Perf measurement: uncomment next line to print cpu usage */
|
||||
printf("Decode %d frames in %f seconds : %f us/frame\n", framesNbr, cpu_time_used/CLOCKS_PER_SEC, cpu_time_used*1000000/((double)framesNbr*CLOCKS_PER_SEC));
|
||||
/* perf measurement */
|
||||
exit (0);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue