${ROOT_DIR}/zhihui/4g/cat1Service/Service
${ROOT_DIR}/zhihui/4gTest
${ROOT_DIR}/zhihui/leiniao/imsl_ln/
+ ${ROOT_DIR}/zhihui/leiniao/imsl_ln/LN_MQTT/
)
set(PUBLIC_HEADER
return AUDIO_SUCCESS;
}
+int32_t OnRenderCallback(const void *caller, AudioCallbackEventType event, const void *info)
+{
+ (void)info;
+ printf("OnRenderCallback event %d\r\n",event);
+ return 0;
+}
+
int32_t AudioStreamOutInit(AudioRendererConfig renderConfig)
{
g_streamOut = std::make_shared<AudioStreamOut>();
return AUDIO_ERROR;
}
- int32_t ret = g_streamOut->Init(renderConfig);
+ int32_t ret = g_streamOut->Init(renderConfig,OnRenderCallback);
if (ret != AUDIO_SUCCESS) {
ALOGE("audio stream out init failed 0x%x", ret);
return AUDIO_ERROR;
{ AUDIO_IN_COMMUNICATION, AUDIO_FORMAT_PCM_16_BIT, 16000, 1},
{ AUDIO_IN_COMMUNICATION, AUDIO_FORMAT_OPUS, 16000, 1 },
{ AUDIO_IN_COMMUNICATION, AUDIO_FORMAT_MP3, 16000, 1 },
+ { AUDIO_IN_COMMUNICATION, AUDIO_FORMAT_SBC, 16000, 1 },
};
static bool isMultipleAIOpen(void)
add_subdirectory_if_exist(minimp3)
add_subdirectory_if_exist(shake)
add_subdirectory_if_exist(dmp)
+add_subdirectory_if_exist(MQTT)
+add_subdirectory_if_exist(test_opus_frame_to_pcm)
+
--- /dev/null
+#===============================================================================
+# @brief MQTT component cmake file
+# Copyright (c) @CompanyNameMagicTag 2023-2023. All rights reserved.
+#===============================================================================
+set(COMPONENT_NAME "mqtt_service")
+
+# 源文件
+set(SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/MQTT_server_mian.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/uapi_mqtt.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/uapi_mqtt_at.c
+ ${ROOT_DIR}/open_source/openharmony/third_party/lwip/lwip_v2.1.3/src/apps/mqtt/mqtt.c
+)
+
+# 公共头文件路径(供其他模块引用)
+set(PUBLIC_HEADER
+ ${CMAKE_CURRENT_SOURCE_DIR}/
+ ${ROOT_DIR}/open_source/openharmony/third_party/lwip/lwip_v2.1.3/src/include
+ ${ROOT_DIR}/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/include
+ ${ROOT_DIR}/open_source/openharmony/third_party/cJSON/
+ ${ROOT_DIR}/zhihui/utils/
+)
+
+# 公共宏定义(可选)
+set(PUBLIC_DEFINES
+ # MQTT服务相关宏定义
+)
+
+# 私有头文件路径(仅当前组件内部使用)
+set(PRIVATE_HEADER
+ ${CMAKE_CURRENT_SOURCE_DIR}/
+)
+
+# 私有宏定义(可选)
+set(PRIVATE_DEFINES
+ # 如无特殊私有宏,可留空
+)
+
+# 公共编译选项(可选)
+set(COMPONENT_PUBLIC_CCFLAGS
+)
+
+# 组件专属编译选项
+set(COMPONENT_CCFLAGS
+ -Wno-incompatible-function-pointer-types
+ -Wno-unused-function # 屏蔽未使用函数的警告(根据实际情况调整)
+)
+
+# 是否启用全量链接(静态库通常需要)
+set(WHOLE_LINK
+ true
+)
+
+# 是否为主组件(通常为false,主组件一般是app)
+set(MAIN_COMPONENT
+ false
+)
+
+# 安装SDK时包含的文件(头文件和库文件)
+install_sdk(${CMAKE_CURRENT_SOURCE_DIR} "*")
+
+# 构建组件
+build_component()
+
--- /dev/null
+#include "custom_utils.h"
+#include "cmsis_os2.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <linux/delay.h>
+#include "uapi_Mqtt_api.h"
+
+/* MQTT 日志等级变量(默认设置为 DEBUG) */
+extern mqtt_log_level_t g_mqtt_log_level ;
+
+#ifndef UINT32_MAX
+#define UINT32_MAX 0xFFFFFFFFUL
+#endif
+
+/* MQTT消息类型定义 */
+#define MQTT_MSG_TYPE_SEND 0x01 // 发送消息
+#define MQTT_MSG_TYPE_RECV 0x02 // 接收消息
+#define MQTT_MSG_TYPE_STOP 0x03 // 停止线程
+#define MQTT_MSG_TYPE_CONNECT 0x04 // 连接请求
+#define MQTT_MSG_TYPE_DISCONNECT 0x05 // 断开请求
+#define MQTT_MSG_TYPE_SUBSCRIBE 0x06 // 订阅结果
+
+/* MQTT连接状态 */
+#define MQTT_STATE_DISCONNECTED 0
+#define MQTT_STATE_CONNECTING 1
+#define MQTT_STATE_CONNECTED 2
+#define MQTT_STATE_RECONNECTING 3
+
+/* MQTT消息队列大小 */
+#define MQTT_SEND_QUEUE_COUNT 64
+#define MQTT_RECV_QUEUE_COUNT 64
+
+/* MQTT发送消息结构体 */
+typedef struct {
+ char topic[256];
+ uint8_t *payload;
+ uint16_t payload_len;
+ uint8_t qos;
+ uint8_t retain;
+} mqtt_send_msg_t;
+
+/* MQTT接收消息结构体 */
+typedef struct {
+ char topic[256];
+ uint8_t *data;
+ uint16_t data_len;
+} mqtt_recv_msg_t;
+
+/* MQTT订阅结果消息结构体 */
+typedef struct {
+ char topic[256];
+ uint8_t qos;
+ int result; // 0表示成功,非0表示失败
+} mqtt_subscribe_msg_t;
+
+/* MQTT消息结构体(用于队列) */
+typedef struct {
+ uint8_t msg_type;
+ union {
+ mqtt_send_msg_t send_msg;
+ mqtt_recv_msg_t recv_msg;
+ mqtt_subscribe_msg_t subscribe_msg;
+ } msg;
+} mqtt_queue_msg_t;
+
+/* 全局变量 */
+static volatile int g_mqtt_thread_running = 0;
+static uint32_t g_mqtt_send_thread_handle = 0;
+static uint32_t g_mqtt_main_thread_handle = 0;
+static osMessageQueueId_t g_mqtt_send_queue = NULL; // 发送队列(发送消息,由发送线程处理)
+static osMessageQueueId_t g_mqtt_recv_queue = NULL; // 接收队列(接收消息,由主线程处理)
+static volatile int g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+static volatile int g_mqtt_connection_status = -1; // 连接状态码(-1表示未初始化,0表示连接成功,其他值表示错误码)
+static volatile int g_mqtt_last_connection_status = -1; // 上一次的连接状态码,用于检测状态变化
+static uint32_t g_mqtt_reconnect_count = 0;
+static uint32_t g_mqtt_last_connect_attempt = 0;
+static mqtt_call_backs_t g_mqtt_callbacks = {0}; // MQTT回调函数结构体
+static uint32_t g_main_thread_interval_ms = 1000; // 主线程循环间隔时长(毫秒),默认1000ms
+#define MQTT_RECONNECT_INTERVAL_MS 5000 // 重连间隔5秒
+
+/* 前向声明 */
+static void mqtt_send_thread(void *arg);
+static void mqtt_main_thread(void *arg);
+static void mqtt_queue_init(void);
+static void mqtt_send_queue_init(void);
+static void mqtt_recv_queue_init(void);
+static void mqtt_main_queue_init(void);
+static int mqtt_try_connect(void);
+static void mqtt_connection_status_cb(void *arg, int status);
+
+/**
+ * @brief 初始化发送队列
+ */
+static void mqtt_send_queue_init(void)
+{
+ MQTT_DEBUG("Initializing send queue\n");
+ g_mqtt_send_queue = osMessageQueueNew(MQTT_SEND_QUEUE_COUNT, sizeof(mqtt_queue_msg_t*), NULL);
+ if (g_mqtt_send_queue == NULL) {
+ MQTT_ERROR("Failed to create send queue\n");
+ } else {
+ MQTT_DEBUG("Send queue created successfully\n");
+ }
+}
+
+/**
+ * @brief 初始化接收队列
+ */
+static void mqtt_recv_queue_init(void)
+{
+ MQTT_DEBUG("Initializing recv queue\n");
+ g_mqtt_recv_queue = osMessageQueueNew(MQTT_RECV_QUEUE_COUNT, sizeof(mqtt_queue_msg_t*), NULL);
+ if (g_mqtt_recv_queue == NULL) {
+ MQTT_ERROR("Failed to create recv queue\n");
+ } else {
+ MQTT_DEBUG("Recv queue created successfully\n");
+ }
+}
+
+/**
+ * @brief 初始化主线程队列(用于连接管理)
+ */
+static void mqtt_main_queue_init(void)
+{
+ // 主线程使用发送队列处理命令消息,不需要单独创建
+ MQTT_DEBUG("Main thread queue initialized\n");
+}
+
+/**
+ * @brief 初始化队列(统一接口)
+ */
+static void mqtt_queue_init(void)
+{
+ mqtt_send_queue_init();
+ mqtt_recv_queue_init();
+ mqtt_main_queue_init();
+}
+
+/**
+ * @brief MQTT连接状态回调(用于主线程)
+ * 只更新全局状态变量,由主线程循环检测状态变化并触发用户回调
+ */
+static void mqtt_connection_status_cb(void *arg, int status)
+{
+ (void)arg;
+ MQTT_DEBUG("Connection status callback: %d\n", status);
+
+ // 更新连接状态码
+ g_mqtt_connection_status = status;
+
+ if (status == 0) { // MQTT_CONNECT_ACCEPTED
+ g_mqtt_connection_state = MQTT_STATE_CONNECTED;
+ g_mqtt_reconnect_count = 0;
+ MQTT_INFO("MQTT connected successfully\n");
+ } else {
+ g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+ MQTT_INFO("MQTT disconnected, status: %d\n", status);
+ }
+}
+
+/**
+ * @brief MQTT消息接收回调(用于主线程)
+ * 将接收到的消息放入接收队列(用户回调将在队列读取时触发)
+ */
+static void mqtt_message_cb(void *arg, const char *topic, const uint8_t *data, uint16_t len)
+{
+ (void)arg;
+
+ MQTT_DEBUG("Message received callback: topic=%s, len=%d\n", topic ? topic : "NULL", len);
+
+
+
+
+ // 将接收到的消息放入接收队列(用户回调将在主线程从队列读取时触发)
+ if (topic && data && len > 0) {
+ int ret = uapi_mqtt_main_recv_enqueue(topic, data, len);
+ if (ret != 0) {
+ MQTT_ERROR("Failed to enqueue received message\n");
+ }
+ }
+}
+
+/**
+ * @brief 尝试连接MQTT服务器
+ */
+static int mqtt_try_connect(void)
+{
+ if (g_mqtt_connection_state == MQTT_STATE_CONNECTING ||
+ g_mqtt_connection_state == MQTT_STATE_CONNECTED) {
+ return 0; // 正在连接或已连接
+ }
+
+ MQTT_INFO("Attempting to connect MQTT server\n");
+ g_mqtt_connection_state = MQTT_STATE_CONNECTING;
+ g_mqtt_last_connect_attempt = osKernelGetTickCount();
+
+ // 初始化MQTT客户端
+ if (uapi_mqtt_init() != 0) {
+ MQTT_ERROR("Failed to initialize MQTT client\n");
+ g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+ return -1;
+ }
+
+ // 尝试通过回调获取凭证
+ mqtt_credentials_t credentials = {0};
+ const mqtt_credentials_t *use_cred = NULL;
+
+ if (g_mqtt_callbacks.credentials_callback != NULL) {
+ MQTT_DEBUG("Getting credentials from callback\n");
+ if (g_mqtt_callbacks.credentials_callback(g_mqtt_callbacks.user_arg, &credentials) == 0) {
+ // 检查凭证是否有效
+ if (credentials.endpoint[0] != '\0' && credentials.client_id[0] != '\0') {
+ use_cred = &credentials;
+ MQTT_DEBUG("Credentials obtained from callback\n");
+ } else {
+ MQTT_WARN("Invalid credentials from callback, will load from file\n");
+ }
+ } else {
+ MQTT_WARN("Credentials callback returned error, will load from file\n");
+ }
+ }
+
+ // 如果回调未提供凭证,则从文件加载(NULL表示从文件加载)
+ // 连接MQTT服务器
+ int ret = uapi_mqtt_connect(use_cred, mqtt_connection_status_cb, mqtt_message_cb, NULL);
+ if (ret != 0) {
+ MQTT_ERROR("Failed to initiate MQTT connection: %d\n", ret);
+ g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief MQTT发送线程
+ */
+static void mqtt_send_thread(void *arg)
+{
+ (void)arg;
+ mqtt_queue_msg_t *msg = NULL;
+
+ MQTT_INFO("Send thread started\n");
+
+ while (g_mqtt_thread_running) {
+ // 从发送队列获取消息(阻塞等待,超时100ms)
+ osStatus_t status = osMessageQueueGet(g_mqtt_send_queue, &msg, NULL, 100);
+
+ if (status == osOK && msg != NULL) {
+ if (msg->msg_type == MQTT_MSG_TYPE_STOP) {
+ MQTT_DEBUG("Send thread received stop signal\n");
+ free(msg);
+ break;
+ }
+
+ // 发送线程只处理发送消息类型
+ if (msg->msg_type == MQTT_MSG_TYPE_SEND) {
+ // 检查连接状态
+ if (uapi_mqtt_is_connected()) {
+ MQTT_DEBUG("Sending message to topic: %s, len: %d\n",
+ msg->msg.send_msg.topic, msg->msg.send_msg.payload_len);
+
+ int ret = uapi_mqtt_publish(msg->msg.send_msg.topic,
+ msg->msg.send_msg.payload,
+ msg->msg.send_msg.payload_len,
+ msg->msg.send_msg.qos,
+ msg->msg.send_msg.retain);
+ if (ret != 0) {
+ MQTT_ERROR("Failed to publish message: %d\n", ret);
+ }
+ } else {
+ MQTT_WARN("MQTT not connected, message dropped\n");
+ }
+
+ // 释放消息内存
+ if (msg->msg.send_msg.payload != NULL) {
+ free(msg->msg.send_msg.payload);
+ }
+
+ free(msg);
+ msg = NULL;
+ } else {
+ // 其他消息类型(命令消息)主线程不再处理,直接释放
+ MQTT_WARN("Send thread: Unknown message type %d, dropping\n", msg->msg_type);
+ free(msg);
+ msg = NULL;
+ }
+ }
+ }
+
+ MQTT_INFO("Send thread exited\n");
+}
+
+
+/**
+ * @brief MQTT主线程(管理连接状态、重连等)
+ */
+static void mqtt_main_thread(void *arg)
+{
+ (void)arg;
+ mqtt_queue_msg_t *msg = NULL;
+ int last_connection_state = MQTT_STATE_DISCONNECTED;
+
+ MQTT_INFO("Main thread started\n");
+
+ // 初始化上一次的连接状态码
+ g_mqtt_last_connection_status = g_mqtt_connection_status;
+
+ // 尝试首次连接(mqtt_try_connect内部会初始化)
+ mqtt_try_connect();
+
+ while (g_mqtt_thread_running) {
+ // 处理接收队列中的接收消息(非阻塞)
+ if (osMessageQueueGet(g_mqtt_recv_queue, &msg, NULL, 0) == osOK) {
+ if (msg != NULL) {
+ if (msg->msg_type == MQTT_MSG_TYPE_RECV) {
+ MQTT_DEBUG("Received message from topic: %s, len: %d\n",
+ msg->msg.recv_msg.topic, msg->msg.recv_msg.data_len);
+
+ // 处理接收到的消息
+ if (msg->msg.recv_msg.data != NULL && msg->msg.recv_msg.data_len > 0) {
+ // 打印消息内容(限制长度)
+ MQTT_DEBUG("Message content: ");
+ uint16_t print_len = msg->msg.recv_msg.data_len > 100 ? 100 : msg->msg.recv_msg.data_len;
+ for (uint16_t i = 0; i < print_len; i++) {
+ uint8_t c = msg->msg.recv_msg.data[i];
+ if (c >= 32 && c < 127) {
+ printf("%c", c);
+ } else {
+ printf(".");
+ }
+ }
+ if (msg->msg.recv_msg.data_len > 100) {
+ printf("...");
+ }
+ printf("\n");
+
+ // 调用用户注册的消息回调(在队列读取时触发)
+ if (g_mqtt_callbacks.message_callback != NULL) {
+ g_mqtt_callbacks.message_callback(g_mqtt_callbacks.user_arg,
+ msg->msg.recv_msg.topic,
+ msg->msg.recv_msg.data,
+ msg->msg.recv_msg.data_len);
+ }
+
+ // 这里可以添加更多消息处理逻辑
+ // 例如:解析JSON、路由到不同的处理函数等
+ }
+
+ // 释放消息内存
+ if (msg->msg.recv_msg.data != NULL) {
+ free(msg->msg.recv_msg.data);
+ }
+ } else if (msg->msg_type == MQTT_MSG_TYPE_SUBSCRIBE) {
+ // 处理订阅结果消息(在主线程中触发用户回调)
+ MQTT_DEBUG("Subscribe result - Topic: %s, QoS: %d, Result: %d\n",
+ msg->msg.subscribe_msg.topic,
+ msg->msg.subscribe_msg.qos,
+ msg->msg.subscribe_msg.result);
+
+ // 调用用户注册的订阅回调(在主线程中触发)
+ if (g_mqtt_callbacks.subscribe_callback != NULL) {
+ g_mqtt_callbacks.subscribe_callback(g_mqtt_callbacks.user_arg,
+ msg->msg.subscribe_msg.topic,
+ msg->msg.subscribe_msg.qos,
+ msg->msg.subscribe_msg.result);
+ }
+ } else {
+ MQTT_WARN("Unknown message type in recv queue: %d\n", msg->msg_type);
+ }
+
+ free(msg);
+ msg = NULL;
+ }
+ }
+
+ // 检测连接状态码变化(在主线程循环中检测并触发用户回调)
+ if (g_mqtt_connection_status != g_mqtt_last_connection_status) {
+ int current_status = g_mqtt_connection_status;
+ int last_status = g_mqtt_last_connection_status;
+
+ MQTT_DEBUG("Connection status changed in main thread: %d -> %d\n",
+ last_status, current_status);
+
+ // 更新上一次的状态码
+ g_mqtt_last_connection_status = current_status;
+
+ // 调用用户注册的连接回调(在主线程循环中触发)
+ if (g_mqtt_callbacks.connect_callback != NULL) {
+ g_mqtt_callbacks.connect_callback(g_mqtt_callbacks.user_arg, current_status);
+ }
+ }
+
+ // 检测连接状态变化(用于日志输出)
+ if (g_mqtt_connection_state != last_connection_state) {
+ MQTT_DEBUG("Connection state changed: %d -> %d\n",
+ last_connection_state, g_mqtt_connection_state);
+ last_connection_state = g_mqtt_connection_state;
+ }
+
+ // 连接管理:检查连接状态并处理重连
+ if (g_mqtt_connection_state == MQTT_STATE_DISCONNECTED) {
+ // 检查是否需要重连
+ uint32_t current_tick = osKernelGetTickCount();
+ uint32_t elapsed_ticks = 0;
+
+ if (current_tick >= g_mqtt_last_connect_attempt) {
+ elapsed_ticks = current_tick - g_mqtt_last_connect_attempt;
+ } else {
+ // 处理tick溢出
+ elapsed_ticks = (UINT32_MAX - g_mqtt_last_connect_attempt) + current_tick;
+ }
+
+ // 将tick转换为毫秒(使用osKernelGetTickFreq获取tick频率)
+ uint32_t tick_freq = osKernelGetTickFreq();
+ uint32_t elapsed_ms = (elapsed_ticks * 1000) / (tick_freq > 0 ? tick_freq : 100);
+
+ if (elapsed_ms >= MQTT_RECONNECT_INTERVAL_MS) {
+ g_mqtt_reconnect_count++;
+ MQTT_INFO("Attempting reconnect #%u\n", g_mqtt_reconnect_count);
+ mqtt_try_connect();
+ }
+ } else if (g_mqtt_connection_state == MQTT_STATE_CONNECTING) {
+ // 检查连接超时(30秒)
+ uint32_t current_tick = osKernelGetTickCount();
+ uint32_t elapsed_ticks = 0;
+
+ if (current_tick >= g_mqtt_last_connect_attempt) {
+ elapsed_ticks = current_tick - g_mqtt_last_connect_attempt;
+ } else {
+ elapsed_ticks = (UINT32_MAX - g_mqtt_last_connect_attempt) + current_tick;
+ }
+
+ // 将tick转换为毫秒
+ uint32_t tick_freq = osKernelGetTickFreq();
+ uint32_t elapsed_ms = (elapsed_ticks * 1000) / (tick_freq > 0 ? tick_freq : 100);
+ uint32_t timeout_ms = 30000;
+
+ if (elapsed_ms >= timeout_ms) {
+ MQTT_WARN("Connection timeout, resetting state\n");
+ g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+ uapi_mqtt_disconnect();
+ }
+ }
+
+ // 检查实际连接状态(与状态标志同步)
+ bool actual_connected = uapi_mqtt_is_connected();
+ if (actual_connected && g_mqtt_connection_state != MQTT_STATE_CONNECTED) {
+ g_mqtt_connection_state = MQTT_STATE_CONNECTED;
+ MQTT_DEBUG("Connection state synchronized to CONNECTED\n");
+ } else if (!actual_connected && g_mqtt_connection_state == MQTT_STATE_CONNECTED) {
+ g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+ MQTT_DEBUG("Connection state synchronized to DISCONNECTED\n");
+ }
+
+ // 延迟,避免CPU占用过高(使用配置的间隔时长)
+ msleep(g_main_thread_interval_ms);
+ }
+
+ // 清理:断开MQTT连接
+ if (g_mqtt_connection_state == MQTT_STATE_CONNECTED) {
+ uapi_mqtt_disconnect();
+ }
+ uapi_mqtt_deinit();
+ g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+
+ MQTT_INFO("Main thread exited\n");
+}
+
+/**
+ * @brief 启动MQTT发送和接收线程
+ * @param callbacks MQTT回调函数结构体(可以为NULL,使用默认处理)
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_start(const mqtt_call_backs_t *callbacks)
+{
+ if (g_mqtt_thread_running) {
+ MQTT_INFO("Threads already running\n");
+ return 0;
+ }
+
+ g_mqtt_thread_running = 1;
+ g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+ g_mqtt_reconnect_count = 0;
+
+ // 注册回调函数结构体
+ if (callbacks != NULL) {
+ g_mqtt_callbacks = *callbacks;
+
+ // 设置主线程间隔时长,如果未设置则使用默认值
+ if (g_mqtt_callbacks.main_thread_interval_ms > 0) {
+ g_main_thread_interval_ms = g_mqtt_callbacks.main_thread_interval_ms;
+ } else {
+ g_main_thread_interval_ms = 1000; // 默认1000ms
+ }
+
+ MQTT_INFO("MQTT callbacks registered successfully, main thread interval: %u ms\n", g_main_thread_interval_ms);
+
+ if (g_mqtt_callbacks.connect_callback != NULL) {
+ MQTT_DEBUG("Connect callback registered\n");
+ } else {
+ MQTT_DEBUG("No connect callback registered\n");
+ }
+
+ if (g_mqtt_callbacks.message_callback != NULL) {
+ MQTT_DEBUG("Message callback registered\n");
+ } else {
+ MQTT_DEBUG("No message callback registered\n");
+ }
+
+ if (g_mqtt_callbacks.credentials_callback != NULL) {
+ MQTT_DEBUG("Credentials callback registered\n");
+ } else {
+ MQTT_DEBUG("No credentials callback registered (will load from file)\n");
+ }
+ } else {
+ memset(&g_mqtt_callbacks, 0, sizeof(mqtt_call_backs_t));
+ g_main_thread_interval_ms = 1000; // 默认1000ms
+ MQTT_INFO("No callbacks provided, using defaults\n");
+ }
+
+ // 初始化队列
+ mqtt_queue_init();
+
+ // 创建主线程(管理连接状态和接收消息)
+ {
+ app_task_definition_ext_t main_task = {
+ .attr = {
+ .name = "uapi_mqtt_main",
+ .stack_size = 0x2000,
+ .priority = osPriorityNormal
+ },
+ .func = mqtt_main_thread,
+ .task_handle = &g_mqtt_main_thread_handle,
+ .create_queue_handle = mqtt_main_queue_init,
+ .use_mem = USE_EXTEND_MEM,
+ .inst_args = NULL
+ };
+
+ errcode_t ret = uapi_create_osThread_custom_with_args(&main_task);
+ if (ret != ERRCODE_SUCC) {
+ MQTT_ERROR("Failed to create main thread: %d\n", ret);
+ g_mqtt_thread_running = 0;
+ return -1;
+ }
+ MQTT_INFO("Main thread created successfully\n");
+ }
+
+ // 创建发送线程(处理发送消息)
+ {
+ app_task_definition_ext_t send_task = {
+ .attr = {
+ .name = "uapi_mqtt_send",
+ .stack_size = 0x2000,
+ .priority = osPriorityNormal
+ },
+ .func = mqtt_send_thread,
+ .task_handle = &g_mqtt_send_thread_handle,
+ .create_queue_handle = NULL, // 发送队列已初始化,不需要单独创建
+ .use_mem = USE_EXTEND_MEM,
+ .inst_args = NULL
+ };
+
+ errcode_t ret = uapi_create_osThread_custom_with_args(&send_task);
+ if (ret != ERRCODE_SUCC) {
+ MQTT_ERROR("Failed to create send thread: %d\n", ret);
+ g_mqtt_thread_running = 0;
+ return -1;
+ }
+ MQTT_INFO("Send thread created successfully\n");
+ }
+
+ MQTT_INFO("MQTT threads started successfully\n");
+ return 0;
+}
+
+/**
+ * @brief 停止MQTT发送和接收线程
+ */
+void uapi_mqtt_main_stop(void)
+{
+ if (!g_mqtt_thread_running) {
+ return;
+ }
+
+ MQTT_INFO("Stopping MQTT threads\n");
+ g_mqtt_thread_running = 0;
+
+ // 断开MQTT连接
+ if (g_mqtt_connection_state == MQTT_STATE_CONNECTED) {
+ uapi_mqtt_disconnect();
+ }
+
+ // 发送停止消息到发送队列(主线程和发送线程都会处理)
+ if (g_mqtt_send_queue != NULL) {
+ mqtt_queue_msg_t *stop_msg = (mqtt_queue_msg_t *)malloc(sizeof(mqtt_queue_msg_t));
+ if (stop_msg != NULL) {
+ stop_msg->msg_type = MQTT_MSG_TYPE_STOP;
+ osMessageQueuePut(g_mqtt_send_queue, &stop_msg, 0, 0);
+ }
+ }
+
+ // 等待线程退出(最多等待2秒)
+ int wait_count = 0;
+ while ((g_mqtt_main_thread_handle != 0 || g_mqtt_send_thread_handle != 0) && wait_count < 200) {
+ msleep(10);
+ wait_count++;
+ }
+
+ // 清理发送队列中的剩余消息
+ if (g_mqtt_send_queue != NULL) {
+ mqtt_queue_msg_t *msg = NULL;
+ while (osMessageQueueGet(g_mqtt_send_queue, &msg, NULL, 0) == osOK) {
+ if (msg != NULL) {
+ if (msg->msg_type == MQTT_MSG_TYPE_SEND && msg->msg.send_msg.payload != NULL) {
+ free(msg->msg.send_msg.payload);
+ }
+ free(msg);
+ }
+ }
+ osMessageQueueDelete(g_mqtt_send_queue);
+ g_mqtt_send_queue = NULL;
+ }
+
+ // 清理接收队列中的剩余消息
+ if (g_mqtt_recv_queue != NULL) {
+ mqtt_queue_msg_t *msg = NULL;
+ while (osMessageQueueGet(g_mqtt_recv_queue, &msg, NULL, 0) == osOK) {
+ if (msg != NULL) {
+ if (msg->msg_type == MQTT_MSG_TYPE_RECV && msg->msg.recv_msg.data != NULL) {
+ free(msg->msg.recv_msg.data);
+ }
+ free(msg);
+ }
+ }
+ osMessageQueueDelete(g_mqtt_recv_queue);
+ g_mqtt_recv_queue = NULL;
+ }
+
+ g_mqtt_main_thread_handle = 0;
+ g_mqtt_send_thread_handle = 0;
+ g_mqtt_connection_state = MQTT_STATE_DISCONNECTED;
+
+ // 清空回调函数结构体
+ memset(&g_mqtt_callbacks, 0, sizeof(mqtt_call_backs_t));
+
+ MQTT_INFO("MQTT threads stopped\n");
+}
+
+/**
+ * @brief 发送MQTT消息到队列
+ * @param topic 主题名称
+ * @param payload 消息内容
+ * @param payload_len 消息长度
+ * @param qos QoS等级
+ * @param retain 保留标志
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_send(const char *topic, const void *payload, uint16_t payload_len, uint8_t qos, uint8_t retain)
+{
+ if (!g_mqtt_thread_running || g_mqtt_send_queue == NULL) {
+ MQTT_WARN("Send queue not available\n");
+ return -1;
+ }
+
+ if (!topic || !payload || payload_len == 0) {
+ MQTT_ERROR("Invalid parameters\n");
+ return -1;
+ }
+
+ // 分配消息结构体
+ mqtt_queue_msg_t *msg = (mqtt_queue_msg_t *)malloc(sizeof(mqtt_queue_msg_t));
+ if (msg == NULL) {
+ MQTT_ERROR("Failed to allocate message\n");
+ return -1;
+ }
+
+ memset(msg, 0, sizeof(mqtt_queue_msg_t));
+ msg->msg_type = MQTT_MSG_TYPE_SEND;
+
+ // 复制主题
+ strncpy(msg->msg.send_msg.topic, topic, sizeof(msg->msg.send_msg.topic) - 1);
+ msg->msg.send_msg.topic[sizeof(msg->msg.send_msg.topic) - 1] = '\0';
+
+ // 分配并复制payload
+ msg->msg.send_msg.payload = (uint8_t *)malloc(payload_len);
+ if (msg->msg.send_msg.payload == NULL) {
+ MQTT_ERROR("Failed to allocate payload\n");
+ free(msg);
+ return -1;
+ }
+ memcpy(msg->msg.send_msg.payload, payload, payload_len);
+
+ msg->msg.send_msg.payload_len = payload_len;
+ msg->msg.send_msg.qos = qos;
+ msg->msg.send_msg.retain = retain;
+
+ // 将消息放入发送队列
+ osStatus_t status = osMessageQueuePut(g_mqtt_send_queue, &msg, 0, 0);
+ if (status != osOK) {
+ MQTT_ERROR("Failed to put message to queue: %d\n", status);
+ free(msg->msg.send_msg.payload);
+ free(msg);
+ return -1;
+ }
+
+ MQTT_DEBUG("Message queued for sending: topic=%s, len=%d\n", topic, payload_len);
+ return 0;
+}
+
+/**
+ * @brief 将订阅结果消息放入接收队列(供MQTT回调函数调用)
+ * @param topic 主题名称
+ * @param qos QoS等级
+ * @param result 订阅结果(0表示成功,非0表示失败)
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_subscribe_enqueue(const char *topic, uint8_t qos, int result)
+{
+ if (!g_mqtt_thread_running || g_mqtt_recv_queue == NULL) {
+ return -1;
+ }
+
+ if (!topic) {
+ return -1;
+ }
+
+ // 分配消息结构体
+ mqtt_queue_msg_t *msg = (mqtt_queue_msg_t *)malloc(sizeof(mqtt_queue_msg_t));
+ if (msg == NULL) {
+ return -1;
+ }
+
+ memset(msg, 0, sizeof(mqtt_queue_msg_t));
+ msg->msg_type = MQTT_MSG_TYPE_SUBSCRIBE;
+
+ // 复制主题
+ strncpy(msg->msg.subscribe_msg.topic, topic, sizeof(msg->msg.subscribe_msg.topic) - 1);
+ msg->msg.subscribe_msg.topic[sizeof(msg->msg.subscribe_msg.topic) - 1] = '\0';
+
+ // 设置QoS和结果
+ msg->msg.subscribe_msg.qos = qos;
+ msg->msg.subscribe_msg.result = result;
+
+ // 将消息放入接收队列
+ osStatus_t status = osMessageQueuePut(g_mqtt_recv_queue, &msg, 0, 0);
+ if (status != osOK) {
+ MQTT_ERROR("Failed to put subscribe message to queue: %d\n", status);
+ free(msg);
+ return -1;
+ }
+
+ MQTT_DEBUG("Subscribe message queued: topic=%s, qos=%d, result=%d\n", topic, qos, result);
+ return 0;
+}
+
+/**
+ * @brief 将接收到的MQTT消息放入接收队列(供MQTT回调函数调用)
+ * @param topic 主题名称
+ * @param data 消息数据
+ * @param data_len 消息长度
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_recv_enqueue(const char *topic, const uint8_t *data, uint16_t data_len)
+{
+ if (!g_mqtt_thread_running || g_mqtt_recv_queue == NULL) {
+ return -1;
+ }
+
+ if (!topic || !data || data_len == 0) {
+ return -1;
+ }
+
+ // 分配消息结构体
+ mqtt_queue_msg_t *msg = (mqtt_queue_msg_t *)malloc(sizeof(mqtt_queue_msg_t));
+ if (msg == NULL) {
+ return -1;
+ }
+
+ memset(msg, 0, sizeof(mqtt_queue_msg_t));
+ msg->msg_type = MQTT_MSG_TYPE_RECV;
+
+ // 复制主题
+ strncpy(msg->msg.recv_msg.topic, topic, sizeof(msg->msg.recv_msg.topic) - 1);
+ msg->msg.recv_msg.topic[sizeof(msg->msg.recv_msg.topic) - 1] = '\0';
+
+ // 分配并复制数据
+ msg->msg.recv_msg.data = (uint8_t *)malloc(data_len);
+ if (msg->msg.recv_msg.data == NULL) {
+ free(msg);
+ return -1;
+ }
+ memcpy(msg->msg.recv_msg.data, data, data_len);
+
+ msg->msg.recv_msg.data_len = data_len;
+
+ // 将消息放入队列
+ osStatus_t status = osMessageQueuePut(g_mqtt_recv_queue, &msg, 0, 0);
+ if (status != osOK) {
+ free(msg->msg.recv_msg.data);
+ free(msg);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief 获取MQTT连接状态
+ * @return 连接状态(MQTT_STATE_DISCONNECTED/MQTT_STATE_CONNECTING/MQTT_STATE_CONNECTED)
+ */
+int uapi_mqtt_main_get_state(void)
+{
+ return g_mqtt_connection_state;
+}
+
--- /dev/null
+#ifndef UAPI_MQTT_H
+#define UAPI_MQTT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "lwip/apps/mqtt.h"
+
+/* ==================== MQTT 统一日志系统 ==================== */
+/* 日志等级枚举 */
+typedef enum {
+ MQTT_LOG_ERROR = 0, // 错误信息
+ MQTT_LOG_WARN = 1, // 警告信息
+ MQTT_LOG_INFO = 2, // 一般信息
+ MQTT_LOG_DEBUG = 3 // 调试信息
+} mqtt_log_level_t;
+
+/* 日志等级字符串数组 */
+#define MQTT_LOG_LEVEL_STR_ERROR "[ERROR]"
+#define MQTT_LOG_LEVEL_STR_WARN "[WARN]"
+#define MQTT_LOG_LEVEL_STR_INFO "[INFO]"
+#define MQTT_LOG_LEVEL_STR_DEBUG "[DEBUG]"
+
+/* 日志宏定义(需要在 .c 文件中定义 g_mqtt_log_level 变量) */
+#define MQTT_LOG(level, line, fmt, ...) do { \
+ extern mqtt_log_level_t g_mqtt_log_level; \
+ if (level <= g_mqtt_log_level) { \
+ const char *level_str = (level == MQTT_LOG_ERROR) ? MQTT_LOG_LEVEL_STR_ERROR : \
+ (level == MQTT_LOG_WARN) ? MQTT_LOG_LEVEL_STR_WARN : \
+ (level == MQTT_LOG_INFO) ? MQTT_LOG_LEVEL_STR_INFO : \
+ MQTT_LOG_LEVEL_STR_DEBUG; \
+ printf("[MQTT]%s " fmt, level_str, ##__VA_ARGS__); \
+ } \
+} while(0)
+
+/* 便捷打印宏 */
+#define MQTT_ERROR(fmt, ...) MQTT_LOG(MQTT_LOG_ERROR, __LINE__, fmt, ##__VA_ARGS__)
+#define MQTT_WARN(fmt, ...) MQTT_LOG(MQTT_LOG_WARN, __LINE__, fmt, ##__VA_ARGS__)
+#define MQTT_INFO(fmt, ...) MQTT_LOG(MQTT_LOG_INFO, __LINE__, fmt, ##__VA_ARGS__)
+#define MQTT_DEBUG(fmt, ...) MQTT_LOG(MQTT_LOG_DEBUG, __LINE__, fmt, ##__VA_ARGS__)
+
+/* 设置日志等级函数声明 */
+void mqtt_set_log_level(uint8_t level);
+/* ==================== MQTT 统一日志系统结束 ==================== */
+
+// /* 前向声明 */
+// struct mqtt_client;
+// typedef struct mqtt_client mqtt_client_t;
+
+/* MQTT 凭证结构体(与ln_OTA.c中的定义保持一致) */
+typedef struct {
+ char endpoint[256];
+ char client_id[256];
+ char username[256];
+ char password[256];
+ char publish_topic[128];
+ char subscribe_topic[128];
+} mqtt_credentials_t;
+
+/* MQTT 连接状态回调函数类型 */
+typedef void (*uapi_mqtt_connect_cb_t)(void *arg, int status);
+
+/* MQTT 消息接收回调函数类型 */
+typedef void (*uapi_mqtt_message_cb_t)(void *arg, const char *topic, const uint8_t *data, uint16_t len);
+
+/* MQTT 凭证获取回调函数类型 */
+/* @param arg 用户参数
+ * @param cred 输出的MQTT凭证结构体指针(由回调函数填充)
+ * @return 0 成功填充凭证,-1 失败或未提供凭证(将使用默认方式从文件加载)
+ */
+typedef int (*uapi_mqtt_credentials_cb_t)(void *arg, mqtt_credentials_t *cred);
+
+/* MQTT 订阅结果回调函数类型 */
+/* @param arg 用户参数
+ * @param topic 订阅的主题
+ * @param qos QoS等级
+ * @param result 订阅结果(0表示成功,非0表示失败)
+ */
+typedef void (*uapi_mqtt_subscribe_cb_t)(void *arg, const char *topic, uint8_t qos, int result);
+
+/* MQTT回调函数结构体 */
+typedef struct {
+ uapi_mqtt_connect_cb_t connect_callback; /* 连接状态回调函数 */
+ uapi_mqtt_message_cb_t message_callback; /* 消息接收回调函数 */
+ uapi_mqtt_credentials_cb_t credentials_callback; /* 凭证获取回调函数 */
+ uapi_mqtt_subscribe_cb_t subscribe_callback; /* 订阅结果回调函数 */
+ void *user_arg; /* 用户参数(传递给回调函数) */
+ uint32_t main_thread_interval_ms; /* 主线程循环间隔时长(毫秒),默认1000ms */
+} mqtt_call_backs_t;
+
+/**
+ * @brief 初始化MQTT客户端
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_init(void);
+
+/**
+ * @brief 反初始化MQTT客户端
+ */
+void uapi_mqtt_deinit(void);
+
+/**
+ * @brief 从文件加载MQTT凭证
+ * @param cred 输出的MQTT凭证结构体指针
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_load_credentials(mqtt_credentials_t *cred);
+
+/**
+ * @brief 连接MQTT服务器
+ * @param cred MQTT凭证(如果为NULL,将从文件加载)
+ * @param connect_cb 连接状态回调函数
+ * @param message_cb 消息接收回调函数
+ * @param arg 回调函数参数
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_connect(const mqtt_credentials_t *cred,
+ uapi_mqtt_connect_cb_t connect_cb,
+ uapi_mqtt_message_cb_t message_cb,
+ void *arg);
+
+/**
+ * @brief 断开MQTT连接
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_disconnect(void);
+
+/**
+ * @brief 检查MQTT连接状态
+ * @return true 已连接,false 未连接
+ */
+bool uapi_mqtt_is_connected(void);
+
+/**
+ * @brief 订阅主题
+ * @param topic 主题名称
+ * @param qos QoS等级(0-2)
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_subscribe(const char *topic, uint8_t qos);
+
+/**
+ * @brief 取消订阅主题
+ * @param topic 主题名称
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_unsubscribe(const char *topic);
+
+/**
+ * @brief 获取当前连接的publish_topic(内部使用,供上层API调用)
+ * @param publish_topic 输出的publish_topic缓冲区
+ * @param len 缓冲区长度
+ * @return 0 成功,-1 失败(如果未设置,返回-1但不表示错误)
+ */
+int uapi_mqtt_get_publish_topic(char *publish_topic, size_t len);
+
+/**
+ * @brief 启动MQTT发送和接收线程
+ * @param callbacks MQTT回调函数结构体(可以为NULL,使用默认处理)
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_start(const mqtt_call_backs_t *callbacks);
+
+/**
+ * @brief 停止MQTT发送和接收线程
+ */
+void uapi_mqtt_main_stop(void);
+
+/**
+ * @brief 发送MQTT消息到队列
+ * @param topic 主题名称
+ * @param payload 消息内容
+ * @param payload_len 消息长度
+ * @param qos QoS等级
+ * @param retain 保留标志
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_send(const char *topic, const void *payload, uint16_t payload_len, uint8_t qos, uint8_t retain);
+
+/**
+ * @brief 将接收到的MQTT消息放入接收队列(供MQTT回调函数调用)
+ * @param topic 主题名称
+ * @param data 消息数据
+ * @param data_len 消息长度
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_recv_enqueue(const char *topic, const uint8_t *data, uint16_t data_len);
+
+/**
+ * @brief 将订阅结果消息放入接收队列(供MQTT回调函数调用)
+ * @param topic 主题名称
+ * @param qos QoS等级
+ * @param result 订阅结果(0表示成功,非0表示失败)
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_main_subscribe_enqueue(const char *topic, uint8_t qos, int result);
+
+/**
+ * @brief 获取MQTT连接状态
+ * @return 连接状态(MQTT_STATE_DISCONNECTED/MQTT_STATE_CONNECTING/MQTT_STATE_CONNECTED)
+ */
+int uapi_mqtt_main_get_state(void);
+
+
+/**
+ * @brief 发布消息
+ */
+ int uapi_mqtt_publish(const char *topic, const void *payload, uint16_t payload_len, uint8_t qos, uint8_t retain);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UAPI_MQTT_H */
+
--- /dev/null
+#include "lwip/apps/mqtt.h"
+#include "lwip/ip_addr.h"
+#include "lwip/ip4_addr.h"
+#include "lwip/inet.h"
+#include "lwip/err.h"
+#include "cJSON.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "uapi_Mqtt_api.h"
+
+/* MQTT 日志等级变量(默认设置为 DEBUG) */
+mqtt_log_level_t g_mqtt_log_level =0;
+
+/**
+ * @brief 设置MQTT日志等级
+ * @param level 日志等级(0=ERROR, 1=WARN, 2=INFO, 3=DEBUG)
+ */
+void mqtt_set_log_level(uint8_t level)
+{
+ if (level <= MQTT_LOG_DEBUG) {
+ g_mqtt_log_level = (mqtt_log_level_t)level;
+ }
+}
+
+// MQTT消息接收缓冲区最大大小(64KB)
+#define MQTT_RECV_BUFFER_MAX_SIZE (64 * 1024)
+
+// MQTT客户端实例
+static mqtt_client_t *g_mqtt_client = NULL;
+static bool g_mqtt_connected = false;
+
+// 回调函数
+static uapi_mqtt_connect_cb_t g_connect_cb = NULL;
+static uapi_mqtt_message_cb_t g_message_cb = NULL;
+static void *g_callback_arg = NULL;
+
+// 当前接收消息的主题(用于数据回调)
+static char g_current_topic[256] = {0};
+
+// 消息接收缓冲区(用于拼包)
+static uint8_t *g_recv_buffer = NULL;
+static uint32_t g_recv_total_len = 0; // 消息总长度
+static uint32_t g_recv_current_len = 0; // 当前接收长度
+
+// 当前连接的client_id(用于自动订阅)
+static char g_current_client_id[256] = {0};
+
+// 当前连接的publish_topic(用于发送连接成功消息)
+static char g_current_publish_topic[128] = {0};
+
+static void mqtt_request_cb(void *arg, err_t err);
+
+/**
+ * @brief 清理接收缓冲区
+ */
+static void mqtt_recv_buffer_cleanup(void)
+{
+ if (g_recv_buffer != NULL) {
+ free(g_recv_buffer);
+ g_recv_buffer = NULL;
+ g_recv_total_len = 0;
+ g_recv_current_len = 0;
+ }
+ g_current_topic[0] = '\0';
+}
+
+/**
+ * @brief 解析endpoint字符串,提取主机和端口
+ * @param endpoint 格式: "host:port" 或 "host"
+ * @param ipaddr 输出的IP地址
+ * @param port 输出的端口号(如果endpoint中没有端口,使用默认值)
+ * @return 0 成功,-1 失败
+ */
+static int parse_endpoint(const char *endpoint, ip_addr_t *ipaddr, uint16_t *port)
+{
+ if (!endpoint || !ipaddr || !port) {
+ return -1;
+ }
+
+ char host[256] = {0};
+ uint16_t default_port = MQTT_PORT; // 默认1883
+
+ // 查找端口分隔符
+ const char *colon = strchr(endpoint, ':');
+ if (colon) {
+ // 有端口号
+ size_t host_len = colon - endpoint;
+ if (host_len >= sizeof(host)) {
+ host_len = sizeof(host) - 1;
+ }
+ strncpy(host, endpoint, host_len);
+ host[host_len] = '\0';
+ *port = (uint16_t)atoi(colon + 1);
+ if (*port == 0) {
+ *port = default_port;
+ }
+ } else {
+ // 无端口号,使用默认端口
+ strncpy(host, endpoint, sizeof(host) - 1);
+ host[sizeof(host) - 1] = '\0';
+ *port = default_port;
+ }
+
+ // 解析IP地址(ipaddr_aton会自动检测IPv4/IPv6)
+ if (ipaddr_aton(host, ipaddr) != 1) {
+ // 如果不是IP地址,尝试DNS解析(这里简化处理,实际应该使用DNS解析)
+ MQTT_WARN("Hostname resolution not implemented, using IP address only\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief MQTT连接状态回调
+ * @note 此回调可能在网络中断或高优先级任务中执行,应尽量减少操作,避免栈溢出
+ */
+static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
+{
+ (void)client;
+ (void)arg;
+
+ if (status == MQTT_CONNECT_ACCEPTED) {
+ g_mqtt_connected = true;
+ // 连接成功后的自动订阅和通知由上层API处理
+ } else {
+ g_mqtt_connected = false;
+ // 连接断开时清理接收缓冲区
+ mqtt_recv_buffer_cleanup();
+ }
+
+ // 调用用户回调(注意:用户回调应尽量快速返回,避免栈溢出)
+ if (g_connect_cb) {
+ g_connect_cb(g_callback_arg, (int)status);
+ }
+}
+
+/**
+ * @brief MQTT消息接收回调(主题)
+ * @note 此回调可能在网络中断或高优先级任务中执行,应尽量减少操作,避免栈溢出
+ */
+static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len)
+{
+ (void)arg;
+
+ // 清理之前的缓冲区(如果存在)
+ if (g_recv_buffer != NULL) {
+ mqtt_recv_buffer_cleanup();
+ }
+
+ // 保存当前主题(快速操作)
+ if (topic) {
+ strncpy(g_current_topic, topic, sizeof(g_current_topic) - 1);
+ g_current_topic[sizeof(g_current_topic) - 1] = '\0';
+ } else {
+ g_current_topic[0] = '\0';
+ }
+
+ // 初始化接收缓冲区
+ if (tot_len > 0) {
+ // 限制最大消息大小
+ if (tot_len > MQTT_RECV_BUFFER_MAX_SIZE) {
+ g_recv_total_len = 0;
+ g_recv_current_len = 0;
+ return;
+ }
+
+ // malloc 可能在回调上下文中执行,但这是必要的
+ g_recv_buffer = (uint8_t *)malloc(tot_len);
+ if (g_recv_buffer == NULL) {
+ g_recv_total_len = 0;
+ g_recv_current_len = 0;
+ return;
+ }
+
+ g_recv_total_len = tot_len;
+ g_recv_current_len = 0;
+ } else {
+ g_recv_total_len = 0;
+ g_recv_current_len = 0;
+ }
+}
+
+/**
+ * @brief MQTT消息接收回调(数据)
+ * @note 此回调可能在网络中断或高优先级任务中执行,应尽量减少操作,避免栈溢出
+ */
+static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
+{
+ (void)arg;
+
+ // 如果缓冲区未初始化,说明消息为空或初始化失败,直接返回
+ if (g_recv_buffer == NULL || g_recv_total_len == 0) {
+ if (flags & MQTT_DATA_FLAG_LAST) {
+ g_current_topic[0] = '\0';
+ }
+ return;
+ }
+
+ // 检查是否会溢出
+ if (g_recv_current_len + len > g_recv_total_len) {
+ // 清理缓冲区
+ mqtt_recv_buffer_cleanup();
+ return;
+ }
+
+ // 将数据片段复制到缓冲区(快速操作)
+ if (data && len > 0) {
+ memcpy(g_recv_buffer + g_recv_current_len, data, len);
+ g_recv_current_len += len;
+ }
+
+ // 如果是最后一段数据,将完整的消息放入队列(由低优先级任务处理,避免在回调中执行耗时操作)
+ if (flags & MQTT_DATA_FLAG_LAST) {
+ // 验证接收长度是否匹配
+ if (g_recv_current_len != g_recv_total_len) {
+ // 长度不匹配,清理缓冲区
+ mqtt_recv_buffer_cleanup();
+ return;
+ }
+
+ // 将消息放入队列,由低优先级任务处理(避免在回调中直接调用用户回调导致栈溢出)
+ if (g_current_topic[0] && g_recv_buffer && g_recv_current_len > 0) {
+ // 使用队列机制,将消息传递给主线程处理(函数内部会复制数据)
+ extern int uapi_mqtt_main_recv_enqueue(const char *topic, const uint8_t *data, uint16_t data_len);
+ uapi_mqtt_main_recv_enqueue(g_current_topic, g_recv_buffer, g_recv_current_len);
+
+ // 清理本地缓冲区(队列已复制数据)
+ mqtt_recv_buffer_cleanup();
+ } else {
+ // 清理缓冲区和主题
+ mqtt_recv_buffer_cleanup();
+ }
+ }
+}
+
+/**
+ * @brief MQTT请求完成回调
+ */
+static void mqtt_request_cb(void *arg, err_t err)
+{
+ (void)arg;
+ if (err == ERR_OK) {
+ MQTT_DEBUG("Request completed successfully\n");
+ } else {
+ MQTT_ERROR("Request failed: %d\n", err);
+ }
+}
+
+
+/**
+ * @brief 初始化MQTT客户端
+ */
+int uapi_mqtt_init(void)
+{
+ if (g_mqtt_client != NULL) {
+ MQTT_INFO("Already initialized\n");
+ return 0;
+ }
+
+ g_mqtt_client = mqtt_client_new();
+ if (g_mqtt_client == NULL) {
+ MQTT_ERROR("Failed to create MQTT client\n");
+ return -1;
+ }
+
+ // 设置消息接收回调
+
+ MQTT_INFO("Initialized successfully\n");
+ return 0;
+}
+
+/**
+ * @brief 反初始化MQTT客户端
+ */
+void uapi_mqtt_deinit(void)
+{
+ if (g_mqtt_client) {
+ if (g_mqtt_connected) {
+ mqtt_disconnect(g_mqtt_client);
+ g_mqtt_connected = false;
+ }
+ mqtt_client_free(g_mqtt_client);
+ g_mqtt_client = NULL;
+ }
+
+ g_connect_cb = NULL;
+ g_message_cb = NULL;
+ g_callback_arg = NULL;
+ g_current_client_id[0] = '\0'; // 清空client_id
+ g_current_publish_topic[0] = '\0'; // 清空publish_topic
+
+ MQTT_INFO("Deinitialized\n");
+}
+
+/**
+ * @brief 从文件加载MQTT凭证
+ */
+int uapi_mqtt_load_credentials(mqtt_credentials_t *cred)
+{
+ if (!cred) {
+ return -1;
+ }
+
+ FILE *fp = fopen("/user/mqtt_credentials.json", "r");
+ if (!fp) {
+ MQTT_ERROR("Failed to open credentials file\n");
+ return -1;
+ }
+
+ // 读取文件内容
+ fseek(fp, 0, SEEK_END);
+ long file_size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
+ if (file_size <= 0 || file_size > 4096) {
+ fclose(fp);
+ return -1;
+ }
+
+ char *json_buf = (char *)malloc(file_size + 1);
+ if (!json_buf) {
+ fclose(fp);
+ return -1;
+ }
+
+ size_t read_len = fread(json_buf, 1, file_size, fp);
+ fclose(fp);
+ json_buf[read_len] = '\0';
+
+ // 解析JSON
+ cJSON *root = cJSON_Parse(json_buf);
+ free(json_buf);
+
+ if (!root) {
+ MQTT_ERROR("Failed to parse credentials JSON\n");
+ return -1;
+ }
+
+ // 提取MQTT凭证
+ cJSON *mqtt_obj = cJSON_GetObjectItem(root, "mqtt");
+ if (!mqtt_obj || !cJSON_IsObject(mqtt_obj)) {
+ MQTT_ERROR("No 'mqtt' object found in JSON\n");
+ cJSON_Delete(root);
+ return -1;
+ }
+
+ memset(cred, 0, sizeof(mqtt_credentials_t));
+
+ cJSON *item = cJSON_GetObjectItem(mqtt_obj, "endpoint");
+ if (item && cJSON_IsString(item) && item->valuestring) {
+ strncpy(cred->endpoint, item->valuestring, sizeof(cred->endpoint) - 1);
+ }
+
+ item = cJSON_GetObjectItem(mqtt_obj, "client_id");
+ if (item && cJSON_IsString(item) && item->valuestring) {
+ strncpy(cred->client_id, item->valuestring, sizeof(cred->client_id) - 1);
+ }
+
+ item = cJSON_GetObjectItem(mqtt_obj, "username");
+ if (item && cJSON_IsString(item) && item->valuestring) {
+ strncpy(cred->username, item->valuestring, sizeof(cred->username) - 1);
+ }
+
+ item = cJSON_GetObjectItem(mqtt_obj, "password");
+ if (item && cJSON_IsString(item) && item->valuestring) {
+ strncpy(cred->password, item->valuestring, sizeof(cred->password) - 1);
+ }
+
+ item = cJSON_GetObjectItem(mqtt_obj, "publish_topic");
+ if (item && cJSON_IsString(item) && item->valuestring) {
+ strncpy(cred->publish_topic, item->valuestring, sizeof(cred->publish_topic) - 1);
+ }
+
+ item = cJSON_GetObjectItem(mqtt_obj, "subscribe_topic");
+ if (item && cJSON_IsString(item) && item->valuestring) {
+ strncpy(cred->subscribe_topic, item->valuestring, sizeof(cred->subscribe_topic) - 1);
+ }
+
+ cJSON_Delete(root);
+
+ MQTT_INFO("Credentials loaded: endpoint=%s, client_id=%s\n",
+ cred->endpoint, cred->client_id);
+ return 0;
+}
+
+/**
+ * @brief 连接MQTT服务器
+ */
+int uapi_mqtt_connect(const mqtt_credentials_t *cred,
+ uapi_mqtt_connect_cb_t connect_cb,
+ uapi_mqtt_message_cb_t message_cb,
+ void *arg)
+{
+ if (!g_mqtt_client) {
+ if (uapi_mqtt_init() != 0) {
+ return -1;
+ }
+ }
+
+ mqtt_credentials_t credentials = {0};
+ const mqtt_credentials_t *use_cred = cred;
+
+ // 如果没有提供凭证,从文件加载
+ if (!use_cred) {
+ if (uapi_mqtt_load_credentials(&credentials) != 0) {
+ MQTT_ERROR("Failed to load credentials\n");
+ return -1;
+ }
+ use_cred = &credentials;
+ }
+
+ // 检查必要的字段
+ if (!use_cred->endpoint[0] || !use_cred->client_id[0]) {
+ MQTT_ERROR("Missing required credentials (endpoint or client_id)\n");
+ return -1;
+ }
+
+ // 保存client_id用于自动订阅
+ strncpy(g_current_client_id, use_cred->client_id, sizeof(g_current_client_id) - 1);
+ g_current_client_id[sizeof(g_current_client_id) - 1] = '\0';
+
+ // 保存publish_topic用于发送连接通知
+ if (use_cred->publish_topic[0] != '\0') {
+ strncpy(g_current_publish_topic, use_cred->publish_topic, sizeof(g_current_publish_topic) - 1);
+ g_current_publish_topic[sizeof(g_current_publish_topic) - 1] = '\0';
+ } else {
+ g_current_publish_topic[0] = '\0'; // 使用默认主题
+ }
+
+ // 保存回调函数
+ g_connect_cb = connect_cb;
+ g_message_cb = message_cb;
+ g_callback_arg = arg;
+
+ // 解析endpoint
+ ip_addr_t ipaddr;
+ uint16_t port;
+ if (parse_endpoint(use_cred->endpoint, &ipaddr, &port) != 0) {
+ MQTT_ERROR("Failed to parse endpoint: %s\n", use_cred->endpoint);
+ return -1;
+ }
+
+ // 准备连接信息
+ struct mqtt_connect_client_info_t ci = {0};
+ ci.client_id = use_cred->client_id;
+ ci.client_user = use_cred->username[0] ? use_cred->username : NULL;
+ ci.client_pass = use_cred->password[0] ? use_cred->password : NULL;
+ ci.keep_alive = 60*10; // 60秒保活
+ ci.will_topic = NULL;
+ ci.will_msg = NULL;
+ ci.will_qos = 0;
+ ci.will_retain = 0;
+
+ MQTT_INFO("Connecting to %s:%d, client_id=%s\n",
+ use_cred->endpoint, port, use_cred->client_id);
+
+ // 连接MQTT服务器
+ err_t err = mqtt_client_connect(g_mqtt_client, &ipaddr, port,
+ mqtt_connection_cb, NULL, &ci);
+ if (err != ERR_OK) {
+ MQTT_ERROR("Failed to initiate connection: %d\n", err);
+ return -1;
+ }
+
+ mqtt_set_inpub_callback(g_mqtt_client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, NULL);
+
+
+ return 0;
+}
+
+/**
+ * @brief 断开MQTT连接
+ */
+int uapi_mqtt_disconnect(void)
+{
+ if (!g_mqtt_client) {
+ return -1;
+ }
+
+ if (g_mqtt_connected) {
+ mqtt_disconnect(g_mqtt_client);
+ g_mqtt_connected = false;
+ MQTT_INFO("Disconnected\n");
+ }
+
+ // 清理接收缓冲区
+ mqtt_recv_buffer_cleanup();
+
+ return 0;
+}
+
+/**
+ * @brief 检查MQTT连接状态
+ */
+bool uapi_mqtt_is_connected(void)
+{
+ if (!g_mqtt_client) {
+ return false;
+ }
+ return g_mqtt_connected && mqtt_client_is_connected(g_mqtt_client);
+}
+
+/**
+ * @brief 获取MQTT客户端实例(内部使用,供上层API调用)
+ * @return mqtt_client_t* 客户端实例,NULL表示未初始化
+ */
+mqtt_client_t *uapi_mqtt_get_client(void)
+{
+ return g_mqtt_client;
+}
+
+/**
+ * @brief 获取当前连接的client_id(内部使用,供上层API调用)
+ * @param client_id 输出的client_id缓冲区
+ * @param len 缓冲区长度
+ * @return 0 成功,-1 失败
+ */
+int uapi_mqtt_get_client_id(char *client_id, size_t len)
+{
+ if (!client_id || len == 0) {
+ return -1;
+ }
+
+ if (g_current_client_id[0] == '\0') {
+ return -1;
+ }
+
+ strncpy(client_id, g_current_client_id, len - 1);
+ client_id[len - 1] = '\0';
+ return 0;
+}
+
+/**
+ * @brief 获取当前连接的publish_topic(内部使用,供上层API调用)
+ * @param publish_topic 输出的publish_topic缓冲区
+ * @param len 缓冲区长度
+ * @return 0 成功,-1 失败(如果未设置,返回-1但不表示错误)
+ */
+int uapi_mqtt_get_publish_topic(char *publish_topic, size_t len)
+{
+ if (!publish_topic || len == 0) {
+ return -1;
+ }
+
+ if (g_current_publish_topic[0] == '\0') {
+ return -1; // 未设置,但不一定是错误
+ }
+
+ strncpy(publish_topic, g_current_publish_topic, len - 1);
+ publish_topic[len - 1] = '\0';
+ return 0;
+}
+
+
+
+
+/* 订阅信息结构体(用于传递给回调) */
+typedef struct {
+ char topic[256];
+ uint8_t qos;
+} subscribe_info_t;
+
+/**
+ * @brief MQTT请求完成回调
+ */
+static void mqtt_request_subscribe_cb(void *arg, err_t err)
+{
+ subscribe_info_t *info = (subscribe_info_t *)arg;
+
+ if (info == NULL) {
+ MQTT_ERROR("mqtt_request_subscribe_cb: invalid arg\n");
+ return;
+ }
+
+ int result = (err == ERR_OK) ? 0 : -1;
+
+ if (err == ERR_OK) {
+ MQTT_DEBUG("mqtt_request_subscribe_cb Request completed successfully for topic: %s\n", info->topic);
+ } else {
+ MQTT_ERROR("Request failed for topic: %s, error: %d\n", info->topic, err);
+ }
+
+ // 将订阅结果放入接收队列,由主线程处理并触发用户回调
+ uapi_mqtt_main_subscribe_enqueue(info->topic, info->qos, result);
+
+ // 释放分配的内存
+ free(info);
+}
+
+
+
+/**
+ * @brief 订阅主题
+ */
+int uapi_mqtt_subscribe(const char *topic, uint8_t qos)
+{
+ if (!g_mqtt_client || !topic) {
+ return -1;
+ }
+
+ if (!uapi_mqtt_is_connected()) {
+ MQTT_WARN("Not connected, cannot subscribe\n");
+ return -1;
+ }
+
+ if (qos > 2) {
+ qos = 1; // 默认QoS 1
+ }
+
+ MQTT_INFO("Subscribing to topic: %s, QoS: %d\n", topic, qos);
+
+ // 分配订阅信息结构体,传递给回调函数
+ subscribe_info_t *info = (subscribe_info_t *)malloc(sizeof(subscribe_info_t));
+ if (info == NULL) {
+ MQTT_ERROR("Failed to allocate subscribe info\n");
+ return -1;
+ }
+
+ strncpy(info->topic, topic, sizeof(info->topic) - 1);
+ info->topic[sizeof(info->topic) - 1] = '\0';
+ info->qos = qos;
+
+ err_t err = mqtt_subscribe(g_mqtt_client, topic, qos, mqtt_request_subscribe_cb, info);
+ if (err != ERR_OK) {
+ MQTT_ERROR("Failed to subscribe: %d\n", err);
+ free(info); // 订阅失败时释放内存
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief 取消订阅主题
+ */
+int uapi_mqtt_unsubscribe(const char *topic)
+{
+ if (!g_mqtt_client || !topic) {
+ return -1;
+ }
+
+ if (!uapi_mqtt_is_connected()) {
+ MQTT_WARN("Not connected, cannot unsubscribe\n");
+ return -1;
+ }
+
+ MQTT_INFO("Unsubscribing from topic: %s\n", topic);
+
+ err_t err = mqtt_unsubscribe(g_mqtt_client, topic, mqtt_request_cb, NULL);
+ if (err != ERR_OK) {
+ MQTT_ERROR("Failed to unsubscribe: %d\n", err);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief 发布消息
+ */
+int uapi_mqtt_publish(const char *topic, const void *payload, uint16_t payload_len, uint8_t qos, uint8_t retain)
+{
+ if (!g_mqtt_client || !topic || !payload) {
+ return -1;
+ }
+
+ if (!uapi_mqtt_is_connected()) {
+ MQTT_WARN("Not connected, cannot publish\n");
+ return -1;
+ }
+
+ if (qos > 2) {
+ qos = 0; // 默认QoS 0
+ }
+
+ MQTT_DEBUG("Publishing to topic: %s, len: %d, QoS: %d\n", topic, payload_len, qos);
+
+ err_t err = mqtt_publish(g_mqtt_client, topic, payload, payload_len, qos, retain,
+ mqtt_request_cb, NULL);
+ if (err != ERR_OK) {
+ MQTT_ERROR("Failed to publish: %d\n", err);
+ return -1;
+ }
+
+ return 0;
+}
--- /dev/null
+#include "at_cmd_api.h"
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include "errcode.h"
+#include "uapi_Mqtt_api.h"
+#include "audio_capture_wrapper.h"
+
+/* MQTT 日志等级变量(默认设置为 DEBUG) */
+extern mqtt_log_level_t g_mqtt_log_level ;
+
+
+// 前向声明ln_OTA.c中的函数(ln_OTA.c仍在原位置)
+extern int ln_ota_send_device_info_json(const char *url, void *credentials);
+
+#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
+#define UAPI_MQTT_MAX_ARGC 8
+#define UAPI_MQTT_MAX_ARGV_LEN 256
+
+
+/**
+ * @brief 解析AT命令参数
+ */
+static int uapi_mqtt_parse_params(uint8_t *para, uint32_t paraLen,
+ uint8_t argv[UAPI_MQTT_MAX_ARGC][UAPI_MQTT_MAX_ARGV_LEN],
+ uint32_t *argc)
+{
+ uint32_t pos = 0;
+ *argc = 0;
+
+ for (uint32_t i = 0; i < paraLen; i++) {
+ if ((para[i] == ' ' || para[i] == '\n' || para[i] == ',' || para[i] == '=') && pos != 0) {
+ argv[*argc][pos] = '\0';
+ *argc += 1;
+ pos = 0;
+ if (*argc >= UAPI_MQTT_MAX_ARGC) {
+ return -1;
+ }
+ } else {
+ if (para[i] == ' ' || para[i] == '\n' || para[i] == ',' || para[i] == '=') {
+ continue;
+ }
+ argv[*argc][pos] = para[i];
+ pos++;
+ if (pos >= UAPI_MQTT_MAX_ARGV_LEN) {
+ return -1;
+ }
+ }
+ }
+ if (pos != 0) {
+ argv[*argc][pos] = '\0';
+ *argc += 1;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief MQTT连接状态回调(用于AT命令测试)
+ */
+static void mqtt_at_connect_cb(void *arg, int status)
+{
+ (void)arg;
+ MQTT_INFO("Connection status changed: %d\n", status);
+}
+
+/**
+ * @brief MQTT消息接收回调(用于AT命令测试)
+ */
+static void mqtt_at_message_cb(void *arg, const char *topic, const uint8_t *data, uint16_t len)
+{
+ (void)arg;
+ MQTT_INFO("Received message - Topic: %s, Length: %d\n", topic, len);
+ if (data && len > 0) {
+ MQTT_DEBUG("Message content: ");
+ for (uint16_t i = 0; i < len && i < 100; i++) { // 限制打印长度
+ printf("%c", (data[i] >= 32 && data[i] < 127) ? data[i] : '.');
+ }
+ printf("\n");
+ }
+}
+
+/* OTA-发送设备信息到服务器:AT^LN_OTA_SEND_DEVICE_INFO */
+// static uint32_t ln_ota_send_device_info_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+// {
+// (void)para;
+// (void)paraLen;
+// (void)strCommonCmd;
+
+// printf("[LN][OTA_SEND_DEVICE_INFO]\n");
+
+// // 直接调用封装函数,使用默认URL(NULL表示使用默认URL)
+// int ret = ln_ota_send_device_info_json(NULL, NULL);
+// if (ret == 0) {
+// printf("+LN_OTA_SEND_DEVICE_INFO: OK\n");
+// return ERRCODE_SUCC;
+// } else {
+// printf("+LN_OTA_SEND_DEVICE_INFO: FAIL\n");
+// return ERRCODE_FAIL;
+// }
+// }
+
+/* MQTT-初始化:AT^LN_MQTT_INIT */
+static uint32_t uapi_mqtt_init_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+ (void)para;
+ (void)paraLen;
+ (void)strCommonCmd;
+
+ printf("[UAPI_MQTT][MQTT_INIT]\n");
+
+ int ret = uapi_mqtt_init();
+ if (ret == 0) {
+ printf("+LN_MQTT_INIT: OK\n");
+ return ERRCODE_SUCC;
+ } else {
+ printf("+LN_MQTT_INIT: FAIL\n");
+ return ERRCODE_FAIL;
+ }
+}
+
+/* MQTT-反初始化:AT^LN_MQTT_DEINIT */
+static uint32_t uapi_mqtt_deinit_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+ (void)para;
+ (void)paraLen;
+ (void)strCommonCmd;
+
+ printf("[UAPI_MQTT][MQTT_DEINIT]\n");
+
+ uapi_mqtt_deinit();
+ printf("+LN_MQTT_DEINIT: OK\n");
+ return ERRCODE_SUCC;
+}
+
+/* MQTT-连接:AT^LN_MQTT_CONNECT */
+static uint32_t uapi_mqtt_connect_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+ (void)strCommonCmd;
+
+ printf("[UAPI_MQTT][MQTT_CONNECT]\n");
+
+ // 从文件加载凭证并连接(不使用参数)
+ int ret = uapi_mqtt_connect(NULL, mqtt_at_connect_cb, mqtt_at_message_cb, NULL);
+ if (ret == 0) {
+ printf("+LN_MQTT_CONNECT: OK\n");
+ return ERRCODE_SUCC;
+ } else {
+ printf("+LN_MQTT_CONNECT: FAIL\n");
+ return ERRCODE_FAIL;
+ }
+}
+
+/* MQTT-断开连接:AT^LN_MQTT_DISCONNECT */
+static uint32_t uapi_mqtt_disconnect_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+ (void)para;
+ (void)paraLen;
+ (void)strCommonCmd;
+
+ printf("[UAPI_MQTT][MQTT_DISCONNECT]\n");
+
+ int ret = uapi_mqtt_disconnect();
+ if (ret == 0) {
+ printf("+LN_MQTT_DISCONNECT: OK\n");
+ return ERRCODE_SUCC;
+ } else {
+ printf("+LN_MQTT_DISCONNECT: FAIL\n");
+ return ERRCODE_FAIL;
+ }
+}
+
+/* MQTT-查询连接状态:AT^LN_MQTT_IS_CONNECTED? */
+static uint32_t uapi_mqtt_is_connected_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+ (void)para;
+ (void)paraLen;
+ (void)strCommonCmd;
+
+ printf("[UAPI_MQTT][MQTT_IS_CONNECTED]\n");
+
+ bool connected = uapi_mqtt_is_connected();
+ if (connected) {
+ printf("+LN_MQTT_IS_CONNECTED: 1\n");
+ } else {
+ printf("+LN_MQTT_IS_CONNECTED: 0\n");
+ }
+ return ERRCODE_SUCC;
+}
+
+
+static uint32_t uapi_mqtt_AudioCaptureSample_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+ (void)para;
+ (void)paraLen;
+ (void)strCommonCmd;
+
+ const char *defaultArgs[6] = {"01", "opus", "16000", "1", "16", "user/userdata/test.ogg"};
+
+ int ret = AudioCaptureSample(6, defaultArgs);
+ LOS_Msleep(1000*10);
+
+ int32_t argc = 1;
+ uint8_t *argv = (uint8_t*)"stop";
+ AudioCaptureSample(argc, (const char **)&argv);
+
+ return ERRCODE_SUCC;
+}
+
+
+
+/* 命令表 */
+static const at_cmd_table_t g_uapi_mqtt_at_cmd[] = {
+ // {(char *)"AT^LN_OTA_SEND_DEVICE_INFO", ln_ota_send_device_info_at, (char *)"发送设备信息到OTA服务器: AT^LN_OTA_SEND_DEVICE_INFO"},
+ {(char *)"AT^LN_MQTT_INIT", uapi_mqtt_init_at, (char *)"初始化MQTT客户端: AT^LN_MQTT_INIT"},
+ {(char *)"AT^LN_MQTT_DEINIT", uapi_mqtt_deinit_at, (char *)"反初始化MQTT客户端: AT^LN_MQTT_DEINIT"},
+ {(char *)"AT^LN_MQTT_CONNECT", uapi_mqtt_connect_at, (char *)"连接MQTT服务器: AT^LN_MQTT_CONNECT"},
+ {(char *)"AT^LN_MQTT_DISCONNECT", uapi_mqtt_disconnect_at, (char *)"断开MQTT连接: AT^LN_MQTT_DISCONNECT"},
+ {(char *)"AT^LN_MQTT_IS_CONNECTED?", uapi_mqtt_is_connected_at, (char *)"查询MQTT连接状态: AT^LN_MQTT_IS_CONNECTED?"},
+ {(char *)"AT^LN_MQTT_CAPTURE?", uapi_mqtt_AudioCaptureSample_at, (char *)"录音测试"},
+
+};
+
+at_cmd_table_t *get_uapi_mqtt_at_cmd_table(uint32_t *cmd_count)
+{
+ if (cmd_count) {
+ *cmd_count = ARRAY_COUNT(g_uapi_mqtt_at_cmd);
+ }
+ return (at_cmd_table_t *)g_uapi_mqtt_at_cmd;
+}
+
--- /dev/null
+#ifndef UAPI_MQTT_AT_H
+#define UAPI_MQTT_AT_H
+
+#include <stdint.h>
+#include "at_cmd_api.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* MQTT AT 指令表导出 */
+at_cmd_table_t *get_uapi_mqtt_at_cmd_table(uint32_t *cmd_count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UAPI_MQTT_AT_H */
+
+
+
${ROOT_DIR}/include
${ROOT_DIR}/open_source/libogg/libogg-1.3.5/include/ogg
${ROOT_DIR}/open_source/libogg/libogg-1.3.5/include
+${ROOT_DIR}/middleware/services/media/foundation/player/interfaces/kits
+${ROOT_DIR}/middleware/services/gui/uikit/surface/interfaces/kits
+${ROOT_DIR}/open_source/openharmony/drivers/peripheral/display/interfaces/include
+${ROOT_DIR}middleware/services/media/foundation/audio_capturer/interfaces/kits
+${ROOT_DIR}/open_source/openharmony/foundation/multimedia/audio_capturer/interfaces/kits
)
set(AI_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/ai_media_service.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ai_media_service_ext.cpp
+${CMAKE_CURRENT_SOURCE_DIR}/ai_media_service_mqtt.cpp
+
)
}
LOS_Msleep(10);
- }
+ }
MEDIA_INFO_LOG("AI voice input thread stopped");
// 写入音频数据到输出流
int32_t ret = AudioStreamOutStreamWrite(data, size);
- // 根据比特率动态计算延迟时间
- // 延迟时间(微秒)= (数据大小(字节)* 8 * 1000000) / 比特率(bps)
- // 当比特率更高时,延迟时间更短
- // 公式:延迟(微秒)= (size * 8 * 1000000) / bit_rate
- uint32_t delay_us = (uint32_t)((uint64_t)(size-(size/10*5)) * 8 * 1000000ULL / g_tts_audio_bit_rate);
- printf("delay_us %d\r\n",delay_us);
-
- // 确保延迟时间在合理范围内(最小10微秒)
- if (delay_us < 20) {
- delay_us = 20;
+ if(g_aiVoiceContext->outputAudioFormat==MP3)
+ {
+ // 根据比特率动态计算延迟时间
+ // 延迟时间(微秒)= (数据大小(字节)* 8 * 1000000) / 比特率(bps)
+ // 当比特率更高时,延迟时间更短
+ // 公式:延迟(微秒)= (size * 8 * 1000000) / bit_rate
+ uint32_t delay_us = (uint32_t)((uint64_t)(size-(size/10*5)) * 8 * 1000000ULL / g_tts_audio_bit_rate);
+ printf("delay_us %d\r\n",delay_us);
+
+ // 确保延迟时间在合理范围内(最小10微秒)
+ if (delay_us < 20) {
+ delay_us = 20;
+ }
+ usleep(delay_us-20);
+ if (ret != 0) {
+ retry_count++;
+ // MEDIA_ERR_LOG("Failed to write audio data to output stream, ret=%d, retry %d/%d", ret, retry_count, MAX_RETRY_COUNT);
+ usleep(delay_us*retry_count/10*5);
+ goto AI_WRITE;
+ }
}
- usleep(delay_us-20);
- if (ret != 0) {
- retry_count++;
- // MEDIA_ERR_LOG("Failed to write audio data to output stream, ret=%d, retry %d/%d", ret, retry_count, MAX_RETRY_COUNT);
- usleep(delay_us*retry_count/10*5);
- goto AI_WRITE;
+ else if(g_aiVoiceContext->outputAudioFormat==PCM)
+ {
+ uint32_t delay_us = size*20;
+ printf("delay_us %d\r\n",delay_us);
+
+ // 确保延迟时间在合理范围内(最小10微秒)
+ if (delay_us < 20) {
+ delay_us = 20;
+ }
+ usleep(delay_us-20);
+ if (ret != 0) {
+ retry_count++;
+ // MEDIA_ERR_LOG("Failed to write audio data to output stream, ret=%d, retry %d/%d", ret, retry_count, MAX_RETRY_COUNT);
+ usleep(delay_us*retry_count/10*5);
+ goto AI_WRITE;
+ }
+
}
+
// 调用注册的回调函数
if (g_writeAudioDataCallback != nullptr && size!=SILENCE_AUDIO_SIZE) {
--- /dev/null
+/*
+ * Copyright (c) CompanyNameMagicTag. 2023-2023. All rights reserved.
+ * Description: AI media service for MQTT recording
+ * Author: Media Software Group
+ * Create: 2023-07-06
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <string>
+#include <memory>
+#include <time.h>
+#include "securec.h"
+#include "audio_manager.h"
+#include "audio_capturer.h"
+#include "audio_base_type.h"
+
+// 宏定义:选择使用 AudioStreamInInit 还是 AudioCapturer
+// 定义 USE_AUDIO_STREAM_IN 则使用 AudioStreamInInit,否则使用 AudioCapturer
+#ifndef USE_AUDIO_STREAM_IN
+#define USE_AUDIO_STREAM_IN 1
+#endif
+
+#if USE_AUDIO_STREAM_IN
+#include "audio_stream_in.h"
+#endif
+#include "media_log.h"
+#include "media_errors.h"
+#include "media_thread_adapt.h"
+#include "audio_manager_c_wrapper.h"
+#include "thread_init.h"
+#include "errcode.h"
+#include "ai_media.h"
+#include "cmsis_os2.h"
+#include "player.h"
+#include "audio_player_service.h"
+#include "ogg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+using namespace OHOS::Media;
+using namespace OHOS::Audio;
+using namespace Audio;
+using OHOS::Media::Player;
+using OHOS::AudioPlayerServiceCallback;
+using OHOS::AudioPlayerService;
+using Audio::InterruptListener;
+using Audio::AudioInterrupt;
+using Audio::AudioManager;
+
+// 录音缓冲区大小
+const uint32_t MQTT_RECORD_BUFFER_SIZE = 0x800; // 2KB
+
+// 录音数据回调函数类型
+typedef void (*MqttRecordDataCallback)(const uint8_t* data, uint32_t size, void* userData);
+
+// 录音参数结构体
+typedef struct {
+ int32_t audioFormat; // 音频格式
+ uint32_t channelCount; // 声道数
+ uint32_t sampleRate; // 采样率
+} MqttRecordAudioParams;
+
+// OGG 封装上下文结构体(参考 audio_capture_wrapper.cpp)
+typedef struct MqttOggContext {
+ ogg_stream_state oggStream;
+ int64_t sampleRate;
+ int64_t channels;
+ int64_t granulepos;
+ int64_t packetCount;
+ int32_t serialno;
+ bool isEnd;
+ ogg_page *page;
+ ogg_packet *packet;
+ unsigned char *idHeader;
+ unsigned char *commentHeader;
+ bool initialized; // OGG 上下文是否已初始化
+} MqttOggContext;
+
+// 录音上下文结构体
+typedef struct {
+ AudioSession sessionId;
+ bool isRecordStopped;
+ MediaThreadCondHandle cond;
+ MediaThreadIdHandle taskHandle;
+ char threadName[32];
+ uint8_t *dataBuffer;
+ uint32_t bufferSize;
+ MqttRecordDataCallback dataCallback;
+ void* callbackUserData;
+ AudioCodecFormat audioFormat;
+ uint32_t channelCount;
+ uint32_t sampleRate;
+#if USE_AUDIO_STREAM_IN
+ // 使用 AudioStreamIn 接口
+ bool streamInInitialized; // AudioStreamIn 是否已初始化
+#else
+ // 使用 AudioCapturer 接口
+ std::shared_ptr<OHOS::Audio::AudioCapturer> audioCapturer;
+ size_t framesize; // 帧大小(用于 Read 接口)
+#endif
+ FILE *debugFile; // 调试文件句柄(用于保存录音数据)
+} MqttRecordContext;
+
+// 全局变量
+static MediaMutexHandle g_mqttRecordMutex = nullptr;
+static MqttRecordContext *g_mqttRecordContext = nullptr;
+static volatile bool g_mqttRecordThreadStopped = false; // 线程停止标志
+
+// 默认音频参数
+static const AudioCodecFormat MQTT_DEFAULT_AUDIO_FORMAT = SBC;
+static const uint32_t MQTT_DEFAULT_CHANNEL_COUNT = 1;
+static const uint32_t MQTT_DEFAULT_SAMPLE_RATE = 16000;
+
+// OGG 封装相关常量(参考 audio_capture_wrapper.cpp)
+const uint32_t MQTT_OGG_HEADER_STRLEN = 8;
+const uint32_t MQTT_OGG_OPUS_DELAY_TIME_DIVISOR = 0;
+const uint32_t MQTT_OGG_OPUS_DELAY_TIME_DIVIDED = 100;
+const uint32_t MQTT_OGG_OPUS_ID_HEADER_LEN = 19;
+const uint32_t MQTT_OGG_OPUS_COMMENT_HEADER_LEN = 25;
+const uint32_t MQTT_OGG_OPUS_ENCODE_HEADER_SIZE = 8;
+const uint32_t MQTT_OGG_OPUS_OPUSTAGS_LEN = 12;
+const uint32_t MQTT_OGG_OPUS_SAMPLERATE = 16000;
+const uint32_t MQTT_OGG_MILLSECOND_TO_SECOND = 6000;
+
+/**
+ * @brief 分配内存并清零(用于 OGG 封装)
+ */
+static void* MqttOggMemCalloc(size_t bytesNum)
+{
+ void *tmp = malloc(bytesNum);
+ if (tmp == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: malloc failed!");
+ return nullptr;
+ }
+ if (memset_s(tmp, bytesNum, 0, bytesNum) != EOK) {
+ MEDIA_ERR_LOG("MQTT OGG: memset_s failed!");
+ free(tmp);
+ return nullptr;
+ }
+ return tmp;
+}
+
+/**
+ * @brief 释放内存(用于 OGG 封装)
+ */
+static void MqttOggMemFree(void **ptr)
+{
+ if (ptr == nullptr || *ptr == nullptr) {
+ return;
+ }
+ free(*ptr);
+ *ptr = nullptr;
+}
+
+/**
+ * @brief 初始化 OGG 头部(参考 audio_capture_wrapper.cpp)
+ */
+static int32_t MqttOggHeaderInit(MqttOggContext *oggCtx, uint32_t sampleRate, uint32_t channelCount)
+{
+ if (oggCtx == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Invalid ogg context");
+ return -1;
+ }
+
+ // 分配并初始化 ID Header
+ oggCtx->idHeader = static_cast<unsigned char*>(MqttOggMemCalloc(MQTT_OGG_OPUS_ID_HEADER_LEN));
+ if (oggCtx->idHeader == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Failed to allocate idHeader");
+ return -1;
+ }
+
+ if (memcpy_s(oggCtx->idHeader, MQTT_OGG_HEADER_STRLEN, "OpusHead", MQTT_OGG_HEADER_STRLEN) != 0) {
+ MEDIA_ERR_LOG("MQTT OGG: memcpy failed!");
+ MqttOggMemFree((void **)&oggCtx->idHeader);
+ return -1;
+ }
+
+ oggCtx->idHeader[0x8] = 0x01;
+ oggCtx->idHeader[0x9] = channelCount;
+ uint32_t preSkip = sampleRate * MQTT_OGG_OPUS_DELAY_TIME_DIVISOR / MQTT_OGG_OPUS_DELAY_TIME_DIVIDED;
+ oggCtx->idHeader[0xA] = preSkip & 0xFF;
+ oggCtx->idHeader[0xB] = (preSkip >> 0x8);
+ oggCtx->idHeader[0xC] = sampleRate & 0xFF;
+ oggCtx->idHeader[0xD] = (sampleRate >> 0x8) & 0xFF;
+ oggCtx->idHeader[0xE] = (sampleRate >> 0x10) & 0xFF;
+ oggCtx->idHeader[0xF] = (sampleRate >> 0x18) & 0xFF;
+
+ // 分配并初始化 Comment Header
+ oggCtx->commentHeader = static_cast<unsigned char*>(MqttOggMemCalloc(MQTT_OGG_OPUS_COMMENT_HEADER_LEN));
+ if (oggCtx->commentHeader == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Failed to allocate commentHeader");
+ MqttOggMemFree((void **)&oggCtx->idHeader);
+ return -1;
+ }
+
+ if (memcpy_s(oggCtx->commentHeader, MQTT_OGG_HEADER_STRLEN, "OpusTags", MQTT_OGG_HEADER_STRLEN) != 0) {
+ MEDIA_ERR_LOG("MQTT OGG: Opus commentHeader memcpy failed!");
+ MqttOggMemFree((void **)&oggCtx->idHeader);
+ MqttOggMemFree((void **)&oggCtx->commentHeader);
+ return -1;
+ }
+
+ const char *vendor = "libogg-1.3.5";
+ uint32_t vendorLen = strlen(vendor);
+ oggCtx->commentHeader[0x8] = vendorLen & 0xFF;
+ oggCtx->commentHeader[0x9] = (vendorLen >> 0x8) & 0xFF;
+ oggCtx->commentHeader[0xA] = (vendorLen >> 0x10) & 0xFF;
+ oggCtx->commentHeader[0xB] = (vendorLen >> 0x18) & 0xFF;
+
+ if (memcpy_s(oggCtx->commentHeader + MQTT_OGG_OPUS_OPUSTAGS_LEN, vendorLen, vendor, vendorLen) != 0) {
+ MEDIA_ERR_LOG("MQTT OGG: Opus commentHeader vendor memcpy failed!");
+ MqttOggMemFree((void **)&oggCtx->idHeader);
+ MqttOggMemFree((void **)&oggCtx->commentHeader);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief 刷新 OGG 流到文件(参考 audio_capture_wrapper.cpp)
+ */
+static int32_t MqttOggStreamFlush(MqttOggContext *oggCtx, FILE *pfd)
+{
+ if (oggCtx == nullptr || pfd == nullptr || oggCtx->page == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Invalid parameters for flush");
+ return -1;
+ }
+
+ while (ogg_stream_flush(&oggCtx->oggStream, oggCtx->page)) {
+ int32_t ret = fwrite(oggCtx->page->header, 1, oggCtx->page->header_len, pfd);
+ if (ret != (int32_t)oggCtx->page->header_len) {
+ MEDIA_ERR_LOG("MQTT OGG: Failed to write page header: errno=%d, errmsg=%s", errno, strerror(errno));
+ return -1;
+ }
+ ret = fwrite(oggCtx->page->body, 1, oggCtx->page->body_len, pfd);
+ if (ret != (int32_t)oggCtx->page->body_len) {
+ MEDIA_ERR_LOG("MQTT OGG: Failed to write page body: errno=%d, errmsg=%s", errno, strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * @brief 写入 OGG 页面到文件(参考 audio_capture_wrapper.cpp)
+ */
+static int32_t MqttOggWritePage(MqttOggContext *oggCtx, FILE *pfd)
+{
+ if (oggCtx == nullptr || pfd == nullptr || oggCtx->page == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Invalid parameters for write page");
+ return -1;
+ }
+
+ if (ogg_stream_pageout(&oggCtx->oggStream, oggCtx->page)) {
+ int32_t ret = fwrite(oggCtx->page->header, 1, oggCtx->page->header_len, pfd);
+ if (ret != (int32_t)oggCtx->page->header_len) {
+ MEDIA_ERR_LOG("MQTT OGG: Failed to write page header: errno=%d, errmsg=%s", errno, strerror(errno));
+ return -1;
+ }
+ ret = fwrite(oggCtx->page->body, 1, oggCtx->page->body_len, pfd);
+ if (ret != (int32_t)oggCtx->page->body_len) {
+ MEDIA_ERR_LOG("MQTT OGG: Failed to write page body: errno=%d, errmsg=%s", errno, strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * @brief 获取全局互斥锁
+ */
+static MediaMutexHandle GetMqttRecordMutex(void)
+{
+ if (g_mqttRecordMutex == nullptr) {
+ static bool init_once = false;
+ if (!init_once) {
+ init_once = true;
+ g_mqttRecordMutex = MediaMutexCreate(nullptr);
+ if (g_mqttRecordMutex != nullptr) {
+ MEDIA_INFO_LOG("MQTT record mutex created successfully");
+ } else {
+ MEDIA_ERR_LOG("Failed to create MQTT record mutex");
+ }
+ }
+ }
+ return g_mqttRecordMutex;
+}
+
+/**
+ * @brief 初始化录音资源
+ */
+static bool InitMqttRecordResources(MqttRecordContext *context)
+{
+ context->cond = MediaThreadCondCreate();
+ if (context->cond == nullptr) {
+ MEDIA_ERR_LOG("Failed to create MQTT record thread cond");
+ return false;
+ }
+
+ context->dataBuffer = (uint8_t*)malloc(MQTT_RECORD_BUFFER_SIZE);
+ if (context->dataBuffer == nullptr) {
+ MEDIA_ERR_LOG("Failed to allocate MQTT record buffer");
+ MediaThreadCondDestroy(&context->cond);
+ return false;
+ }
+
+ context->bufferSize = MQTT_RECORD_BUFFER_SIZE;
+
+ // 打开调试文件用于保存录音数据(方便验证数据正确性)
+ time_t now = time(nullptr);
+ struct tm *tm_info = localtime(&now);
+ char filename[128];
+ snprintf(filename, sizeof(filename), "/user/mqtt_record_%04d%02d%02d_%02d%02d%02d.sbc",
+ tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
+ tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec);
+
+ context->debugFile = fopen(filename, "wb");
+ if (context->debugFile == nullptr) {
+ MEDIA_ERR_LOG("Failed to open debug file: %s", filename);
+ // 文件打开失败不影响录音功能,继续执行
+ } else {
+ MEDIA_INFO_LOG("MQTT record debug file opened: %s", filename);
+ }
+
+ return true;
+}
+
+/**
+ * @brief 清理录音资源
+ */
+static void DeinitMqttRecordResources(MqttRecordContext *context)
+{
+ if (context != nullptr) {
+#if USE_AUDIO_STREAM_IN
+ // 使用 AudioStreamIn 接口
+ if (context->streamInInitialized) {
+ AudioStreamInStop();
+ AudioStreamInDeinit();
+ context->streamInInitialized = false;
+ }
+#else
+ // 使用 AudioCapturer 接口
+ if (context->audioCapturer != nullptr) {
+ context->audioCapturer->Stop();
+ context->audioCapturer->Release();
+ context->audioCapturer.reset();
+ context->audioCapturer = nullptr;
+ }
+#endif
+
+ // 关闭调试文件
+ if (context->debugFile != nullptr) {
+ fclose(context->debugFile);
+ context->debugFile = nullptr;
+ MEDIA_INFO_LOG("MQTT record debug file closed");
+ }
+
+ if (context->dataBuffer != nullptr) {
+ free(context->dataBuffer);
+ context->dataBuffer = nullptr;
+ }
+
+ if (context->cond != nullptr) {
+ MediaThreadCondDestroy(&context->cond);
+ context->cond = nullptr;
+ }
+ }
+}
+
+/**
+ * @brief 请求音频焦点
+ */
+static bool RequestMqttRecordAudioFocus(MqttRecordContext *context)
+{
+ bool success = AudioManagerInit();
+ if (!success) {
+ MEDIA_ERR_LOG("AudioManager init failed");
+ return false;
+ }
+
+ AudioSession sessionId = AudioManagerMakeSessionId();
+ if (sessionId == AUDIO_SESSION_ID_NONE) {
+ MEDIA_ERR_LOG("Audio session id invalid");
+ return false;
+ }
+
+ if (AudioManagerActivateInterrupt(AUDIO_STREAM_VOICE_RECORD, sessionId) == INTERRUPT_FAILED) {
+ MEDIA_ERR_LOG("Activate audio interrupt failed");
+ return false;
+ }
+
+ context->sessionId = sessionId;
+ return true;
+}
+
+/**
+ * @brief 释放音频焦点
+ */
+static bool ReleaseMqttRecordAudioFocus(void)
+{
+ if (AudioManagerDeactivateInterrupt() != 0) {
+ MEDIA_ERR_LOG("Deactivate audio interrupt failed");
+ return false;
+ }
+ return true;
+}
+
+/**
+ * @brief 启动录音流(根据宏选择使用 AudioStreamInInit 或 AudioCapturer)
+ */
+static int32_t StartMqttRecordStream(MqttRecordContext *context)
+{
+#if USE_AUDIO_STREAM_IN
+ // 使用 AudioStreamInInit 接口
+ CapturerInputConfig captureConfig = {};
+ captureConfig.audioFormat = context->audioFormat;
+ captureConfig.channelCount = context->channelCount;
+ captureConfig.linkDir = AUDIO_UP_LINK;
+ captureConfig.sampleRate = context->sampleRate;
+ captureConfig.sessionID = context->sessionId;
+ captureConfig.streamType = AUDIO_STREAM_VOICE_RECORD;
+
+ int32_t ret = AudioStreamInInit(captureConfig);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("AudioStreamInInit failed: %d", ret);
+ return -1;
+ }
+
+ ret = AudioStreamInStart();
+ if (ret != 0) {
+ MEDIA_ERR_LOG("AudioStreamInStart failed: %d", ret);
+ AudioStreamInDeinit();
+ return -1;
+ }
+
+ context->streamInInitialized = true;
+ MEDIA_INFO_LOG("MQTT record stream started successfully (AudioStreamIn)");
+ return 0;
+#else
+ // 使用 AudioCapturer 接口(与 audio_capture_wrapper.cpp 一致)
+ // 创建音频采集器
+ context->audioCapturer = std::make_shared<OHOS::Audio::AudioCapturer>();
+ if (context->audioCapturer == nullptr || context->audioCapturer.get() == nullptr) {
+ MEDIA_ERR_LOG("Failed to create audio capturer");
+ return -1;
+ }
+
+ // 配置采集器参数(使用 AudioCapturerInfo,与 audio_capture_wrapper.cpp 一致)
+ AudioCapturerInfo info = {};
+ info.inputSource = AUDIO_MIC;
+ info.audioFormat = SBC; // 硬编码为 SBC,用于排查 SBC 问题
+ info.sampleRate = context->sampleRate;
+ info.channelCount = context->channelCount;
+ info.streamType = AUDIO_STREAM_VOICE_RECORD;
+ info.bitWidth = BIT_WIDTH_16; // 默认16位
+ info.sessionID = context->sessionId;
+
+ // 设置采集器信息
+ if (context->audioCapturer->SetCapturerInfo(info) != 0) {
+ MEDIA_ERR_LOG("Failed to set capturer info");
+ context->audioCapturer.reset();
+ context->audioCapturer = nullptr;
+ return -1;
+ }
+
+ // 获取帧数并计算帧大小(与 audio_capture_wrapper.cpp 一致)
+ size_t frameCount = context->audioCapturer->GetFrameCount();
+ if (frameCount == 0) {
+ MEDIA_ERR_LOG("Failed to get frame count");
+ context->audioCapturer->Release();
+ context->audioCapturer.reset();
+ context->audioCapturer = nullptr;
+ return -1;
+ }
+
+ context->framesize = frameCount * context->channelCount;
+ MEDIA_INFO_LOG("MQTT record frameCount: %zu, framesize: %zu", frameCount, context->framesize);
+
+ // 根据 framesize 重新分配缓冲区(如果现有缓冲区不够大)
+ if (context->bufferSize < context->framesize) {
+ if (context->dataBuffer != nullptr) {
+ free(context->dataBuffer);
+ context->dataBuffer = nullptr;
+ }
+ context->dataBuffer = (uint8_t*)malloc(context->framesize);
+ if (context->dataBuffer == nullptr) {
+ MEDIA_ERR_LOG("Failed to allocate buffer for framesize: %zu", context->framesize);
+ context->audioCapturer->Release();
+ context->audioCapturer.reset();
+ context->audioCapturer = nullptr;
+ return -1;
+ }
+ context->bufferSize = context->framesize;
+ }
+
+ // 启动采集器
+ if (!context->audioCapturer->Start()) {
+ MEDIA_ERR_LOG("Failed to start audio capturer");
+ context->audioCapturer->Release();
+ context->audioCapturer.reset();
+ context->audioCapturer = nullptr;
+ return -1;
+ }
+
+ MEDIA_INFO_LOG("MQTT record stream started successfully (AudioCapturer)");
+ return 0;
+#endif
+}
+
+/**
+ * @brief 录音主线程函数
+ */
+static void MqttRecordMainThread(void *priv)
+{
+ MqttRecordContext *context = g_mqttRecordContext;
+ if (context == nullptr) {
+ MEDIA_ERR_LOG("MQTT record context is null in main thread");
+ return;
+ }
+
+ // 请求音频焦点
+ bool success = RequestMqttRecordAudioFocus(context);
+ if (!success) {
+ MEDIA_ERR_LOG("Request audio focus failed");
+ return;
+ }
+
+ // 启动录音流
+ int32_t ret = StartMqttRecordStream(context);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("Start record stream failed");
+ ReleaseMqttRecordAudioFocus();
+ return;
+ }
+
+ // 录音循环(根据宏选择使用 AudioStreamInObtainBuffer 或 AudioCapturer::Read)
+ while (!context->isRecordStopped) {
+#if USE_AUDIO_STREAM_IN
+ // 使用 AudioStreamInObtainBuffer 接口
+ if (context->streamInInitialized) {
+ uint32_t readSize = context->bufferSize;
+ int32_t ret = AudioStreamInObtainBuffer(context->dataBuffer, &readSize);
+
+ if (ret == 0 && readSize > 0) {
+ // 保存数据到文件(用于验证数据正确性)
+ if (context->debugFile != nullptr) {
+ size_t written = fwrite(context->dataBuffer, 1, readSize, context->debugFile);
+ if (written != (size_t)readSize) {
+ MEDIA_ERR_LOG("Failed to write to debug file: written=%zu, expected=%u", written, readSize);
+ }
+ }
+
+ if (context->dataCallback != nullptr) {
+ context->dataCallback(context->dataBuffer, readSize, context->callbackUserData);
+ }
+ } else if (ret != 0) {
+ // 获取缓冲区失败,短暂休眠后继续
+ usleep(10*1000); // 10ms
+ continue;
+ }
+ }
+#else
+ // 使用 AudioCapturer::Read 接口(与 audio_capture_wrapper.cpp 一致)
+ if (context->audioCapturer != nullptr) {
+ // 使用 Read 接口读取音频数据
+ int32_t readSize = context->audioCapturer->Read(context->dataBuffer,
+ context->framesize,
+ false);
+
+ if (readSize > 0) {
+ // 保存数据到文件(用于验证数据正确性)
+ if (context->debugFile != nullptr) {
+ size_t written = fwrite(context->dataBuffer, 1, readSize, context->debugFile);
+ if (written != (size_t)readSize) {
+ MEDIA_ERR_LOG("Failed to write to debug file: written=%zu, expected=%d", written, readSize);
+ }
+ }
+
+ if (context->dataCallback != nullptr) {
+ context->dataCallback(context->dataBuffer, (uint32_t)readSize, context->callbackUserData);
+ }
+ } else if (readSize == ERR_RETRY_READ) {
+ // 需要重试,短暂休眠后继续(与 audio_capture_wrapper.cpp 一致)
+ usleep(10*1000); // 10ms
+ continue;
+ }
+ }
+#endif
+
+ usleep(10*1000);
+ }
+
+ // 清理资源
+ DeinitMqttRecordResources(context);
+ ReleaseMqttRecordAudioFocus();
+
+ // 设置线程停止标志
+ g_mqttRecordThreadStopped = true;
+
+ MEDIA_INFO_LOG("MQTT record main thread completed");
+}
+
+/**
+ * @brief 启动MQTT录音
+ * @param dataCallback 录音数据回调函数
+ * @param userData 用户数据指针
+ * @param audioParams 录音音频参数,为nullptr时使用默认参数
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_StartRecord(MqttRecordDataCallback dataCallback, void* userData,
+ const MqttRecordAudioParams* audioParams)
+{
+ MEDIA_INFO_LOG("MQTT_StartRecord");
+
+ MediaMutexHandle mutex = GetMqttRecordMutex();
+ if (mutex == nullptr) {
+ MEDIA_ERR_LOG("Failed to get MQTT record mutex");
+ return -1;
+ }
+
+ MediaMutexLock(mutex);
+ if (g_mqttRecordContext != nullptr) {
+ MEDIA_ERR_LOG("MQTT record already started");
+ MediaMutexUnLock(mutex);
+ return -1;
+ }
+
+ // 分配上下文
+ g_mqttRecordContext = (MqttRecordContext *)malloc(sizeof(MqttRecordContext));
+ if (g_mqttRecordContext == nullptr) {
+ MEDIA_ERR_LOG("Failed to allocate MQTT record context");
+ MediaMutexUnLock(mutex);
+ return -1;
+ }
+
+ if (memset_s(g_mqttRecordContext, sizeof(MqttRecordContext), 0, sizeof(MqttRecordContext)) != EOK) {
+ MEDIA_ERR_LOG("memset_s failed");
+ free(g_mqttRecordContext);
+ g_mqttRecordContext = nullptr;
+ MediaMutexUnLock(mutex);
+ return -1;
+ }
+
+ // 初始化线程停止标志
+ g_mqttRecordThreadStopped = false;
+
+ // 设置回调
+ g_mqttRecordContext->dataCallback = dataCallback;
+ g_mqttRecordContext->callbackUserData = userData;
+
+ // 设置音频参数
+ if (audioParams != nullptr) {
+ g_mqttRecordContext->audioFormat = (AudioCodecFormat)audioParams->audioFormat;
+ g_mqttRecordContext->channelCount = audioParams->channelCount;
+ g_mqttRecordContext->sampleRate = audioParams->sampleRate;
+ MEDIA_INFO_LOG("Using custom audio params: format=%d, channels=%u, sampleRate=%u",
+ audioParams->audioFormat, audioParams->channelCount, audioParams->sampleRate);
+ } else {
+ g_mqttRecordContext->audioFormat = MQTT_DEFAULT_AUDIO_FORMAT;
+ g_mqttRecordContext->channelCount = MQTT_DEFAULT_CHANNEL_COUNT;
+ g_mqttRecordContext->sampleRate = MQTT_DEFAULT_SAMPLE_RATE;
+ MEDIA_INFO_LOG("Using default audio params: format=%d, channels=%u, sampleRate=%u",
+ MQTT_DEFAULT_AUDIO_FORMAT, MQTT_DEFAULT_CHANNEL_COUNT, MQTT_DEFAULT_SAMPLE_RATE);
+ }
+
+ // 初始化资源
+ if (!InitMqttRecordResources(g_mqttRecordContext)) {
+ MEDIA_ERR_LOG("Failed to init MQTT record resources");
+ free(g_mqttRecordContext);
+ g_mqttRecordContext = nullptr;
+ MediaMutexUnLock(mutex);
+ return -1;
+ }
+
+ MediaMutexUnLock(mutex);
+
+ // 创建录音线程
+ app_task_definition_t task_cfg;
+ memset(&task_cfg, 0, sizeof(task_cfg));
+
+ task_cfg.create_queue_handle = NULL;
+ task_cfg.attr.name = "MqttRecordThread";
+ task_cfg.attr.priority = (osPriority_t)24;
+ task_cfg.attr.stack_size = 0x2000; // 8KB
+ task_cfg.func = MqttRecordMainThread;
+ task_cfg.use_mem = USE_EXTEND_MEM;
+
+ extern errcode_t uapi_create_osThread_custom(app_task_definition_t* task_cfg);
+ errcode_t ret = uapi_create_osThread_custom(&task_cfg);
+
+ if (ret != ERRCODE_SUCC) {
+ MEDIA_ERR_LOG("Failed to create MQTT record thread: %d", ret);
+ MediaMutexLock(mutex);
+ DeinitMqttRecordResources(g_mqttRecordContext);
+ free(g_mqttRecordContext);
+ g_mqttRecordContext = nullptr;
+ MediaMutexUnLock(mutex);
+ return -1;
+ }
+
+ // 保存线程句柄
+ g_mqttRecordContext->taskHandle = (void*)task_cfg.task_handle;
+ strncpy(g_mqttRecordContext->threadName, task_cfg.attr.name, sizeof(g_mqttRecordContext->threadName) - 1);
+ g_mqttRecordContext->threadName[sizeof(g_mqttRecordContext->threadName) - 1] = '\0';
+
+ MEDIA_INFO_LOG("MQTT record started successfully");
+ return 0;
+}
+
+/**
+ * @brief 停止MQTT录音
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_StopRecord(void)
+{
+ MEDIA_INFO_LOG("MQTT_StopRecord");
+
+ MediaMutexHandle mutex = GetMqttRecordMutex();
+ if (mutex == nullptr) {
+ MEDIA_ERR_LOG("Failed to get MQTT record mutex");
+ return -1;
+ }
+
+ MediaMutexLock(mutex);
+ if (g_mqttRecordContext == nullptr) {
+ MEDIA_ERR_LOG("MQTT record not started");
+ MediaMutexUnLock(mutex);
+ return -1;
+ }
+
+ if (g_mqttRecordContext->isRecordStopped) {
+ MEDIA_ERR_LOG("MQTT record already stopped");
+ MediaMutexUnLock(mutex);
+ return 0;
+ }
+
+ // 设置停止标志
+ g_mqttRecordContext->isRecordStopped = true;
+ MediaMutexUnLock(mutex);
+
+ // 等待线程结束
+ MEDIA_INFO_LOG("Waiting for MQTT record thread to stop...");
+
+ if (g_mqttRecordContext->taskHandle != nullptr) {
+ osThreadId_t threadId = (osThreadId_t)g_mqttRecordContext->taskHandle;
+ const char* threadName = g_mqttRecordContext->threadName;
+
+ // 验证线程ID和名称是否匹配,避免ID被复用
+ bool isValid = true;
+ if (threadName != nullptr && threadName[0] != '\0') {
+ osThreadState_t threadState = osThreadGetState(threadId);
+ if (threadState == osThreadError) {
+ isValid = false; // 线程不存在或无效
+ } else {
+ const char* actualName = osThreadGetName(threadId);
+ if (actualName == nullptr || strcmp(actualName, threadName) != 0) {
+ isValid = false; // 线程名称不匹配
+ }
+ }
+ }
+
+ if (!isValid) {
+ MEDIA_INFO_LOG("Thread ID may have been reused, thread name mismatch. Expected: %s",
+ threadName ? threadName : "unknown");
+ MEDIA_INFO_LOG("Assuming thread already stopped due to ID reuse");
+ } else {
+ MEDIA_INFO_LOG("Thread validation passed, waiting for thread: %s",
+ threadName ? threadName : "unknown");
+
+ // 首先尝试使用 osThreadJoin 等待线程结束
+ osStatus_t joinStatus = osThreadJoin(threadId);
+ if (joinStatus == osOK) {
+ MEDIA_INFO_LOG("MQTT record thread stopped successfully (osThreadJoin)");
+ } else {
+ // 如果 osThreadJoin 不可用或失败,使用状态检查
+ MEDIA_INFO_LOG("osThreadJoin failed (%d), using state check...", joinStatus);
+
+ // 使用 osThreadGetState 检查线程状态
+ for (int i = 0; i < 500; i++) {
+ usleep(1000*1000); // 100ms
+
+ // 再次验证线程,防止在等待过程中ID被复用
+ if (threadName != nullptr && threadName[0] != '\0') {
+ osThreadState_t checkState = osThreadGetState(threadId);
+ if (checkState == osThreadError) {
+ MEDIA_INFO_LOG("Thread ID invalid during wait, stopping check");
+ usleep(1000*1000); // 100ms
+
+ break;
+ }
+ const char* checkName = osThreadGetName(threadId);
+ if (checkName == nullptr || strcmp(checkName, threadName) != 0) {
+ if (g_mqttRecordThreadStopped) {
+ MEDIA_INFO_LOG("Thread ID reused during wait, stopping check");
+ usleep(1000*1000); // 100ms
+
+ break;
+ }
+ }
+ }
+
+ osThreadState_t threadState = osThreadGetState(threadId);
+
+ // 检查线程状态,如果线程不存在或已终止,则认为已停止
+ bool thread_running = (threadState == osThreadReady ||
+ threadState == osThreadRunning ||
+ threadState == osThreadBlocked);
+
+ MEDIA_INFO_LOG("Waiting... %d/50 (state: %d, running: %s, stopped_flag: %d)",
+ i + 1, threadState, thread_running ? "yes" : "no",
+ g_mqttRecordThreadStopped ? 1 : 0);
+
+ if (!thread_running && g_mqttRecordThreadStopped) {
+ MEDIA_INFO_LOG("MQTT record thread stopped successfully (state check)");
+ usleep(1000*1000); // 100ms
+
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ MEDIA_INFO_LOG("No valid thread handle, assuming thread already stopped");
+ }
+
+ MEDIA_INFO_LOG("MQTT record stopped and resources cleaned up");
+ return 0;
+}
+
+/**
+ * @brief 检查MQTT录音是否正在运行
+ * @return true 正在运行,false 未运行
+ */
+bool MQTT_IsRecordRunning(void)
+{
+ bool isRunning = false;
+
+ MediaMutexHandle mutex = GetMqttRecordMutex();
+ if (mutex == nullptr) {
+ return false;
+ }
+
+ MediaMutexLock(mutex);
+ if (g_mqttRecordContext != nullptr && !g_mqttRecordContext->isRecordStopped) {
+ isRunning = true;
+ }
+ MediaMutexUnLock(mutex);
+
+ return isRunning;
+}
+
+/**
+ * @brief 获取MQTT录音参数
+ * @param audioParams 输出参数:当前录音音频参数
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_GetRecordParams(MqttRecordAudioParams* audioParams)
+{
+ if (audioParams == nullptr) {
+ MEDIA_ERR_LOG("Invalid output parameter");
+ return -1;
+ }
+
+ MediaMutexHandle mutex = GetMqttRecordMutex();
+ if (mutex == nullptr) {
+ MEDIA_ERR_LOG("Failed to get MQTT record mutex");
+ return -1;
+ }
+
+ MediaMutexLock(mutex);
+ if (g_mqttRecordContext == nullptr) {
+ MEDIA_ERR_LOG("MQTT record not started");
+ MediaMutexUnLock(mutex);
+ return -1;
+ }
+
+ audioParams->audioFormat = (int32_t)g_mqttRecordContext->audioFormat;
+ audioParams->channelCount = g_mqttRecordContext->channelCount;
+ audioParams->sampleRate = g_mqttRecordContext->sampleRate;
+
+ MediaMutexUnLock(mutex);
+ return 0;
+}
+
+// ==================== 音频播放接口 ====================
+
+// 播放回调函数类型
+typedef void (*MqttPlayerCallback)(int32_t event, void* userData);
+
+// 播放事件定义
+enum MqttPlayerEvent {
+ MQTT_PLAYER_EVENT_PLAY = 0,
+ MQTT_PLAYER_EVENT_PAUSE,
+ MQTT_PLAYER_EVENT_STOP,
+ MQTT_PLAYER_EVENT_COMPLETE,
+ MQTT_PLAYER_EVENT_ERROR
+};
+
+// 播放回调实现类
+class MqttPlayerCallbackImpl : public AudioPlayerServiceCallback {
+public:
+ MqttPlayerCallbackImpl() : callback_(nullptr), userData_(nullptr) {}
+ ~MqttPlayerCallbackImpl() override {}
+
+ void SetCallback(MqttPlayerCallback cb, void* userData) {
+ callback_ = cb;
+ userData_ = userData;
+ }
+
+ void OnInterrupt(int32_t type, int32_t hint) override {
+ MEDIA_INFO_LOG("OnInterrupt type[%d], hint[%d]", type, hint);
+ if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_PAUSE) {
+ AudioPlayerService::GetInstance()->Pause();
+ } else if (type == INTERRUPT_TYPE_END && hint == INTERRUPT_HINT_RESUME) {
+ AudioPlayerService::GetInstance()->Resume();
+ } else if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_STOP) {
+ AudioPlayerService::GetInstance()->Reset();
+ }
+ }
+
+ void OnError(int32_t errorType, int32_t errorCode) override {
+ MEDIA_ERR_LOG("OnError errorType[%d], errorCode[%d]", errorType, errorCode);
+ if (callback_ != nullptr) {
+ callback_(MQTT_PLAYER_EVENT_ERROR, userData_);
+ }
+ AudioPlayerService::GetInstance()->Reset();
+ }
+
+ void OnPlaybackComplete() override {
+ MEDIA_INFO_LOG("OnPlaybackComplete");
+ if (callback_ != nullptr) {
+ callback_(MQTT_PLAYER_EVENT_COMPLETE, userData_);
+ }
+ }
+
+ void OnPlay() override {
+ MEDIA_INFO_LOG("OnPlay");
+ if (callback_ != nullptr) {
+ callback_(MQTT_PLAYER_EVENT_PLAY, userData_);
+ }
+ }
+
+ void OnPause() override {
+ MEDIA_INFO_LOG("OnPause");
+ if (callback_ != nullptr) {
+ callback_(MQTT_PLAYER_EVENT_PAUSE, userData_);
+ }
+ }
+
+ void OnStop() override {
+ MEDIA_INFO_LOG("OnStop");
+ if (callback_ != nullptr) {
+ callback_(MQTT_PLAYER_EVENT_STOP, userData_);
+ }
+ }
+
+private:
+ MqttPlayerCallback callback_;
+ void* userData_;
+};
+
+// 全局播放回调实例
+static std::shared_ptr<MqttPlayerCallbackImpl> g_mqttPlayerCallback = nullptr;
+
+/**
+ * @brief 播放指定路径的音频文件
+ * @param filePath 音频文件路径
+ * @param callback 播放事件回调函数(可为nullptr)
+ * @param userData 用户数据指针
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_PlayAudioFile(const char* filePath, MqttPlayerCallback callback, void* userData)
+{
+ if (filePath == nullptr || strlen(filePath) == 0) {
+ MEDIA_ERR_LOG("Invalid file path");
+ return -1;
+ }
+
+ MEDIA_INFO_LOG("MQTT_PlayAudioFile: %s", filePath);
+
+ // 创建回调实例
+ if (g_mqttPlayerCallback == nullptr) {
+ g_mqttPlayerCallback = std::make_shared<MqttPlayerCallbackImpl>();
+ }
+ g_mqttPlayerCallback->SetCallback(callback, userData);
+
+ // 设置回调
+ AudioPlayerService::GetInstance()->SetAudioPlayerCallback(g_mqttPlayerCallback);
+
+ // 设置播放源
+ std::string src(filePath);
+ int32_t ret = AudioPlayerService::GetInstance()->SetPlaySource(src);
+ if (ret != MEDIA_OK) {
+ MEDIA_ERR_LOG("Failed to set play source: %s", filePath);
+ return -1;
+ }
+
+ // 开始播放
+ ret = AudioPlayerService::GetInstance()->Start();
+ if (ret != MEDIA_OK) {
+ MEDIA_ERR_LOG("Failed to start playback");
+ return -1;
+ }
+
+ MEDIA_INFO_LOG("Audio playback started: %s", filePath);
+ return 0;
+}
+
+/**
+ * @brief 停止当前音频播放
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_StopAudioPlay(void)
+{
+ MEDIA_INFO_LOG("MQTT_StopAudioPlay");
+ return AudioPlayerService::GetInstance()->Reset();
+}
+
+/**
+ * @brief 暂停当前音频播放
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_PauseAudioPlay(void)
+{
+ MEDIA_INFO_LOG("MQTT_PauseAudioPlay");
+ return AudioPlayerService::GetInstance()->Pause();
+}
+
+/**
+ * @brief 恢复当前音频播放
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_ResumeAudioPlay(void)
+{
+ MEDIA_INFO_LOG("MQTT_ResumeAudioPlay");
+ return AudioPlayerService::GetInstance()->Resume();
+}
+
+/**
+ * @brief 跳转到指定位置
+ * @param mSeconds 目标位置(毫秒)
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_SeekAudioPlay(int64_t mSeconds)
+{
+ MEDIA_INFO_LOG("MQTT_SeekAudioPlay: %lld ms", mSeconds);
+ return AudioPlayerService::GetInstance()->Seek(mSeconds);
+}
+
+/**
+ * @brief 获取当前播放时间
+ * @param time 输出参数:当前播放时间(毫秒)
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_GetCurrentTime(int64_t* time)
+{
+ if (time == nullptr) {
+ MEDIA_ERR_LOG("Invalid output parameter");
+ return -1;
+ }
+
+ int64_t currentTime = 0;
+ int32_t ret = AudioPlayerService::GetInstance()->GetCurrentTime(currentTime);
+ if (ret != MEDIA_OK) {
+ MEDIA_ERR_LOG("Failed to get current time");
+ return -1;
+ }
+
+ *time = currentTime;
+ return 0;
+}
+
+/**
+ * @brief 获取音频文件总时长
+ * @param duration 输出参数:总时长(毫秒)
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_GetDuration(int64_t* duration)
+{
+ if (duration == nullptr) {
+ MEDIA_ERR_LOG("Invalid output parameter");
+ return -1;
+ }
+
+ int64_t durationMs = -1;
+ int32_t ret = AudioPlayerService::GetInstance()->GetDuration(durationMs);
+ if (ret != MEDIA_OK) {
+ MEDIA_ERR_LOG("Failed to get duration");
+ return -1;
+ }
+
+ *duration = durationMs;
+ return 0;
+}
+
+/**
+ * @brief 检查是否正在播放
+ * @return true 正在播放,false 未播放
+ */
+bool MQTT_IsPlaying(void)
+{
+ return AudioPlayerService::GetInstance()->IsPlaying();
+}
+
+/**
+ * @brief 获取当前播放状态
+ * @return 播放状态值
+ */
+int32_t MQTT_GetPlayStatus(void)
+{
+ return AudioPlayerService::GetInstance()->GetPlayStatus();
+}
+
+/**
+ * @brief 设置单曲循环模式
+ * @param enable true 开启单曲循环,false 关闭
+ * @return 0 成功,-1 失败
+ */
+int32_t MQTT_SetSingleLoop(bool enable)
+{
+ MEDIA_INFO_LOG("MQTT_SetSingleLoop: %s", enable ? "true" : "false");
+ OHOS::AudioPlayerLoopMode loopMode = enable ? OHOS::AudioPlayerLoopMode::AUDIO_PLAYER_SINGLE_LOOP
+ : OHOS::AudioPlayerLoopMode::AUDIO_PLAYER_INVAILD_LOOP;
+ return AudioPlayerService::GetInstance()->SetPlayLoopMode(loopMode);
+}
+
+// ==================== OGG 封装接口(独立接口,用于将 OPUS 数据封装为 OGG 文件)====================
+
+// OGG 上下文管理器(用于 ln_UDP.c,避免其直接依赖 ogg.h)
+static MqttOggContext g_ln_udp_ogg_ctx = {0}; // 全局 OGG 上下文(用于 UDP 接收)
+
+// 前向声明内部函数
+static int32_t MqttOggEncapsulationInit(MqttOggContext *oggCtx, FILE *pfd, uint32_t sampleRate, uint32_t channelCount);
+static int32_t MqttOggEncapsulationWrite(MqttOggContext *oggCtx, const uint8_t *buffer, uint32_t bufferLen, FILE *pfd, bool isEos);
+static int32_t MqttOggEncapsulationFinish(MqttOggContext *oggCtx, FILE *pfd);
+
+/**
+ * @brief 获取全局 OGG 上下文句柄(供 ln_UDP.c 使用)
+ * @return OGG 上下文句柄(不透明指针),失败返回 nullptr
+ */
+extern "C" void* MqttOggGetContext(void)
+{
+ return (void*)&g_ln_udp_ogg_ctx;
+}
+
+/**
+ * @brief 初始化 OGG 封装上下文(参考 audio_capture_wrapper.cpp)
+ * @param oggCtx OGG 上下文指针(由调用者分配,大小至少为 sizeof(MqttOggContext))
+ * @param pfd 输出文件句柄(已打开的文件,用于写入 OGG 数据)
+ * @param sampleRate 采样率
+ * @param channelCount 声道数
+ * @return 0 成功,-1 失败
+ * @note 调用此函数前需要先打开文件并获取文件句柄
+ */
+static int32_t MqttOggEncapsulationInit(MqttOggContext *oggCtx, FILE *pfd, uint32_t sampleRate, uint32_t channelCount)
+{
+ if (oggCtx == nullptr || pfd == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Invalid parameters for init");
+ return -1;
+ }
+
+ // 分配 packet 和 page
+ oggCtx->packet = (ogg_packet *)MqttOggMemCalloc(sizeof(ogg_packet));
+ if (oggCtx->packet == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Failed to allocate packet");
+ return -1;
+ }
+
+ oggCtx->page = (ogg_page *)MqttOggMemCalloc(sizeof(ogg_page));
+ if (oggCtx->page == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Failed to allocate page");
+ MqttOggMemFree((void **)&oggCtx->packet);
+ return -1;
+ }
+
+ // 初始化 OGG 上下文
+ oggCtx->sampleRate = sampleRate;
+ oggCtx->channels = channelCount;
+ oggCtx->granulepos = -1; // -1 means start page
+ oggCtx->packetCount = 0;
+ oggCtx->isEnd = false;
+ oggCtx->serialno = 0x1; // unique serialno
+
+ if (ogg_stream_init(&oggCtx->oggStream, oggCtx->serialno) != 0) {
+ MEDIA_ERR_LOG("MQTT OGG: ogg stream init failed");
+ MqttOggMemFree((void **)&oggCtx->packet);
+ MqttOggMemFree((void **)&oggCtx->page);
+ return -1;
+ }
+
+ // 初始化 OGG 头部
+ if (MqttOggHeaderInit(oggCtx, sampleRate, channelCount) != 0) {
+ MEDIA_ERR_LOG("MQTT OGG: Header init failed");
+ ogg_stream_clear(&oggCtx->oggStream);
+ MqttOggMemFree((void **)&oggCtx->packet);
+ MqttOggMemFree((void **)&oggCtx->page);
+ return -1;
+ }
+
+ // 写入 ID Header packet
+ oggCtx->packet->packet = oggCtx->idHeader;
+ oggCtx->packet->bytes = MQTT_OGG_OPUS_ID_HEADER_LEN;
+ oggCtx->packet->b_o_s = 1; // 1 means beginning of ogg stream
+ oggCtx->packet->e_o_s = 0;
+ oggCtx->packet->granulepos = oggCtx->granulepos;
+ oggCtx->packet->packetno = oggCtx->packetCount++;
+ oggCtx->granulepos = 0;
+ ogg_stream_packetin(&oggCtx->oggStream, oggCtx->packet);
+
+ if (MqttOggStreamFlush(oggCtx, pfd) != 0) {
+ MEDIA_ERR_LOG("MQTT OGG: Flush ID header failed");
+ ogg_stream_clear(&oggCtx->oggStream);
+ MqttOggMemFree((void **)&oggCtx->packet);
+ MqttOggMemFree((void **)&oggCtx->page);
+ MqttOggMemFree((void **)&oggCtx->idHeader);
+ MqttOggMemFree((void **)&oggCtx->commentHeader);
+ return -1;
+ }
+
+ // 写入 Comment Header packet
+ oggCtx->packet->packet = oggCtx->commentHeader;
+ oggCtx->packet->bytes = MQTT_OGG_OPUS_COMMENT_HEADER_LEN;
+ oggCtx->packet->b_o_s = 0;
+ oggCtx->packet->e_o_s = 0;
+ oggCtx->packet->granulepos = 0;
+ oggCtx->packet->packetno = oggCtx->packetCount++;
+ ogg_stream_packetin(&oggCtx->oggStream, oggCtx->packet);
+
+ if (MqttOggStreamFlush(oggCtx, pfd) != 0) {
+ MEDIA_ERR_LOG("MQTT OGG: Flush comment header failed");
+ ogg_stream_clear(&oggCtx->oggStream);
+ MqttOggMemFree((void **)&oggCtx->packet);
+ MqttOggMemFree((void **)&oggCtx->page);
+ MqttOggMemFree((void **)&oggCtx->idHeader);
+ MqttOggMemFree((void **)&oggCtx->commentHeader);
+ return -1;
+ }
+
+ oggCtx->initialized = true;
+ MEDIA_INFO_LOG("MQTT OGG: Encapsulation initialized successfully");
+ return 0;
+}
+
+/**
+ * @brief 写入音频数据到 OGG 封装(参考 audio_capture_wrapper.cpp)
+ * @param oggCtx OGG 上下文指针
+ * @param buffer 音频数据缓冲区(包含 OPUS 编码头,前8字节为编码头)
+ * @param bufferLen 数据长度(包含编码头)
+ * @param pfd 输出文件句柄
+ * @param isEos 是否为结束标志
+ * @return 0 成功,-1 失败
+ * @note buffer 的前 8 字节为 OPUS 编码头,实际 OPUS 数据从 buffer[8] 开始
+ */
+static int32_t MqttOggEncapsulationWrite(MqttOggContext *oggCtx, const uint8_t *buffer, uint32_t bufferLen, FILE *pfd, bool isEos)
+{
+ if (oggCtx == nullptr || buffer == nullptr || pfd == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Invalid parameters for write");
+ return -1;
+ }
+
+ if (!oggCtx->initialized) {
+ MEDIA_ERR_LOG("MQTT OGG: Context not initialized");
+ return -1;
+ }
+
+ if (bufferLen < MQTT_OGG_OPUS_ENCODE_HEADER_SIZE) {
+ MEDIA_ERR_LOG("MQTT OGG: Buffer too small for OPUS encode header");
+ return -1;
+ }
+
+ // 构造 OGG packet(跳过 OPUS 编码头)
+ oggCtx->packet->packet = (unsigned char *)(buffer + MQTT_OGG_OPUS_ENCODE_HEADER_SIZE);
+ oggCtx->packet->bytes = bufferLen - MQTT_OGG_OPUS_ENCODE_HEADER_SIZE;
+ oggCtx->packet->b_o_s = 0;
+ oggCtx->packet->e_o_s = isEos ? 1 : 0;
+ oggCtx->packet->granulepos = oggCtx->granulepos;
+ oggCtx->packet->packetno = oggCtx->packetCount++;
+ // 计算 granulepos(假设每帧 10ms,采样率为 OPUS_SAMPLERATE)
+ oggCtx->granulepos += MQTT_OGG_OPUS_SAMPLERATE * 10 / MQTT_OGG_MILLSECOND_TO_SECOND;
+
+ ogg_stream_packetin(&oggCtx->oggStream, oggCtx->packet);
+
+ if (!isEos) {
+ return MqttOggWritePage(oggCtx, pfd);
+ } else {
+ return MqttOggStreamFlush(oggCtx, pfd);
+ }
+}
+
+/**
+ * @brief 结束 OGG 封装并清理资源(参考 audio_capture_wrapper.cpp)
+ * @param oggCtx OGG 上下文指针
+ * @param pfd 输出文件句柄(用于最终刷新,可为 nullptr)
+ * @return 0 成功,-1 失败
+ * @note 调用此函数后,需要调用者自行关闭文件句柄
+ */
+static int32_t MqttOggEncapsulationFinish(MqttOggContext *oggCtx, FILE *pfd)
+{
+ if (oggCtx == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Invalid ogg context for finish");
+ return -1;
+ }
+
+ if (!oggCtx->initialized) {
+ MEDIA_ERR_LOG("MQTT OGG: Context not initialized, nothing to finish");
+ return 0; // 未初始化,直接返回成功
+ }
+
+ // 如果文件句柄有效,进行最终刷新
+ if (pfd != nullptr) {
+ MqttOggStreamFlush(oggCtx, pfd);
+ }
+
+ // 清理资源
+ oggCtx->sampleRate = 0;
+ oggCtx->channels = 0;
+ oggCtx->granulepos = 0;
+ oggCtx->packetCount = 0;
+ oggCtx->isEnd = false;
+
+ MqttOggMemFree((void **)&oggCtx->packet);
+ MqttOggMemFree((void **)&oggCtx->page);
+ MqttOggMemFree((void **)&oggCtx->idHeader);
+ MqttOggMemFree((void **)&oggCtx->commentHeader);
+
+ ogg_stream_clear(&oggCtx->oggStream);
+ oggCtx->initialized = false;
+
+ MEDIA_INFO_LOG("MQTT OGG: Encapsulation finished and resources cleaned");
+ return 0;
+}
+
+/**
+ * @brief 初始化 OGG 封装上下文(Handle 版本,供 ln_UDP.c 使用)
+ * @param oggCtxHandle OGG 上下文句柄(不透明指针,由 MqttOggGetContext 获取)
+ * @param pfd 输出文件句柄(已打开的文件,用于写入 OGG 数据)
+ * @param sampleRate 采样率
+ * @param channelCount 声道数
+ * @return 0 成功,-1 失败
+ * @note 调用此函数前需要先打开文件并获取文件句柄
+ */
+extern "C" int32_t MqttOggEncapsulationInitHandle(void* oggCtxHandle, FILE *pfd, uint32_t sampleRate, uint32_t channelCount)
+{
+ if (oggCtxHandle == nullptr || pfd == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Invalid parameters for init");
+ return -1;
+ }
+
+ MqttOggContext *oggCtx = (MqttOggContext *)oggCtxHandle;
+ return MqttOggEncapsulationInit(oggCtx, pfd, sampleRate, channelCount);
+}
+
+/**
+ * @brief 写入音频数据到 OGG 封装(Handle 版本,供 ln_UDP.c 使用)
+ * @param oggCtxHandle OGG 上下文句柄(不透明指针,由 MqttOggGetContext 获取)
+ * @param buffer 音频数据缓冲区(包含 OPUS 编码头,前8字节为编码头)
+ * @param bufferLen 数据长度(包含编码头)
+ * @param pfd 输出文件句柄
+ * @param isEos 是否为结束标志
+ * @return 0 成功,-1 失败
+ * @note buffer 的前 8 字节为 OPUS 编码头,实际 OPUS 数据从 buffer[8] 开始
+ */
+extern "C" int32_t MqttOggEncapsulationWriteHandle(void* oggCtxHandle, const uint8_t *buffer, uint32_t bufferLen, FILE *pfd, bool isEos)
+{
+ if (oggCtxHandle == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Invalid ogg context handle for write");
+ return -1;
+ }
+
+ MqttOggContext *oggCtx = (MqttOggContext *)oggCtxHandle;
+ return MqttOggEncapsulationWrite(oggCtx, buffer, bufferLen, pfd, isEos);
+}
+
+/**
+ * @brief 结束 OGG 封装并清理资源(Handle 版本,供 ln_UDP.c 使用)
+ * @param oggCtxHandle OGG 上下文句柄(不透明指针,由 MqttOggGetContext 获取)
+ * @param pfd 输出文件句柄(用于最终刷新,可为 nullptr)
+ * @return 0 成功,-1 失败
+ * @note 调用此函数后,需要调用者自行关闭文件句柄
+ */
+extern "C" int32_t MqttOggEncapsulationFinishHandle(void* oggCtxHandle, FILE *pfd)
+{
+ if (oggCtxHandle == nullptr) {
+ MEDIA_ERR_LOG("MQTT OGG: Invalid ogg context handle for finish");
+ return -1;
+ }
+
+ MqttOggContext *oggCtx = (MqttOggContext *)oggCtxHandle;
+ return MqttOggEncapsulationFinish(oggCtx, pfd);
+}
+
+#ifdef __cplusplus
+};
+#endif
+
)
+# LN_MQTT:根据 SUPPORT_LN_MQTT_SERVICE 灵活添加
+# - 该宏通常来自 target_config 的 DEFINES 列表(由构建系统注入到 CMake 变量 DEFINES 中)
+# - 兼容:如果外部直接以 -DSUPPORT_LN_MQTT_SERVICE=1 形式传入,也可生效
+if((DEFINED SUPPORT_LN_MQTT_SERVICE AND SUPPORT_LN_MQTT_SERVICE) OR ("SUPPORT_LN_MQTT_SERVICE" IN_LIST DEFINES))
+ list(APPEND SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/LN_MQTT/ln_mqtt_api.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/LN_MQTT/ln_mqtt_api_at.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/LN_MQTT/ln_OTA.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/LN_MQTT/ln_UDP.c
+ )
+endif()
+
# 公共头文件路径(供其他模块引用)
set(PUBLIC_HEADER
${ROOT_DIR}/zhihui/4g/cat1Service/include/
${ROOT_DIR}/open_source/openharmony/foundation/ace/ace_engine_lite/modules/netstack/websocket/include
${ROOT_DIR}/zhihui/websocket/os_ws
${ROOT_DIR}/application/wearable/ln/nativeapp/nativeui/include/bluetooth
+ ${ROOT_DIR}/open_source/openharmony/foundation/ace/ace_engine_lite/modules/netstack/http/include
)
# 公共宏定义(可选)
${CMAKE_CURRENT_SOURCE_DIR}/
)
+# LN_MQTT 头文件路径(仅在使能时添加,避免无关组件污染 include path)
+if((DEFINED SUPPORT_LN_MQTT_SERVICE AND SUPPORT_LN_MQTT_SERVICE) OR ("SUPPORT_LN_MQTT_SERVICE" IN_LIST DEFINES))
+ set(PRIVATE_HEADER
+ ${PRIVATE_HEADER}
+ ${CMAKE_CURRENT_SOURCE_DIR}/LN_MQTT
+ ${ROOT_DIR}/zhihui/test_opus_frame_to_pcm/include
+ )
+endif()
+
# 私有宏定义(可选)
set(PRIVATE_DEFINES
# 如无特殊私有宏,可留空
)
+# LN_MQTT 双流接口开关(仅在使能 LN_MQTT 时添加)
+# 定义 USE_DUAL_STREAM_INTERFACE=1 使用双流接口,否则使用 MQTT_StartRecord
+if((DEFINED SUPPORT_LN_MQTT_SERVICE AND SUPPORT_LN_MQTT_SERVICE) OR ("SUPPORT_LN_MQTT_SERVICE" IN_LIST DEFINES))
+ if((DEFINED USE_DUAL_STREAM_INTERFACE AND USE_DUAL_STREAM_INTERFACE) OR ("USE_DUAL_STREAM_INTERFACE" IN_LIST DEFINES))
+ list(APPEND PRIVATE_DEFINES USE_DUAL_STREAM_INTERFACE=1)
+ message(STATUS "[LN_MQTT] Dual stream interface enabled")
+ endif()
+endif()
+
# 公共编译选项(可选)
set(COMPONENT_PUBLIC_CCFLAGS
)
--- /dev/null
+
+#include "httpclient.h"
+#include "cJSON.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "cJSON.h"
+#include "ln_api.h"
+// #include "ppp_lwip.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// MQTT 凭证结构体
+typedef struct {
+ char endpoint[256];
+ char client_id[256];
+ char username[256];
+ char password[256];
+ char publish_topic[128];
+ char subscribe_topic[128];
+} mqtt_credentials_t;
+
+// http://115.190.94.208:8085/api/v1/ota
+
+// 保存 MQTT 凭证到文件
+static int save_mqtt_credentials(const mqtt_credentials_t *cred)
+{
+ if (!cred) {
+ return -1;
+ }
+
+ FILE *fp = fopen("/user/mqtt_credentials.json", "w");
+ if (!fp) {
+ printf("Failed to open mqtt credentials file for writing\n");
+ return -1;
+ }
+
+ cJSON *root = cJSON_CreateObject();
+ cJSON *mqtt = cJSON_CreateObject();
+
+ cJSON_AddStringToObject(mqtt, "endpoint", cred->endpoint);
+ cJSON_AddStringToObject(mqtt, "client_id", cred->client_id);
+ cJSON_AddStringToObject(mqtt, "username", cred->username);
+ cJSON_AddStringToObject(mqtt, "password", cred->password);
+ cJSON_AddStringToObject(mqtt, "publish_topic", cred->publish_topic);
+ cJSON_AddStringToObject(mqtt, "subscribe_topic", cred->subscribe_topic);
+
+ cJSON_AddItemToObject(root, "mqtt", mqtt);
+
+ char *json_str = cJSON_Print(root);
+ if (json_str) {
+ fputs(json_str, fp);
+ cJSON_free(json_str);
+ }
+
+ cJSON_Delete(root);
+ fclose(fp);
+
+ printf("MQTT credentials saved successfully\n");
+ return 0;
+}
+
+/**
+ * @brief 从响应 JSON 中提取 MQTT 凭证
+ * @param response_json 服务器响应的 JSON 字符串
+ * @param credentials 输出的 MQTT 凭证结构体指针
+ * @return 0 成功,-1 失败
+ */
+static int extract_mqtt_credentials(const char *response_json, mqtt_credentials_t *credentials)
+{
+ if (!response_json || !credentials) {
+ printf("Invalid parameters for extract_mqtt_credentials\n");
+ return -1;
+ }
+
+ // 解析响应 JSON
+ cJSON *root = cJSON_Parse(response_json);
+ if (!root) {
+ printf("Failed to parse response JSON\n");
+ return -1;
+ }
+
+ // 提取 MQTT 凭证
+ cJSON *mqtt_obj = cJSON_GetObjectItem(root, "mqtt");
+ if (!mqtt_obj || !cJSON_IsObject(mqtt_obj)) {
+ printf("No 'mqtt' object found in response\n");
+ cJSON_Delete(root);
+ return -1;
+ }
+
+ // 初始化凭证结构体
+ memset(credentials, 0, sizeof(mqtt_credentials_t));
+
+ // 提取各个字段
+ cJSON *item = cJSON_GetObjectItem(mqtt_obj, "endpoint");
+ if (item && cJSON_IsString(item) && item->valuestring) {
+ strncpy(credentials->endpoint, item->valuestring, sizeof(credentials->endpoint) - 1);
+ credentials->endpoint[sizeof(credentials->endpoint) - 1] = '\0';
+ }
+
+ item = cJSON_GetObjectItem(mqtt_obj, "client_id");
+ if (item && cJSON_IsString(item) && item->valuestring) {
+ strncpy(credentials->client_id, item->valuestring, sizeof(credentials->client_id) - 1);
+ credentials->client_id[sizeof(credentials->client_id) - 1] = '\0';
+ }
+
+ item = cJSON_GetObjectItem(mqtt_obj, "username");
+ if (item && cJSON_IsString(item) && item->valuestring) {
+ strncpy(credentials->username, item->valuestring, sizeof(credentials->username) - 1);
+ credentials->username[sizeof(credentials->username) - 1] = '\0';
+ }
+
+ item = cJSON_GetObjectItem(mqtt_obj, "password");
+ if (item && cJSON_IsString(item) && item->valuestring) {
+ strncpy(credentials->password, item->valuestring, sizeof(credentials->password) - 1);
+ credentials->password[sizeof(credentials->password) - 1] = '\0';
+ }
+
+ item = cJSON_GetObjectItem(mqtt_obj, "publish_topic");
+ if (item && cJSON_IsString(item) && item->valuestring) {
+ strncpy(credentials->publish_topic, item->valuestring, sizeof(credentials->publish_topic) - 1);
+ credentials->publish_topic[sizeof(credentials->publish_topic) - 1] = '\0';
+ }
+
+ item = cJSON_GetObjectItem(mqtt_obj, "subscribe_topic");
+ if (item && cJSON_IsString(item) && item->valuestring) {
+ strncpy(credentials->subscribe_topic, item->valuestring, sizeof(credentials->subscribe_topic) - 1);
+ credentials->subscribe_topic[sizeof(credentials->subscribe_topic) - 1] = '\0';
+ }
+
+ cJSON_Delete(root);
+
+ printf("MQTT credentials extracted successfully\n");
+ return 0;
+}
+
+// 数据
+// {
+// "version": 3,
+// "application": {
+// "idf_version": "5.1.2",
+// "elf_sha256": "9e30c2135880f10c3b0d32ea4754a7d1afc6d53c8e7e63d4bf9d0029553db9bb"
+// },
+// "ota": {
+// "label": "ota_0"
+// },
+// "board": {
+// "type": "bread-compact-wifi",
+// "ip": "192.168.2.100",
+// "mac": "8c:85:90:65:53:8d"
+// }
+// }
+
+//回复
+
+// {
+// "mqtt": {
+// "endpoint": "192.168.2.200:1883",
+// "client_id": "GID_test@@@8c_85_90_65_53_8d@@@63a2c34b-fa85-4e4b-a289-7eb562e545ae",
+// "username": "eyJpcCI6IjE5Mi4xNjguMi4xMDAifQ==",
+// "password": "VMLUCd86BtIYg9kBRQ9b6K7HyFyP4vnqWf0giGClMK8=",
+// "publish_topic": "device-server",
+// "subscribe_topic": ""
+// },
+// "server_time": {
+// "timestamp": 1733760000000,
+// "timezone_offset": 480
+// },
+// "firmware": {
+// "version": "2.0.1",
+// "url": "https://example.com/firmware/2.0.1.bin"
+// },
+// "websocket": {
+// "url": "wss://api.example.com/ws",
+// "token": "xxx"
+// },
+// "activation": {
+// "code": "ABCD1234",
+// "message": "请在APP中输入激活码",
+// "challenge": "xxx",
+// "timeout_ms": 300000
+// }
+// }
+
+/**
+ * @brief 构建设备信息JSON并发送到服务器
+ * @param url 服务器URL(如果为NULL,使用默认URL: http://115.190.94.208:8085/api/v1/ota)
+ * @param credentials 输出的MQTT凭证(可以为NULL)
+ * @return 0 成功,-1 失败
+ *
+ * 根据以下格式构建设备信息JSON:
+ * {
+ * "version": 3,
+ * "application": {
+ * "idf_version": "5.1.2",
+ * "elf_sha256": "9e30c2135880f10c3b0d32ea4754a7d1afc6d53c8e7e63d4bf9d0029553db9bb"
+ * },
+ * "ota": {
+ * "label": "ota_0"
+ * },
+ * "board": {
+ * "type": "bread-compact-wifi",
+ * "ip": "192.168.2.100",
+ * "mac": "8c:85:90:65:53:8d"
+ * }
+ * }
+ */
+int ln_ota_send_device_info_json(const char *url, void *credentials)
+{
+ const char *default_url = "http://115.190.94.208:8085/api/v1/ota";
+ const char *target_url = url ? url : default_url;
+
+ // 构建设备信息JSON
+ cJSON *root = cJSON_CreateObject();
+ if (!root) {
+ printf("[LN_OTA] Failed to create JSON root object\n");
+ return -1;
+ }
+
+ // version
+ cJSON_AddNumberToObject(root, "version", 3);
+
+ // application
+ cJSON *application = cJSON_CreateObject();
+ if (!application) {
+ cJSON_Delete(root);
+ return -1;
+ }
+ cJSON_AddStringToObject(application, "idf_version", "5.1.2");
+ cJSON_AddStringToObject(application, "elf_sha256", "9e30c2135880f10c3b0d32ea4754a7d1afc6d53c8e7e63d4bf9d0029553db9bb");
+ cJSON_AddItemToObject(root, "application", application);
+
+ // ota
+ cJSON *ota = cJSON_CreateObject();
+ if (!ota) {
+ cJSON_Delete(root);
+ return -1;
+ }
+ cJSON_AddStringToObject(ota, "label", "ota_0");
+ cJSON_AddItemToObject(root, "ota", ota);
+
+ // board
+ cJSON *board = cJSON_CreateObject();
+ if (!board) {
+ cJSON_Delete(root);
+ return -1;
+ }
+
+ // 获取设备信息
+ const char *device_model = uapi_ln_get_device_model();
+ const char *board_type = device_model ? device_model : "bread-compact-wifi";
+ cJSON_AddStringToObject(board, "type", board_type);
+
+ // 获取IP地址
+ const char *ip_addr = NULL;//ppp_lwip_get_ip_address();
+ if (ip_addr && strcmp(ip_addr, "0.0.0.0") != 0) {
+ cJSON_AddStringToObject(board, "ip", ip_addr);
+ } else {
+ cJSON_AddStringToObject(board, "ip", "0.0.0.0");
+ }
+
+ // MAC地址 - 使用占位符,实际应从网络接口获取
+ cJSON_AddStringToObject(board, "mac", "00:00:00:00:00:00");
+
+ cJSON_AddItemToObject(root, "board", board);
+
+ // 转换为JSON字符串
+ char *json_str = cJSON_Print(root);
+ if (!json_str) {
+ printf("[LN_OTA] Failed to print JSON\n");
+ cJSON_Delete(root);
+ return -1;
+ }
+
+ printf("[LN_OTA] Device info JSON: %s\n", json_str);
+
+ // 调用发送函数
+ int ret = ln_ota_send_device_info(target_url, json_str, (mqtt_credentials_t *)credentials);
+
+ // 清理
+ free(json_str);
+ cJSON_Delete(root);
+
+ return ret;
+}
+
+/**
+ * @brief 发送设备信息到服务器并解析回复,保存 MQTT 凭证
+ * @param url 服务器 URL
+ * @param device_info_json 设备信息的 JSON 字符串(如果为 NULL,将使用默认结构)
+ * @param credentials 输出的 MQTT 凭证(可以为 NULL,如果只需要保存到文件)
+ * @return 0 成功,-1 失败
+ */
+int ln_ota_send_device_info(const char *url, const char *device_info_json, mqtt_credentials_t *credentials)
+{
+ HttpClient client = {0};
+ HttpClientData client_data = {0};
+ int ret = -1;
+
+ // 构建自定义请求头
+ char *header_buf = (char *)malloc(256);
+ if (!header_buf) {
+ printf("[LN_OTA] Failed to allocate header buffer\n");
+ return -1;
+ }
+
+ memset(header_buf, 0, 256);
+ int hdr = snprintf(header_buf, 256,
+ "Device-Id: %s\r\n",
+ "8c:85:90:65:53:8d");
+ if (hdr <= 0 || hdr >= 256) {
+ printf("[LN_OTA] Failed to build header\n");
+ free(header_buf);
+ return -1;
+ }
+
+ // 设置自定义头(只包含Device-Id,Content-Type通过postContentType设置)
+ HttpClientSetCustomHeader(&client, header_buf);
+
+ // 准备HTTP缓冲区(自动分配headerBuf和responseBuf)
+ HTTPC_RESULT prep = HttpClientPrepare(&client_data, 2048, 4096);
+ if (prep != HTTP_SUCCESS) {
+ printf("[LN_OTA] HttpClientPrepare failed: %d\n", prep);
+ free(header_buf);
+ return -1;
+ }
+
+ // 设置POST数据和Content-Type(放在Prepare之后,避免被重置)
+ client_data.postBuf = (char *)device_info_json;
+ client_data.postBufLen = strlen(device_info_json);
+ client_data.postContentType = "application/json";
+
+ printf("Sending POST request to: %s\n", url);
+ printf("POST data: %s\n", device_info_json);
+ printf("Custom header: %s\n", header_buf);
+
+ ret = HttpClientPostRequest(&client, url, &client_data);
+
+ if (ret == HTTP_SUCCESS && client.responseCode == 200) {
+ printf("HTTP request successful, response code: %d\n", client.responseCode);
+ printf("Response data: %s\n", client_data.responseBuf);
+
+ // 提取 MQTT 凭证
+ mqtt_credentials_t cred = {0};
+ if (extract_mqtt_credentials(client_data.responseBuf, &cred) == 0) {
+ // 保存凭证到文件
+ if (save_mqtt_credentials(&cred) == 0) {
+ printf("MQTT credentials saved:\n");
+ printf(" endpoint: %s\n", cred.endpoint);
+ printf(" client_id: %s\n", cred.client_id);
+ printf(" username: %s\n", cred.username);
+ printf(" password: %s\n", cred.password);
+ printf(" publish_topic: %s\n", cred.publish_topic);
+ printf(" subscribe_topic: %s\n", cred.subscribe_topic);
+
+ // 如果提供了输出参数,复制凭证
+ if (credentials) {
+ memcpy(credentials, &cred, sizeof(mqtt_credentials_t));
+ }
+
+ ret = 0;
+ } else {
+ printf("Failed to save MQTT credentials\n");
+ ret = -1;
+ }
+ } else {
+ printf("Failed to extract MQTT credentials from response\n");
+ ret = -1;
+ }
+ } else {
+ printf("HTTP request failed, response code: %d, error: %d\n", client.responseCode, ret);
+ if (client_data.responseBuf && client_data.responseBufLen > 0) {
+ printf("Response data: %s\n", client_data.responseBuf);
+ }
+ ret = -1;
+ }
+
+ // 清理资源
+ HttpClientUnprepare(&client_data);
+ free(header_buf);
+
+ return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
--- /dev/null
+/*
+ * Copyright (c) Zhihui Technologies Co., Ltd. 2025-2025. All rights reserved.
+ */
+
+#include "ln_mqtt_api.h"
+#include "ln_api.h"
+#include "custom_utils.h"
+#include "cmsis_os2.h"
+#include "soc_osal.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <errno.h>
+#include "lwip/sockets.h"
+#include "lwip/netdb.h"
+#include "lwip/inet.h"
+#include "mbedtls/cipher.h"
+#include "mbedtls/aes.h"
+#include <time.h>
+#include "opus_frame_to_pcm.h"
+#include "ai_media.h"
+
+/* 双流接口开关:定义 USE_DUAL_STREAM_INTERFACE 则使用 old_Start_AIVoice 双流接口,否则使用 MQTT_StartRecord */
+/* 可在 CMakeLists.txt 或编译选项中定义,例如:-DUSE_DUAL_STREAM_INTERFACE=1 */
+#ifndef USE_DUAL_STREAM_INTERFACE
+#define USE_DUAL_STREAM_INTERFACE 0
+#endif
+
+/* OGG 封装相关前向声明(不透明句柄,避免依赖 ogg.h) */
+/* OGG 上下文句柄(不透明指针,实际类型在 ai_media_service_mqtt.cpp 中定义) */
+typedef void* MqttOggContextHandle;
+
+/* OGG 封装接口声明(使用不透明句柄) */
+extern void* MqttOggGetContext(void);
+extern int32_t MqttOggEncapsulationInitHandle(MqttOggContextHandle oggCtxHandle, FILE *pfd, uint32_t sampleRate, uint32_t channelCount);
+extern int32_t MqttOggEncapsulationWriteHandle(MqttOggContextHandle oggCtxHandle, const uint8_t *buffer, uint32_t bufferLen, FILE *pfd, bool isEos);
+extern int32_t MqttOggEncapsulationFinishHandle(MqttOggContextHandle oggCtxHandle, FILE *pfd);
+
+/* MQTT 播放接口声明 */
+typedef void (*MqttPlayerCallback)(int32_t event, void* userData);
+extern int32_t MQTT_PlayAudioFile(const char* filePath, MqttPlayerCallback callback, void* userData);
+
+/* UDP接收缓冲区大小 */
+#define UDP_RECV_BUFFER_SIZE 4096
+
+/* UDP数据包头部大小 */
+#define UDP_PACKET_HEADER_SIZE 16 // 1+1+2+4+4+4 = 16 bytes
+
+/* UDP数据包结构体 */
+typedef struct {
+ uint8_t type; // 类型 (1 byte)
+ uint8_t flags; // 标志 (1 byte)
+ uint16_t payload_len; // 负载长度 (2 bytes, 网络字节序)
+ uint32_t ssrc; // SSRC (4 bytes, 网络字节序)
+ uint32_t timestamp; // 时间戳 (4 bytes, 网络字节序)
+ uint32_t sequence; // 序列号 (4 bytes, 网络字节序)
+ uint8_t *payload; // 加密负载数据指针
+ uint16_t payload_size; // 负载数据大小
+} ln_udp_packet_t;
+
+/* UDP套接字全局变量 */
+static int g_udp_socket = -1;
+static volatile bool g_udp_thread_running = false;
+static uint32_t g_udp_thread_handle = 0;
+
+/* UDP数据包序列号和SSRC管理 */
+static uint32_t g_udp_ssrc = 0; // SSRC标识
+static uint32_t g_udp_sequence = 0; // 序列号(自动递增)
+
+/* 音频数据发送队列和线程 */
+#define AUDIO_SEND_QUEUE_SIZE 32 // 队列大小
+
+/* OGG 封装相关全局变量 */
+#define OGG_PACKETS_PER_FILE 50 // 每50个数据包打包成一个文件
+#define OGG_PACKET_CACHE_SIZE 32 // 数据包缓存大小(用于处理乱序)
+#define OGG_OPUS_ENCODE_HEADER_SIZE 8 // Opus 编码头大小(前8字节)
+#define ENABLE_OPUS_RAW_DEBUG 1 // 启用 Opus 原始数据保存调试(1=启用,0=禁用)
+
+static MqttOggContextHandle g_ogg_ctx_handle = NULL; // OGG 上下文句柄(不透明指针)
+static FILE *g_ogg_file = NULL; // 当前 OGG 文件句柄
+static uint32_t g_ogg_packet_count = 0; // 当前文件的数据包计数
+static uint32_t g_ogg_file_index = 0; // 文件序号
+static bool g_ogg_initialized = false; // OGG 上下文是否已初始化
+static char g_completed_ogg_filename[128] = {0}; // 已完成的 OGG 文件名(用于播放)
+
+/* Opus 原始数据调试相关全局变量 */
+static FILE *g_opus_debug_file = NULL; // Opus 调试文件句柄
+static uint32_t g_opus_debug_packet_count = 0; // Opus 调试文件的数据包计数
+static uint32_t g_opus_debug_file_index = 0; // Opus 调试文件序号
+#define OPUS_DEBUG_PCM_BUF_SAMPLES 5760 // 单帧解码 PCM 缓冲(120ms@48kHz)
+static short g_opus_debug_pcm_buf[OPUS_DEBUG_PCM_BUF_SAMPLES];
+static FILE *g_opus_debug_pcm_file = NULL; // 解码 PCM 测试输出文件(追加)
+
+/* 数据包缓存结构(用于处理乱序接收) */
+typedef struct {
+ uint32_t sequence; // 序列号
+ uint8_t *data; // 数据指针(动态分配)
+ uint32_t data_size; // 数据大小
+ bool valid; // 是否有效
+} ogg_packet_cache_t;
+
+static ogg_packet_cache_t g_ogg_packet_cache[OGG_PACKET_CACHE_SIZE] = {0}; // 数据包缓存
+static uint32_t g_ogg_expected_sequence = 0; // 期望的下一个序列号(0表示未初始化)
+static uint32_t g_ogg_out_of_order_count = 0; // 连续错序计数器(用于检测丢包)
+#define OGG_MAX_OUT_OF_ORDER_COUNT 5 // 最大连续错序次数,超过后跳过一包
+#define AUDIO_SEND_MAX_DATA_SIZE 0x800 // 最大音频数据大小(与 LN_MQTT_RECORD_MAX_FRAME 一致)
+
+/* 音频数据消息结构体 */
+typedef struct {
+ uint8_t *data; // 音频数据指针(动态分配)
+ uint32_t size; // 数据大小
+} audio_send_msg_t;
+
+static unsigned long g_audio_send_queue = 0xFFFFFFFF; // 消息队列句柄
+static volatile bool g_audio_send_thread_running = false;
+static uint32_t g_audio_send_thread_handle = 0;
+
+/* 前向声明 */
+static void ln_udp_recv_thread(void *arg);
+static int ln_udp_process_received_data(const uint8_t *data, uint16_t data_len);
+int ln_udp_unpack_packet(const uint8_t *data, uint16_t data_len, ln_udp_packet_t *packet);
+void ln_udp_free_packet(ln_udp_packet_t *packet);
+void ln_udp_close_socket(void);
+int ln_udp_decrypt_audio(const char *key_hex, const char *base_nonce_hex,
+ uint16_t payload_len, uint32_t timestamp, uint32_t sequence,
+ const uint8_t *encrypted_data, uint16_t encrypted_len, uint8_t *decrypted_data);
+static void ln_udp_audio_send_thread(void *arg);
+static void create_audio_send_queue(void);
+/* OGG 封装相关函数声明 */
+static int ln_udp_ogg_handle_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size);
+static void ln_udp_ogg_cache_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size);
+static int ln_udp_ogg_write_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size);
+static void ln_udp_ogg_flush_cache(void);
+static void ln_udp_ogg_complete_current_file(void);
+static int ln_udp_ogg_create_new_file(void);
+
+#if USE_DUAL_STREAM_INTERFACE
+/* 双流接口相关函数声明 */
+static int ln_udp_dual_stream_handle_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size);
+static int ln_udp_dual_stream_decode_and_send(uint32_t sequence, const uint8_t *data, uint32_t data_size);
+static void ln_udp_dual_stream_flush_cache(void);
+#endif /* USE_DUAL_STREAM_INTERFACE */
+/* Opus 原始数据调试相关函数声明 */
+static int ln_udp_opus_debug_create_new_file(void);
+static void ln_udp_opus_debug_complete_current_file(void);
+static int ln_udp_opus_debug_write_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size);
+/* Opus 数据包解析函数声明 */
+static int ln_udp_parse_opus_packet(const uint8_t *data, uint32_t data_size,
+ const uint8_t **opus_data, uint32_t *opus_data_size);
+
+
+
+/**
+ * @brief 处理接收到的UDP数据(解包、解密)
+ * @param data 原始接收数据
+ * @param data_len 数据长度
+ * @return 0 成功,-1 失败
+ */
+static int ln_udp_process_received_data(const uint8_t *data, uint16_t data_len)
+{
+ ln_udp_packet_t packet;
+ memset(&packet, 0, sizeof(packet));
+
+ // 1. 解包数据包
+ if (ln_udp_unpack_packet(data, data_len, &packet) != 0) {
+ printf("[LN_UDP] Failed to unpack packet\n");
+ return -1;
+ }
+
+ printf("[LN_UDP] Packet unpacked: type=%d, flags=%d, ssrc=%u, timestamp=%u, sequence=%u, payload_len=%d\n",
+ packet.type, packet.flags, packet.ssrc, packet.timestamp, packet.sequence, packet.payload_len);
+
+ // 2. 获取UDP信息(用于解密)
+ ln_mqtt_udp_info_t udp_info;
+ if (ln_mqtt_api_get_udp_info(&udp_info) != 0 || !udp_info.valid) {
+ printf("[LN_UDP] UDP info not available for decryption\n");
+ ln_udp_free_packet(&packet);
+ return -1;
+ }
+
+ // 3. 解密负载数据
+ if (packet.payload_len > 0 && packet.payload) {
+ // 分配解密数据缓冲区
+ uint8_t *decrypted_data = (uint8_t *)malloc(packet.payload_len);
+ if (!decrypted_data) {
+ printf("[LN_UDP] Failed to allocate memory for decrypted data\n");
+ ln_udp_free_packet(&packet);
+ return -1;
+ }
+
+ // 执行解密(nonce在函数内部构造)
+ if (ln_udp_decrypt_audio(udp_info.key, udp_info.nonce, packet.payload_len,
+ packet.timestamp, packet.sequence,
+ packet.payload, packet.payload_len, decrypted_data) != 0) {
+ printf("[LN_UDP] Failed to decrypt payload data\n");
+ free(decrypted_data);
+ ln_udp_free_packet(&packet);
+ return -1;
+ }
+ printf("decrypted_data: ");
+
+ printf("\n");
+
+ printf("[LN_UDP] Payload decrypted successfully, size=%d bytes\n", packet.payload_len);
+
+ printf("packet.sequence: %u\n", packet.sequence);
+
+#if USE_DUAL_STREAM_INTERFACE
+ // 使用双流接口时,不进行 OGG 封装,但需要保持包顺序处理
+ // 注意:decrypted_data 的所有权会转移给处理函数,不需要在这里释放
+ if (ln_udp_dual_stream_handle_packet(packet.sequence, decrypted_data, packet.payload_len) != 0) {
+ printf("[LN_UDP] Failed to handle dual stream packet (sequence=%u)\n", packet.sequence);
+ free(decrypted_data); // 处理失败时才释放
+ }
+#else
+ // OGG 封装处理:使用独立函数处理,支持乱序数据包缓存和排序
+ // 注意:decrypted_data 的所有权会转移给处理函数,不需要在这里释放
+ if (ln_udp_ogg_handle_packet(packet.sequence, decrypted_data, packet.payload_len) != 0) {
+ printf("[LN_UDP] Failed to handle OGG packet (sequence=%u)\n", packet.sequence);
+ free(decrypted_data); // 处理失败时才释放
+ }
+#endif /* USE_DUAL_STREAM_INTERFACE */
+ } else {
+ printf("[LN_UDP] Packet has no payload data\n");
+ }
+
+ // 4. 释放数据包
+ ln_udp_free_packet(&packet);
+
+ return 0;
+}
+
+/**
+ * @brief 解包UDP数据包
+ * @param data 原始数据缓冲区
+ * @param data_len 数据长度
+ * @param packet 输出的数据包结构体指针(payload字段需要外部释放)
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_unpack_packet(const uint8_t *data, uint16_t data_len, ln_udp_packet_t *packet)
+{
+ if (!data || !packet || data_len < UDP_PACKET_HEADER_SIZE) {
+ printf("[LN_UDP] Invalid parameters or data too short for unpack\n");
+ return -1;
+ }
+
+ memset(packet, 0, sizeof(ln_udp_packet_t));
+
+ // 解析头部字段(网络字节序)
+ const uint8_t *ptr = data;
+ packet->type = ptr[0];
+ packet->flags = ptr[1];
+ packet->payload_len = lwip_ntohs(*(uint16_t *)(ptr + 2));
+ packet->ssrc = lwip_ntohl(*(uint32_t *)(ptr + 4));
+ packet->timestamp = lwip_ntohl(*(uint32_t *)(ptr + 8));
+ packet->sequence = lwip_ntohl(*(uint32_t *)(ptr + 12));
+
+ // 验证负载长度
+ uint16_t expected_len = UDP_PACKET_HEADER_SIZE + packet->payload_len;
+ if (data_len < expected_len) {
+ printf("[LN_UDP] Data length mismatch: expected %d, got %d\n", expected_len, data_len);
+ return -1;
+ }
+
+ // 分配并复制负载数据
+ if (packet->payload_len > 0) {
+ packet->payload = (uint8_t *)malloc(packet->payload_len);
+ if (!packet->payload) {
+ printf("[LN_UDP] Failed to allocate memory for payload\n");
+ return -1;
+ }
+ memcpy(packet->payload, ptr + UDP_PACKET_HEADER_SIZE, packet->payload_len);
+ packet->payload_size = packet->payload_len;
+ } else {
+ packet->payload = NULL;
+ packet->payload_size = 0;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief 封包UDP数据包
+ * @param packet 数据包结构体指针
+ * @param buffer 输出缓冲区指针(由调用者分配)
+ * @param buffer_size 缓冲区大小
+ * @param out_len 输出的实际数据长度
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_pack_packet(const ln_udp_packet_t *packet, uint8_t *buffer, uint16_t buffer_size, uint16_t *out_len)
+{
+ if (!packet || !buffer || !out_len) {
+ printf("[LN_UDP] Invalid parameters for pack\n");
+ return -1;
+ }
+
+ // 计算所需缓冲区大小
+ uint16_t total_len = UDP_PACKET_HEADER_SIZE + packet->payload_len;
+ if (buffer_size < total_len) {
+ printf("[LN_UDP] Buffer too small: need %d, have %d\n", total_len, buffer_size);
+ return -1;
+ }
+
+ // 打包头部字段(转换为网络字节序)
+ uint8_t *ptr = buffer;
+ ptr[0] = packet->type;
+ ptr[1] = packet->flags;
+ *(uint16_t *)(ptr + 2) = lwip_htons(packet->payload_len);
+ *(uint32_t *)(ptr + 4) = lwip_htonl(packet->ssrc);
+ *(uint32_t *)(ptr + 8) = lwip_htonl(packet->timestamp);
+ *(uint32_t *)(ptr + 12) = lwip_htonl(packet->sequence);
+
+ // 复制负载数据
+ if (packet->payload_len > 0 && packet->payload) {
+ memcpy(ptr + UDP_PACKET_HEADER_SIZE, packet->payload, packet->payload_len);
+ }
+
+ *out_len = total_len;
+ return 0;
+}
+
+/**
+ * @brief 释放数据包结构体的负载数据
+ * @param packet 数据包结构体指针
+ */
+void ln_udp_free_packet(ln_udp_packet_t *packet)
+{
+ if (packet && packet->payload) {
+ free(packet->payload);
+ packet->payload = NULL;
+ packet->payload_size = 0;
+ }
+}
+
+// ==================== OGG 封装处理函数(支持乱序数据包缓存和排序)====================
+
+/**
+ * @brief 清空数据包缓存
+ */
+static void ln_udp_ogg_clear_cache(void)
+{
+ for (int i = 0; i < OGG_PACKET_CACHE_SIZE; i++) {
+ if (g_ogg_packet_cache[i].valid && g_ogg_packet_cache[i].data != NULL) {
+ free(g_ogg_packet_cache[i].data);
+ g_ogg_packet_cache[i].data = NULL;
+ }
+ g_ogg_packet_cache[i].valid = false;
+ g_ogg_packet_cache[i].sequence = 0;
+ g_ogg_packet_cache[i].data_size = 0;
+ }
+}
+
+/**
+ * @brief 将数据包缓存(用于处理乱序接收)
+ * @param sequence 序列号
+ * @param data 数据指针(会被复制,调用者可以释放)
+ * @param data_size 数据大小
+ */
+static void ln_udp_ogg_cache_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size)
+{
+ // 查找空闲的缓存槽
+ int empty_slot = -1;
+ for (int i = 0; i < OGG_PACKET_CACHE_SIZE; i++) {
+ if (!g_ogg_packet_cache[i].valid) {
+ empty_slot = i;
+ break;
+ }
+ }
+
+ if (empty_slot < 0) {
+ printf("[LN_UDP] OGG cache full, dropping packet sequence=%u\n", sequence);
+ return;
+ }
+
+ // 分配内存并复制数据
+ uint8_t *cached_data = (uint8_t *)malloc(data_size);
+ if (cached_data == NULL) {
+ printf("[LN_UDP] Failed to allocate memory for cached packet sequence=%u\n", sequence);
+ return;
+ }
+
+ memcpy(cached_data, data, data_size);
+
+ // 保存到缓存
+ g_ogg_packet_cache[empty_slot].sequence = sequence;
+ g_ogg_packet_cache[empty_slot].data = cached_data;
+ g_ogg_packet_cache[empty_slot].data_size = data_size;
+ g_ogg_packet_cache[empty_slot].valid = true;
+
+ printf("[LN_UDP] Cached packet sequence=%u (slot=%d)\n", sequence, empty_slot);
+}
+
+/**
+ * @brief 创建新的 Opus 调试文件(直接保存 Opus 原始数据)
+ * @return 0 成功,-1 失败
+ */
+static int ln_udp_opus_debug_create_new_file(void)
+{
+#if ENABLE_OPUS_RAW_DEBUG
+ // 创建新文件(使用时间戳和序号命名)
+ time_t now = time(NULL);
+ struct tm *tm_info = localtime(&now);
+ char filename[128];
+ snprintf(filename, sizeof(filename), "/user/udp_opus_raw_%04d%02d%02d_%02d%02d%02d_%03u.opus",
+ tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
+ tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec, g_opus_debug_file_index);
+
+ g_opus_debug_file = fopen(filename, "wb");
+ if (g_opus_debug_file == NULL) {
+ printf("[LN_UDP] Failed to open Opus debug file: %s\n", filename);
+ return -1;
+ }
+
+ g_opus_debug_packet_count = 0;
+ g_opus_debug_file_index++;
+ printf("[LN_UDP] Created new Opus debug file: %s (index: %u)\n", filename, g_opus_debug_file_index - 1);
+
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+/**
+ * @brief 完成当前 Opus 调试文件
+ */
+static void ln_udp_opus_debug_complete_current_file(void)
+{
+#if ENABLE_OPUS_RAW_DEBUG
+ if (g_opus_debug_file == NULL) {
+ return;
+ }
+
+ fclose(g_opus_debug_file);
+ g_opus_debug_file = NULL;
+ g_opus_debug_packet_count = 0;
+ printf("[LN_UDP] Completed Opus debug file #%u\n", g_opus_debug_file_index - 1);
+#endif
+}
+
+/**
+ * @brief 解析 Opus 数据包,找到实际 Opus 编码数据的起始位置和大小
+ * @param data 完整的 Opus 数据包(包含 TOC 字节和可能的帧长度表)
+ * @param data_size 数据包总大小
+ * @param opus_data 输出的实际 Opus 数据起始指针
+ * @param opus_data_size 输出的实际 Opus 数据大小
+ * @return 0 成功,-1 失败
+ * @note 根据 RFC 6716 Opus 编码标准解析
+ */
+static int ln_udp_parse_opus_packet(const uint8_t *data, uint32_t data_size,
+ const uint8_t **opus_data, uint32_t *opus_data_size)
+{
+ if (!data || data_size == 0 || !opus_data || !opus_data_size) {
+ printf("[LN_UDP] Invalid parameters for Opus packet parsing\n");
+ return -1;
+ }
+
+ // 至少需要 TOC 字节
+ if (data_size < 1) {
+ printf("[LN_UDP] Opus packet too small (size=%u)\n", data_size);
+ return -1;
+ }
+
+ const uint8_t *ptr = data;
+ uint32_t remaining = data_size;
+
+ // 1. 读取 TOC 字节
+ uint8_t toc = ptr[0];
+ ptr++;
+ remaining--;
+
+ // 2. 解析帧计数编码(bit 3-7)
+ uint8_t frame_count_code = (toc >> 3) & 0x1F; // bit 3-7
+ uint8_t frame_count = 0;
+ uint32_t header_size = 1; // TOC 字节
+
+ // 3. 判断是单帧还是多帧
+ if (frame_count_code < 16) {
+ // 单帧:帧计数 = 编码值(0表示1帧,1-15表示对应帧数)
+ if (frame_count_code == 0) {
+ frame_count = 1; // 编码值0表示单帧
+ } else {
+ frame_count = frame_count_code;
+ }
+ } else {
+ // 多帧:需要读取帧计数字节
+ if (remaining < 1) {
+ printf("[LN_UDP] Opus packet too small for frame count byte\n");
+ return -1;
+ }
+ frame_count = frame_count_code - 16 + 1 + ptr[0];
+ ptr++;
+ remaining--;
+ header_size++;
+ }
+
+ // 4. 如果是多帧,需要读取帧长度表(但不跳过数据)
+ if (frame_count > 1) {
+ // 多帧数据包需要帧长度表
+ // 每个帧长度使用可变长度编码(1-2字节)
+ // 如果长度 < 252,使用1字节;否则使用2字节(0xFC + 实际长度)
+ // 注意:我们只读取长度值,不跳过帧数据,因为所有帧数据是连续存储的
+ for (uint8_t i = 0; i < frame_count - 1; i++) {
+ if (remaining < 1) {
+ printf("[LN_UDP] Opus packet too small for frame length table\n");
+ return -1;
+ }
+
+ if (ptr[0] < 252) {
+ // 1字节编码
+ ptr++;
+ remaining--;
+ header_size++;
+ } else {
+ // 2字节编码:0xFC + 实际长度(大端序)
+ if (remaining < 2) {
+ printf("[LN_UDP] Opus packet too small for 2-byte frame length\n");
+ return -1;
+ }
+ ptr += 2;
+ remaining -= 2;
+ header_size += 2;
+ }
+ }
+ }
+
+ // 5. 现在 header_size 包含了所有头部信息(TOC + 帧计数 + 帧长度表)
+ // 从 header_size 之后的所有数据都是 Opus 编码数据(包含所有帧的数据)
+ if (header_size >= data_size) {
+ printf("[LN_UDP] Opus header size (%u) >= total size (%u)\n", header_size, data_size);
+ return -1;
+ }
+
+ *opus_data = data + header_size;
+ *opus_data_size = data_size - header_size;
+
+ printf("[LN_UDP] Opus parsed: frame_count=%d, header_size=%u, opus_data_size=%u\n",
+ frame_count, header_size, *opus_data_size);
+
+ return 0;
+}
+
+/**
+ * @brief 写入 Opus 原始数据到调试文件(不进行 OGG 封装)
+ * @param sequence 序列号
+ * @param data 数据指针(包含 Opus TOC 字节和可能的帧长度表)
+ * @param data_size 数据大小
+ * @return 0 成功,-1 失败
+ */
+static int ln_udp_opus_debug_write_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size)
+{
+#if ENABLE_OPUS_RAW_DEBUG
+ // 检查是否需要创建新文件
+ if (g_opus_debug_file == NULL || g_opus_debug_packet_count >= OGG_PACKETS_PER_FILE) {
+ // 完成当前文件
+ if (g_opus_debug_file != NULL) {
+ ln_udp_opus_debug_complete_current_file();
+ }
+
+ // 创建新文件
+ if (ln_udp_opus_debug_create_new_file() != 0) {
+ return -1;
+ }
+ }
+ printf("opus debug data: ");
+ for (int i = 0; i < data_size; i++) {
+ printf("%02X ", data[i]);
+ }
+ printf("\n");
+
+ // 解析 Opus 数据包(用于验证和日志输出,但不影响保存)
+ const uint8_t *opus_data = NULL;
+ uint32_t opus_data_size = 0;
+ int parse_ret = ln_udp_parse_opus_packet(data, data_size, &opus_data, &opus_data_size);
+ if (parse_ret == 0) {
+ printf("[LN_UDP] Opus debug: Parsed packet sequence=%u, total_size=%u, opus_data_size=%u\n",
+ sequence, data_size, opus_data_size);
+ } else {
+ printf("[LN_UDP] Opus debug: Parse warning (sequence=%u, size=%u), but saving raw data anyway\n",
+ sequence, data_size);
+ }
+
+ /* 调用 opus 解码接口测试:完整包 data/data_size 送入解码 */
+ {
+ int pcm_samples = 0;
+ int dec_ret = opus_frame_to_pcm_decode_packet(
+ data, (int)data_size,
+ 16000, 1,
+ g_opus_debug_pcm_buf, OPUS_DEBUG_PCM_BUF_SAMPLES,
+ &pcm_samples);
+ if (dec_ret == 0) {
+ printf("[LN_UDP] Opus decode test OK sequence=%u pcm_samples=%d\n", sequence, pcm_samples);
+ if (g_opus_debug_pcm_file == NULL) {
+ g_opus_debug_pcm_file = fopen("user/udp_opus_debug.pcm", "ab");
+ if (g_opus_debug_pcm_file != NULL) {
+ printf("[LN_UDP] Opus decode PCM output: udp_opus_debug.pcm (append)\n");
+ }
+ }
+ if (g_opus_debug_pcm_file != NULL && pcm_samples > 0) {
+ size_t n = fwrite(g_opus_debug_pcm_buf, sizeof(short), (size_t)pcm_samples, g_opus_debug_pcm_file);
+ if (n != (size_t)pcm_samples) {
+ printf("[LN_UDP] Opus decode PCM write short: %zu/%d\n", n, pcm_samples);
+ }
+ fflush(g_opus_debug_pcm_file);
+ }
+ fclose(g_opus_debug_pcm_file);
+ g_opus_debug_pcm_file = NULL;
+ } else {
+ printf("[LN_UDP] Opus decode test FAIL sequence=%u\n", sequence);
+ }
+ }
+
+ // 保存完整的原始数据(包含 TOC 字节和帧长度表)
+ size_t written = fwrite(data, 1, data_size, g_opus_debug_file);
+ if (written != data_size) {
+ printf("[LN_UDP] Opus debug: Failed to write data (sequence=%u, written=%zu, expected=%u)\n",
+ sequence, written, data_size);
+ return -1;
+ }
+
+ fflush(g_opus_debug_file); // 立即刷新到文件
+
+ g_opus_debug_packet_count++;
+ printf("[LN_UDP] Opus debug: Written packet sequence=%u (%u/%u, raw_size=%u bytes)\n",
+ sequence, g_opus_debug_packet_count, OGG_PACKETS_PER_FILE, data_size);
+
+ return 0;
+#else
+ return 0; // 未启用时直接返回成功
+#endif
+}
+
+/**
+ * @brief 写入数据包到 OGG 文件
+ * @param sequence 序列号
+ * @param data 数据指针
+ * @param data_size 数据大小
+ * @return 0 成功,-1 失败
+ */
+static int ln_udp_ogg_write_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size)
+{
+ // 调试模式:同时保存 Opus 原始数据
+#if ENABLE_OPUS_RAW_DEBUG
+ ln_udp_opus_debug_write_packet(sequence, data, data_size);
+#endif
+
+ // 检查是否需要创建新文件
+ if (!g_ogg_initialized || g_ogg_packet_count >= OGG_PACKETS_PER_FILE) {
+ // 完成当前文件
+ if (g_ogg_initialized) {
+ ln_udp_ogg_complete_current_file();
+ }
+
+ // 创建新文件
+ if (ln_udp_ogg_create_new_file() != 0) {
+ return -1;
+ }
+ }
+
+ // 写入数据包
+ if (g_ogg_ctx_handle == NULL) {
+ printf("[LN_UDP] OGG context handle is null\n");
+ return -1;
+ }
+ if (MqttOggEncapsulationWriteHandle(g_ogg_ctx_handle, data, data_size, g_ogg_file, false) != 0) {
+ printf("[LN_UDP] Failed to write OGG data (sequence=%u)\n", sequence);
+ return -1;
+ }
+
+ g_ogg_packet_count++;
+ printf("[LN_UDP] Written packet sequence=%u (%u/%u to OGG file)\n",
+ sequence, g_ogg_packet_count, OGG_PACKETS_PER_FILE);
+
+ return 0;
+}
+
+/**
+ * @brief 刷新缓存:尝试按顺序写入缓存中的数据包
+ */
+static void ln_udp_ogg_flush_cache(void)
+{
+ bool found = true;
+ while (found) {
+ found = false;
+ // 查找期望的下一个序列号
+ for (int i = 0; i < OGG_PACKET_CACHE_SIZE; i++) {
+ if (g_ogg_packet_cache[i].valid &&
+ g_ogg_packet_cache[i].sequence == g_ogg_expected_sequence) {
+ // 找到期望的包,写入
+ if (ln_udp_ogg_write_packet(g_ogg_packet_cache[i].sequence,
+ g_ogg_packet_cache[i].data,
+ g_ogg_packet_cache[i].data_size) == 0) {
+ // 更新期望的序列号
+ g_ogg_expected_sequence++;
+ // 释放缓存
+ free(g_ogg_packet_cache[i].data);
+ g_ogg_packet_cache[i].data = NULL;
+ g_ogg_packet_cache[i].valid = false;
+ g_ogg_packet_cache[i].sequence = 0;
+ g_ogg_packet_cache[i].data_size = 0;
+ found = true;
+ printf("[LN_UDP] Flushed cached packet sequence=%u\n",
+ g_ogg_expected_sequence - 1);
+ break; // 重新开始查找
+ } else {
+ // 写入失败,保留在缓存中
+ break;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * @brief 完成当前 OGG 文件并播放
+ */
+static void ln_udp_ogg_complete_current_file(void)
+{
+ if (!g_ogg_initialized || g_ogg_file == NULL) {
+ return;
+ }
+
+ // 写入结束标志并完成封装
+ if (g_ogg_ctx_handle != NULL) {
+ uint8_t empty_data[8] = {0}; // 至少需要8字节的编码头
+ MqttOggEncapsulationWriteHandle(g_ogg_ctx_handle, empty_data, 8, g_ogg_file, true);
+ MqttOggEncapsulationFinishHandle(g_ogg_ctx_handle, g_ogg_file);
+ }
+ fclose(g_ogg_file);
+ g_ogg_file = NULL;
+ g_ogg_initialized = false;
+
+ printf("[LN_UDP] Completed OGG file #%u with %u packets: %s\n",
+ g_ogg_file_index - 1, g_ogg_packet_count, g_completed_ogg_filename);
+
+ // 使用 MQTT 播放接口播放完成的文件
+ if (g_completed_ogg_filename[0] != '\0') {
+ int32_t play_ret = MQTT_PlayAudioFile(g_completed_ogg_filename, NULL, NULL);
+ if (play_ret == 0) {
+ printf("[LN_UDP] Started playing OGG file: %s\n", g_completed_ogg_filename);
+ } else {
+ printf("[LN_UDP] Failed to play OGG file: %s (ret=%d)\n",
+ g_completed_ogg_filename, play_ret);
+ }
+ g_completed_ogg_filename[0] = '\0';
+ }
+}
+
+/**
+ * @brief 创建新的 OGG 文件
+ * @return 0 成功,-1 失败
+ */
+static int ln_udp_ogg_create_new_file(void)
+{
+ // 创建新文件(使用时间戳和序号命名)
+ time_t now = time(NULL);
+ struct tm *tm_info = localtime(&now);
+ char filename[128];
+ snprintf(filename, sizeof(filename), "/user/udp_audio_%04d%02d%02d_%02d%02d%02d_%03u.ogg",
+ tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
+ tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec, g_ogg_file_index);
+
+ // 保存文件名(用于后续播放)
+ strncpy(g_completed_ogg_filename, filename, sizeof(g_completed_ogg_filename) - 1);
+ g_completed_ogg_filename[sizeof(g_completed_ogg_filename) - 1] = '\0';
+
+ g_ogg_file = fopen(filename, "wb");
+ if (g_ogg_file == NULL) {
+ printf("[LN_UDP] Failed to open OGG file: %s\n", filename);
+ g_completed_ogg_filename[0] = '\0';
+ return -1;
+ }
+
+ // 获取 OGG 上下文句柄(如果尚未获取)
+ if (g_ogg_ctx_handle == NULL) {
+ g_ogg_ctx_handle = MqttOggGetContext();
+ if (g_ogg_ctx_handle == NULL) {
+ printf("[LN_UDP] Failed to get OGG context handle\n");
+ fclose(g_ogg_file);
+ g_ogg_file = NULL;
+ g_completed_ogg_filename[0] = '\0';
+ return -1;
+ }
+ }
+
+ // 初始化 OGG 上下文
+ if (MqttOggEncapsulationInitHandle(g_ogg_ctx_handle, g_ogg_file, 16000, 1) != 0) {
+ printf("[LN_UDP] Failed to initialize OGG context\n");
+ fclose(g_ogg_file);
+ g_ogg_file = NULL;
+ g_completed_ogg_filename[0] = '\0';
+ return -1;
+ }
+
+ g_ogg_initialized = true;
+ g_ogg_packet_count = 0;
+ g_ogg_file_index++;
+ printf("[LN_UDP] Created new OGG file: %s (index: %u)\n", filename, g_ogg_file_index - 1);
+
+ return 0;
+}
+
+/**
+ * @brief 处理 OGG 数据包(支持乱序接收和缓存)
+ * @param sequence 数据包序列号
+ * @param data 解密后的数据(所有权转移,函数内部负责释放)
+ * @param data_size 数据大小
+ * @return 0 成功,-1 失败
+ * @note 此函数会接管 data 的所有权,调用者不应再释放 data
+ */
+static int ln_udp_ogg_handle_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size)
+{
+ // 初始化期望序列号(首次接收)
+ if (g_ogg_expected_sequence == 0) {
+ g_ogg_expected_sequence = sequence;
+ g_ogg_out_of_order_count = 0; // 重置错序计数器
+ printf("[LN_UDP] Initialized expected sequence to %u\n", sequence);
+ }
+
+ // 检查是否是期望的下一个包
+ if (sequence == g_ogg_expected_sequence) {
+ // 是期望的包,直接写入
+ if (ln_udp_ogg_write_packet(sequence, data, data_size) == 0) {
+ g_ogg_expected_sequence++;
+ g_ogg_out_of_order_count = 0; // 重置错序计数器(收到期望的包)
+ free((void *)data); // 释放数据(所有权已转移)
+
+ // 尝试刷新缓存中的后续包
+ ln_udp_ogg_flush_cache();
+ return 0;
+ } else {
+ // 写入失败,缓存这个包
+ ln_udp_ogg_cache_packet(sequence, data, data_size);
+ free((void *)data);
+ return -1;
+ }
+ } else if (sequence > g_ogg_expected_sequence) {
+ // 是未来的包,缓存起来
+ g_ogg_out_of_order_count++; // 增加错序计数器
+ printf("[LN_UDP] Received future packet sequence=%u (expected=%u), caching (out_of_order_count=%u)\n",
+ sequence, g_ogg_expected_sequence, g_ogg_out_of_order_count);
+
+ // 如果连续错序超过阈值,跳过期望的序列号(避免丢包时一直无法正常输出)
+ if (g_ogg_out_of_order_count > OGG_MAX_OUT_OF_ORDER_COUNT) {
+ uint32_t old_expected = g_ogg_expected_sequence;
+ printf("[LN_UDP] Out of order count exceeded %d, skipping sequence %u\n",
+ OGG_MAX_OUT_OF_ORDER_COUNT, g_ogg_expected_sequence);
+
+ // 1. 先将期望序号往后加一(跳过丢失的包)
+ g_ogg_expected_sequence++;
+ g_ogg_out_of_order_count = 0; // 重置计数器
+
+ // 2. 处理缓存中的包(尝试写入缓存中所有能写入的连续包)
+ ln_udp_ogg_flush_cache();
+
+ // 3. 再尝试写入当前包
+ if (sequence == g_ogg_expected_sequence) {
+ // 当前包正好是期望的包,直接写入
+ if (ln_udp_ogg_write_packet(sequence, data, data_size) == 0) {
+ g_ogg_expected_sequence++;
+ free((void *)data);
+ // 继续刷新缓存中的后续包
+ ln_udp_ogg_flush_cache();
+ printf("[LN_UDP] Successfully wrote skipped packet sequence=%u (old_expected=%u)\n",
+ sequence, old_expected);
+ return 0;
+ } else {
+ // 写入失败,缓存这个包
+ ln_udp_ogg_cache_packet(sequence, data, data_size);
+ free((void *)data);
+ return -1;
+ }
+ } else if (sequence > g_ogg_expected_sequence) {
+ // 当前包仍然是未来的包,缓存起来
+ printf("[LN_UDP] Current packet sequence=%u still ahead of expected=%u after skip, caching\n",
+ sequence, g_ogg_expected_sequence);
+ ln_udp_ogg_cache_packet(sequence, data, data_size);
+ free((void *)data);
+ return 0;
+ } else {
+ // 当前包已经是过去的包(在刷新缓存时已处理),丢弃
+ printf("[LN_UDP] Current packet sequence=%u is now old (expected=%u), dropping\n",
+ sequence, g_ogg_expected_sequence);
+ free((void *)data);
+ return 0;
+ }
+ } else {
+ // 正常缓存未来包
+ ln_udp_ogg_cache_packet(sequence, data, data_size);
+ free((void *)data);
+ return 0;
+ }
+ } else {
+ // 是过去的包(重复或乱序),丢弃
+ printf("[LN_UDP] Received old/duplicate packet sequence=%u (expected=%u), dropping\n",
+ sequence, g_ogg_expected_sequence);
+ free((void *)data);
+ return 0;
+ }
+}
+
+#if USE_DUAL_STREAM_INTERFACE
+// ==================== 双流接口处理函数(支持乱序数据包缓存和排序)====================
+
+/**
+ * @brief 解码 Opus 数据包并送入 AI_SendAudioDataToQueue
+ * @param sequence 序列号
+ * @param data 数据指针
+ * @param data_size 数据大小
+ * @return 0 成功,-1 失败
+ */
+static int ln_udp_dual_stream_decode_and_send(uint32_t sequence, const uint8_t *data, uint32_t data_size)
+{
+ int pcm_samples = 0;
+ int dec_ret = opus_frame_to_pcm_decode_packet(
+ data, (int)data_size,
+ 16000, 1,
+ g_opus_debug_pcm_buf, OPUS_DEBUG_PCM_BUF_SAMPLES,
+ &pcm_samples);
+
+ if (dec_ret == 0 && pcm_samples > 0) {
+ // 解码成功,将 PCM 数据送入 AI_SendAudioDataToQueue
+ uint32_t pcm_data_size = (uint32_t)(pcm_samples * sizeof(short));
+ int32_t send_ret = AI_SendAudioDataToQueue((const uint8_t *)g_opus_debug_pcm_buf, pcm_data_size);
+ if (send_ret == 0) {
+ printf("[LN_UDP] Dual stream: Decoded and sent to queue: sequence=%u, pcm_samples=%d\n",
+ sequence, pcm_samples);
+ return 0;
+ } else {
+ printf("[LN_UDP] Dual stream: Failed to send decoded PCM to queue: sequence=%u, ret=%d\n",
+ sequence, (int)send_ret);
+ return -1;
+ }
+ } else {
+ printf("[LN_UDP] Dual stream: Opus decode failed: sequence=%u, ret=%d\n",
+ sequence, dec_ret);
+ return -1;
+ }
+}
+
+/**
+ * @brief 刷新双流数据包缓存(按顺序处理缓存中的包)
+ */
+static void ln_udp_dual_stream_flush_cache(void)
+{
+ bool found = true;
+ while (found) {
+ found = false;
+ // 查找期望序列号的包
+ for (int i = 0; i < OGG_PACKET_CACHE_SIZE; i++) {
+ if (g_ogg_packet_cache[i].valid &&
+ g_ogg_packet_cache[i].sequence == g_ogg_expected_sequence) {
+ // 找到期望的包,解码并发送
+ if (ln_udp_dual_stream_decode_and_send(g_ogg_packet_cache[i].sequence,
+ g_ogg_packet_cache[i].data,
+ g_ogg_packet_cache[i].data_size) == 0) {
+ g_ogg_expected_sequence++;
+ // 释放缓存数据
+ free(g_ogg_packet_cache[i].data);
+ g_ogg_packet_cache[i].data = NULL;
+ g_ogg_packet_cache[i].valid = false;
+ g_ogg_packet_cache[i].sequence = 0;
+ g_ogg_packet_cache[i].data_size = 0;
+ found = true; // 继续查找下一个期望的包
+ printf("[LN_UDP] Dual stream: Flushed cached packet sequence=%u\n",
+ g_ogg_expected_sequence - 1);
+ break; // 重新开始查找
+ } else {
+ // 解码失败,停止刷新
+ found = false;
+ break;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * @brief 处理双流数据包(支持乱序接收和缓存)
+ * @param sequence 数据包序列号
+ * @param data 解密后的数据(所有权转移,函数内部负责释放)
+ * @param data_size 数据大小
+ * @return 0 成功,-1 失败
+ * @note 此函数会接管 data 的所有权,调用者不应再释放 data
+ */
+static int ln_udp_dual_stream_handle_packet(uint32_t sequence, const uint8_t *data, uint32_t data_size)
+{
+ // 初始化期望序列号(首次接收)
+ if (g_ogg_expected_sequence == 0) {
+ g_ogg_expected_sequence = sequence;
+ g_ogg_out_of_order_count = 0; // 重置错序计数器
+ printf("[LN_UDP] Dual stream: Initialized expected sequence to %u\n", sequence);
+ }
+
+ // 检查是否是期望的下一个包
+ if (sequence == g_ogg_expected_sequence) {
+ // 是期望的包,直接解码并发送
+ if (ln_udp_dual_stream_decode_and_send(sequence, data, data_size) == 0) {
+ g_ogg_expected_sequence++;
+ g_ogg_out_of_order_count = 0; // 重置错序计数器(收到期望的包)
+ free((void *)data); // 释放数据(所有权已转移)
+
+ // 尝试刷新缓存中的后续包
+ ln_udp_dual_stream_flush_cache();
+ return 0;
+ } else {
+ // 解码失败,缓存这个包
+ ln_udp_ogg_cache_packet(sequence, data, data_size);
+ free((void *)data);
+ return -1;
+ }
+ } else if (sequence > g_ogg_expected_sequence) {
+ // 是未来的包,缓存起来
+ g_ogg_out_of_order_count++; // 增加错序计数器
+ printf("[LN_UDP] Dual stream: Received future packet sequence=%u (expected=%u), caching (out_of_order_count=%u)\n",
+ sequence, g_ogg_expected_sequence, g_ogg_out_of_order_count);
+
+ // 如果连续错序超过阈值,跳过期望的序列号(避免丢包时一直无法正常输出)
+ if (g_ogg_out_of_order_count > OGG_MAX_OUT_OF_ORDER_COUNT) {
+ uint32_t old_expected = g_ogg_expected_sequence;
+ printf("[LN_UDP] Dual stream: Out of order count exceeded %d, skipping sequence %u\n",
+ OGG_MAX_OUT_OF_ORDER_COUNT, g_ogg_expected_sequence);
+
+ // 1. 先将期望序号往后加一(跳过丢失的包)
+ g_ogg_expected_sequence++;
+ g_ogg_out_of_order_count = 0; // 重置计数器
+
+ // 2. 处理缓存中的包(尝试解码并发送缓存中所有能处理的连续包)
+ ln_udp_dual_stream_flush_cache();
+
+ // 3. 再尝试处理当前包
+ if (sequence == g_ogg_expected_sequence) {
+ // 当前包正好是期望的包,直接解码并发送
+ if (ln_udp_dual_stream_decode_and_send(sequence, data, data_size) == 0) {
+ g_ogg_expected_sequence++;
+ free((void *)data);
+ // 继续刷新缓存中的后续包
+ ln_udp_dual_stream_flush_cache();
+ printf("[LN_UDP] Dual stream: Successfully decoded and sent skipped packet sequence=%u (old_expected=%u)\n",
+ sequence, old_expected);
+ return 0;
+ } else {
+ // 解码失败,缓存这个包
+ ln_udp_ogg_cache_packet(sequence, data, data_size);
+ free((void *)data);
+ return -1;
+ }
+ } else if (sequence > g_ogg_expected_sequence) {
+ // 当前包仍然是未来的包,缓存起来
+ printf("[LN_UDP] Dual stream: Current packet sequence=%u still ahead of expected=%u after skip, caching\n",
+ sequence, g_ogg_expected_sequence);
+ ln_udp_ogg_cache_packet(sequence, data, data_size);
+ free((void *)data);
+ return 0;
+ } else {
+ // 当前包已经是过去的包(在刷新缓存时已处理),丢弃
+ printf("[LN_UDP] Dual stream: Current packet sequence=%u is now old (expected=%u), dropping\n",
+ sequence, g_ogg_expected_sequence);
+ free((void *)data);
+ return 0;
+ }
+ } else {
+ // 正常缓存未来包
+ ln_udp_ogg_cache_packet(sequence, data, data_size);
+ free((void *)data);
+ return 0;
+ }
+ } else {
+ // 是过去的包(重复或乱序),丢弃
+ printf("[LN_UDP] Dual stream: Received old/duplicate packet sequence=%u (expected=%u), dropping\n",
+ sequence, g_ogg_expected_sequence);
+ free((void *)data);
+ return 0;
+ }
+}
+#endif /* USE_DUAL_STREAM_INTERFACE */
+
+/**
+ * @brief UDP接收线程
+ */
+static void ln_udp_recv_thread(void *arg)
+{
+ (void)arg;
+ uint8_t recv_buffer[UDP_RECV_BUFFER_SIZE];
+ struct sockaddr_in server_addr;
+ socklen_t addr_len = sizeof(server_addr);
+
+ printf("[LN_UDP] Receive thread started\n");
+
+ // 获取服务器地址信息
+ ln_mqtt_udp_info_t udp_info;
+ if (ln_mqtt_api_get_udp_info(&udp_info) != 0 || !udp_info.valid) {
+ printf("[LN_UDP] UDP info not available in receive thread\n");
+ g_udp_thread_running = false;
+ return;
+ }
+
+ // 设置服务器地址
+ memset(&server_addr, 0, sizeof(server_addr));
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = lwip_htons(udp_info.port);
+ server_addr.sin_addr.s_addr = inet_addr(udp_info.server);
+
+
+ // printf("[LN_UDP] Ready to receive UDP packets from %s:%d\n", udp_info.server, udp_info.port);
+
+ while (g_udp_thread_running && g_udp_socket >= 0) {
+ // 接收UDP数据(阻塞,超时1秒)
+ fd_set read_fds;
+ struct timeval timeout;
+
+ FD_ZERO(&read_fds);
+ FD_SET(g_udp_socket, &read_fds);
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ int select_ret = lwip_select(g_udp_socket + 1, &read_fds, NULL, NULL, &timeout);
+ if (select_ret > 0 && FD_ISSET(g_udp_socket, &read_fds)) {
+ // 有数据可读
+ ssize_t recv_len = lwip_recvfrom(g_udp_socket, recv_buffer, sizeof(recv_buffer) - 1, 0,
+ (struct sockaddr *)&server_addr, &addr_len);
+
+ if (recv_len > 0) {
+ printf("[LN_UDP] Received %d bytes\r\n",
+ (int)recv_len
+ );
+
+ // 处理接收到的数据(解包、解密)
+ ln_udp_process_received_data(recv_buffer, (uint16_t)recv_len);
+
+ } else if (recv_len == 0) {
+ printf("[LN_UDP] Connection closed by peer\n");
+ break;
+ } else {
+ if (errno != EAGAIN && errno != EWOULDBLOCK) {
+ printf("[LN_UDP] Recvfrom error: %s\n", strerror(errno));
+ }
+ }
+ } else if (select_ret < 0) {
+ if (errno != EINTR) {
+ printf("[LN_UDP] Select error: %s\n", strerror(errno));
+ break;
+ }
+ }
+ // select_ret == 0 表示超时,继续循环
+ }
+
+ printf("[LN_UDP] Receive thread exited\n");
+ g_udp_thread_running = false;
+}
+
+/**
+ * @brief 创建UDP套接字
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_create_socket(void)
+{
+ // 获取UDP信息
+ ln_mqtt_udp_info_t udp_info;
+ if (ln_mqtt_api_get_udp_info(&udp_info) != 0) {
+ printf("[LN_UDP] UDP info not available, cannot create socket\n");
+ return -1;
+ }
+
+ if (!udp_info.valid) {
+ printf("[LN_UDP] UDP info invalid, cannot create socket\n");
+ return -1;
+ }
+
+ printf("[LN_UDP] Creating UDP socket for server: %s:%d\n", udp_info.server, udp_info.port);
+
+ // 如果socket已存在,先关闭
+ if (g_udp_socket >= 0) {
+ printf("[LN_UDP] Closing existing UDP socket\n");
+ ln_udp_close_socket();
+ }
+
+ // 创建UDP套接字
+ g_udp_socket = lwip_socket(AF_INET, SOCK_DGRAM, 0);
+ if (g_udp_socket < 0) {
+ printf("[LN_UDP] Failed to create UDP socket: %s\n", strerror(errno));
+ return -1;
+ }
+
+ // 设置socket选项(允许地址重用)
+ int opt = 1;
+ lwip_setsockopt(g_udp_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+
+ // 设置为非阻塞模式(可选,用于select超时)
+ // int flags = lwip_fcntl(g_udp_socket, F_GETFL, 0);
+ // lwip_fcntl(g_udp_socket, F_SETFL, flags | O_NONBLOCK);
+
+ printf("[LN_UDP] UDP socket created successfully, fd=%d\n", g_udp_socket);
+
+ // 创建接收线程
+ if (!g_udp_thread_running) {
+ app_task_definition_ext_t recv_task = {
+ .attr = {
+ .name = "ln_udp_recv",
+ .stack_size = 0x8000,
+ .priority = osPriorityNormal
+ },
+ .func = ln_udp_recv_thread,
+ .task_handle = &g_udp_thread_handle,
+ .create_queue_handle = NULL,
+ .use_mem = USE_EXTEND_MEM,
+ .inst_args = NULL
+ };
+
+ g_udp_thread_running = true;
+ errcode_t ret = uapi_create_osThread_custom_with_args(&recv_task);
+ if (ret != ERRCODE_SUCC) {
+ printf("[LN_UDP] ERROR: Failed to create receive thread: %d\n", ret);
+ g_udp_thread_running = false;
+ lwip_close(g_udp_socket);
+ g_udp_socket = -1;
+ return -1;
+ }
+ printf("[LN_UDP] Receive thread created successfully\n");
+ }
+
+ return 0;
+}
+
+/**
+ * @brief 关闭UDP套接字
+ */
+void ln_udp_close_socket(void)
+{
+ // 完成并关闭 OGG 文件
+ if (g_ogg_initialized) {
+ ln_udp_ogg_complete_current_file();
+ }
+
+ // 完成并关闭 Opus 调试文件
+#if ENABLE_OPUS_RAW_DEBUG
+ if (g_opus_debug_file != NULL) {
+ ln_udp_opus_debug_complete_current_file();
+ }
+#endif
+
+ // 停止接收线程
+ if (g_udp_thread_running) {
+ printf("[LN_UDP] Stopping receive thread\n");
+ g_udp_thread_running = false;
+
+ // 等待线程退出(最多等待2秒)
+ uint32_t timeout = osKernelGetTickCount() + osKernelGetTickFreq() * 2;
+ while (g_udp_thread_handle != 0 && osKernelGetTickCount() < timeout) {
+ osDelay(10);
+ }
+
+ if (g_udp_thread_handle != 0) {
+ printf("[LN_UDP] WARNING: Receive thread did not exit in time\n");
+ }
+
+ g_udp_thread_handle = 0;
+ }
+
+ // 关闭套接字
+ if (g_udp_socket >= 0) {
+ printf("[LN_UDP] Closing UDP socket, fd=%d\n", g_udp_socket);
+ lwip_close(g_udp_socket);
+ g_udp_socket = -1;
+ }
+}
+
+/**
+ * @brief 获取UDP套接字文件描述符
+ * @return socket文件描述符,-1表示未创建
+ */
+int ln_udp_get_socket(void)
+{
+ return g_udp_socket;
+}
+
+/**
+ * @brief 检查UDP套接字是否已创建
+ * @return true 已创建,false 未创建
+ */
+bool ln_udp_is_socket_created(void)
+{
+ return (g_udp_socket >= 0);
+}
+
+// +------+-------+-------------+----------+------------+----------+-------------------+
+// | Type | Flags | Payload Len | SSRC | Timestamp | Sequence | Encrypted Payload |
+// +------+-------+-------------+----------+------------+----------+-------------------+
+// |1 byte|1 byte | 2 bytes | 4 bytes | 4 bytes | 4 bytes | N bytes |
+// +------+-------+-------------+----------+------------+----------+-------------------+
+
+
+// import struct
+// from Crypto.Cipher import AES
+// from Crypto.Util import Counter
+
+// def encrypt_audio(key_hex: str, nonce_hex: str, timestamp: int, sequence: int, audio_data: bytes) -> bytes:
+// """
+// 加密音频数据
+
+// Args:
+// key_hex: 32字符十六进制密钥
+// nonce_hex: 32字符十六进制nonce
+// timestamp: 数据包时间戳
+// sequence: 数据包序列号
+// audio_data: 原始Opus音频数据
+
+// Returns:
+// 加密后的音频数据
+// """
+// key = bytes.fromhex(key_hex)
+// nonce = bytes.fromhex(nonce_hex)
+
+// # 构建计数器初始值:结合timestamp和sequence
+// counter_init = int.from_bytes(nonce[:12] + struct.pack('>I', sequence), 'big')
+// ctr = Counter.new(128, initial_value=counter_init)
+
+// cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
+// return cipher.encrypt(audio_data)
+
+// def decrypt_audio(key_hex: str, nonce_hex: str, timestamp: int, sequence: int, encrypted_data: bytes) -> bytes:
+// """解密音频数据(与加密相同,CTR模式对称)"""
+// return encrypt_audio(key_hex, nonce_hex, timestamp, sequence, encrypted_data)
+
+/**
+ * @brief 将十六进制字符串转换为字节数组
+ * @param hex_str 十六进制字符串(如 "01020304")
+ * @param output 输出的字节数组
+ * @param output_size 输出缓冲区大小
+ * @return 转换的字节数,-1表示失败
+ */
+static int hex_string_to_bytes(const char *hex_str, uint8_t *output, size_t output_size)
+{
+ if (!hex_str || !output) {
+ return -1;
+ }
+
+ size_t hex_len = strlen(hex_str);
+ if (hex_len % 2 != 0 || hex_len / 2 > output_size) {
+ printf("[LN_UDP] Invalid hex string length: %zu\n", hex_len);
+ return -1;
+ }
+
+ for (size_t i = 0; i < hex_len; i += 2) {
+ char hex_byte[3] = {hex_str[i], hex_str[i + 1], '\0'};
+ char *endptr;
+ unsigned long val = strtoul(hex_byte, &endptr, 16);
+ if (*endptr != '\0' || val > 255) {
+ printf("[LN_UDP] Invalid hex character at position %zu\n", i);
+ return -1;
+ }
+ output[i / 2] = (uint8_t)val;
+ }
+
+ return (int)(hex_len / 2);
+}
+
+/**
+ * @brief 加密音频数据(AES-128-CTR模式)
+ * @param key_hex 32字符十六进制密钥
+ * @param base_nonce_hex 32字符十六进制基础nonce(从hello消息中获取的原始nonce)
+ * @param payload_len 负载长度(2字节,用于构造nonce)
+ * @param timestamp 时间戳(4字节,用于构造nonce)
+ * @param sequence 数据包序列号(4字节,用于构造nonce)
+ * @param audio_data 原始音频数据
+ * @param audio_len 音频数据长度
+ * @param encrypted_data 输出的加密数据缓冲区(由调用者分配,大小至少为audio_len)
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_encrypt_audio(const char *key_hex, const char *base_nonce_hex,
+ uint16_t payload_len, uint32_t timestamp, uint32_t sequence,
+ const uint8_t *audio_data, uint16_t audio_len, uint8_t *encrypted_data)
+{
+ if (!key_hex || !base_nonce_hex || !audio_data || !encrypted_data || audio_len == 0) {
+ printf("[LN_UDP] Invalid parameters for encryption\n");
+ return -1;
+ }
+
+ // 转换密钥(32字符十六进制 = 16字节)
+ uint8_t key[16];
+ if (hex_string_to_bytes(key_hex, key, sizeof(key)) != 16) {
+ printf("[LN_UDP] Failed to convert key from hex\n");
+ return -1;
+ }
+
+ // 转换基础nonce(32字符十六进制 = 16字节)
+ uint8_t base_nonce[16];
+ if (hex_string_to_bytes(base_nonce_hex, base_nonce, sizeof(base_nonce)) != 16) {
+ printf("[LN_UDP] Failed to convert base nonce from hex\n");
+ return -1;
+ }
+
+ // 构造nonce:参考代码 std::string nonce(aes_nonce_);
+ // 然后修改特定位置:*(uint16_t*)&nonce[2] = htons(payload.size());
+ // *(uint32_t*)&nonce[8] = htonl(timestamp);
+ // *(uint32_t*)&nonce[12] = htonl(sequence);
+ uint8_t nonce_counter[16];
+ memcpy(nonce_counter, base_nonce, 16); // 复制基础nonce
+ *(uint16_t*)&nonce_counter[2] = lwip_htons(payload_len); // 位置2:payload长度(2字节)
+ *(uint32_t*)&nonce_counter[8] = lwip_htonl(timestamp); // 位置8:时间戳(4字节)
+ *(uint32_t*)&nonce_counter[12] = lwip_htonl(sequence); // 位置12:序列号(4字节)
+
+ // 初始化AES上下文
+ mbedtls_aes_context aes_ctx;
+ mbedtls_aes_init(&aes_ctx);
+
+ // 设置AES-128密钥(128位 = 16字节)
+ if (mbedtls_aes_setkey_enc(&aes_ctx, key, 128) != 0) {
+ printf("[LN_UDP] Failed to set AES key\n");
+ mbedtls_aes_free(&aes_ctx);
+ return -1;
+ }
+
+ // 使用AES-CTR模式加密(直接使用 mbedtls_aes_crypt_ctr)
+ size_t nc_off = 0; // nonce counter offset(CTR模式内部使用)
+ uint8_t stream_block[16] = {0}; // stream block(CTR模式内部使用)
+
+ printf("nonce_counter: ");
+ for (int i = 0; i < 16; i++) {
+ printf("%02x ", nonce_counter[i]);
+ }
+ printf("\n");
+
+ if (mbedtls_aes_crypt_ctr(&aes_ctx, audio_len, &nc_off, nonce_counter, stream_block,
+ audio_data, encrypted_data) != 0) {
+ printf("[LN_UDP] Failed to encrypt audio data with AES-CTR\n");
+ mbedtls_aes_free(&aes_ctx);
+ return -1;
+ }
+
+ mbedtls_aes_free(&aes_ctx);
+
+ return 0;
+}
+
+/**
+ * @brief 解密音频数据(AES-128-CTR模式,与加密相同)
+ * @param key_hex 32字符十六进制密钥
+ * @param nonce_hex 32字符十六进制nonce
+ * @param sequence 数据包序列号
+ * @param encrypted_data 加密的音频数据
+ * @param encrypted_len 加密数据长度
+ * @param decrypted_data 输出的解密数据缓冲区(由调用者分配,大小至少为encrypted_len)
+ * @return 0 成功,-1 失败
+ */
+/**
+ * @brief 解密音频数据(AES-128-CTR模式,与加密相同)
+ * @param key_hex 32字符十六进制密钥
+ * @param base_nonce_hex 32字符十六进制基础nonce(从hello消息中获取的原始nonce)
+ * @param payload_len 负载长度(2字节,用于构造nonce)
+ * @param timestamp 时间戳(4字节,用于构造nonce)
+ * @param sequence 数据包序列号(4字节,用于构造nonce)
+ * @param encrypted_data 加密的音频数据
+ * @param encrypted_len 加密数据长度
+ * @param decrypted_data 输出的解密数据缓冲区(由调用者分配,大小至少为encrypted_len)
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_decrypt_audio(const char *key_hex, const char *base_nonce_hex,
+ uint16_t payload_len, uint32_t timestamp, uint32_t sequence,
+ const uint8_t *encrypted_data, uint16_t encrypted_len, uint8_t *decrypted_data)
+{
+ // CTR模式是对称的,解密和加密使用相同的操作
+ return ln_udp_encrypt_audio(key_hex, base_nonce_hex, payload_len, timestamp, sequence,
+ encrypted_data, encrypted_len, decrypted_data);
+}
+
+/**
+ * @brief 完整的数据打包函数(加密+打包)
+ * @param audio_data 原始音频数据
+ * @param audio_len 音频数据长度
+ * @param buffer 输出缓冲区(由调用者分配,大小至少为 UDP_PACKET_HEADER_SIZE + audio_len)
+ * @param buffer_size 缓冲区大小
+ * @param out_len 输出的实际数据长度
+ * @return 0 成功,-1 失败
+ * @note 函数内部自动处理type、flags、ssrc、timestamp、sequence等字段
+ */
+int ln_udp_pack_audio_data(const uint8_t *audio_data, uint16_t audio_len,
+ uint8_t *buffer, uint16_t buffer_size, uint16_t *out_len)
+{
+ if (!audio_data || audio_len == 0 || !buffer || !out_len) {
+ printf("[LN_UDP] Invalid parameters for pack audio data\n");
+ return -1;
+ }
+
+ // 计算所需缓冲区大小
+ uint16_t total_len = UDP_PACKET_HEADER_SIZE + audio_len;
+ if (buffer_size < total_len) {
+ printf("[LN_UDP] Buffer too small: need %d, have %d\n", total_len, buffer_size);
+ return -1;
+ }
+
+ // 1. 获取UDP信息(用于加密)
+ ln_mqtt_udp_info_t udp_info;
+ if (ln_mqtt_api_get_udp_info(&udp_info) != 0 || !udp_info.valid) {
+ printf("[LN_UDP] UDP info not available for encryption\n");
+ return -1;
+ }
+ // 01 00 00 00 1d 38 db 20 69 70 a0 da 00000000
+ // 2. 初始化SSRC(如果未初始化,从 nonce 字节数组的索引 4-8 提取,只取 4 个字节)
+ if (g_udp_ssrc == 0) {
+ // 先将 nonce_hex 转换为字节数组
+ uint8_t nonce_bytes[16]; // nonce 是 32 个十六进制字符 = 16 字节
+ if (hex_string_to_bytes(udp_info.nonce, nonce_bytes, sizeof(nonce_bytes)) == 16) {
+ // 从字节数组中取索引 4-7(4 个字节)作为 SSRC(大端序)
+ g_udp_ssrc = ((uint32_t)nonce_bytes[4] << 24) |
+ ((uint32_t)nonce_bytes[5] << 16) |
+ ((uint32_t)nonce_bytes[6] << 8) |
+ ((uint32_t)nonce_bytes[7]);
+ printf("[LN_UDP] SSRC initialized from nonce bytes[4-7]: 0x%02X%02X%02X%02X -> 0x%08X\n",
+ nonce_bytes[4], nonce_bytes[5], nonce_bytes[6], nonce_bytes[7], g_udp_ssrc);
+ } else {
+ printf("[LN_UDP] Failed to convert nonce to bytes, using default SSRC\n");
+ g_udp_ssrc = 0x12345678;
+ }
+ }
+
+ // 3. 自动递增序列号
+ uint32_t sequence = g_udp_sequence++;
+
+ // 4. 获取时间戳(使用系统时钟)
+ uint32_t timestamp = (uint32_t)osKernelGetTickCount(); // 使用系统tick作为时间戳
+
+ // 5. 设置数据包类型和标志(使用默认值)
+ uint8_t type = 0x01; // 默认类型
+ uint8_t flags = 0; // 默认标志
+
+ // 6. 加密音频数据(nonce在函数内部构造)
+ uint8_t *encrypted_payload = buffer + UDP_PACKET_HEADER_SIZE;
+ if (ln_udp_encrypt_audio(udp_info.key, udp_info.nonce, audio_len, timestamp, sequence,
+ audio_data, audio_len, encrypted_payload) != 0) {
+ printf("[LN_UDP] Failed to encrypt audio data\n");
+ return -1;
+ }
+
+ // 7. 打包数据包头部
+ uint8_t *ptr = buffer;
+ ptr[0] = type;
+ ptr[1] = flags;
+ *(uint16_t *)(ptr + 2) = lwip_htons(audio_len); // payload_len(加密后的长度等于原始长度)
+ *(uint32_t *)(ptr + 4) = lwip_htonl(g_udp_ssrc);
+ *(uint32_t *)(ptr + 8) = lwip_htonl(timestamp);
+ *(uint32_t *)(ptr + 12) = lwip_htonl(sequence);
+
+ // 加密的payload已经在步骤6中写入buffer + UDP_PACKET_HEADER_SIZE位置
+
+ *out_len = total_len;
+
+ printf( "buffer: ");
+ for (int i = 0; i < 16; i++) {
+ printf("%02x ", buffer[i]);
+ }
+ printf("\n");
+
+ printf("[LN_UDP] Audio data packed: type=%d, flags=%d, ssrc=0x%08X, timestamp=%u, sequence=%u, payload_len=%d, total_len=%d\n",
+ type, flags, g_udp_ssrc, timestamp, sequence, audio_len, total_len);
+
+ return 0;
+}
+
+/**
+ * @brief 创建音频发送队列
+ */
+static void create_audio_send_queue(void)
+{
+ if (g_audio_send_queue != 0xFFFFFFFF) {
+ // 队列已创建
+ return;
+ }
+
+ if (osal_msg_queue_create("ln_udp_audio_send_queue", AUDIO_SEND_QUEUE_SIZE, &g_audio_send_queue,
+ 0, sizeof(audio_send_msg_t)) != ERRCODE_SUCC) {
+ printf("[LN_UDP] Failed to create audio send queue\n");
+ g_audio_send_queue = 0xFFFFFFFF;
+ } else {
+ printf("[LN_UDP] Audio send queue created successfully\n");
+ }
+}
+
+/**
+ * @brief 音频数据发送线程
+ */
+static void ln_udp_audio_send_thread(void *arg)
+{
+ (void)arg;
+ audio_send_msg_t msg;
+ uint32_t msgsize = sizeof(audio_send_msg_t);
+
+ printf("[LN_UDP] Audio send thread started\n");
+
+ while (g_audio_send_thread_running) {
+ // 从队列读取音频数据(阻塞等待)
+ int32_t ret = osal_msg_queue_read_copy(g_audio_send_queue, (void *)&msg, &msgsize,
+ OSAL_MSGQ_WAIT_FOREVER);
+ if (ret != OSAL_SUCCESS) {
+ printf("[LN_UDP] Failed to read from audio send queue: %d\n", ret);
+ continue;
+ }
+
+ // 检查数据大小和数据指针
+ if (msg.size == 0 || msg.size > AUDIO_SEND_MAX_DATA_SIZE || msg.data == NULL) {
+ printf("[LN_UDP] Invalid audio data: size=%u, data=%p\n", msg.size, msg.data);
+ // 释放内存(如果存在)
+ if (msg.data != NULL) {
+ free(msg.data);
+ }
+ continue;
+ }
+
+ // 确保 UDP socket 已创建
+ if (!ln_udp_is_socket_created()) {
+ printf("[LN_UDP] UDP socket not ready, drop audio frame\n");
+ free(msg.data);
+ continue;
+ }
+
+ int sock = ln_udp_get_socket();
+ if (sock < 0) {
+ printf("[LN_UDP] UDP socket invalid, drop audio frame\n");
+ free(msg.data);
+ continue;
+ }
+
+ // 打包(加密+UDP头)
+ uint8_t send_buf[UDP_PACKET_HEADER_SIZE + AUDIO_SEND_MAX_DATA_SIZE];
+ uint16_t out_len = 0;
+ if (ln_udp_pack_audio_data(msg.data, (uint16_t)msg.size, send_buf,
+ (uint16_t)sizeof(send_buf), &out_len) != 0) {
+ printf("[LN_UDP] Failed to pack audio frame\n");
+ free(msg.data);
+ continue;
+ }
+
+ // 获取UDP信息(用于发送)
+ ln_mqtt_udp_info_t udp_info;
+ if (ln_mqtt_api_get_udp_info(&udp_info) != 0 || !udp_info.valid) {
+ printf("[LN_UDP] UDP info not available, drop audio frame\n");
+ free(msg.data);
+ continue;
+ }
+
+ // 发送到服务器
+ struct sockaddr_in server_addr;
+ memset(&server_addr, 0, sizeof(server_addr));
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = lwip_htons(udp_info.port);
+ server_addr.sin_addr.s_addr = inet_addr(udp_info.server);
+
+ ssize_t sent = lwip_sendto(sock, send_buf, out_len, 0,
+ (struct sockaddr *)&server_addr, sizeof(server_addr));
+ if (sent < 0) {
+ printf("[LN_UDP] UDP sendto failed: %s\n", strerror(errno));
+ }
+
+ // 释放音频数据内存
+ free(msg.data);
+ msg.data = NULL;
+ }
+
+ printf("[LN_UDP] Audio send thread exited\n");
+ g_audio_send_thread_running = false;
+}
+
+/**
+ * @brief 初始化音频发送队列和线程
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_audio_send_init(void)
+{
+ // 创建消息队列
+ create_audio_send_queue();
+ if (g_audio_send_queue == 0xFFFFFFFF) {
+ printf("[LN_UDP] Failed to create audio send queue\n");
+ return -1;
+ }
+
+ // 创建发送线程(如果尚未创建)
+ if (!g_audio_send_thread_running) {
+ app_task_definition_ext_t send_task = {
+ .attr = {
+ .name = "ln_udp_audio_send",
+ .stack_size = 0x2000,
+ .priority = osPriorityNormal
+ },
+ .func = ln_udp_audio_send_thread,
+ .task_handle = &g_audio_send_thread_handle,
+ .create_queue_handle = NULL,
+ .use_mem = USE_EXTEND_MEM,
+ .inst_args = NULL
+ };
+
+ g_audio_send_thread_running = true;
+ errcode_t ret = uapi_create_osThread_custom_with_args(&send_task);
+ if (ret != ERRCODE_SUCC) {
+ printf("[LN_UDP] ERROR: Failed to create audio send thread: %d\n", ret);
+ g_audio_send_thread_running = false;
+ return -1;
+ }
+ printf("[LN_UDP] Audio send thread created successfully\n");
+ }
+
+ return 0;
+}
+
+/**
+ * @brief 停止音频发送线程
+ */
+void ln_udp_audio_send_deinit(void)
+{
+ // 停止发送线程
+ if (g_audio_send_thread_running) {
+ printf("[LN_UDP] Stopping audio send thread\n");
+ g_audio_send_thread_running = false;
+
+ // 发送一个空消息唤醒线程(如果队列为空)
+ // 注意:data 为 NULL,size 为 0,线程会检查并释放
+ audio_send_msg_t wake_msg = {0};
+ wake_msg.data = NULL;
+ wake_msg.size = 0;
+ osal_msg_queue_write_copy(g_audio_send_queue, (void *)&wake_msg, sizeof(audio_send_msg_t), 0);
+
+ // 等待线程退出(最多等待2秒)
+ uint32_t timeout = osKernelGetTickCount() + osKernelGetTickFreq() * 2;
+ while (g_audio_send_thread_handle != 0 && osKernelGetTickCount() < timeout) {
+ osDelay(10);
+ }
+
+ if (g_audio_send_thread_handle != 0) {
+ printf("[LN_UDP] WARNING: Audio send thread did not exit in time\n");
+ }
+
+ g_audio_send_thread_handle = 0;
+ }
+
+ // 清空队列中剩余的消息(释放内存)
+ if (g_audio_send_queue != 0xFFFFFFFF) {
+ audio_send_msg_t msg;
+ uint32_t msgsize = sizeof(audio_send_msg_t);
+ while (osal_msg_queue_read_copy(g_audio_send_queue, (void *)&msg, &msgsize, 0) == OSAL_SUCCESS) {
+ if (msg.data != NULL) {
+ free(msg.data);
+ }
+ msgsize = sizeof(audio_send_msg_t);
+ }
+ }
+
+ // 删除消息队列
+ if (g_audio_send_queue != 0xFFFFFFFF) {
+ osal_msg_queue_delete(g_audio_send_queue);
+ g_audio_send_queue = 0xFFFFFFFF;
+ printf("[LN_UDP] Audio send queue deleted\n");
+ }
+}
+
+/**
+ * @brief 将音频数据放入发送队列(供录音回调函数调用)
+ * @param data 音频数据指针
+ * @param size 音频数据大小
+ * @return 0 成功,-1 失败
+ * @note 函数内部会动态分配内存并复制数据,发送线程负责释放内存
+ */
+int ln_udp_audio_send_enqueue(const uint8_t *data, uint32_t size)
+{
+ if (!data || size == 0 || size > AUDIO_SEND_MAX_DATA_SIZE) {
+ printf("[LN_UDP] Invalid parameters for audio send enqueue\n");
+ return -1;
+ }
+
+ if (g_audio_send_queue == 0xFFFFFFFF) {
+ printf("[LN_UDP] Audio send queue not initialized\n");
+ return -1;
+ }
+
+ // 动态分配内存并复制数据
+ uint8_t *data_copy = (uint8_t *)malloc(size);
+ if (data_copy == NULL) {
+ printf("[LN_UDP] Failed to allocate memory for audio data\n");
+ return -1;
+ }
+ memcpy(data_copy, data, size);
+
+ // 构造消息
+ audio_send_msg_t msg;
+ msg.data = data_copy;
+ msg.size = size;
+
+ // 写入队列(非阻塞,如果队列满则丢弃并释放内存)
+ int32_t ret = osal_msg_queue_write_copy(g_audio_send_queue, (void *)&msg, sizeof(audio_send_msg_t), 0);
+ if (ret != OSAL_SUCCESS) {
+ printf("[LN_UDP] Failed to enqueue audio data: %d (queue may be full)\n", ret);
+ free(data_copy); // 队列满时释放内存
+ return -1;
+ }
+
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+#include "ln_api.h"
+#include "ln_mqtt_api.h"
+#include "uapi_Mqtt_api.h"
+#include "lwip/apps/mqtt.h"
+#include "lwip/err.h"
+#include "cJSON.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "wearable_log.h"
+#include "custom_utils.h"
+#include "ai_media.h"
+#include "audio_base_type.h"
+#include "lwip/sockets.h"
+#include "lwip/inet.h"
+#include "lwip/netdb.h"
+
+#define LN_MQTT_SEND_TOPIC "device-server-enhanced"
+
+/* MQTT API 全局状态 */
+static bool g_ln_mqtt_service_started = false;
+
+/* UDP信息全局变量 */
+static ln_mqtt_udp_info_t g_udp_info = {0};
+
+/* hello 消息中的 session_id(用于后续 listen 控制消息) */
+static char g_ln_mqtt_session_id[64] = {0};
+static bool g_ln_mqtt_session_id_valid = false;
+
+/* 音频初始化状态标志位 */
+static volatile bool g_mqtt_audio_initialized = false;
+
+int ln_mqtt_api_send_hello(void);
+
+// --- MQTT 录音(来自 ai_media_service_mqtt.cpp,无对应头文件时在此声明) ---
+typedef void (*MqttRecordDataCallback)(const uint8_t* data, uint32_t size, void* userData);
+typedef struct {
+ int32_t audioFormat;
+ uint32_t channelCount;
+ uint32_t sampleRate;
+} MqttRecordAudioParams;
+extern int32_t MQTT_StartRecord(MqttRecordDataCallback dataCallback, void* userData,
+ const MqttRecordAudioParams* audioParams);
+extern int32_t MQTT_StopRecord(void);
+
+// --- LN UDP(定义在 ln_UPD.c)---
+extern int ln_udp_create_socket(void);
+extern bool ln_udp_is_socket_created(void);
+extern int ln_udp_get_socket(void);
+extern int ln_udp_pack_audio_data(const uint8_t *audio_data, uint16_t audio_len,
+ uint8_t *buffer, uint16_t buffer_size, uint16_t *out_len);
+extern int ln_udp_audio_send_init(void);
+extern void ln_udp_audio_send_deinit(void);
+extern int ln_udp_audio_send_enqueue(const uint8_t *data, uint32_t size);
+
+#define LN_UDP_PACKET_HEADER_SIZE 16
+#define LN_MQTT_RECORD_MAX_FRAME 0x800
+#define LN_MQTT_RECORD_BATCH_SIZE 5 // 每5包数据合并后入队
+
+/* 双流接口开关:定义 USE_DUAL_STREAM_INTERFACE 则使用 old_Start_AIVoice 双流接口,否则使用 MQTT_StartRecord */
+/* 可在 CMakeLists.txt 或编译选项中定义,例如:-DUSE_DUAL_STREAM_INTERFACE=1 */
+
+
+/* 音频数据缓存结构体(用于批量入队) */
+typedef struct {
+ uint8_t *buffer; // 缓存缓冲区指针(动态分配)
+ uint32_t buffer_size; // 缓冲区大小
+ uint32_t current_size; // 当前缓存的数据大小
+ uint32_t packet_count; // 当前累积的包数
+} ln_mqtt_record_cache_t;
+
+/* 全局缓存变量 */
+static ln_mqtt_record_cache_t g_record_cache = {0};
+
+#if USE_DUAL_STREAM_INTERFACE
+/* 录音上传状态标志位(用于控制是否处理并上传音频数据) */
+static volatile bool g_recording_upload_started = false;
+#endif /* USE_DUAL_STREAM_INTERFACE */
+
+static void ln_mqtt_record_data_cb(const uint8_t* data, uint32_t size, void* userData)
+{
+ (void)userData;
+ if (!data || size == 0) {
+ return;
+ }
+ if (size > LN_MQTT_RECORD_MAX_FRAME) {
+ printf("[LN_MQTT_API] Record frame too large: %u\n", (unsigned)size);
+ return;
+ }
+
+#if USE_DUAL_STREAM_INTERFACE
+ // 如果录音上传未开始,只缓存数据,不处理上传
+ if (!g_recording_upload_started) {
+ // 可以在这里缓存数据,等待开始标志位设置后再处理
+ // 目前先直接返回,不处理数据
+ return;
+ }
+#endif /* USE_DUAL_STREAM_INTERFACE */
+
+ printf("ln_mqtt_record_data_cb size %d\r\n",size);
+
+ // 如果缓冲区未分配,先分配
+ if (g_record_cache.buffer == NULL) {
+ uint32_t initial_size = LN_MQTT_RECORD_MAX_FRAME * LN_MQTT_RECORD_BATCH_SIZE;
+ g_record_cache.buffer = (uint8_t *)malloc(initial_size);
+ if (g_record_cache.buffer == NULL) {
+ printf("[LN_MQTT_API] Failed to allocate cache buffer, drop frame\n");
+ return;
+ }
+ g_record_cache.buffer_size = initial_size;
+ g_record_cache.current_size = 0;
+ g_record_cache.packet_count = 0;
+ printf("[LN_MQTT_API] Cache buffer allocated: %u bytes\n", initial_size);
+ }
+
+ // 检查缓存是否足够大,如果不够则扩容
+ if (g_record_cache.current_size + size > g_record_cache.buffer_size) {
+ printf("[LN_MQTT_API] Cache overflow, force flush: current=%u, new=%u, max=%u\n",
+ g_record_cache.current_size, size, g_record_cache.buffer_size);
+ // 如果缓存已满,强制刷新当前缓存
+ if (g_record_cache.current_size > 0) {
+ if (ln_udp_audio_send_enqueue(g_record_cache.buffer, g_record_cache.current_size) != 0) {
+ printf("[LN_MQTT_API] Failed to enqueue cached audio data\n");
+ }
+ g_record_cache.current_size = 0;
+ g_record_cache.packet_count = 0;
+ }
+ }
+
+ // 将数据添加到缓存
+ memcpy(g_record_cache.buffer + g_record_cache.current_size, data, size);
+ g_record_cache.current_size += size;
+ g_record_cache.packet_count++;
+
+ // 如果累积到5包,将缓存数据入队
+ if (g_record_cache.packet_count >= LN_MQTT_RECORD_BATCH_SIZE) {
+ if (ln_udp_audio_send_enqueue(g_record_cache.buffer, g_record_cache.current_size) != 0) {
+ printf("[LN_MQTT_API] Failed to enqueue batched audio data, drop frame\n");
+ } else {
+ printf("[LN_MQTT_API] Enqueued %u packets, total size: %u bytes\n",
+ g_record_cache.packet_count, g_record_cache.current_size);
+ }
+ // 清空缓存
+ g_record_cache.current_size = 0;
+ g_record_cache.packet_count = 0;
+ }
+
+ msleep(10);
+}
+
+/**
+ * @brief 解析hello类型消息并保存UDP信息
+ * @param data JSON数据(完整数据,以null结尾)
+ * @return 0 成功,-1 失败
+ */
+static int ln_mqtt_handle_hello_message(const char *data);
+
+/**
+ * @brief 统一的消息解析函数,根据type字段分发到不同的处理函数
+ * @param data 原始数据
+ * @param len 数据长度
+ * @return 0 成功处理,-1 失败或未处理
+ */
+static int ln_mqtt_parse_message_by_type(const uint8_t *data, uint16_t len)
+{
+ if (!data || len == 0) {
+ return -1;
+ }
+
+ // 确保字符串以null结尾
+ char *json_str = (char *)malloc(len + 1);
+ if (!json_str) {
+ printf("[LN_MQTT_API] Failed to allocate memory for JSON string\n");
+ return -1;
+ }
+ memcpy(json_str, data, len);
+ json_str[len] = '\0';
+
+ // 解析JSON
+ cJSON *root = cJSON_Parse(json_str);
+ if (!root) {
+ const char *error_ptr = cJSON_GetErrorPtr();
+ if (error_ptr != NULL) {
+ printf("[LN_MQTT_API] JSON parse error: %s\n", error_ptr);
+ }
+ free(json_str);
+ return -1;
+ }
+
+ // 获取type字段
+ cJSON *type_item = cJSON_GetObjectItemCaseSensitive(root, "type");
+ if (!cJSON_IsString(type_item)) {
+ printf("[LN_MQTT_API] No 'type' field or invalid type field in message\n");
+ cJSON_Delete(root);
+ free(json_str);
+ return -1;
+ }
+
+ const char *type_value = type_item->valuestring;
+ printf("[LN_MQTT_API] Message type detected: %s\n", type_value);
+
+ printf("[LN_MQTT_API] Message: %s\n", json_str);
+
+ // 根据type值调用相应的处理函数
+ int ret = -1;
+ if (strcmp(type_value, "hello") == 0) {
+ ret = ln_mqtt_handle_hello_message(json_str);
+ if(ret==0)
+ {
+ extern int ln_udp_create_socket(void);
+ ln_udp_create_socket();
+ }
+ } else {
+ printf("[LN_MQTT_API] Unknown message type: %s, skipping\n", type_value);
+ }
+
+ cJSON_Delete(root);
+ free(json_str);
+ return ret;
+}
+
+
+
+// {
+// "type": "hello",
+// "version": 3,
+// "session_id": "3326285112",
+// "transport": "udp",
+// "features": {
+// "voice": true,
+// "tts": true,
+// "asr": true,
+// "mcp": true
+// },
+// "udp": {
+// "server": "192.168.2.200",
+// "port": 50000,
+// "encryption": "aes-128-ctr",
+// "key": "90470f78e3edffc2bf5130d8d73b5d80",
+// "nonce": "01000000a8bdec683dbe440fa41ec435"
+// },
+// "audio_params": {
+// "format": "opus",
+// "sample_rate": 16000,
+// "channels": 1,
+// "frame_duration": 60
+// }
+// }
+/**
+ * @brief 解析hello类型消息并保存UDP信息
+ * @param data JSON数据(完整数据,以null结尾)
+ * @return 0 成功,-1 失败
+ */
+static int ln_mqtt_handle_hello_message(const char *data)
+{
+ if (!data) {
+ printf("[LN_MQTT_API] Invalid data for parsing hello message\n");
+ return -1;
+ }
+
+ // 解析JSON
+ cJSON *root = cJSON_Parse(data);
+ if (!root) {
+ const char *error_ptr = cJSON_GetErrorPtr();
+ if (error_ptr != NULL) {
+ printf("[LN_MQTT_API] JSON parse error: %s\n", error_ptr);
+ }
+ return -1;
+ }
+
+ printf("[LN_MQTT_API] Parsing hello message...\n");
+
+ // 提取并保存 session_id(供后续 listen 消息使用)
+ cJSON *session_id_item = cJSON_GetObjectItemCaseSensitive(root, "session_id");
+ if (cJSON_IsString(session_id_item) && session_id_item->valuestring && session_id_item->valuestring[0] != '\0') {
+ strncpy(g_ln_mqtt_session_id, session_id_item->valuestring, sizeof(g_ln_mqtt_session_id) - 1);
+ g_ln_mqtt_session_id[sizeof(g_ln_mqtt_session_id) - 1] = '\0';
+ g_ln_mqtt_session_id_valid = true;
+ printf("[LN_MQTT_API] session_id saved: %s\n", g_ln_mqtt_session_id);
+ } else {
+ // 不直接失败:UDP 信息可能仍然有效
+ g_ln_mqtt_session_id[0] = '\0';
+ g_ln_mqtt_session_id_valid = false;
+ printf("[LN_MQTT_API] WARNING: session_id missing or invalid in hello message\n");
+ }
+
+ // 解析UDP信息
+ cJSON *udp_item = cJSON_GetObjectItemCaseSensitive(root, "udp");
+ if (udp_item && cJSON_IsObject(udp_item)) {
+ // 清空之前的UDP信息
+ memset(&g_udp_info, 0, sizeof(g_udp_info));
+
+ // 解析server
+ cJSON *server_item = cJSON_GetObjectItemCaseSensitive(udp_item, "server");
+ if (cJSON_IsString(server_item)) {
+ strncpy(g_udp_info.server, server_item->valuestring, sizeof(g_udp_info.server) - 1);
+ g_udp_info.server[sizeof(g_udp_info.server) - 1] = '\0';
+ printf("[LN_MQTT_API] UDP server: %s\n", g_udp_info.server);
+ }
+
+ // 解析port
+ cJSON *port_item = cJSON_GetObjectItemCaseSensitive(udp_item, "port");
+ if (cJSON_IsNumber(port_item)) {
+ g_udp_info.port = (uint16_t)port_item->valueint;
+ printf("[LN_MQTT_API] UDP port: %d\n", g_udp_info.port);
+ }
+
+ // 解析encryption
+ cJSON *encryption_item = cJSON_GetObjectItemCaseSensitive(udp_item, "encryption");
+ if (cJSON_IsString(encryption_item)) {
+ strncpy(g_udp_info.encryption, encryption_item->valuestring, sizeof(g_udp_info.encryption) - 1);
+ g_udp_info.encryption[sizeof(g_udp_info.encryption) - 1] = '\0';
+ printf("[LN_MQTT_API] UDP encryption: %s\n", g_udp_info.encryption);
+ }
+
+ // 解析key
+ cJSON *key_item = cJSON_GetObjectItemCaseSensitive(udp_item, "key");
+ if (cJSON_IsString(key_item)) {
+ strncpy(g_udp_info.key, key_item->valuestring, sizeof(g_udp_info.key) - 1);
+ g_udp_info.key[sizeof(g_udp_info.key) - 1] = '\0';
+ printf("[LN_MQTT_API] UDP key: %s\n", g_udp_info.key);
+ }
+
+ // 解析nonce
+ cJSON *nonce_item = cJSON_GetObjectItemCaseSensitive(udp_item, "nonce");
+ if (cJSON_IsString(nonce_item)) {
+ strncpy(g_udp_info.nonce, nonce_item->valuestring, sizeof(g_udp_info.nonce) - 1);
+ g_udp_info.nonce[sizeof(g_udp_info.nonce) - 1] = '\0';
+ printf("[LN_MQTT_API] UDP nonce: %s\n", g_udp_info.nonce);
+ }
+
+ // 标记信息有效
+ if (g_udp_info.server[0] != '\0' && g_udp_info.port > 0) {
+ g_udp_info.valid = true;
+ printf("[LN_MQTT_API] UDP info saved successfully\n");
+ } else {
+ printf("[LN_MQTT_API] WARNING: UDP info incomplete (server or port missing)\n");
+ }
+ } else {
+ printf("[LN_MQTT_API] No UDP information in hello message\n");
+ }
+
+ cJSON_Delete(root);
+ return 0;
+}
+
+/**
+ * @brief 自动订阅 devices/p2p/{clientId} 主题
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_auto_subscribe_p2p(void)
+{
+ char client_id[256] = {0};
+ if (uapi_mqtt_get_client_id(client_id, sizeof(client_id)) != 0) {
+ printf("[LN_MQTT_API] Warning: client_id not available for auto-subscribe\n");
+ return -1;
+ }
+
+ char p2p_topic[256] = {0};
+ int ret = snprintf(p2p_topic, sizeof(p2p_topic), "devices/p2p/%s", client_id);
+ if (ret <= 0 || ret >= (int)sizeof(p2p_topic)) {
+ printf("[LN_MQTT_API] Failed to construct p2p topic (buffer too small)\n");
+ return -1;
+ }
+
+ printf("[LN_MQTT_API] Auto-subscribing to topic: %s\n", p2p_topic);
+
+ int subscribe_ret = uapi_mqtt_subscribe(p2p_topic, 1);
+ if (subscribe_ret == 0) {
+ printf("[LN_MQTT_API] Auto-subscribe request sent successfully\n");
+ return 0;
+ } else {
+ printf("[LN_MQTT_API] Auto-subscribe request failed: %d\n", subscribe_ret);
+ return -1;
+ }
+}
+
+/**
+ * @brief MQTT连接状态回调(内部回调,供服务模式使用)
+ */
+static void ln_mqtt_internal_connect_cb(void *arg, int status)
+{
+ (void)arg;
+
+ printf("[LN_MQTT_API] Connection status changed: %d\n", status);
+
+ // 连接成功时(status == 0 对应 MQTT_CONNECT_ACCEPTED),自动订阅和发送通知
+ if (status == 0) {
+ // 自动订阅 devices/p2p/{clientId} 主题
+ ln_mqtt_api_auto_subscribe_p2p();
+
+ // 发送连接通知消息
+
+ }
+ else
+ {
+ extern void ln_udp_close_socket(void);
+ ln_udp_close_socket();
+ }
+}
+
+/**
+ * @brief MQTT消息接收回调(内部回调,供服务模式使用)
+ */
+static void ln_mqtt_internal_message_cb(void *arg, const char *topic, const uint8_t *data, uint16_t len)
+{
+ (void)arg;
+
+ printf("[LN_MQTT_API] Message received - Topic: %s, Length: %d\n", topic ? topic : "NULL", len);
+
+ // 统一解析消息,根据type字段分发处理
+ if (data && len > 0) {
+ ln_mqtt_parse_message_by_type(data, len);
+ }
+}
+
+/**
+ * @brief MQTT订阅结果回调(内部回调,供服务模式使用)
+ */
+static void ln_mqtt_internal_subscribe_cb(void *arg, const char *topic, uint8_t qos, int result)
+{
+ (void)arg;
+
+ if (result == 0) {
+ printf("[LN_MQTT_API] Subscribe successful - Topic: %s, QoS: %d\n", topic ? topic : "NULL", qos);
+
+ // ln_mqtt_api_send_connection_notification();
+
+ ln_mqtt_api_send_hello();
+
+ } else {
+ printf("[LN_MQTT_API] Subscribe failed - Topic: %s, QoS: %d, Result: %d\n", topic ? topic : "NULL", qos, result);
+ }
+}
+
+/**
+ * @brief 启动MQTT服务(启动线程、自动连接等)
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_start_service(void)
+{
+ if (g_ln_mqtt_service_started) {
+ WEARABLE_LOGW(WEARABLE_LOG_MODULE_APP, "[LN_MQTT_API] Service already started");
+ return 0;
+ }
+
+ printf("[LN_MQTT_API] Starting MQTT service\n");
+
+ // 构建回调函数结构体,使用内部回调
+ mqtt_call_backs_t callbacks = {0};
+ callbacks.connect_callback = ln_mqtt_internal_connect_cb;
+ callbacks.message_callback = ln_mqtt_internal_message_cb;
+ callbacks.subscribe_callback = ln_mqtt_internal_subscribe_cb;
+ callbacks.user_arg = NULL;
+ callbacks.main_thread_interval_ms = 1000; // 默认1000ms
+
+ // 启动MQTT主线程(会自动初始化、连接和管理消息队列)
+ int ret = uapi_mqtt_main_start(&callbacks);
+ if (ret != 0) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[LN_MQTT_API] Failed to start MQTT service");
+ return -1;
+ }
+
+ // 初始化音频发送队列和线程
+ if (ln_udp_audio_send_init() != 0) {
+ printf("[LN_MQTT_API] WARNING: Failed to init audio send queue/thread\n");
+ // 不影响服务启动,继续执行
+ }
+
+#if USE_DUAL_STREAM_INTERFACE
+ // 使用 old_Start_AIVoice 接口时,在服务初始化时就启动音频
+ printf("[LN_MQTT_API] Initializing audio with old_Start_AIVoice dual stream interface\n");
+
+ // 检查 AI 语音服务是否已经在运行(如果已运行则先停止)
+ if (AI_IsVoiceServiceRunning()) {
+ printf("[LN_MQTT_API] AI voice service already running, stopping it first\n");
+ StopAIVoice();
+ }
+
+ // 设置第二个上行流参数:SBC 格式,16kHz,单声道
+ AIVoiceAudioParams secondStreamParams = {
+ .audioFormat = SBC, // SBC 格式(对应 AudioCodecFormat)
+ .channelCount = 1, // 单声道
+ .sampleRate = 16000 // 16kHz 采样率
+ };
+
+ // 输入流参数(主输入流)
+ AIVoiceAudioParams inputParams = {
+ .audioFormat = SBC,
+ .channelCount = 1,
+ .sampleRate = 16000
+ };
+
+
+
+ // 输出流参数(设置为NULL,因为我们只关心录音输入)
+ AIVoiceAudioParams outputParams = {
+ .audioFormat = PCM,
+ .channelCount = 1,
+ .sampleRate = 16000
+ };
+
+ // 使用 old_Start_AIVoice 启动,传入第二个上行流参数启用双流
+ int32_t start_ret = old_Start_AIVoice(
+ (AIVoiceDataCallback)ln_mqtt_record_data_cb, // 数据回调函数(类型转换)
+ NULL, // 用户数据
+ &inputParams, // 输入流参数(主输入流)
+ &outputParams, // 输出流参数(NULL使用默认)
+ NULL, // 第二个上行流参数(启用双流)
+ false // 不使用OGG封装
+ );
+
+ if (start_ret != 0) {
+ printf("[LN_MQTT_API] WARNING: old_Start_AIVoice failed during service init: %d\n", (int)start_ret);
+ // 不影响服务启动,继续执行
+ } else {
+ printf("[LN_MQTT_API] old_Start_AIVoice initialized successfully (SBC, 16kHz, mono)\n");
+ }
+#endif /* USE_DUAL_STREAM_INTERFACE */
+
+ g_ln_mqtt_service_started = true;
+ printf("[LN_MQTT_API] MQTT service started successfully\n");
+
+ return 0;
+}
+
+/**
+ * @brief 停止MQTT服务(停止线程、断开连接、清理资源等)
+ */
+void ln_mqtt_api_stop_service(void)
+{
+ if (!g_ln_mqtt_service_started) {
+ return;
+ }
+
+ printf("[LN_MQTT_API] Stopping MQTT service\n");
+
+ // 停止音频发送线程
+ ln_udp_audio_send_deinit();
+
+ // 释放缓存缓冲区(如果存在)
+ if (g_record_cache.buffer != NULL) {
+ // 如果有剩余数据,先刷新
+ if (g_record_cache.current_size > 0) {
+ printf("[LN_MQTT_API] Flushing remaining cached audio data before service stop\n");
+ if (ln_udp_audio_send_enqueue(g_record_cache.buffer, g_record_cache.current_size) != 0) {
+ printf("[LN_MQTT_API] Failed to enqueue remaining cached audio data\n");
+ }
+ }
+ free(g_record_cache.buffer);
+ g_record_cache.buffer = NULL;
+ g_record_cache.buffer_size = 0;
+ g_record_cache.current_size = 0;
+ g_record_cache.packet_count = 0;
+ printf("[LN_MQTT_API] Cache buffer freed\n");
+ }
+
+#if USE_DUAL_STREAM_INTERFACE
+ // 清理双流接口资源
+ // 清除录音上传标志位
+ g_recording_upload_started = false;
+ // 停止 AI 语音服务(在服务初始化时已启动)
+ if (AI_IsVoiceServiceRunning()) {
+ (void)StopAIVoice();
+ printf("[LN_MQTT_API] AI voice service stopped\n");
+ }
+#endif /* USE_DUAL_STREAM_INTERFACE */
+
+ // 停止MQTT主线程(会自动断开连接和清理资源)
+ uapi_mqtt_main_stop();
+
+ g_ln_mqtt_service_started = false;
+
+ printf("[LN_MQTT_API] MQTT service stopped\n");
+}
+
+
+/**
+ * @brief 断开MQTT连接
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_disconnect(void)
+{
+ if (g_ln_mqtt_service_started) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[LN_MQTT_API] Service is running, use ln_mqtt_api_stop_service instead");
+ return -1;
+ }
+
+ printf("[LN_MQTT_API] Disconnecting MQTT\n");
+
+ int ret = uapi_mqtt_disconnect();
+ if (ret != 0) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[LN_MQTT_API] Failed to disconnect MQTT");
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief 检查MQTT连接状态
+ * @return true 已连接,false 未连接
+ */
+bool ln_mqtt_api_is_connected(void)
+{
+ if (g_ln_mqtt_service_started) {
+ // 服务模式下,通过状态查询
+ int state = uapi_mqtt_main_get_state();
+ return (state == 2); // 2 = MQTT_STATE_CONNECTED
+ }
+
+ return uapi_mqtt_is_connected();
+}
+
+/**
+ * @brief 发送MQTT连接通知消息
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_send_connection_notification(void)
+{
+ if (!uapi_mqtt_is_connected()) {
+ printf("[LN_MQTT_API] Client not connected, cannot send connection notification\n");
+ return -1;
+ }
+
+ char client_id[256] = {0};
+ if (uapi_mqtt_get_client_id(client_id, sizeof(client_id)) != 0) {
+ printf("[LN_MQTT_API] client_id not available, cannot send connection notification\n");
+ return -1;
+ }
+
+ // 构建JSON数据
+ cJSON *root = cJSON_CreateObject();
+ if (!root) {
+ printf("[LN_MQTT_API] Failed to create JSON object\n");
+ return -1;
+ }
+
+ cJSON_AddStringToObject(root, "clientId", client_id);
+
+ cJSON *data = cJSON_CreateObject();
+ if (!data) {
+ printf("[LN_MQTT_API] Failed to create data object\n");
+ cJSON_Delete(root);
+ return -1;
+ }
+
+ cJSON_AddStringToObject(data, "type", "connected");
+ cJSON_AddItemToObject(root, "data", data);
+
+ char *json_str = cJSON_Print(root);
+ if (!json_str) {
+ printf("[LN_MQTT_API] Failed to create JSON string\n");
+ cJSON_Delete(root);
+ return -1;
+ }
+
+ // 确定发布主题
+ char publish_topic[128] = {0};
+ const char *use_topic = NULL;
+ if (uapi_mqtt_get_publish_topic(publish_topic, sizeof(publish_topic)) == 0) {
+ use_topic = publish_topic;
+ } else {
+ use_topic = LN_MQTT_SEND_TOPIC; // 使用默认主题
+ }
+
+ printf("[LN_MQTT_API] Publishing connection notification to topic: %s\n", use_topic);
+ printf("[LN_MQTT_API] Message: %s\n", json_str);
+
+ uint16_t msg_len = (uint16_t)strlen(json_str);
+ int ret = uapi_mqtt_main_send(use_topic, json_str, msg_len, 1, 0);
+
+ cJSON_free(json_str);
+ cJSON_Delete(root);
+
+ if (ret == 0) {
+ printf("[LN_MQTT_API] Connection notification queued for sending successfully\n");
+ return 0;
+ } else {
+ printf("[LN_MQTT_API] Failed to queue connection notification: %d\n", ret);
+ return -1;
+ }
+}
+
+/**
+ * @brief 发送MQTT hello消息
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_send_hello(void)
+{
+ if (!uapi_mqtt_is_connected()) {
+ printf("[LN_MQTT_API] Client not connected, cannot send hello message\n");
+ return -1;
+ }
+
+ // 构建JSON数据
+ cJSON *root = cJSON_CreateObject();
+ if (!root) {
+ printf("[LN_MQTT_API] Failed to create JSON object\n");
+ return -1;
+ }
+
+ cJSON_AddStringToObject(root, "type", "hello");
+ cJSON_AddNumberToObject(root, "version", 3);
+ cJSON_AddStringToObject(root, "transport", "udp");
+
+ // 添加 features 对象
+ cJSON *features = cJSON_CreateObject();
+ if (!features) {
+ printf("[LN_MQTT_API] Failed to create features object\n");
+ cJSON_Delete(root);
+ return -1;
+ }
+ cJSON_AddTrueToObject(features, "mcp");
+ cJSON_AddTrueToObject(features, "voice");
+ cJSON_AddItemToObject(root, "features", features);
+
+ // 添加 audio_params 对象
+ cJSON *audio_params = cJSON_CreateObject();
+ if (!audio_params) {
+ printf("[LN_MQTT_API] Failed to create audio_params object\n");
+ cJSON_Delete(root);
+ return -1;
+ }
+ cJSON_AddStringToObject(audio_params, "format", "sbc");
+ cJSON_AddNumberToObject(audio_params, "sample_rate", 16000);
+ cJSON_AddNumberToObject(audio_params, "channels", 1);
+ cJSON_AddNumberToObject(audio_params, "frame_duration", 60);
+ cJSON_AddItemToObject(root, "audio_params", audio_params);
+
+ char *json_str = cJSON_Print(root);
+ if (!json_str) {
+ printf("[LN_MQTT_API] Failed to create JSON string\n");
+ cJSON_Delete(root);
+ return -1;
+ }
+
+ // 确定发布主题
+ char publish_topic[128] = {0};
+ const char *use_topic = NULL;
+ if (uapi_mqtt_get_publish_topic(publish_topic, sizeof(publish_topic)) == 0) {
+ use_topic = publish_topic;
+ } else {
+ use_topic = LN_MQTT_SEND_TOPIC; // 使用默认主题
+ }
+
+ printf("[LN_MQTT_API] Publishing hello message to topic: %s\n", use_topic);
+ printf("[LN_MQTT_API] Message: %s\n", json_str);
+
+ uint16_t msg_len = (uint16_t)strlen(json_str);
+ int ret = uapi_mqtt_main_send(use_topic, json_str, msg_len, 1, 0);
+
+ cJSON_free(json_str);
+ cJSON_Delete(root);
+
+ if (ret == 0) {
+ printf("[LN_MQTT_API] Hello message queued for sending successfully\n");
+ return 0;
+ } else {
+ printf("[LN_MQTT_API] Failed to queue hello message: %d\n", ret);
+ return -1;
+ }
+}
+
+/**
+ * @brief 发送 listen 控制消息
+ * payload 示例:
+ * {
+ * "session_id": "3326285112",
+ * "type": "listen",
+ * "state": "start|stop",
+ * "mode": "auto"
+ * }
+ */
+int ln_mqtt_api_send_listen_state(bool start)
+{
+ if (!uapi_mqtt_is_connected()) {
+ printf("[LN_MQTT_API] Client not connected, cannot send listen message\n");
+ return -1;
+ }
+ if (!g_ln_mqtt_session_id_valid || g_ln_mqtt_session_id[0] == '\0') {
+ printf("[LN_MQTT_API] session_id not ready (missing hello?), cannot send listen message\n");
+ return -1;
+ }
+
+ // 构建JSON数据
+ cJSON *root = cJSON_CreateObject();
+ if (!root) {
+ printf("[LN_MQTT_API] Failed to create JSON object\n");
+ return -1;
+ }
+
+ cJSON_AddStringToObject(root, "session_id", g_ln_mqtt_session_id);
+ cJSON_AddStringToObject(root, "type", "listen");
+ cJSON_AddStringToObject(root, "state", start ? "start" : "stop");
+ cJSON_AddStringToObject(root, "mode", "auto");
+
+ char *json_str = cJSON_Print(root);
+ if (!json_str) {
+ printf("[LN_MQTT_API] Failed to create JSON string\n");
+ cJSON_Delete(root);
+ return -1;
+ }
+
+ // 确定发布主题
+ char publish_topic[128] = {0};
+ const char *use_topic = NULL;
+ if (uapi_mqtt_get_publish_topic(publish_topic, sizeof(publish_topic)) == 0) {
+ use_topic = publish_topic;
+ } else {
+ use_topic = LN_MQTT_SEND_TOPIC; // 使用默认主题
+ }
+
+ printf("[LN_MQTT_API] Publishing listen message to topic: %s\n", use_topic);
+ printf("[LN_MQTT_API] Message: %s\n", json_str);
+
+ uint16_t msg_len = (uint16_t)strlen(json_str);
+ int ret = uapi_mqtt_main_send(use_topic, json_str, msg_len, 1, 0);
+
+ cJSON_free(json_str);
+ cJSON_Delete(root);
+
+ if (ret != 0) {
+ printf("[LN_MQTT_API] Failed to queue listen message: %d\n", ret);
+ return -1;
+ }
+
+ printf("[LN_MQTT_API] Listen message queued for sending successfully\n");
+
+ // 发送完成后控制录音:start->开始录音,stop->停止录音
+ if (start) {
+#if USE_DUAL_STREAM_INTERFACE
+ // 使用 old_Start_AIVoice 双流接口(音频已在服务初始化时启动)
+ printf("[LN_MQTT_API] Starting dual stream recording (audio already initialized in service)\n");
+
+ // 检查 AI 语音服务是否运行(应该在服务初始化时已启动)
+ if (!AI_IsVoiceServiceRunning()) {
+ printf("[LN_MQTT_API] WARNING: AI voice service not running, audio should be initialized in service start\n");
+ return -1;
+ }
+
+ // 设置录音上传标志位,开始处理并上传音频数据
+ g_recording_upload_started = true;
+ printf("[LN_MQTT_API] Dual stream recording started, upload enabled\n");
+#else
+ // 使用原有 MQTT_StartRecord 接口
+ MqttRecordAudioParams audioParams = {
+ .audioFormat = SBC, // SBC 格式
+ .channelCount = 1, // 单声道
+ .sampleRate = 16000 // 16kHz 采样率
+ };
+
+ int32_t rec_ret = MQTT_StartRecord(ln_mqtt_record_data_cb, NULL, &audioParams);
+ if (rec_ret != 0) {
+ printf("[LN_MQTT_API] WARNING: MQTT_StartRecord failed: %d\n", (int)rec_ret);
+ } else {
+ printf("[LN_MQTT_API] MQTT_StartRecord started with SBC format (16kHz, mono)\n");
+ }
+#endif /* USE_DUAL_STREAM_INTERFACE */
+ } else {
+ // 停止录音前,先刷新缓存中剩余的数据
+ if (g_record_cache.buffer != NULL && g_record_cache.current_size > 0) {
+ printf("[LN_MQTT_API] Flushing remaining cached audio data: %u bytes, %u packets\n",
+ g_record_cache.current_size, g_record_cache.packet_count);
+ if (ln_udp_audio_send_enqueue(g_record_cache.buffer, g_record_cache.current_size) != 0) {
+ printf("[LN_MQTT_API] Failed to enqueue remaining cached audio data\n");
+ }
+ g_record_cache.current_size = 0;
+ g_record_cache.packet_count = 0;
+ }
+ // 释放缓存缓冲区
+ if (g_record_cache.buffer != NULL) {
+ free(g_record_cache.buffer);
+ g_record_cache.buffer = NULL;
+ g_record_cache.buffer_size = 0;
+ printf("[LN_MQTT_API] Cache buffer freed\n");
+ }
+
+#if USE_DUAL_STREAM_INTERFACE
+ // 清除录音上传标志位,停止处理并上传音频数据
+ g_recording_upload_started = false;
+ printf("[LN_MQTT_API] Dual stream recording stopped, upload disabled (AI voice service still running)\n");
+#else
+ // 停止原有 MQTT_StartRecord 接口
+ (void)MQTT_StopRecord();
+#endif /* USE_DUAL_STREAM_INTERFACE */
+ }
+
+ return 0;
+}
+
+
+/**
+ * @brief 获取UDP信息
+ * @param udp_info 输出的UDP信息结构体指针
+ * @return 0 成功(信息有效),-1 失败(信息无效或未设置)
+ */
+int ln_mqtt_api_get_udp_info(ln_mqtt_udp_info_t *udp_info)
+{
+ if (!udp_info) {
+ return -1;
+ }
+
+ if (!g_udp_info.valid) {
+ printf("[LN_MQTT_API] UDP info not available or invalid\n");
+ return -1;
+ }
+
+ // 复制UDP信息
+ memcpy(udp_info, &g_udp_info, sizeof(ln_mqtt_udp_info_t));
+ return 0;
+}
+
+// {
+// "session_id": "3326285112",
+// "type": "listen",
+// "state": "start",
+// "mode": "auto"
+// }
\ No newline at end of file
--- /dev/null
+#ifndef LN_MQTT_API_H
+#define LN_MQTT_API_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "uapi_Mqtt_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef USE_DUAL_STREAM_INTERFACE
+#define USE_DUAL_STREAM_INTERFACE 1
+#endif
+
+/**
+ * @brief 启动MQTT服务(启动线程、自动连接等)
+ * @note 启动服务时会自动进行初始化,无需单独调用初始化函数
+ * @note 服务模式下使用内部回调,自动处理连接状态和消息接收
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_start_service(void);
+
+/**
+ * @brief 停止MQTT服务(停止线程、断开连接等)
+ */
+void ln_mqtt_api_stop_service(void);
+
+
+/**
+ * @brief 检查MQTT连接状态
+ * @return true 已连接,false 未连接
+ */
+bool ln_mqtt_api_is_connected(void);
+
+/**
+ * @brief 发送MQTT hello消息
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_send_hello(void);
+
+/**
+ * @brief 发送 listen 控制消息
+ * @param start true 表示 state=start;false 表示 state=stop
+ * @note session_id 从 hello 消息中解析并在内部保存
+ * @note mode 当前固定发送为 "auto"
+ * @return 0 成功,-1 失败
+ */
+int ln_mqtt_api_send_listen_state(bool start);
+
+/**
+ * @brief UDP信息结构体
+ */
+typedef struct {
+ char server[64]; // UDP服务器地址
+ uint16_t port; // UDP端口
+ char encryption[32]; // 加密方式
+ char key[64]; // 加密密钥
+ char nonce[64]; // 加密随机数
+ bool valid; // 信息是否有效
+} ln_mqtt_udp_info_t;
+
+/**
+ * @brief 获取UDP信息
+ * @param udp_info 输出的UDP信息结构体指针
+ * @return 0 成功(信息有效),-1 失败(信息无效或未设置)
+ */
+int ln_mqtt_api_get_udp_info(ln_mqtt_udp_info_t *udp_info);
+
+/**
+ * @brief 初始化MQTT音频服务
+ * @note 只有在MQTT连接时才进行音频初始化
+ */
+void ln_mqtt_audio_init(void);
+
+/**
+ * @brief 反初始化MQTT音频服务
+ */
+void ln_mqtt_audio_deinit(void);
+
+/**
+ * @brief 获取MQTT音频初始化状态
+ * @return true 已初始化,false 未初始化
+ */
+bool ln_mqtt_is_audio_initialized(void);
+
+/**
+ * @brief 初始化音频发送队列和线程(在 ln_UPD.c 中实现)
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_audio_send_init(void);
+
+/**
+ * @brief 停止音频发送线程
+ */
+void ln_udp_audio_send_deinit(void);
+
+/**
+ * @brief 将音频数据放入发送队列(供录音回调函数调用)
+ * @param data 音频数据指针
+ * @param size 音频数据大小
+ * @return 0 成功,-1 失败
+ */
+int ln_udp_audio_send_enqueue(const uint8_t *data, uint32_t size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LN_MQTT_API_H */
+
--- /dev/null
+/*\r
+ * LN MQTT AT test commands\r
+ * - Follow the style in `leiniao_api_at.c` / `uapi_mqtt_at.c`\r
+ * - Provide simple AT commands to drive LN MQTT listen start/stop and hello send\r
+ */\r
+\r
+#include "at_cmd_api.h"\r
+#include <stdio.h>\r
+#include <stdint.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include "errcode.h"\r
+#include "ln_mqtt_api.h"\r
+#include "ln_mqtt_api_at.h"\r
+#include "cmsis_os2.h"\r
+\r
+#define ARRAY_COUNT(array) (sizeof(array) / sizeof((array)[0]))\r
+#define LN_MQTT_AT_MAX_ARGC 8\r
+#define LN_MQTT_AT_MAX_ARGV_LEN 256\r
+\r
+/* 自动停止定时器(10秒后停止录音) */\r
+static osTimerId_t g_listen_auto_stop_timer = NULL;\r
+\r
+/**\r
+ * @brief 解析AT命令参数\r
+ * 兼容 "AT^XXX=arg1,arg2" 或 "AT^XXX arg1 arg2"\r
+ */\r
+static int ln_mqtt_at_parse_params(uint8_t *para, uint32_t paraLen,\r
+ uint8_t argv[LN_MQTT_AT_MAX_ARGC][LN_MQTT_AT_MAX_ARGV_LEN],\r
+ uint32_t *argc)\r
+{\r
+ uint32_t pos = 0;\r
+ *argc = 0;\r
+\r
+ for (uint32_t i = 0; i < paraLen; i++) {\r
+ if ((para[i] == ' ' || para[i] == '\n' || para[i] == ',' || para[i] == '=') && pos != 0) {\r
+ argv[*argc][pos] = '\0';\r
+ *argc += 1;\r
+ pos = 0;\r
+ if (*argc >= LN_MQTT_AT_MAX_ARGC) {\r
+ return -1;\r
+ }\r
+ } else {\r
+ if (para[i] == ' ' || para[i] == '\n' || para[i] == ',' || para[i] == '=') {\r
+ continue;\r
+ }\r
+ argv[*argc][pos] = para[i];\r
+ pos++;\r
+ if (pos >= LN_MQTT_AT_MAX_ARGV_LEN) {\r
+ return -1;\r
+ }\r
+ }\r
+ }\r
+ if (pos != 0) {\r
+ argv[*argc][pos] = '\0';\r
+ *argc += 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+/**\r
+ * @brief 自动停止录音的定时器回调函数\r
+ */\r
+static void ln_mqtt_listen_auto_stop_callback(void *arg)\r
+{\r
+ (void)arg;\r
+ printf("[LN_MQTT_AT] Auto stop timer expired, stopping listen...\n");\r
+ (void)ln_mqtt_api_send_listen_state(false);\r
+}\r
+\r
+/* LN MQTT - 发送 listen 控制并开始/停止录音:AT^LN_MQTT_LISTEN=1/0 */\r
+static uint32_t ln_mqtt_listen_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)\r
+{\r
+ (void)strCommonCmd;\r
+\r
+ uint8_t argv[LN_MQTT_AT_MAX_ARGC][LN_MQTT_AT_MAX_ARGV_LEN] = {0};\r
+ uint32_t argc = 0;\r
+ if (ln_mqtt_at_parse_params(para, paraLen, argv, &argc) != 0 || argc < 1) {\r
+ printf("Usage: AT^LN_MQTT_LISTEN=1/0\n");\r
+ return ERRCODE_FAIL;\r
+ }\r
+\r
+ int enable = atoi((char *)argv[0]);\r
+ if (enable != 0 && enable != 1) {\r
+ printf("Usage: AT^LN_MQTT_LISTEN=1/0\n");\r
+ return ERRCODE_FAIL;\r
+ }\r
+\r
+ // 如果之前有定时器在运行,先停止\r
+ if (g_listen_auto_stop_timer != NULL) {\r
+ if (osTimerIsRunning(g_listen_auto_stop_timer) == 1) {\r
+ osTimerStop(g_listen_auto_stop_timer);\r
+ }\r
+ }\r
+\r
+ int ret = ln_mqtt_api_send_listen_state(enable ? true : false);\r
+ if (ret == 0) {\r
+ printf("+LN_MQTT_LISTEN: OK\n");\r
+ \r
+ // 如果 enable == 1,启动10秒后自动停止的定时器\r
+ if (enable == 1) {\r
+ // 如果定时器未创建,先创建\r
+ if (g_listen_auto_stop_timer == NULL) {\r
+ g_listen_auto_stop_timer = osTimerNew((osTimerFunc_t)ln_mqtt_listen_auto_stop_callback, \r
+ osTimerOnce, NULL, NULL);\r
+ if (g_listen_auto_stop_timer == NULL) {\r
+ printf("[LN_MQTT_AT] WARNING: Failed to create auto stop timer\n");\r
+ }\r
+ }\r
+ \r
+ // 启动定时器(10秒 = 10000毫秒)\r
+ if (g_listen_auto_stop_timer != NULL) {\r
+ osStatus_t timer_ret = osTimerStart(g_listen_auto_stop_timer, 10000);\r
+ if (timer_ret != osOK) {\r
+ printf("[LN_MQTT_AT] WARNING: Failed to start auto stop timer: %d\n", timer_ret);\r
+ } else {\r
+ printf("[LN_MQTT_AT] Auto stop timer started (10 seconds)\n");\r
+ }\r
+ }\r
+ }\r
+ \r
+ return ERRCODE_SUCC;\r
+ }\r
+ printf("+LN_MQTT_LISTEN: FAIL\n");\r
+ return ERRCODE_FAIL;\r
+}\r
+\r
+/* LN MQTT - 发送 hello:AT^LN_MQTT_HELLO */\r
+static uint32_t ln_mqtt_hello_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)\r
+{\r
+ (void)para;\r
+ (void)paraLen;\r
+ (void)strCommonCmd;\r
+\r
+ int ret = ln_mqtt_api_send_hello();\r
+ if (ret == 0) {\r
+ printf("+LN_MQTT_HELLO: OK\n");\r
+ return ERRCODE_SUCC;\r
+ }\r
+ printf("+LN_MQTT_HELLO: FAIL\n");\r
+ return ERRCODE_FAIL;\r
+}\r
+\r
+/* LN MQTT - 启动服务:AT^LN_MQTT_START_SERVICE */\r
+static uint32_t ln_mqtt_start_service_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)\r
+{\r
+ (void)para;\r
+ (void)paraLen;\r
+ (void)strCommonCmd;\r
+\r
+ printf("[LN_MQTT_AT] Starting MQTT service...\n");\r
+ int ret = ln_mqtt_api_start_service();\r
+ if (ret == 0) {\r
+ printf("+LN_MQTT_START_SERVICE: OK\n");\r
+ return ERRCODE_SUCC;\r
+ }\r
+ printf("+LN_MQTT_START_SERVICE: FAIL\n");\r
+ return ERRCODE_FAIL;\r
+}\r
+\r
+/* LN MQTT - 停止服务:AT^LN_MQTT_STOP_SERVICE */\r
+static uint32_t ln_mqtt_stop_service_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)\r
+{\r
+ (void)para;\r
+ (void)paraLen;\r
+ (void)strCommonCmd;\r
+\r
+ printf("[LN_MQTT_AT] Stopping MQTT service...\n");\r
+ ln_mqtt_api_stop_service();\r
+ printf("+LN_MQTT_STOP_SERVICE: OK\n");\r
+ return ERRCODE_SUCC;\r
+}\r
+\r
+static const at_cmd_table_t g_ln_mqtt_at_cmds[] = {\r
+ {(char *)"AT^LN_MQTT_LISTEN", ln_mqtt_listen_at, (char *)"LN MQTT listen start/stop: AT^LN_MQTT_LISTEN=1/0"},\r
+ {(char *)"AT^LN_MQTT_HELLO", ln_mqtt_hello_at, (char *)"LN MQTT send hello: AT^LN_MQTT_HELLO"},\r
+ {(char *)"AT^LN_MQTT_START_SERVICE", ln_mqtt_start_service_at, (char *)"LN MQTT start service: AT^LN_MQTT_START_SERVICE"},\r
+ {(char *)"AT^LN_MQTT_STOP_SERVICE", ln_mqtt_stop_service_at, (char *)"LN MQTT stop service: AT^LN_MQTT_STOP_SERVICE"},\r
+};\r
+\r
+at_cmd_table_t *get_ln_mqtt_at_cmd_table(uint32_t *cmd_count)\r
+{\r
+ if (cmd_count) {\r
+ *cmd_count = ARRAY_COUNT(g_ln_mqtt_at_cmds);\r
+ }\r
+ return (at_cmd_table_t *)g_ln_mqtt_at_cmds;\r
+}\r
+\r
--- /dev/null
+#ifndef LN_MQTT_API_AT_H\r
+#define LN_MQTT_API_AT_H\r
+\r
+#include <stdint.h>\r
+#include "at_cmd_api.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* 导出 LN MQTT AT 指令表 */\r
+at_cmd_table_t *get_ln_mqtt_at_cmd_table(uint32_t *cmd_count);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* LN_MQTT_API_AT_H */\r
--- /dev/null
+#ifndef LN_OTA_AT_H
+#define LN_OTA_AT_H
+
+#include <stdint.h>
+#include "at_cmd_api.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* OTA AT 指令表导出 */
+at_cmd_table_t *get_ln_ota_at_cmd_table(uint32_t *cmd_count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LN_OTA_AT_H */
+
--- /dev/null
+# 在 test_opus_frame_to_pcm 中构建最小 Opus 解码库\r
+\r
+本文档说明如何在 `test_opus_frame_to_pcm` 目录中从源码直接编译生成最小化的 Opus 解码库 `libopus_min.a`。\r
+\r
+## 概述\r
+\r
+这个构建系统允许你:\r
+1. 只保留解码器必需的源码文件\r
+2. 在 `test_opus_frame_to_pcm` 目录中独立编译\r
+3. 生成一个最小化的 `libopus_min.a` 静态库\r
+4. 验证 `opus_frame_to_pcm` 工具可以正常工作\r
+\r
+## 快速开始\r
+\r
+### 1. 复制必需的源码文件\r
+\r
+运行脚本复制所有必需的源码文件:\r
+\r
+```bash\r
+cd test_opus_frame_to_pcm\r
+./copy_sources.sh\r
+```\r
+\r
+这个脚本会:\r
+- 从主项目复制所有解码器相关的 `.c` 文件\r
+- 复制所有必需的头文件 (`.h`)\r
+- 创建必要的目录结构\r
+\r
+### 2. 复制配置文件\r
+\r
+确保 `config.h` 来自主项目(包含正确的编译定义):\r
+\r
+```bash\r
+cp ../config.h config.h\r
+```\r
+\r
+### 3. 复制额外的头文件\r
+\r
+复制一些可能缺失的头文件:\r
+\r
+```bash\r
+# Opus API 头文件\r
+cp ../include/opus_custom.h include/\r
+cp ../include/opus_multistream.h include/\r
+cp ../include/opus_projection.h include/\r
+\r
+# 主项目 src 目录的头文件\r
+find ../src -name '*.h' -exec cp {} src_lib/ \;\r
+\r
+# x86 优化头文件\r
+cp ../celt/x86/*.h celt/x86/ 2>/dev/null || true\r
+cp ../silk/x86/*.h silk/x86/ 2>/dev/null || true\r
+\r
+# SILK 头文件\r
+find ../silk -name '*.h' -exec cp {} silk/ \;\r
+```\r
+\r
+### 4. 编译库\r
+\r
+使用 `Makefile.libopus` 编译:\r
+\r
+```bash\r
+make -f Makefile.libopus\r
+```\r
+\r
+这将:\r
+- 编译所有源文件为 `.o` 对象文件\r
+- 使用 `ar` 创建 `libopus_min.a` 静态库\r
+- 运行 `ranlib` 生成索引\r
+\r
+### 5. 测试\r
+\r
+编译 `opus_frame_to_pcm` 工具并测试:\r
+\r
+```bash\r
+make clean\r
+make\r
+./opus_frame_to_pcm test_frame.opus -o test_output.pcm -r 16000 -c 1\r
+```\r
+\r
+## 文件结构\r
+\r
+构建后的目录结构:\r
+\r
+```\r
+test_opus_frame_to_pcm/\r
+├── src_lib/ # Opus API 层源码(解码器)\r
+├── celt/ # CELT 解码器源码\r
+│ └── x86/ # CELT x86 优化\r
+├── silk/ # SILK 解码器源码\r
+│ ├── float/ # SILK 浮点实现\r
+│ └── x86/ # SILK x86 优化\r
+├── include/ # Opus 公共头文件\r
+├── config.h # 编译配置\r
+├── Makefile.libopus # 库构建 Makefile\r
+├── copy_sources.sh # 源码复制脚本\r
+└── libopus_min.a # 生成的静态库\r
+```\r
+\r
+## 包含的源码\r
+\r
+### Opus API 层 (7 个文件)\r
+- `src_lib/opus.c`\r
+- `src_lib/opus_decoder.c`\r
+- `src_lib/opus_multistream_decoder.c`\r
+- `src_lib/opus_projection_decoder.c`\r
+- `src_lib/extensions.c`\r
+- `src_lib/repacketizer.c`\r
+- `src_lib/mapping_matrix.c`\r
+\r
+### CELT 解码器 (~17 个文件)\r
+- 核心解码器文件\r
+- x86 SIMD 优化(SSE, SSE2, SSE4.1, AVX)\r
+\r
+### SILK 解码器 (~70 个文件)\r
+- 核心解码器文件\r
+- 信号处理\r
+- NLSF 处理\r
+- 立体声处理\r
+- 表格数据\r
+- 浮点实现\r
+- x86 优化\r
+\r
+## 编译选项\r
+\r
+`Makefile.libopus` 中的主要编译选项:\r
+\r
+- `-Wall -O2`: 警告和优化级别\r
+- `-DHAVE_CONFIG_H`: 使用 config.h\r
+- `-I. -I./include -I./src_lib -I./celt -I./silk ...`: 包含路径\r
+\r
+特殊处理:\r
+- `celt/x86/pitch_avx.c` 需要 `-mavx2 -mfma` 选项\r
+\r
+## 清理\r
+\r
+### 基本清理\r
+\r
+清理所有编译产物:\r
+\r
+```bash\r
+make -f Makefile.libopus clean\r
+```\r
+\r
+清理所有文件(包括源码):\r
+\r
+```bash\r
+make -f Makefile.libopus distclean\r
+```\r
+\r
+### 完全清理(仅保留源码)\r
+\r
+使用清理脚本清理所有编译产物和中间文件,仅保留源码:\r
+\r
+**Linux/macOS:**\r
+```bash\r
+./clean_all.sh\r
+```\r
+\r
+**Windows PowerShell:**\r
+```powershell\r
+.\clean_all.ps1\r
+```\r
+\r
+**或使用 Makefile:**\r
+```bash\r
+make -f Makefile.libopus cleanall\r
+```\r
+\r
+清理脚本会删除:\r
+- 所有 `.o` 对象文件\r
+- 生成的库文件 (`libopus_min.a`, `libopus.a`)\r
+- 可执行文件 (`opus_frame_to_pcm`)\r
+- 测试输出文件\r
+- Makefile 临时文件\r
+- 备份文件 (`*~`, `*.bak`, `*.swp`, `*.tmp`)\r
+\r
+但会保留:\r
+- 所有源码文件 (`.c`)\r
+- 所有头文件 (`.h`)\r
+- 配置文件 (`config.h`)\r
+- 脚本文件 (`.sh`, `.ps1`, `.bat`)\r
+- Makefile 文件\r
+- 文档文件 (`.md`)\r
+\r
+## 库大小\r
+\r
+生成的 `libopus_min.a` 大小约为 **500-600 KB**(取决于编译选项和优化级别)。\r
+\r
+这比完整的 `libopus.a`(通常 2-3 MB)要小得多,因为:\r
+- 排除了所有编码器代码\r
+- 排除了 DNN/DRED/OSCE 等可选功能\r
+- 只包含解码器必需的代码\r
+\r
+## 故障排除\r
+\r
+### 编译错误:缺少头文件\r
+\r
+确保所有头文件都已复制:\r
+```bash\r
+# 重新复制所有头文件\r
+find ../src -name '*.h' -exec cp {} src_lib/ \;\r
+find ../silk -name '*.h' -exec cp {} silk/ \;\r
+cp ../celt/x86/*.h celt/x86/ 2>/dev/null || true\r
+```\r
+\r
+### 编译错误:AVX 相关\r
+\r
+如果系统不支持 AVX2,可以暂时从 `Makefile.libopus` 中移除 `pitch_avx.c`。\r
+\r
+### 链接错误:未定义符号\r
+\r
+确保 `config.h` 包含正确的定义(特别是 `OPUS_BUILD` 和 `VAR_ARRAYS`)。\r
+\r
+## 验证\r
+\r
+成功构建后,验证库是否正常工作:\r
+\r
+```bash\r
+# 编译工具\r
+make\r
+\r
+# 测试解码\r
+./opus_frame_to_pcm test_frame.opus -o test_output.pcm -r 16000 -c 1\r
+\r
+# 检查输出\r
+ls -lh test_output.pcm\r
+```\r
+\r
+如果一切正常,你应该看到:\r
+- 成功编译 `opus_frame_to_pcm`\r
+- 成功解码 Opus 帧\r
+- 生成有效的 PCM 输出文件\r
--- /dev/null
+# 清理脚本使用说明\r
+\r
+## 概述\r
+\r
+`clean_all.sh` (Linux/macOS) 和 `clean_all.ps1` (Windows PowerShell) 用于清理所有编译产物和中间文件,仅保留源码文件。\r
+\r
+## 使用方法\r
+\r
+### Linux/macOS\r
+\r
+```bash\r
+cd test_opus_frame_to_pcm\r
+./clean_all.sh\r
+```\r
+\r
+### Windows PowerShell\r
+\r
+```powershell\r
+cd test_opus_frame_to_pcm\r
+.\clean_all.ps1\r
+```\r
+\r
+### 使用 Makefile\r
+\r
+```bash\r
+make -f Makefile.libopus cleanall\r
+```\r
+\r
+## 清理内容\r
+\r
+脚本会删除以下文件:\r
+\r
+### 编译产物\r
+- 所有 `.o` 对象文件\r
+- 生成的库文件:`libopus_min.a`, `libopus.a` (包括符号链接)\r
+- 可执行文件:`opus_frame_to_pcm`, `opus_frame_to_pcm.exe`\r
+\r
+### 测试文件\r
+- `test_output.pcm`\r
+- `test_output_new.pcm`\r
+- `test_frame.opus`\r
+\r
+### 临时文件\r
+- Makefile 依赖文件 (`.d`)\r
+- 备份文件 (`*~`, `*.bak`, `*.swp`, `*.tmp`)\r
+- 其他临时文件\r
+\r
+## 保留的文件\r
+\r
+清理后,以下文件会被保留:\r
+\r
+- ✅ 所有源码文件 (`.c`)\r
+- ✅ 所有头文件 (`.h`)\r
+- ✅ 配置文件 (`config.h`)\r
+- ✅ 脚本文件 (`.sh`, `.ps1`, `.bat`)\r
+- ✅ Makefile 文件 (`Makefile`, `Makefile.libopus`)\r
+- ✅ 文档文件 (`.md`)\r
+\r
+## 示例\r
+\r
+### 清理前\r
+```\r
+test_opus_frame_to_pcm/\r
+├── src_lib/\r
+│ ├── opus.c\r
+│ ├── opus.o ← 将被删除\r
+│ └── opus_decoder.c\r
+├── libopus_min.a ← 将被删除\r
+├── opus_frame_to_pcm ← 将被删除\r
+└── test_output.pcm ← 将被删除\r
+```\r
+\r
+### 清理后\r
+```\r
+test_opus_frame_to_pcm/\r
+├── src_lib/\r
+│ ├── opus.c ← 保留\r
+│ └── opus_decoder.c ← 保留\r
+└── (其他源码文件) ← 保留\r
+```\r
+\r
+## 重新构建\r
+\r
+清理后,可以重新构建:\r
+\r
+```bash\r
+# 1. 确保源码已复制(如果之前已清理源码)\r
+./copy_sources.sh\r
+\r
+# 2. 编译库\r
+make -f Makefile.libopus\r
+\r
+# 3. 编译工具\r
+make\r
+```\r
+\r
+## 注意事项\r
+\r
+1. **清理是不可逆的**:删除的文件无法恢复,请确保已保存重要数据\r
+2. **符号链接**:脚本会正确处理符号链接(如 `libopus.a -> libopus_min.a`)\r
+3. **空目录**:脚本会尝试清理空目录,但会保留源码目录结构\r
+4. **权限**:确保脚本有执行权限(`chmod +x clean_all.sh`)\r
+\r
+## 与其他清理命令的区别\r
+\r
+| 命令 | 清理范围 |\r
+|------|---------|\r
+| `make -f Makefile.libopus clean` | 仅清理 Makefile.libopus 生成的文件 |\r
+| `make clean` | 仅清理主 Makefile 生成的文件 |\r
+| `./clean_all.sh` | **完全清理**:所有编译产物和中间文件 |\r
+| `make -f Makefile.libopus distclean` | 清理所有文件,包括源码目录 |\r
+\r
+## 故障排除\r
+\r
+### 权限错误\r
+```bash\r
+chmod +x clean_all.sh\r
+```\r
+\r
+### 找不到文件\r
+如果某些文件不存在,脚本会跳过,不会报错。\r
+\r
+### 符号链接问题\r
+脚本会自动检测并正确处理符号链接。\r
--- /dev/null
+cmake_minimum_required(VERSION 3.16)
+
+# 设置模块名称
+# 注意:系统链接阶段依赖的是 -lopus_frame_to_pcm_interface
+# build_component() 通常会基于 COMPONENT_NAME 生成 *_interface 库名
+# 因此这里 COMPONENT_NAME 需要为 "opus_frame_to_pcm",以产出 "opus_frame_to_pcm_interface"
+set(COMPONENT_NAME "opus_frame_to_pcm")
+
+# 应用主程序
+set(SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/opus_frame_to_pcm.c
+)
+
+# 将 opus 库的 .c 源文件全部链接进来(替代原有静态库)
+file(GLOB OPUS_SRC_LIB "${CMAKE_CURRENT_SOURCE_DIR}/src_lib/*.c")
+file(GLOB OPUS_CELT "${CMAKE_CURRENT_SOURCE_DIR}/celt/*.c")
+file(GLOB OPUS_SILK "${CMAKE_CURRENT_SOURCE_DIR}/silk/*.c")
+file(GLOB OPUS_SILK_FLOAT "${CMAKE_CURRENT_SOURCE_DIR}/silk/float/*.c")
+
+# 仅 x86 平台编译 SIMD 优化源;非 x86(如 ARM/Cortex/RISC-V)不包含,使用 C 通用实现
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "[xX]86|i686|AMD64|x86_64")
+ file(GLOB OPUS_CELT_X86 "${CMAKE_CURRENT_SOURCE_DIR}/celt/x86/*.c")
+ file(GLOB OPUS_SILK_X86 "${CMAKE_CURRENT_SOURCE_DIR}/silk/x86/*.c")
+ list(APPEND SOURCES ${OPUS_SRC_LIB} ${OPUS_CELT} ${OPUS_CELT_X86} ${OPUS_SILK} ${OPUS_SILK_FLOAT} ${OPUS_SILK_X86})
+else()
+ # 非 x86 平台:排除 x86 特定的 AVX2 文件
+ list(REMOVE_ITEM OPUS_SILK_FLOAT "${CMAKE_CURRENT_SOURCE_DIR}/silk/float/inner_product_FLP_avx2.c")
+ list(APPEND SOURCES ${OPUS_SRC_LIB} ${OPUS_CELT} ${OPUS_SILK} ${OPUS_SILK_FLOAT})
+endif()
+
+# 头文件目录
+set(PUBLIC_HEADER
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+)
+
+set(PRIVATE_HEADER
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/src_lib
+ ${CMAKE_CURRENT_SOURCE_DIR}/silk
+ ${CMAKE_CURRENT_SOURCE_DIR}/silk/float
+ ${CMAKE_CURRENT_SOURCE_DIR}/celt
+)
+
+set(PUBLIC_DEFINES
+ SUPPORT_OPUS_FRAME_TO_PCM
+ # 非 x86 平台避免引入本目录的 config.h(其包含 x86/RTCD 宏会导致引用 *_sse 等符号)
+ # 如需平台特定优化,可在对应架构下单独打开
+ OPUS_BUILD=1
+ OPUS_HAVE_RTCD=0
+ # 选择 Opus 临时内存分配方式:使用 C99 VLA,避免 pseudostack/ALIGN 冲突
+ VAR_ARRAYS=1
+ # 解决 celt/float_cast.h 在 -Werror 下的 #warning 报错
+ HAVE_LRINT=1
+ HAVE_LRINTF=1
+)
+
+set(PRIVATE_DEFINES
+)
+
+set(COMPONENT_PUBLIC_CCFLAGS
+)
+
+# 编译选项
+set(COMPONENT_CCFLAGS
+ -Wall
+ -Wextra
+ -O2
+)
+
+# 是否整体链接
+set(WHOLE_LINK
+ false
+)
+
+# 是否为主组件
+set(MAIN_COMPONENT
+ false
+)
+
+# 构建组件
+build_component()
--- /dev/null
+# Makefile for opus_frame_to_pcm test\r
+# This is a minimal build configuration for testing\r
+\r
+CC = gcc\r
+CFLAGS = -Wall -O2 -I. -I./include -I./src\r
+LDFLAGS = -L. -lopus -lm\r
+\r
+# Source files\r
+SRC_DIR = src\r
+INCLUDE_DIR = include\r
+\r
+# Target executable\r
+TARGET = opus_frame_to_pcm\r
+\r
+# Source file\r
+SOURCES = $(SRC_DIR)/opus_frame_to_pcm.c\r
+\r
+# Object files\r
+OBJECTS = $(SOURCES:.c=.o)\r
+\r
+# Default target\r
+all: $(TARGET)\r
+\r
+# Build executable\r
+LIBOPUS ?= libopus_min.a\r
+\r
+$(TARGET): $(OBJECTS) $(LIBOPUS)\r
+ # Ensure we link against the chosen archive name\r
+ @if [ "$(LIBOPUS)" != "libopus.a" ]; then \\r
+ rm -f libopus.a; \\r
+ ln -s "$(LIBOPUS)" libopus.a; \\r
+ fi\r
+ $(CC) $(OBJECTS) -o $(TARGET) $(LDFLAGS)\r
+\r
+# Compile source files\r
+$(SRC_DIR)/%.o: $(SRC_DIR)/%.c\r
+ $(CC) $(CFLAGS) -c $< -o $@\r
+\r
+# Check if libopus.a exists\r
+$(LIBOPUS):\r
+ @if [ ! -f $(LIBOPUS) ]; then \\r
+ echo "Error: libopus.a not found!"; \\r
+ echo "Please create $(LIBOPUS) first."; \\r
+ echo "Recommended (PowerShell):"; \\r
+ echo " ./build_min_libopus.ps1"; \\r
+ echo "Fallback: copy the full libopus.a as $(LIBOPUS) (NOT recommended for size validation)."; \\r
+ exit 1; \\r
+ fi\r
+\r
+# Clean build artifacts\r
+clean:\r
+ rm -f $(OBJECTS) $(TARGET)\r
+\r
+# Test with a sample file (if available)\r
+test: $(TARGET)\r
+ @if [ -f test_frame.opus ]; then \\r
+ ./$(TARGET) test_frame.opus -o test_output.pcm -r 16000 -c 1; \\r
+ echo "Test completed. Check test_output.pcm"; \\r
+ else \\r
+ echo "No test_frame.opus found. Please provide a test file."; \\r
+ fi\r
+\r
+.PHONY: all clean test\r
--- /dev/null
+# Makefile for building minimal Opus decoder library (libopus_min.a)\r
+# This builds a decoder-only library from source files\r
+\r
+CC = gcc\r
+AR = ar\r
+RANLIB = ranlib\r
+\r
+# Compiler flags\r
+CFLAGS = -Wall -O2 -I. -I./include -I./src_lib -I./celt -I./silk -I./silk/float -I./silk/fixed\r
+CFLAGS += -DHAVE_CONFIG_H -I.\r
+\r
+# Optional: Use fixed-point mode (smaller, but lower quality)\r
+# CFLAGS += -DFIXED_POINT\r
+\r
+# Optional: Disable float API\r
+# CFLAGS += -DDISABLE_FLOAT_API\r
+\r
+# Library name\r
+LIBRARY = libopus_min.a\r
+\r
+# Source directories\r
+SRC_LIB_DIR = src_lib\r
+CELT_DIR = celt\r
+SILK_DIR = silk\r
+\r
+# Opus API layer sources (decoder only)\r
+OPUS_SOURCES = \\r
+ $(SRC_LIB_DIR)/opus.c \\r
+ $(SRC_LIB_DIR)/opus_decoder.c \\r
+ $(SRC_LIB_DIR)/opus_multistream_decoder.c \\r
+ $(SRC_LIB_DIR)/opus_projection_decoder.c \\r
+ $(SRC_LIB_DIR)/extensions.c \\r
+ $(SRC_LIB_DIR)/repacketizer.c \\r
+ $(SRC_LIB_DIR)/mapping_matrix.c\r
+\r
+# CELT decoder sources\r
+CELT_SOURCES = \\r
+ $(CELT_DIR)/bands.c \\r
+ $(CELT_DIR)/celt.c \\r
+ $(CELT_DIR)/celt_decoder.c \\r
+ $(CELT_DIR)/cwrs.c \\r
+ $(CELT_DIR)/entcode.c \\r
+ $(CELT_DIR)/entdec.c \\r
+ $(CELT_DIR)/entenc.c \\r
+ $(CELT_DIR)/kiss_fft.c \\r
+ $(CELT_DIR)/laplace.c \\r
+ $(CELT_DIR)/mathops.c \\r
+ $(CELT_DIR)/mdct.c \\r
+ $(CELT_DIR)/modes.c \\r
+ $(CELT_DIR)/pitch.c \\r
+ $(CELT_DIR)/celt_lpc.c \\r
+ $(CELT_DIR)/quant_bands.c \\r
+ $(CELT_DIR)/rate.c \\r
+ $(CELT_DIR)/vq.c\r
+\r
+# CELT x86 optimization (if available)\r
+CELT_X86_SOURCES = \\r
+ $(CELT_DIR)/x86/x86cpu.c \\r
+ $(CELT_DIR)/x86/x86_celt_map.c \\r
+ $(CELT_DIR)/x86/pitch_sse.c \\r
+ $(CELT_DIR)/x86/pitch_sse2.c \\r
+ $(CELT_DIR)/x86/vq_sse2.c \\r
+ $(CELT_DIR)/x86/celt_lpc_sse4_1.c \\r
+ $(CELT_DIR)/x86/pitch_sse4_1.c \\r
+ $(CELT_DIR)/x86/pitch_avx.c\r
+\r
+# SILK decoder sources (core)\r
+SILK_CORE_SOURCES = \\r
+ $(SILK_DIR)/dec_API.c \\r
+ $(SILK_DIR)/init_decoder.c \\r
+ $(SILK_DIR)/decode_core.c \\r
+ $(SILK_DIR)/decode_frame.c \\r
+ $(SILK_DIR)/decode_parameters.c \\r
+ $(SILK_DIR)/decode_indices.c \\r
+ $(SILK_DIR)/decode_pulses.c \\r
+ $(SILK_DIR)/decoder_set_fs.c\r
+\r
+# SILK signal processing (shared)\r
+SILK_SIGNAL_SOURCES = \\r
+ $(SILK_DIR)/CNG.c \\r
+ $(SILK_DIR)/PLC.c \\r
+ $(SILK_DIR)/resampler.c \\r
+ $(SILK_DIR)/resampler_down2_3.c \\r
+ $(SILK_DIR)/resampler_down2.c \\r
+ $(SILK_DIR)/resampler_private_AR2.c \\r
+ $(SILK_DIR)/resampler_private_down_FIR.c \\r
+ $(SILK_DIR)/resampler_private_IIR_FIR.c \\r
+ $(SILK_DIR)/resampler_private_up2_HQ.c \\r
+ $(SILK_DIR)/resampler_rom.c \\r
+ $(SILK_DIR)/biquad_alt.c \\r
+ $(SILK_DIR)/bwexpander_32.c \\r
+ $(SILK_DIR)/bwexpander.c \\r
+ $(SILK_DIR)/LP_variable_cutoff.c \\r
+ $(SILK_DIR)/HP_variable_cutoff.c\r
+\r
+# SILK NLSF processing\r
+SILK_NLSF_SOURCES = \\r
+ $(SILK_DIR)/NLSF_decode.c \\r
+ $(SILK_DIR)/NLSF_unpack.c \\r
+ $(SILK_DIR)/NLSF2A.c \\r
+ $(SILK_DIR)/NLSF_stabilize.c \\r
+ $(SILK_DIR)/A2NLSF.c \\r
+ $(SILK_DIR)/NLSF_VQ_weights_laroia.c \\r
+ $(SILK_DIR)/table_LSF_cos.c \\r
+ $(SILK_DIR)/LPC_inv_pred_gain.c\r
+\r
+# SILK stereo processing\r
+SILK_STEREO_SOURCES = \\r
+ $(SILK_DIR)/stereo_MS_to_LR.c \\r
+ $(SILK_DIR)/stereo_decode_pred.c \\r
+ $(SILK_DIR)/stereo_find_predictor.c\r
+\r
+# SILK tables\r
+SILK_TABLE_SOURCES = \\r
+ $(SILK_DIR)/tables_gain.c \\r
+ $(SILK_DIR)/tables_LTP.c \\r
+ $(SILK_DIR)/tables_NLSF_CB_NB_MB.c \\r
+ $(SILK_DIR)/tables_NLSF_CB_WB.c \\r
+ $(SILK_DIR)/tables_other.c \\r
+ $(SILK_DIR)/tables_pitch_lag.c \\r
+ $(SILK_DIR)/tables_pulses_per_block.c \\r
+ $(SILK_DIR)/pitch_est_tables.c\r
+\r
+# SILK helper functions\r
+SILK_HELPER_SOURCES = \\r
+ $(SILK_DIR)/code_signs.c \\r
+ $(SILK_DIR)/interpolate.c \\r
+ $(SILK_DIR)/shell_coder.c \\r
+ $(SILK_DIR)/decode_pitch.c \\r
+ $(SILK_DIR)/inner_prod_aligned.c \\r
+ $(SILK_DIR)/lin2log.c \\r
+ $(SILK_DIR)/log2lin.c \\r
+ $(SILK_DIR)/LPC_analysis_filter.c \\r
+ $(SILK_DIR)/LPC_fit.c \\r
+ $(SILK_DIR)/sigm_Q15.c \\r
+ $(SILK_DIR)/sort.c \\r
+ $(SILK_DIR)/sum_sqr_shift.c \\r
+ $(SILK_DIR)/gain_quant.c\r
+\r
+# SILK float implementation (default, comment out if using fixed-point)\r
+SILK_FLOAT_SOURCES = \\r
+ $(SILK_DIR)/float/apply_sine_window_FLP.c \\r
+ $(SILK_DIR)/float/corrMatrix_FLP.c \\r
+ $(SILK_DIR)/float/find_LPC_FLP.c \\r
+ $(SILK_DIR)/float/find_LTP_FLP.c \\r
+ $(SILK_DIR)/float/find_pitch_lags_FLP.c \\r
+ $(SILK_DIR)/float/find_pred_coefs_FLP.c \\r
+ $(SILK_DIR)/float/LPC_analysis_filter_FLP.c \\r
+ $(SILK_DIR)/float/LTP_analysis_filter_FLP.c \\r
+ $(SILK_DIR)/float/LTP_scale_ctrl_FLP.c \\r
+ $(SILK_DIR)/float/noise_shape_analysis_FLP.c \\r
+ $(SILK_DIR)/float/process_gains_FLP.c \\r
+ $(SILK_DIR)/float/regularize_correlations_FLP.c \\r
+ $(SILK_DIR)/float/residual_energy_FLP.c \\r
+ $(SILK_DIR)/float/warped_autocorrelation_FLP.c \\r
+ $(SILK_DIR)/float/wrappers_FLP.c \\r
+ $(SILK_DIR)/float/autocorrelation_FLP.c \\r
+ $(SILK_DIR)/float/burg_modified_FLP.c \\r
+ $(SILK_DIR)/float/bwexpander_FLP.c \\r
+ $(SILK_DIR)/float/energy_FLP.c \\r
+ $(SILK_DIR)/float/inner_product_FLP.c \\r
+ $(SILK_DIR)/float/k2a_FLP.c \\r
+ $(SILK_DIR)/float/LPC_inv_pred_gain_FLP.c \\r
+ $(SILK_DIR)/float/pitch_analysis_core_FLP.c \\r
+ $(SILK_DIR)/float/scale_copy_vector_FLP.c \\r
+ $(SILK_DIR)/float/scale_vector_FLP.c \\r
+ $(SILK_DIR)/float/schur_FLP.c \\r
+ $(SILK_DIR)/float/sort_FLP.c\r
+\r
+# SILK x86 optimization (if available)\r
+SILK_X86_SOURCES = \\r
+ $(SILK_DIR)/x86/x86_silk_map.c\r
+\r
+# Combine all sources\r
+ALL_SOURCES = \\r
+ $(OPUS_SOURCES) \\r
+ $(CELT_SOURCES) \\r
+ $(CELT_X86_SOURCES) \\r
+ $(SILK_CORE_SOURCES) \\r
+ $(SILK_SIGNAL_SOURCES) \\r
+ $(SILK_NLSF_SOURCES) \\r
+ $(SILK_STEREO_SOURCES) \\r
+ $(SILK_TABLE_SOURCES) \\r
+ $(SILK_HELPER_SOURCES) \\r
+ $(SILK_FLOAT_SOURCES) \\r
+ $(SILK_X86_SOURCES)\r
+\r
+# Object files\r
+OBJECTS = $(ALL_SOURCES:.c=.o)\r
+\r
+# Default target\r
+all: $(LIBRARY)\r
+\r
+# Build library\r
+$(LIBRARY): $(OBJECTS)\r
+ @echo "Creating $(LIBRARY)..."\r
+ $(AR) rcs $(LIBRARY) $(OBJECTS)\r
+ $(RANLIB) $(LIBRARY)\r
+ @echo "Library created: $(LIBRARY)"\r
+ @ls -lh $(LIBRARY)\r
+\r
+# Compile source files\r
+%.o: %.c\r
+ @echo "Compiling $<..."\r
+ @mkdir -p $(dir $@)\r
+ $(CC) $(CFLAGS) -c $< -o $@\r
+\r
+# Special handling for AVX files (requires -mavx2 -mfma)\r
+celt/x86/pitch_avx.o: celt/x86/pitch_avx.c\r
+ @echo "Compiling $< (AVX2+FMA)..."\r
+ @mkdir -p $(dir $@)\r
+ $(CC) $(CFLAGS) -mavx2 -mfma -c $< -o $@\r
+\r
+# Check if source files exist\r
+check-sources:\r
+ @echo "Checking source files..."\r
+ @missing=0; \\r
+ for src in $(ALL_SOURCES); do \\r
+ if [ ! -f "$$src" ]; then \\r
+ echo "Missing: $$src"; \\r
+ missing=1; \\r
+ fi; \\r
+ done; \\r
+ if [ $$missing -eq 1 ]; then \\r
+ echo "Error: Some source files are missing!"; \\r
+ echo "Please run: ./copy_sources.sh"; \\r
+ exit 1; \\r
+ else \\r
+ echo "All source files present."; \\r
+ fi\r
+\r
+# Clean build artifacts\r
+clean:\r
+ rm -f $(OBJECTS) $(LIBRARY)\r
+ find . -name "*.o" -type f -delete\r
+\r
+# Clean everything including source files\r
+distclean: clean\r
+ rm -rf $(SRC_LIB_DIR) $(CELT_DIR) $(SILK_DIR)\r
+\r
+# Clean all build artifacts and intermediate files (keep source only)\r
+cleanall:\r
+ @echo "Running comprehensive cleanup..."\r
+ @if [ -f "./clean_all.sh" ]; then \\r
+ chmod +x ./clean_all.sh; \\r
+ ./clean_all.sh; \\r
+ else \\r
+ echo "Warning: clean_all.sh not found, using basic clean"; \\r
+ $(MAKE) clean; \\r
+ fi\r
+\r
+.PHONY: all clean distclean cleanall check-sources\r
--- /dev/null
+# Opus Frame to PCM 测试环境\r
+\r
+这是一个用于验证 `opus_frame_to_pcm.c` 功能的独立测试环境。\r
+\r
+## 目录结构\r
+\r
+```\r
+test_opus_frame_to_pcm/\r
+├── src/\r
+│ └── opus_frame_to_pcm.c # 测试的源代码文件\r
+├── include/\r
+│ ├── opus.h # Opus API 头文件\r
+│ ├── opus_defines.h # Opus 定义\r
+│ └── opus_types.h # Opus 类型定义\r
+├── libopus.a # Opus 静态库(需要从主项目复制)\r
+├── Makefile # 构建脚本\r
+└── README.md # 本文件\r
+```\r
+\r
+## 依赖要求\r
+\r
+### 必需文件\r
+\r
+1. **libopus.a** - Opus 静态库\r
+ - 可以从主项目的 `.libs/libopus.a` 复制\r
+ - 或者从主项目构建:`cd opus-1.6.1 && make`\r
+\r
+2. **头文件** - 已包含在 `include/` 目录中\r
+\r
+### 系统要求\r
+\r
+- GCC 编译器(或兼容的 C 编译器)\r
+- Make 工具\r
+- 数学库(libm,通常系统自带)\r
+\r
+## 构建步骤\r
+\r
+### 1. 准备库文件\r
+\r
+如果你要验证“删减解码库代码”是否可行,**不要**直接复制主工程的 `libopus.a`。\r
+\r
+推荐创建一个新的 **decoder-only** 静态库:`libopus_min.a`。\r
+\r
+#### 方式 A(Linux/WSL,推荐):生成 libopus_min.a\r
+\r
+先确保主工程已经编译出 `src/*.o`、`celt/*.o`、`silk/*.o`:\r
+\r
+```bash\r
+make\r
+```\r
+\r
+然后生成最小库:\r
+\r
+```bash\r
+./test_opus_frame_to_pcm/build_min_libopus.sh\r
+```\r
+\r
+生成结果:\r
+\r
+- `test_opus_frame_to_pcm/libopus_min.a`\r
+\r
+> Windows 原生 PowerShell 环境如果没有 `ar`(binutils),无法生成 `.a`,建议使用 WSL 或安装 MSYS2/MinGW(带 ar.exe)。\r
+\r
+#### 方式 B(仅验证工具能跑,不验证删减):复制完整 libopus.a\r
+\r
+如果只是想验证 `opus_frame_to_pcm.c` 能编译运行(不关心库是否精简),可以从主项目复制:\r
+\r
+```bash\r
+# 在 opus-1.6.1 目录下\r
+make\r
+cp .libs/libopus.a test_opus_frame_to_pcm/\r
+```\r
+\r
+### 2. 编译\r
+\r
+```bash\r
+cd test_opus_frame_to_pcm\r
+make\r
+```\r
+\r
+### 3. 测试\r
+\r
+```bash\r
+# 使用测试文件(如果有)\r
+make test\r
+\r
+# 或手动测试\r
+./opus_frame_to_pcm test_frame.opus -o output.pcm -r 16000 -c 1\r
+```\r
+\r
+## 使用方法\r
+\r
+```bash\r
+./opus_frame_to_pcm <input_file> [options]\r
+\r
+选项:\r
+ -o, --output FILE 输出 PCM 文件(默认:标准输出)\r
+ -r, --rate RATE 采样率(Hz,默认:16000)\r
+ -c, --channels N 声道数(默认:1)\r
+ -h, --help 显示帮助信息\r
+```\r
+\r
+## 示例\r
+\r
+```bash\r
+# 基本用法\r
+./opus_frame_to_pcm frame.opus -o output.pcm -r 16000 -c 1\r
+\r
+# 输出到标准输出\r
+./opus_frame_to_pcm frame.opus -r 48000 -c 2 > output.pcm\r
+\r
+# 查看帮助\r
+./opus_frame_to_pcm -h\r
+```\r
+\r
+## 验证功能\r
+\r
+### 1. 编译验证\r
+\r
+```bash\r
+make clean\r
+make\r
+```\r
+\r
+如果编译成功,说明:\r
+- ✅ 源代码语法正确\r
+- ✅ 头文件依赖正确\r
+- ✅ 库文件链接正确\r
+\r
+### 2. 功能验证\r
+\r
+使用一个已知的 Opus 帧文件进行测试:\r
+\r
+```bash\r
+# 如果有测试文件\r
+./opus_frame_to_pcm test_frame.opus -o test.pcm -r 16000 -c 1\r
+\r
+# 检查输出文件\r
+ls -lh test.pcm\r
+file test.pcm\r
+```\r
+\r
+### 3. 输出验证\r
+\r
+PCM 文件应该是:\r
+- 16-bit 小端格式\r
+- 原始 PCM 数据(无头部)\r
+- 文件大小 = 样本数 × 声道数 × 2 字节\r
+\r
+## 故障排除\r
+\r
+### 错误:libopus.a not found\r
+\r
+**解决方法**:\r
+```bash\r
+# 从主项目复制库文件\r
+cp ../.libs/libopus.a .\r
+```\r
+\r
+### 错误:undefined reference to opus_*\r
+\r
+**原因**:库文件不完整或链接错误\r
+\r
+**解决方法**:\r
+1. 确保 `libopus.a` 包含解码器功能\r
+2. 检查链接顺序:`-lopus -lm`\r
+\r
+### 错误:找不到头文件\r
+\r
+**解决方法**:\r
+```bash\r
+# 检查头文件是否存在\r
+ls include/\r
+# 确保 Makefile 中的 -I./include 正确\r
+```\r
+\r
+## 清理\r
+\r
+```bash\r
+make clean\r
+```\r
+\r
+## 注意事项\r
+\r
+1. 这个测试环境只包含最小化的文件,用于验证 `opus_frame_to_pcm.c` 的功能\r
+2. 如果需要完整的 Opus 库功能,请使用主项目的完整构建\r
+3. 测试环境假设使用静态链接,如果需要动态链接,需要修改 Makefile\r
--- /dev/null
+# 验证步骤说明\r
+\r
+## 一、文件完整性检查\r
+\r
+### 必需文件清单\r
+\r
+✅ **源代码**\r
+- `src/opus_frame_to_pcm.c` - 主程序源代码\r
+\r
+✅ **头文件**\r
+- `include/opus.h` - Opus API 头文件\r
+- `include/opus_defines.h` - Opus 定义\r
+- `include/opus_types.h` - Opus 类型定义\r
+\r
+✅ **库文件**\r
+- `libopus.a` - Opus 静态库(约 5MB)\r
+\r
+✅ **配置文件**\r
+- `config.h` - 最小配置(已创建)\r
+- `Makefile` - 构建脚本(Linux/macOS)\r
+- `build.sh` - 自动构建脚本(Linux/macOS)\r
+- `build.bat` - 自动构建脚本(Windows)\r
+\r
+✅ **文档**\r
+- `README.md` - 使用说明\r
+- `VERIFY.md` - 本文件\r
+\r
+## 二、编译验证\r
+\r
+### Linux/macOS\r
+\r
+```bash\r
+cd test_opus_frame_to_pcm\r
+\r
+# 方法1:使用自动构建脚本\r
+chmod +x build.sh\r
+./build.sh\r
+\r
+# 方法2:手动构建\r
+make clean\r
+make\r
+```\r
+\r
+### Windows\r
+\r
+```cmd\r
+cd test_opus_frame_to_pcm\r
+\r
+# 使用批处理脚本\r
+build.bat\r
+\r
+# 或手动编译(需要 MinGW)\r
+gcc -Wall -O2 -I. -I./include -I./src -c src/opus_frame_to_pcm.c -o src/opus_frame_to_pcm.o\r
+gcc src/opus_frame_to_pcm.o -o opus_frame_to_pcm.exe -L. -lopus -lm\r
+```\r
+\r
+### 预期结果\r
+\r
+如果编译成功,应该生成:\r
+- Linux/macOS: `opus_frame_to_pcm` 可执行文件\r
+- Windows: `opus_frame_to_pcm.exe` 可执行文件\r
+\r
+## 三、功能验证\r
+\r
+### 1. 帮助信息测试\r
+\r
+```bash\r
+./opus_frame_to_pcm -h\r
+# 或\r
+./opus_frame_to_pcm --help\r
+```\r
+\r
+**预期输出**:\r
+```\r
+Usage: opus_frame_to_pcm [options] <input_opus_file> [-o output.pcm]\r
+Options:\r
+ -o, --output FILE Output PCM file (default: stdout)\r
+ -r, --rate RATE Sample rate in Hz (default: 16000)\r
+ -c, --channels N Number of channels (default: 1)\r
+ -h, --help Show this help message\r
+\r
+Example:\r
+ opus_frame_to_pcm frame.opus -o output.pcm -r 16000 -c 1\r
+```\r
+\r
+### 2. 使用测试文件\r
+\r
+如果有 Opus 帧文件(例如从 `opus_frames_20260128_112654/` 目录):\r
+\r
+```bash\r
+# 复制一个测试文件\r
+cp ../opus_frames_20260128_112654/frame_0001.opus test_frame.opus\r
+\r
+# 运行解码\r
+./opus_frame_to_pcm test_frame.opus -o test_output.pcm -r 16000 -c 1\r
+```\r
+\r
+**预期输出**:\r
+```\r
+=== Decoding Opus Frame to PCM ===\r
+Input: test_frame.opus\r
+Output: test_output.pcm\r
+Sample rate: 16000 Hz, Channels: 1\r
+Read XX bytes from input file\r
+Packet info: 1 frame(s), TOC: 0x58\r
+Decoded XXX samples per channel\r
+Total PCM samples: XXX\r
+Saved PCM data to: test_output.pcm\r
+PCM file size: XXX bytes\r
+```\r
+\r
+### 3. 验证输出文件\r
+\r
+```bash\r
+# 检查文件是否存在\r
+ls -lh test_output.pcm\r
+\r
+# 检查文件类型(应该是原始 PCM 数据)\r
+file test_output.pcm\r
+\r
+# 检查文件大小(应该是 样本数 × 声道数 × 2 字节)\r
+# 例如:960 样本 × 1 声道 × 2 = 1920 字节\r
+```\r
+\r
+## 四、常见问题排查\r
+\r
+### 问题1:编译错误 - 找不到 opus.h\r
+\r
+**错误信息**:\r
+```\r
+src/opus_frame_to_pcm.c:37:10: fatal error: opus.h: No such file or directory\r
+```\r
+\r
+**解决方法**:\r
+1. 检查 `include/opus.h` 是否存在\r
+2. 确保 Makefile 中的 `-I./include` 正确\r
+3. 检查当前目录是否正确\r
+\r
+### 问题2:链接错误 - 找不到 libopus.a\r
+\r
+**错误信息**:\r
+```\r
+/usr/bin/ld: cannot find -lopus\r
+```\r
+\r
+**解决方法**:\r
+1. 检查 `libopus.a` 是否存在\r
+2. 确保 Makefile 中的 `-L.` 正确(表示当前目录)\r
+3. 如果库在其他位置,修改 `-L` 路径\r
+\r
+### 问题3:链接错误 - undefined reference\r
+\r
+**错误信息**:\r
+```\r
+undefined reference to `opus_decoder_create'\r
+undefined reference to `opus_decode'\r
+```\r
+\r
+**解决方法**:\r
+1. 确保 `libopus.a` 是完整的库文件\r
+2. 检查库文件是否包含解码器功能\r
+3. 确保链接顺序正确:`-lopus -lm`\r
+\r
+### 问题4:运行时错误 - 无法打开文件\r
+\r
+**错误信息**:\r
+```\r
+Error opening input file: test_frame.opus\r
+```\r
+\r
+**解决方法**:\r
+1. 检查文件路径是否正确\r
+2. 检查文件是否存在\r
+3. 检查文件权限\r
+\r
+### 问题5:运行时错误 - 解析失败\r
+\r
+**错误信息**:\r
+```\r
+Error parsing Opus packet: invalid packet\r
+```\r
+\r
+**解决方法**:\r
+1. 确保输入文件是有效的 Opus 数据包\r
+2. 检查文件是否损坏\r
+3. 尝试使用其他 Opus 帧文件\r
+\r
+## 五、成功标准\r
+\r
+### ✅ 编译成功标准\r
+\r
+1. 无编译错误\r
+2. 无链接错误\r
+3. 生成可执行文件\r
+4. 可执行文件有执行权限(Linux/macOS)\r
+\r
+### ✅ 功能成功标准\r
+\r
+1. 帮助信息正常显示\r
+2. 能够正确解析 Opus 数据包\r
+3. 能够正确解码为 PCM\r
+4. 输出文件格式正确(16-bit 小端 PCM)\r
+5. 输出文件大小符合预期\r
+\r
+## 六、测试用例\r
+\r
+### 测试用例1:基本解码\r
+\r
+```bash\r
+./opus_frame_to_pcm test_frame.opus -o output1.pcm -r 16000 -c 1\r
+```\r
+\r
+**验证点**:\r
+- ✅ 程序正常退出(返回码 0)\r
+- ✅ 输出文件存在\r
+- ✅ 输出文件大小 > 0\r
+\r
+### 测试用例2:不同采样率\r
+\r
+```bash\r
+./opus_frame_to_pcm test_frame.opus -o output2.pcm -r 48000 -c 1\r
+```\r
+\r
+**验证点**:\r
+- ✅ 程序正常退出\r
+- ✅ 输出文件存在\r
+- ✅ 文件大小可能不同(取决于实际解码的样本数)\r
+\r
+### 测试用例3:标准输出\r
+\r
+```bash\r
+./opus_frame_to_pcm test_frame.opus -r 16000 -c 1 > output3.pcm\r
+```\r
+\r
+**验证点**:\r
+- ✅ 程序正常退出\r
+- ✅ 输出文件存在\r
+- ✅ 文件内容正确\r
+\r
+### 测试用例4:错误处理\r
+\r
+```bash\r
+# 测试不存在的文件\r
+./opus_frame_to_pcm nonexistent.opus -o output.pcm -r 16000 -c 1\r
+```\r
+\r
+**验证点**:\r
+- ✅ 程序返回错误码(非 0)\r
+- ✅ 显示错误信息\r
+- ✅ 不生成输出文件\r
+\r
+## 七、性能验证(可选)\r
+\r
+### 解码速度测试\r
+\r
+```bash\r
+time ./opus_frame_to_pcm test_frame.opus -o output.pcm -r 16000 -c 1\r
+```\r
+\r
+### 内存使用测试(Linux)\r
+\r
+```bash\r
+valgrind --leak-check=full ./opus_frame_to_pcm test_frame.opus -o output.pcm -r 16000 -c 1\r
+```\r
+\r
+**验证点**:\r
+- ✅ 无内存泄漏\r
+- ✅ 无非法内存访问\r
+\r
+## 八、总结\r
+\r
+如果以上所有验证步骤都通过,说明:\r
+\r
+1. ✅ `opus_frame_to_pcm.c` 代码正确\r
+2. ✅ 依赖关系正确\r
+3. ✅ 库文件完整\r
+4. ✅ 功能正常\r
+\r
+可以确认该工具可以在独立环境中正常工作。\r
--- /dev/null
+@echo off\r
+REM Windows batch script for building opus_frame_to_pcm test\r
+\r
+echo ==========================================\r
+echo Opus Frame to PCM Test Build Script\r
+echo ==========================================\r
+echo.\r
+\r
+REM Check if libopus.a exists\r
+if not exist libopus.a (\r
+ echo Error: libopus.a not found!\r
+ echo Please copy libopus.a from ..\.libs\libopus.a\r
+ echo.\r
+ if exist ..\.libs\libopus.a (\r
+ echo Copying from ..\.libs\libopus.a...\r
+ copy ..\.libs\libopus.a . >nul\r
+ echo Done.\r
+ ) else (\r
+ echo Please build the library first with: make\r
+ exit /b 1\r
+ )\r
+)\r
+\r
+REM Check compiler\r
+where gcc >nul 2>&1\r
+if %errorlevel% neq 0 (\r
+ echo Error: gcc not found in PATH\r
+ echo Please install MinGW or use WSL\r
+ exit /b 1\r
+)\r
+\r
+echo Building...\r
+gcc -Wall -O2 -I. -I./include -I./src -c src/opus_frame_to_pcm.c -o src/opus_frame_to_pcm.o\r
+if %errorlevel% neq 0 (\r
+ echo Compilation failed!\r
+ exit /b 1\r
+)\r
+\r
+gcc src/opus_frame_to_pcm.o -o opus_frame_to_pcm.exe -L. -lopus -lm\r
+if %errorlevel% neq 0 (\r
+ echo Linking failed!\r
+ exit /b 1\r
+)\r
+\r
+echo.\r
+echo ==========================================\r
+echo Build successful!\r
+echo ==========================================\r
+echo.\r
+echo Executable: opus_frame_to_pcm.exe\r
+echo.\r
+echo Usage:\r
+echo opus_frame_to_pcm.exe input.opus -o output.pcm -r 16000 -c 1\r
+echo.\r
--- /dev/null
+#!/bin/bash
+# 构建脚本 - 自动准备和构建测试环境
+
+set -e
+
+echo "=========================================="
+echo "Opus Frame to PCM 测试环境构建脚本"
+echo "=========================================="
+echo ""
+
+# 检查是否在主项目目录
+if [ ! -f "../src/opus_frame_to_pcm.c" ] && [ ! -f "src/opus_frame_to_pcm.c" ]; then
+ echo "错误:找不到 opus_frame_to_pcm.c"
+ echo "请确保在正确的目录下运行此脚本"
+ exit 1
+fi
+
+# 检查并复制库文件
+if [ ! -f "libopus.a" ]; then
+ echo "正在查找 libopus.a..."
+
+ # 尝试从主项目的 .libs 目录复制
+ if [ -f "../.libs/libopus.a" ]; then
+ echo "从 ../.libs/libopus.a 复制..."
+ cp ../.libs/libopus.a .
+ elif [ -f "../../.libs/libopus.a" ]; then
+ echo "从 ../../.libs/libopus.a 复制..."
+ cp ../../.libs/libopus.a .
+ else
+ echo "警告:找不到 libopus.a"
+ echo "请先在主项目目录下运行 'make' 构建库"
+ echo "然后手动复制 .libs/libopus.a 到此目录"
+ exit 1
+ fi
+else
+ echo "libopus.a 已存在"
+fi
+
+# 检查库文件大小
+if [ -f "libopus.a" ]; then
+ SIZE=$(stat -c%s libopus.a 2>/dev/null || stat -f%z libopus.a 2>/dev/null)
+ echo "库文件大小: $SIZE 字节"
+fi
+
+# 构建
+echo ""
+echo "开始构建..."
+make clean 2>/dev/null || true
+make
+
+if [ $? -eq 0 ]; then
+ echo ""
+ echo "=========================================="
+ echo "构建成功!"
+ echo "=========================================="
+ echo ""
+ echo "可执行文件: ./opus_frame_to_pcm"
+ echo ""
+ echo "使用方法:"
+ echo " ./opus_frame_to_pcm <input.opus> -o output.pcm -r 16000 -c 1"
+ echo ""
+else
+ echo ""
+ echo "=========================================="
+ echo "构建失败!"
+ echo "=========================================="
+ exit 1
+fi
--- /dev/null
+param(\r
+ [string]$OutDir = "test_opus_frame_to_pcm",\r
+ [string]$OutLib = "libopus_min.a"\r
+)\r
+\r
+$ErrorActionPreference = "Stop"\r
+\r
+function Find-Tool([string[]]$names) {\r
+ foreach ($n in $names) {\r
+ $cmd = Get-Command $n -ErrorAction SilentlyContinue\r
+ if ($cmd) { return $cmd.Path }\r
+ }\r
+ return $null\r
+}\r
+\r
+$ar = Find-Tool @("ar", "llvm-ar")\r
+if (-not $ar) {\r
+ Write-Host "Error: cannot find 'ar' or 'llvm-ar' in PATH."\r
+ Write-Host "This script needs an archiver to create a new .a file."\r
+ exit 1\r
+}\r
+\r
+if (-not (Test-Path $OutDir)) {\r
+ New-Item -ItemType Directory -Path $OutDir -Force | Out-Null\r
+}\r
+\r
+$outPath = Join-Path $OutDir $OutLib\r
+if (Test-Path $outPath) { Remove-Item $outPath -Force }\r
+\r
+# Decoder-only object set:\r
+# - src/: drop *encoder*, analysis/mlp (encoder-side), demos/tools\r
+# - celt/: drop celt_encoder (BUT keep entenc: see note below)\r
+# - silk/: drop encoder-side units\r
+$srcObjs = Get-ChildItem -Path "src" -Filter "*.o" -File | Where-Object {\r
+ $_.Name -notmatch "encoder" -and\r
+ $_.Name -notmatch "^analysis\\.o$" -and\r
+ $_.Name -notmatch "^mlp(_data)?\\.o$" -and\r
+ $_.Name -notmatch "^opus_(demo|compare)\\.o$" -and\r
+ $_.Name -notmatch "^repacketizer_demo\\.o$" -and\r
+ $_.Name -notmatch "^opus_frame_to_pcm\\.o$" -and\r
+ $_.Name -notmatch "^opus_hex_parser\\.o$"\r
+}\r
+\r
+$celtObjs = Get-ChildItem -Path "celt" -Filter "*.o" -File | Where-Object {\r
+ # NOTE: keep entenc.o even for decoder-only validation because several CELT\r
+ # compilation units contain both encoder+decoder code paths in the same .o and\r
+ # will reference ec_enc_* symbols.\r
+ $_.Name -notmatch "celt_encoder\\.o$"\r
+}\r
+\r
+$silkExclude = @(\r
+ "^enc_API\\.o$",\r
+ "^init_encoder\\.o$",\r
+ "^encode_.*\\.o$",\r
+ "^stereo_encode_.*\\.o$",\r
+ "^stereo_quant_.*\\.o$",\r
+ "^stereo_find_predictor\\.o$",\r
+ "^VAD\\.o$",\r
+ "^control_.*\\.o$",\r
+ "^check_control_input\\.o$",\r
+ "^ana_filt_bank_1\\.o$",\r
+ "^NSQ.*\\.o$",\r
+ # gain_quant.o is REQUIRED by the decoder (silk_gains_dequant), so we keep it.\r
+ "^quant_LTP_gains\\.o$",\r
+ "^VQ_WMat_EC\\.o$",\r
+ "^NLSF_encode\\.o$",\r
+ "^NLSF_VQ\\.o$",\r
+ "^NLSF_del_dec_quant\\.o$",\r
+ "^process_NLSFs\\.o$"\r
+)\r
+\r
+$silkObjs = Get-ChildItem -Path "silk" -Filter "*.o" -File | Where-Object {\r
+ $name = $_.Name\r
+ foreach ($re in $silkExclude) {\r
+ if ($name -match $re) { return $false }\r
+ }\r
+ return $true\r
+}\r
+\r
+# RTCD/SIMD dispatch objects:\r
+# If you built with x86 RTCD/SSE, opus_select_arch() and SIMD stubs live under celt/x86 and silk/x86.\r
+$celtX86 = @()\r
+if (Test-Path "celt\\x86") {\r
+ $celtX86 = Get-ChildItem -Path "celt\\x86" -Filter "*.o" -File\r
+}\r
+$silkX86 = @()\r
+if (Test-Path "silk\\x86") {\r
+ $silkX86 = Get-ChildItem -Path "silk\\x86" -Filter "*.o" -File\r
+}\r
+\r
+$all = @($srcObjs + $celtObjs + $celtX86 + $silkObjs + $silkX86)\r
+if ($all.Count -lt 10) {\r
+ Write-Host "Error: too few object files selected ($($all.Count))."\r
+ Write-Host "Make sure you have built the project first so .o files exist."\r
+ exit 1\r
+}\r
+\r
+Write-Host "Using archiver: $ar"\r
+Write-Host "Writing: $outPath"\r
+Write-Host ("Selected objects: src={0}, celt={1}, silk={2}, total={3}" -f $srcObjs.Count, $celtObjs.Count, $silkObjs.Count, $all.Count)\r
+\r
+# Create the new archive\r
+& $ar rcs $outPath @($all.FullName)\r
+\r
+if (-not (Test-Path $outPath)) {\r
+ Write-Host "Error: failed to create $outPath"\r
+ exit 1\r
+}\r
+\r
+$size = (Get-Item $outPath).Length\r
+Write-Host ("Done. {0} created ({1} KB)" -f $OutLib, [math]::Round($size/1KB, 2))\r
--- /dev/null
+#!/bin/bash
+# Build a decoder-only libopus_min.a from already-built *.o files in this repo.
+# This is intended to validate code deletion by linking opus_frame_to_pcm against a smaller archive.
+set -euo pipefail
+
+OUT_DIR="${1:-test_opus_frame_to_pcm}"
+OUT_LIB="${2:-libopus_min.a}"
+OUT_PATH="$OUT_DIR/$OUT_LIB"
+
+if ! command -v ar >/dev/null 2>&1; then
+ echo "Error: 'ar' not found. Please install binutils (or use a toolchain that provides ar)." >&2
+ exit 1
+fi
+
+mkdir -p "$OUT_DIR"
+rm -f "$OUT_PATH"
+
+echo "Building $OUT_PATH ..."
+
+# src objects (decoder-side)
+src_objs=()
+while IFS= read -r -d '' f; do src_objs+=("$f"); done < <(find src -maxdepth 1 -name '*.o' -print0)
+
+src_keep=()
+for o in "${src_objs[@]}"; do
+ base="$(basename "$o")"
+ case "$base" in
+ *encoder*.o) continue ;;
+ analysis.o|mlp.o|mlp_data.o) continue ;;
+ opus_demo.o|opus_compare.o|repacketizer_demo.o) continue ;;
+ opus_frame_to_pcm.o|opus_hex_parser.o) continue ;;
+ esac
+ src_keep+=("$o")
+done
+
+# celt objects
+# NOTE: even for decoder-only validation we KEEP entenc.o because several CELT
+# compilation units (e.g. bands/rate/vq) contain both encoder+decoder code paths
+# in the same .o, and will reference ec_enc_* symbols.
+# We still drop celt_encoder.o.
+celt_keep=()
+while IFS= read -r -d '' o; do
+ base="$(basename "$o")"
+ case "$base" in
+ celt_encoder.o) continue ;;
+ esac
+ celt_keep+=("$o")
+done < <(find celt -maxdepth 1 -name '*.o' -print0)
+
+# silk objects (drop encoder-side units)
+silk_keep=()
+while IFS= read -r -d '' o; do
+ base="$(basename "$o")"
+ case "$base" in
+ enc_API.o|init_encoder.o) continue ;;
+ encode_*.o) continue ;;
+ stereo_encode_*.o|stereo_quant_*.o) continue ;;
+ VAD.o) continue ;;
+ control_*.o|check_control_input.o) continue ;;
+ ana_filt_bank_1.o) continue ;;
+ NSQ*.o) continue ;;
+ # gain_quant.o is REQUIRED by the decoder (silk_gains_dequant), so we keep it.
+ quant_LTP_gains.o|VQ_WMat_EC.o) continue ;;
+ NLSF_encode.o|NLSF_VQ.o|NLSF_del_dec_quant.o|process_NLSFs.o) continue ;;
+ esac
+ silk_keep+=("$o")
+done < <(find silk -maxdepth 1 -name '*.o' -print0)
+
+# RTCD/SIMD dispatch objects:
+# opus_select_arch() is provided by arch-specific cpu code when RTCD is enabled.
+# If you built with x86 RTCD/SSE, you must include celt/x86/*.o (and silk/x86 map).
+if [ -d "celt/x86" ]; then
+ while IFS= read -r -d '' o; do
+ # include all built x86 objects (cpu + maps + sse stubs) to satisfy references
+ celt_keep+=("$o")
+ done < <(find celt/x86 -maxdepth 1 -name '*.o' -print0)
+fi
+if [ -d "silk/x86" ]; then
+ while IFS= read -r -d '' o; do
+ silk_keep+=("$o")
+ done < <(find silk/x86 -maxdepth 1 -name '*.o' -print0)
+fi
+
+total=$(( ${#src_keep[@]} + ${#celt_keep[@]} + ${#silk_keep[@]} ))
+echo "Selected objects: src=${#src_keep[@]}, celt=${#celt_keep[@]}, silk=${#silk_keep[@]}, total=$total"
+
+if [ "$total" -lt 10 ]; then
+ echo "Error: too few objects selected ($total). Did you build the main project first (so *.o exist)?" >&2
+ exit 1
+fi
+
+ar rcs "$OUT_PATH" "${src_keep[@]}" "${celt_keep[@]}" "${silk_keep[@]}"
+echo "Done: $(ls -lh "$OUT_PATH")"
--- /dev/null
+/*Copyright (c) 2003-2004, Mark Borgerding
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 KISS_FFT_GUTS_H
+#define KISS_FFT_GUTS_H
+
+#define MIN(a,b) ((a)<(b) ? (a):(b))
+#define MAX(a,b) ((a)>(b) ? (a):(b))
+
+/* kiss_fft.h
+ defines kiss_fft_scalar as either short or a float type
+ and defines
+ typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
+#include "kiss_fft.h"
+
+/*
+ Explanation of macros dealing with complex math:
+
+ C_MUL(m,a,b) : m = a*b
+ C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
+ C_SUB( res, a,b) : res = a - b
+ C_SUBFROM( res , a) : res -= a
+ C_ADDTO( res , a) : res += a
+ * */
+#ifdef FIXED_POINT
+#include "arch.h"
+
+
+#define SAMP_MAX 2147483647
+#define TWID_MAX 32767
+#define TRIG_UPSCALE 1
+
+#define SAMP_MIN -SAMP_MAX
+
+#ifdef ENABLE_QEXT
+# define S_MUL(a,b) MULT32_32_P31_ovflw(b, a)
+# define S_MUL2(a,b) MULT32_32_P31_ovflw(b, a)
+#else
+# define S_MUL(a,b) MULT16_32_Q15(b, a)
+# define S_MUL2(a,b) MULT16_32_Q16(b, a)
+#endif
+
+# define C_MUL(m,a,b) \
+ do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
+ (m).i = ADD32_ovflw(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
+
+# define C_MULC(m,a,b) \
+ do{ (m).r = ADD32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
+ (m).i = SUB32_ovflw(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
+
+# define C_MULBYSCALAR( c, s ) \
+ do{ (c).r = S_MUL( (c).r , s ) ;\
+ (c).i = S_MUL( (c).i , s ) ; }while(0)
+
+# define DIVSCALAR(x,k) \
+ (x) = S_MUL( x, (TWID_MAX-((k)>>1))/(k)+1 )
+
+# define C_FIXDIV(c,div) \
+ do { DIVSCALAR( (c).r , div); \
+ DIVSCALAR( (c).i , div); }while (0)
+
+#define C_ADD( res, a,b)\
+ do {(res).r=ADD32_ovflw((a).r,(b).r); (res).i=ADD32_ovflw((a).i,(b).i); \
+ }while(0)
+#define C_SUB( res, a,b)\
+ do {(res).r=SUB32_ovflw((a).r,(b).r); (res).i=SUB32_ovflw((a).i,(b).i); \
+ }while(0)
+#define C_ADDTO( res , a)\
+ do {(res).r = ADD32_ovflw((res).r, (a).r); (res).i = ADD32_ovflw((res).i,(a).i);\
+ }while(0)
+
+#define C_SUBFROM( res , a)\
+ do {(res).r = ADD32_ovflw((res).r,(a).r); (res).i = SUB32_ovflw((res).i,(a).i); \
+ }while(0)
+
+#if defined(OPUS_ARM_INLINE_ASM)
+#include "arm/kiss_fft_armv4.h"
+#endif
+
+#if defined(OPUS_ARM_INLINE_EDSP)
+#include "arm/kiss_fft_armv5e.h"
+#endif
+#if defined(__mips)
+#include "mips/kiss_fft_mipsr1.h"
+#endif
+
+#else /* not FIXED_POINT*/
+
+# define S_MUL(a,b) ( (a)*(b) )
+# define S_MUL2(a,b) ( (a)*(b) )
+#define C_MUL(m,a,b) \
+ do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
+ (m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
+#define C_MULC(m,a,b) \
+ do{ (m).r = (a).r*(b).r + (a).i*(b).i;\
+ (m).i = (a).i*(b).r - (a).r*(b).i; }while(0)
+
+#define C_MUL4(m,a,b) C_MUL(m,a,b)
+
+# define C_FIXDIV(c,div) /* NOOP */
+# define C_MULBYSCALAR( c, s ) \
+ do{ (c).r *= (s);\
+ (c).i *= (s); }while(0)
+#endif
+
+#ifndef CHECK_OVERFLOW_OP
+# define CHECK_OVERFLOW_OP(a,op,b) /* noop */
+#endif
+
+#ifndef C_ADD
+#define C_ADD( res, a,b)\
+ do { \
+ CHECK_OVERFLOW_OP((a).r,+,(b).r)\
+ CHECK_OVERFLOW_OP((a).i,+,(b).i)\
+ (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
+ }while(0)
+#define C_SUB( res, a,b)\
+ do { \
+ CHECK_OVERFLOW_OP((a).r,-,(b).r)\
+ CHECK_OVERFLOW_OP((a).i,-,(b).i)\
+ (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
+ }while(0)
+#define C_ADDTO( res , a)\
+ do { \
+ CHECK_OVERFLOW_OP((res).r,+,(a).r)\
+ CHECK_OVERFLOW_OP((res).i,+,(a).i)\
+ (res).r += (a).r; (res).i += (a).i;\
+ }while(0)
+
+#define C_SUBFROM( res , a)\
+ do {\
+ CHECK_OVERFLOW_OP((res).r,-,(a).r)\
+ CHECK_OVERFLOW_OP((res).i,-,(a).i)\
+ (res).r -= (a).r; (res).i -= (a).i; \
+ }while(0)
+#endif /* C_ADD defined */
+
+#ifdef FIXED_POINT
+/*# define KISS_FFT_COS(phase) TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase))))
+# define KISS_FFT_SIN(phase) TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase))))*/
+# define KISS_FFT_COS(phase) floor(.5+TWID_MAX*cos (phase))
+# define KISS_FFT_SIN(phase) floor(.5+TWID_MAX*sin (phase))
+# define HALF_OF(x) ((x)>>1)
+#elif defined(USE_SIMD)
+# define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
+# define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
+# define HALF_OF(x) ((x)*_mm_set1_ps(.5f))
+#else
+# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
+# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
+# define HALF_OF(x) ((x)*.5f)
+#endif
+
+#define kf_cexp(x,phase) \
+ do{ \
+ (x)->r = KISS_FFT_COS(phase);\
+ (x)->i = KISS_FFT_SIN(phase);\
+ }while(0)
+
+#define kf_cexp2(x,phase) \
+ do{ \
+ (x)->r = TRIG_UPSCALE*celt_cos_norm((phase));\
+ (x)->i = TRIG_UPSCALE*celt_cos_norm((phase)-32768);\
+}while(0)
+
+#endif /* KISS_FFT_GUTS_H */
--- /dev/null
+/* Copyright (c) 2003-2008 Jean-Marc Valin
+ Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/**
+ @file arch.h
+ @brief Various architecture definitions for CELT
+*/
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 ARCH_H
+#define ARCH_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+# if !defined(__GNUC_PREREQ)
+# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
+# define __GNUC_PREREQ(_maj,_min) \
+ ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
+# else
+# define __GNUC_PREREQ(_maj,_min) 0
+# endif
+# endif
+
+#if OPUS_GNUC_PREREQ(3, 0)
+#define opus_likely(x) (__builtin_expect(!!(x), 1))
+#define opus_unlikely(x) (__builtin_expect(!!(x), 0))
+#else
+#define opus_likely(x) (!!(x))
+#define opus_unlikely(x) (!!(x))
+#endif
+
+#define CELT_SIG_SCALE 32768.f
+
+#define CELT_FATAL(str) celt_fatal(str, __FILE__, __LINE__)
+
+#if defined(ENABLE_ASSERTIONS) || defined(ENABLE_HARDENING)
+#ifdef __GNUC__
+__attribute__((noreturn))
+#endif
+void celt_fatal(const char *str, const char *file, int line);
+
+#if defined(CELT_C) && !defined(OVERRIDE_celt_fatal)
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef __GNUC__
+__attribute__((noreturn))
+#endif
+void celt_fatal(const char *str, const char *file, int line)
+{
+ fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
+#if defined(_MSC_VER)
+ _set_abort_behavior( 0, _WRITE_ABORT_MSG);
+#endif
+ abort();
+}
+#endif
+
+#define celt_assert(cond) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond);}}
+#define celt_assert2(cond, message) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond "\n" message);}}
+#define MUST_SUCCEED(call) celt_assert((call) == OPUS_OK)
+#else
+#define celt_assert(cond) ((void)(cond))
+#define celt_assert2(cond, message) ((void)(cond))
+#define MUST_SUCCEED(call) do {if((call) != OPUS_OK) {RESTORE_STACK; return OPUS_INTERNAL_ERROR;} } while (0)
+#endif
+
+#if defined(ENABLE_ASSERTIONS)
+#define celt_sig_assert(cond) {if (!(cond)) {CELT_FATAL("signal assertion failed: " #cond);}}
+#else
+#define celt_sig_assert(cond) ((void)(cond))
+#endif
+
+#define IMUL32(a,b) ((a)*(b))
+
+#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 16-bit value. */
+#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */
+#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 32-bit value. */
+#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */
+#define IMIN(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum int value. */
+#define IMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum int value. */
+#define FMIN(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum float value. */
+#define FMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum float value. */
+#define UADD32(a,b) ((a)+(b))
+#define USUB32(a,b) ((a)-(b))
+#define MAXG(a,b) MAX32(a, b)
+#define MING(a,b) MIN32(a, b)
+
+/* Throughout the code, we use the following scaling for signals:
+ FLOAT: used for float API, normalized to +/-1.
+ INT16: used for 16-bit API, normalized to +/- 32768
+ RES: internal Opus resolution, defined as +/-1. in float builds, or either 16-bit or 24-bit int for fixed-point builds
+ SIG: internal CELT resolution: defined as +/- 32768. in float builds, or Q27 in fixed-point builds (int16 shifted by 12)
+*/
+
+
+/* Set this if opus_int64 is a native type of the CPU. */
+/* Assume that all LP64 architectures have fast 64-bit types; also x86_64
+ (which can be ILP32 for x32) and Win64 (which is LLP64). */
+#if defined(__x86_64__) || defined(__LP64__) || defined(_WIN64) || defined (__mips)
+#define OPUS_FAST_INT64 1
+#else
+#define OPUS_FAST_INT64 0
+#endif
+
+#ifdef FIXED_POINT
+#define ARG_FIXED(arg) , arg
+#else
+#define ARG_FIXED(arg)
+#endif
+
+#define PRINT_MIPS(file)
+
+#ifdef FIXED_POINT
+
+typedef opus_int16 opus_val16;
+typedef opus_int32 opus_val32;
+typedef opus_int64 opus_val64;
+
+typedef opus_val32 celt_sig;
+typedef opus_val32 celt_norm;
+typedef opus_val32 celt_ener;
+typedef opus_val32 celt_glog;
+
+#ifdef ENABLE_RES24
+typedef opus_val32 opus_res;
+#define RES_SHIFT 8
+#define SIG2RES(a) PSHR32(a, SIG_SHIFT-RES_SHIFT)
+#define RES2INT16(a) SAT16(PSHR32(a, RES_SHIFT))
+#define RES2INT24(a) (a)
+#define RES2FLOAT(a) ((1.f/32768.f/256.f)*(a))
+#define INT16TORES(a) SHL32(EXTEND32(a), RES_SHIFT)
+#define INT24TORES(a) (a)
+#define ADD_RES(a, b) ADD32(a, b)
+#define FLOAT2RES(a) FLOAT2INT24(a)
+#define RES2SIG(a) SHL32((a), SIG_SHIFT-RES_SHIFT)
+#define MULT16_RES_Q15(a,b) MULT16_32_Q15(a,b)
+#define MAX_ENCODING_DEPTH 24
+#else
+typedef opus_val16 opus_res;
+#define RES_SHIFT 0
+#define SIG2RES(a) SIG2WORD16(a)
+#define RES2INT16(a) (a)
+#define RES2INT24(a) SHL32(EXTEND32(a), 8)
+#define RES2FLOAT(a) ((1.f/32768.f)*(a))
+#define INT16TORES(a) (a)
+#define INT24TORES(a) SAT16(PSHR32(a, 8))
+#define ADD_RES(a, b) SAT16(ADD32((a), (b)));
+#define FLOAT2RES(a) FLOAT2INT16(a)
+#define RES2SIG(a) SHL32(EXTEND32(a), SIG_SHIFT)
+#define MULT16_RES_Q15(a,b) MULT16_16_Q15(a,b)
+#define MAX_ENCODING_DEPTH 16
+#endif
+
+#define RES2VAL16(a) RES2INT16(a)
+#define INT16TOSIG(a) SHL32(EXTEND32(a), SIG_SHIFT)
+#define INT24TOSIG(a) SHL32(a, SIG_SHIFT-8)
+
+#define NORM_SHIFT 24
+#ifdef ENABLE_QEXT
+typedef opus_val32 celt_coef;
+#define COEF_ONE Q31ONE
+#define MULT_COEF_32(a, b) MULT32_32_P31(a,b)
+#define MAC_COEF_32_ARM(c, a, b) ADD32((c), MULT32_32_Q32(a,b))
+#define MULT_COEF(a, b) MULT32_32_Q31(a,b)
+#define MULT_COEF_TAPS(a, b) SHL32(MULT16_16(a,b), 1)
+#define COEF2VAL16(x) EXTRACT16(SHR32(x, 16))
+#else
+typedef opus_val16 celt_coef;
+#define COEF_ONE Q15ONE
+#define MULT_COEF_32(a, b) MULT16_32_Q15(a,b)
+#define MAC_COEF_32_ARM(a, b, c) MAC16_32_Q16(a,b,c)
+#define MULT_COEF(a, b) MULT16_16_Q15(a,b)
+#define MULT_COEF_TAPS(a, b) MULT16_16_P15(a,b)
+#define COEF2VAL16(x) (x)
+#endif
+
+#define celt_isnan(x) 0
+
+#define Q15ONE 32767
+#define Q31ONE 2147483647
+
+#define SIG_SHIFT 12
+/* Safe saturation value for 32-bit signals. We need to make sure that we can
+ add two sig values and that the first stages of the MDCT don't cause an overflow.
+ The most constraining is the ARM_ASM comb filter where we shift left by one
+ and then add two values. Because of that, we use 2^29-1. SIG_SAT must be large
+ enough to fit a full-scale high-freq tone through the prefilter and comb filter,
+ meaning 1.85*1.75*2^(15+SIG_SHIFT) = 434529895.
+ so the limit should be about 2^31*sqrt(.5). */
+#define SIG_SAT (536870911)
+
+#define NORM_SCALING (1<<NORM_SHIFT)
+
+#define DB_SHIFT 24
+
+#define EPSILON 1
+#define VERY_SMALL 0
+#define VERY_LARGE16 ((opus_val16)32767)
+#define Q15_ONE ((opus_val16)32767)
+
+
+#define ABS16(x) ((x) < 0 ? (-(x)) : (x))
+#define ABS32(x) ((x) < 0 ? (-(x)) : (x))
+
+static OPUS_INLINE opus_int16 SAT16(opus_int32 x) {
+ return x > 32767 ? 32767 : x < -32768 ? -32768 : (opus_int16)x;
+}
+
+#ifdef FIXED_DEBUG
+#include "fixed_debug.h"
+#else
+
+#include "fixed_generic.h"
+
+#ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR
+#include "arm/fixed_arm64.h"
+#elif defined (OPUS_ARM_INLINE_EDSP)
+#include "arm/fixed_armv5e.h"
+#elif defined (OPUS_ARM_INLINE_ASM)
+#include "arm/fixed_armv4.h"
+#elif defined (BFIN_ASM)
+#include "fixed_bfin.h"
+#elif defined (TI_C5X_ASM)
+#include "fixed_c5x.h"
+#elif defined (TI_C6X_ASM)
+#include "fixed_c6x.h"
+#endif
+
+#endif
+
+#else /* FIXED_POINT */
+
+typedef float opus_val16;
+typedef float opus_val32;
+typedef float opus_val64;
+
+typedef float celt_sig;
+typedef float celt_norm;
+typedef float celt_ener;
+typedef float celt_glog;
+
+typedef float opus_res;
+typedef float celt_coef;
+
+#ifdef FLOAT_APPROX
+/* This code should reliably detect NaN/inf even when -ffast-math is used.
+ Assumes IEEE 754 format. */
+static OPUS_INLINE int celt_isnan(float x)
+{
+ union {float f; opus_uint32 i;} in;
+ in.f = x;
+ return ((in.i>>23)&0xFF)==0xFF && (in.i&0x007FFFFF)!=0;
+}
+#else
+#ifdef __FAST_MATH__
+#error Cannot build libopus with -ffast-math unless FLOAT_APPROX is defined. This could result in crashes on extreme (e.g. NaN) input
+#endif
+#define celt_isnan(x) ((x)!=(x))
+#endif
+
+#define Q15ONE 1.0f
+#define Q31ONE 1.0f
+#define COEF_ONE 1.0f
+#define COEF2VAL16(x) (x)
+
+#define NORM_SCALING 1.f
+
+#define EPSILON 1e-15f
+#define VERY_SMALL 1e-30f
+#define VERY_LARGE16 1e15f
+#define Q15_ONE ((opus_val16)1.f)
+
+/* This appears to be the same speed as C99's fabsf() but it's more portable. */
+#define ABS16(x) ((float)fabs(x))
+#define ABS32(x) ((float)fabs(x))
+
+#define QCONST16(x,bits) (x)
+#define QCONST32(x,bits) (x)
+#define GCONST(x) (x)
+
+#define NEG16(x) (-(x))
+#define NEG32(x) (-(x))
+#define NEG32_ovflw(x) (-(x))
+#define EXTRACT16(x) (x)
+#define EXTEND32(x) (x)
+#define SHR16(a,shift) (a)
+#define SHL16(a,shift) (a)
+#define SHR32(a,shift) (a)
+#define SHL32(a,shift) (a)
+#define PSHR32(a,shift) (a)
+#define VSHR32(a,shift) (a)
+
+#define SHR64(a,shift) (a)
+
+#define PSHR(a,shift) (a)
+#define SHR(a,shift) (a)
+#define SHL(a,shift) (a)
+#define SATURATE(x,a) (x)
+#define SATURATE16(x) (x)
+
+#define ROUND16(a,shift) (a)
+#define SROUND16(a,shift) (a)
+#define HALF16(x) (.5f*(x))
+#define HALF32(x) (.5f*(x))
+
+#define ADD16(a,b) ((a)+(b))
+#define SUB16(a,b) ((a)-(b))
+#define ADD32(a,b) ((a)+(b))
+#define SUB32(a,b) ((a)-(b))
+#define ADD32_ovflw(a,b) ((a)+(b))
+#define SUB32_ovflw(a,b) ((a)-(b))
+#define SHL32_ovflw(a,shift) (a)
+#define PSHR32_ovflw(a,shift) (a)
+
+#define MULT16_16_16(a,b) ((a)*(b))
+#define MULT16_16(a,b) ((opus_val32)(a)*(opus_val32)(b))
+#define MAC16_16(c,a,b) ((c)+(opus_val32)(a)*(opus_val32)(b))
+
+#define MULT16_32_Q15(a,b) ((a)*(b))
+#define MULT16_32_Q16(a,b) ((a)*(b))
+
+#define MULT32_32_Q16(a,b) ((a)*(b))
+#define MULT32_32_Q31(a,b) ((a)*(b))
+#define MULT32_32_P31(a,b) ((a)*(b))
+#define MULT32_32_P31_ovflw(a,b) ((a)*(b))
+
+#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b))
+#define MAC16_32_Q16(c,a,b) ((c)+(a)*(b))
+#define MAC_COEF_32_ARM(c,a,b) ((c)+(a)*(b))
+
+#define MULT16_16_Q11_32(a,b) ((a)*(b))
+#define MULT16_16_Q11(a,b) ((a)*(b))
+#define MULT16_16_Q13(a,b) ((a)*(b))
+#define MULT16_16_Q14(a,b) ((a)*(b))
+#define MULT16_16_Q15(a,b) ((a)*(b))
+#define MULT16_16_P15(a,b) ((a)*(b))
+#define MULT16_16_P13(a,b) ((a)*(b))
+#define MULT16_16_P14(a,b) ((a)*(b))
+#define MULT16_32_P16(a,b) ((a)*(b))
+
+#define MULT_COEF_32(a, b) ((a)*(b))
+#define MULT_COEF(a, b) ((a)*(b))
+#define MULT_COEF_TAPS(a, b) ((a)*(b))
+
+#define DIV32_16(a,b) (((opus_val32)(a))/(opus_val16)(b))
+#define DIV32(a,b) (((opus_val32)(a))/(opus_val32)(b))
+
+#define SIG2RES(a) ((1/CELT_SIG_SCALE)*(a))
+#define RES2INT16(a) FLOAT2INT16(a)
+#define RES2INT24(a) float2int(32768.f*256.f*(a))
+#define RES2FLOAT(a) (a)
+#define INT16TORES(a) ((a)*(1/CELT_SIG_SCALE))
+#define INT24TORES(a) ((1.f/32768.f/256.f)*(a))
+#define ADD_RES(a, b) ADD32(a, b)
+#define FLOAT2RES(a) (a)
+#define RES2SIG(a) (CELT_SIG_SCALE*(a))
+#define MULT16_RES_Q15(a,b) MULT16_16_Q15(a,b)
+
+#define RES2VAL16(a) (a)
+#define FLOAT2SIG(a) ((a)*CELT_SIG_SCALE)
+#define INT16TOSIG(a) ((float)(a))
+#define INT24TOSIG(a) ((float)(a)*(1.f/256.f))
+#define MAX_ENCODING_DEPTH 24
+
+#endif /* !FIXED_POINT */
+
+#ifndef GLOBAL_STACK_SIZE
+#ifdef FIXED_POINT
+#define GLOBAL_STACK_SIZE 120000
+#else
+#define GLOBAL_STACK_SIZE 120000
+#endif
+#endif
+
+#endif /* ARCH_H */
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Copyright (c) 2008-2009 Gregory Maxwell
+ Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include "bands.h"
+#include "modes.h"
+#include "vq.h"
+#include "cwrs.h"
+#include "stack_alloc.h"
+#include "os_support.h"
+#include "mathops.h"
+#include "rate.h"
+#include "quant_bands.h"
+#include "pitch.h"
+
+int hysteresis_decision(opus_val16 val, const opus_val16 *thresholds, const opus_val16 *hysteresis, int N, int prev)
+{
+ int i;
+ for (i=0;i<N;i++)
+ {
+ if (val < thresholds[i])
+ break;
+ }
+ if (i>prev && val < thresholds[prev]+hysteresis[prev])
+ i=prev;
+ if (i<prev && val > thresholds[prev-1]-hysteresis[prev-1])
+ i=prev;
+ return i;
+}
+
+opus_uint32 celt_lcg_rand(opus_uint32 seed)
+{
+ return 1664525 * seed + 1013904223;
+}
+
+/* This is a cos() approximation designed to be bit-exact on any platform. Bit exactness
+ with this approximation is important because it has an impact on the bit allocation */
+opus_int16 bitexact_cos(opus_int16 x)
+{
+ opus_int32 tmp;
+ opus_int16 x2;
+ tmp = (4096+((opus_int32)(x)*(x)))>>13;
+ celt_sig_assert(tmp<=32767);
+ x2 = tmp;
+ x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2)))));
+ celt_sig_assert(x2<=32766);
+ return 1+x2;
+}
+
+int bitexact_log2tan(int isin,int icos)
+{
+ int lc;
+ int ls;
+ lc=EC_ILOG(icos);
+ ls=EC_ILOG(isin);
+ icos<<=15-lc;
+ isin<<=15-ls;
+ return (ls-lc)*(1<<11)
+ +FRAC_MUL16(isin, FRAC_MUL16(isin, -2597) + 7932)
+ -FRAC_MUL16(icos, FRAC_MUL16(icos, -2597) + 7932);
+}
+
+#ifdef FIXED_POINT
+/* Compute the amplitude (sqrt energy) in each of the bands */
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch)
+{
+ int i, c, N;
+ const opus_int16 *eBands = m->eBands;
+ (void)arch;
+ N = m->shortMdctSize<<LM;
+ c=0; do {
+ for (i=0;i<end;i++)
+ {
+ int j;
+ opus_val32 maxval=0;
+ opus_val32 sum = 0;
+
+ maxval = celt_maxabs32(&X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM);
+ if (maxval > 0)
+ {
+ int shift = IMAX(0, 30 - celt_ilog2(maxval+(maxval>>14)+1) - ((((m->logN[i]+7)>>BITRES)+LM+1)>>1));
+ j=eBands[i]<<LM; do {
+ opus_val32 x = SHL32(X[j+c*N],shift);
+ sum = ADD32(sum, MULT32_32_Q31(x, x));
+ } while (++j<eBands[i+1]<<LM);
+ bandE[i+c*m->nbEBands] = MAX32(maxval, PSHR32(celt_sqrt32(SHR32(sum,1)), shift));
+ } else {
+ bandE[i+c*m->nbEBands] = EPSILON;
+ }
+ }
+ } while (++c<C);
+}
+
+/* Normalise each band such that the energy is one. */
+void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M)
+{
+ int i, c, N;
+ const opus_int16 *eBands = m->eBands;
+ N = M*m->shortMdctSize;
+ c=0; do {
+ i=0; do {
+ int j,shift;
+ opus_val32 E;
+ opus_val32 g;
+ E = bandE[i+c*m->nbEBands];
+ /* For very low energies, we need this to make sure not to prevent energy rounding from
+ blowing up the normalized signal. */
+ if (E < 10) E += EPSILON;
+ shift = 30-celt_zlog2(E);
+ E = SHL32(E, shift);
+ g = celt_rcp_norm32(E);
+ j=M*eBands[i]; do {
+ X[j+c*N] = PSHR32(MULT32_32_Q31(g, SHL32(freq[j+c*N], shift)), 30-NORM_SHIFT);
+ } while (++j<M*eBands[i+1]);
+ } while (++i<end);
+ } while (++c<C);
+}
+
+#else /* FIXED_POINT */
+/* Compute the amplitude (sqrt energy) in each of the bands */
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch)
+{
+ int i, c, N;
+ const opus_int16 *eBands = m->eBands;
+ N = m->shortMdctSize<<LM;
+ c=0; do {
+ for (i=0;i<end;i++)
+ {
+ opus_val32 sum;
+ sum = 1e-27f + celt_inner_prod(&X[c*N+(eBands[i]<<LM)], &X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM, arch);
+ bandE[i+c*m->nbEBands] = celt_sqrt(sum);
+ /*printf ("%f ", bandE[i+c*m->nbEBands]);*/
+ }
+ } while (++c<C);
+ /*printf ("\n");*/
+}
+
+/* Normalise each band such that the energy is one. */
+void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M)
+{
+ int i, c, N;
+ const opus_int16 *eBands = m->eBands;
+ N = M*m->shortMdctSize;
+ c=0; do {
+ for (i=0;i<end;i++)
+ {
+ int j;
+ opus_val16 g = 1.f/(1e-27f+bandE[i+c*m->nbEBands]);
+ for (j=M*eBands[i];j<M*eBands[i+1];j++)
+ X[j+c*N] = freq[j+c*N]*g;
+ }
+ } while (++c<C);
+}
+
+#endif /* FIXED_POINT */
+
+/* De-normalise the energy to produce the synthesis from the unit-energy bands */
+void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
+ celt_sig * OPUS_RESTRICT freq, const celt_glog *bandLogE, int start,
+ int end, int M, int downsample, int silence)
+{
+ int i, N;
+ int bound;
+ celt_sig * OPUS_RESTRICT f;
+ const celt_norm * OPUS_RESTRICT x;
+ const opus_int16 *eBands = m->eBands;
+ N = M*m->shortMdctSize;
+ bound = M*eBands[end];
+ if (downsample!=1)
+ bound = IMIN(bound, N/downsample);
+ if (silence)
+ {
+ bound = 0;
+ start = end = 0;
+ }
+ f = freq;
+ x = X+M*eBands[start];
+ if (start != 0)
+ {
+ for (i=0;i<M*eBands[start];i++)
+ *f++ = 0;
+ } else {
+ f += M*eBands[start];
+ }
+ for (i=start;i<end;i++)
+ {
+ int j, band_end;
+ opus_val32 g;
+ celt_glog lg;
+#ifdef FIXED_POINT
+ int shift;
+#endif
+ j=M*eBands[i];
+ band_end = M*eBands[i+1];
+ lg = ADD32(bandLogE[i], SHL32((opus_val32)eMeans[i],DB_SHIFT-4));
+#ifndef FIXED_POINT
+ g = celt_exp2_db(MIN32(32.f, lg));
+#else
+ /* Handle the integer part of the log energy */
+ shift = 17-(lg>>DB_SHIFT);
+ if (shift>=31)
+ {
+ shift=0;
+ g=0;
+ } else {
+ /* Handle the fractional part. */
+ g = SHL32(celt_exp2_db_frac((lg&((1<<DB_SHIFT)-1))), 2);
+ }
+ /* Handle extreme gains with negative shift. */
+ if (shift<0)
+ {
+ /* To avoid overflow, we're
+ capping the gain here, which is equivalent to a cap of 18 on lg.
+ This shouldn't trigger unless the bitstream is already corrupted. */
+ g = 2147483647;
+ shift = 0;
+ }
+#endif
+ do {
+ *f++ = PSHR32(MULT32_32_Q31(SHL32(*x, 30-NORM_SHIFT), g), shift);
+ x++;
+ } while (++j<band_end);
+ }
+ celt_assert(start <= end);
+ OPUS_CLEAR(&freq[bound], N-bound);
+}
+
+/* This prevents energy collapse for transients with multiple short MDCTs */
+void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_masks, int LM, int C, int size,
+ int start, int end, const celt_glog *logE, const celt_glog *prev1logE,
+ const celt_glog *prev2logE, const int *pulses, opus_uint32 seed, int encode, int arch)
+{
+ int c, i, j, k;
+ for (i=start;i<end;i++)
+ {
+ int N0;
+ opus_val16 thresh, sqrt_1;
+ int depth;
+#ifdef FIXED_POINT
+ int shift;
+ opus_val32 thresh32;
+#endif
+
+ N0 = m->eBands[i+1]-m->eBands[i];
+ /* depth in 1/8 bits */
+ celt_sig_assert(pulses[i]>=0);
+ depth = celt_udiv(1+pulses[i], (m->eBands[i+1]-m->eBands[i]))>>LM;
+
+#ifdef FIXED_POINT
+ thresh32 = SHR32(celt_exp2(-SHL16(depth, 10-BITRES)),1);
+ thresh = MULT16_32_Q15(QCONST16(0.5f, 15), MIN32(32767,thresh32));
+ {
+ opus_val32 t;
+ t = N0<<LM;
+ shift = celt_ilog2(t)>>1;
+ t = SHL32(t, (7-shift)<<1);
+ sqrt_1 = celt_rsqrt_norm(t);
+ }
+#else
+ thresh = .5f*celt_exp2(-.125f*depth);
+ sqrt_1 = celt_rsqrt(N0<<LM);
+#endif
+
+ c=0; do
+ {
+ celt_norm *X;
+ celt_glog prev1;
+ celt_glog prev2;
+ opus_val32 Ediff;
+ celt_norm r;
+ int renormalize=0;
+ prev1 = prev1logE[c*m->nbEBands+i];
+ prev2 = prev2logE[c*m->nbEBands+i];
+ if (!encode && C==1)
+ {
+ prev1 = MAXG(prev1,prev1logE[m->nbEBands+i]);
+ prev2 = MAXG(prev2,prev2logE[m->nbEBands+i]);
+ }
+ Ediff = logE[c*m->nbEBands+i]-MING(prev1,prev2);
+ Ediff = MAX32(0, Ediff);
+
+#ifdef FIXED_POINT
+ if (Ediff < GCONST(16.f))
+ {
+ opus_val32 r32 = SHR32(celt_exp2_db(-Ediff),1);
+ r = 2*MIN16(16383,r32);
+ } else {
+ r = 0;
+ }
+ if (LM==3)
+ r = MULT16_16_Q14(23170, MIN32(23169, r));
+ r = SHR16(MIN16(thresh, r),1);
+ r = VSHR32(MULT16_16_Q15(sqrt_1, r),shift+14-NORM_SHIFT);
+#else
+ /* r needs to be multiplied by 2 or 2*sqrt(2) depending on LM because
+ short blocks don't have the same energy as long */
+ r = 2.f*celt_exp2_db(-Ediff);
+ if (LM==3)
+ r *= 1.41421356f;
+ r = MIN16(thresh, r);
+ r = r*sqrt_1;
+#endif
+ X = X_+c*size+(m->eBands[i]<<LM);
+ for (k=0;k<1<<LM;k++)
+ {
+ /* Detect collapse */
+ if (!(collapse_masks[i*C+c]&1<<k))
+ {
+ /* Fill with noise */
+ for (j=0;j<N0;j++)
+ {
+ seed = celt_lcg_rand(seed);
+ X[(j<<LM)+k] = (seed&0x8000 ? r : -r);
+ }
+ renormalize = 1;
+ }
+ }
+ /* We just added some energy, so we need to renormalise */
+ if (renormalize)
+ renormalise_vector(X, N0<<LM, Q31ONE, arch);
+ } while (++c<C);
+ }
+}
+
+/* Compute the weights to use for optimizing normalized distortion across
+ channels. We use the amplitude to weight square distortion, which means
+ that we use the square root of the value we would have been using if we
+ wanted to minimize the MSE in the non-normalized domain. This roughly
+ corresponds to some quick-and-dirty perceptual experiments I ran to
+ measure inter-aural masking (there doesn't seem to be any published data
+ on the topic). */
+static void compute_channel_weights(celt_ener Ex, celt_ener Ey, opus_val16 w[2])
+{
+ celt_ener minE;
+#ifdef FIXED_POINT
+ int shift;
+#endif
+ minE = MIN32(Ex, Ey);
+ /* Adjustment to make the weights a bit more conservative. */
+ Ex = ADD32(Ex, minE/3);
+ Ey = ADD32(Ey, minE/3);
+#ifdef FIXED_POINT
+ shift = celt_ilog2(EPSILON+MAX32(Ex, Ey))-14;
+#endif
+ w[0] = VSHR32(Ex, shift);
+ w[1] = VSHR32(Ey, shift);
+}
+
+static void intensity_stereo(const CELTMode *m, celt_norm * OPUS_RESTRICT X, const celt_norm * OPUS_RESTRICT Y, const celt_ener *bandE, int bandID, int N)
+{
+ int i = bandID;
+ int j;
+ opus_val16 a1, a2;
+ opus_val16 left, right;
+ opus_val16 norm;
+#ifdef FIXED_POINT
+ int shift = celt_zlog2(MAX32(bandE[i], bandE[i+m->nbEBands]))-13;
+#endif
+ left = VSHR32(bandE[i],shift);
+ right = VSHR32(bandE[i+m->nbEBands],shift);
+ norm = EPSILON + celt_sqrt(EPSILON+MULT16_16(left,left)+MULT16_16(right,right));
+#ifdef FIXED_POINT
+ left = MIN32(left, norm-1);
+ right = MIN32(right, norm-1);
+#endif
+ a1 = DIV32_16(SHL32(EXTEND32(left),15),norm);
+ a2 = DIV32_16(SHL32(EXTEND32(right),15),norm);
+ for (j=0;j<N;j++)
+ {
+ X[j] = ADD32(MULT16_32_Q15(a1, X[j]), MULT16_32_Q15(a2, Y[j]));
+ /* Side is not encoded, no need to calculate */
+ }
+}
+
+static void stereo_split(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT Y, int N)
+{
+ int j;
+ for (j=0;j<N;j++)
+ {
+ opus_val32 r, l;
+ l = MULT32_32_Q31(QCONST32(.70710678f,31), X[j]);
+ r = MULT32_32_Q31(QCONST32(.70710678f,31), Y[j]);
+ X[j] = ADD32(l, r);
+ Y[j] = SUB32(r, l);
+ }
+}
+
+static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT Y, opus_val32 mid, int N, int arch)
+{
+ int j;
+ opus_val32 xp=0, side=0;
+ opus_val32 El, Er;
+#ifdef FIXED_POINT
+ int kl, kr;
+#endif
+ opus_val32 t, lgain, rgain;
+
+ /* Compute the norm of X+Y and X-Y as |X|^2 + |Y|^2 +/- sum(xy) */
+ xp = celt_inner_prod_norm_shift(Y, X, N, arch);
+ side = celt_inner_prod_norm_shift(Y, Y, N, arch);
+ /* Compensating for the mid normalization */
+ xp = MULT32_32_Q31(mid, xp);
+ /* mid and side are in Q15, not Q14 like X and Y */
+ El = SHR32(MULT32_32_Q31(mid, mid),3) + side - 2*xp;
+ Er = SHR32(MULT32_32_Q31(mid, mid),3) + side + 2*xp;
+ if (Er < QCONST32(6e-4f, 28) || El < QCONST32(6e-4f, 28))
+ {
+ OPUS_COPY(Y, X, N);
+ return;
+ }
+
+#ifdef FIXED_POINT
+ kl = celt_ilog2(El)>>1;
+ kr = celt_ilog2(Er)>>1;
+#endif
+ t = VSHR32(El, (kl<<1)-29);
+ lgain = celt_rsqrt_norm32(t);
+ t = VSHR32(Er, (kr<<1)-29);
+ rgain = celt_rsqrt_norm32(t);
+
+#ifdef FIXED_POINT
+ if (kl < 7)
+ kl = 7;
+ if (kr < 7)
+ kr = 7;
+#endif
+
+ for (j=0;j<N;j++)
+ {
+ celt_norm r, l;
+ /* Apply mid scaling (side is already scaled) */
+ l = MULT32_32_Q31(mid, X[j]);
+ r = Y[j];
+ X[j] = VSHR32(MULT32_32_Q31(lgain, SUB32(l,r)), kl-15);
+ Y[j] = VSHR32(MULT32_32_Q31(rgain, ADD32(l,r)), kr-15);
+ }
+}
+
+/* Decide whether we should spread the pulses in the current frame */
+int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
+ int last_decision, int *hf_average, int *tapset_decision, int update_hf,
+ int end, int C, int M, const int *spread_weight)
+{
+ int i, c, N0;
+ int sum = 0, nbBands=0;
+ const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
+ int decision;
+ int hf_sum=0;
+
+ celt_assert(end>0);
+
+ N0 = M*m->shortMdctSize;
+
+ if (M*(eBands[end]-eBands[end-1]) <= 8)
+ return SPREAD_NONE;
+ c=0; do {
+ for (i=0;i<end;i++)
+ {
+ int j, N, tmp=0;
+ int tcount[3] = {0,0,0};
+ const celt_norm * OPUS_RESTRICT x = X+M*eBands[i]+c*N0;
+ N = M*(eBands[i+1]-eBands[i]);
+ if (N<=8)
+ continue;
+ /* Compute rough CDF of |x[j]| */
+ for (j=0;j<N;j++)
+ {
+ opus_val32 x2N; /* Q13 */
+
+ x2N = MULT16_16(MULT16_16_Q15(SHR32(x[j], NORM_SHIFT-14), SHR32(x[j], NORM_SHIFT-14)), N);
+ if (x2N < QCONST16(0.25f,13))
+ tcount[0]++;
+ if (x2N < QCONST16(0.0625f,13))
+ tcount[1]++;
+ if (x2N < QCONST16(0.015625f,13))
+ tcount[2]++;
+ }
+
+ /* Only include four last bands (8 kHz and up) */
+ if (i>m->nbEBands-4)
+ hf_sum += celt_udiv(32*(tcount[1]+tcount[0]), N);
+ tmp = (2*tcount[2] >= N) + (2*tcount[1] >= N) + (2*tcount[0] >= N);
+ sum += tmp*spread_weight[i];
+ nbBands+=spread_weight[i];
+ }
+ } while (++c<C);
+
+ if (update_hf)
+ {
+ if (hf_sum)
+ hf_sum = celt_udiv(hf_sum, C*(4-m->nbEBands+end));
+ *hf_average = (*hf_average+hf_sum)>>1;
+ hf_sum = *hf_average;
+ if (*tapset_decision==2)
+ hf_sum += 4;
+ else if (*tapset_decision==0)
+ hf_sum -= 4;
+ if (hf_sum > 22)
+ *tapset_decision=2;
+ else if (hf_sum > 18)
+ *tapset_decision=1;
+ else
+ *tapset_decision=0;
+ }
+ /*printf("%d %d %d\n", hf_sum, *hf_average, *tapset_decision);*/
+ celt_assert(nbBands>0); /* end has to be non-zero */
+ celt_assert(sum>=0);
+ sum = celt_udiv((opus_int32)sum<<8, nbBands);
+ /* Recursive averaging */
+ sum = (sum+*average)>>1;
+ *average = sum;
+ /* Hysteresis */
+ sum = (3*sum + (((3-last_decision)<<7) + 64) + 2)>>2;
+ if (sum < 80)
+ {
+ decision = SPREAD_AGGRESSIVE;
+ } else if (sum < 256)
+ {
+ decision = SPREAD_NORMAL;
+ } else if (sum < 384)
+ {
+ decision = SPREAD_LIGHT;
+ } else {
+ decision = SPREAD_NONE;
+ }
+#ifdef FUZZING
+ decision = rand()&0x3;
+ *tapset_decision=rand()%3;
+#endif
+ return decision;
+}
+
+/* Indexing table for converting from natural Hadamard to ordery Hadamard
+ This is essentially a bit-reversed Gray, on top of which we've added
+ an inversion of the order because we want the DC at the end rather than
+ the beginning. The lines are for N=2, 4, 8, 16 */
+static const int ordery_table[] = {
+ 1, 0,
+ 3, 0, 2, 1,
+ 7, 0, 4, 3, 6, 1, 5, 2,
+ 15, 0, 8, 7, 12, 3, 11, 4, 14, 1, 9, 6, 13, 2, 10, 5,
+};
+
+static void deinterleave_hadamard(celt_norm *X, int N0, int stride, int hadamard)
+{
+ int i,j;
+ VARDECL(celt_norm, tmp);
+ int N;
+ SAVE_STACK;
+ N = N0*stride;
+ ALLOC(tmp, N, celt_norm);
+ celt_assert(stride>0);
+ if (hadamard)
+ {
+ const int *ordery = ordery_table+stride-2;
+ for (i=0;i<stride;i++)
+ {
+ for (j=0;j<N0;j++)
+ tmp[ordery[i]*N0+j] = X[j*stride+i];
+ }
+ } else {
+ for (i=0;i<stride;i++)
+ for (j=0;j<N0;j++)
+ tmp[i*N0+j] = X[j*stride+i];
+ }
+ OPUS_COPY(X, tmp, N);
+ RESTORE_STACK;
+}
+
+static void interleave_hadamard(celt_norm *X, int N0, int stride, int hadamard)
+{
+ int i,j;
+ VARDECL(celt_norm, tmp);
+ int N;
+ SAVE_STACK;
+ N = N0*stride;
+ ALLOC(tmp, N, celt_norm);
+ if (hadamard)
+ {
+ const int *ordery = ordery_table+stride-2;
+ for (i=0;i<stride;i++)
+ for (j=0;j<N0;j++)
+ tmp[j*stride+i] = X[ordery[i]*N0+j];
+ } else {
+ for (i=0;i<stride;i++)
+ for (j=0;j<N0;j++)
+ tmp[j*stride+i] = X[i*N0+j];
+ }
+ OPUS_COPY(X, tmp, N);
+ RESTORE_STACK;
+}
+
+void haar1(celt_norm *X, int N0, int stride)
+{
+ int i, j;
+ N0 >>= 1;
+ for (i=0;i<stride;i++)
+ for (j=0;j<N0;j++)
+ {
+ opus_val32 tmp1, tmp2;
+ tmp1 = MULT32_32_Q31(QCONST32(.70710678f,31), X[stride*2*j+i]);
+ tmp2 = MULT32_32_Q31(QCONST32(.70710678f,31), X[stride*(2*j+1)+i]);
+ X[stride*2*j+i] = ADD32(tmp1, tmp2);
+ X[stride*(2*j+1)+i] = SUB32(tmp1, tmp2);
+ }
+}
+
+static int compute_qn(int N, int b, int offset, int pulse_cap, int stereo)
+{
+ static const opus_int16 exp2_table8[8] =
+ {16384, 17866, 19483, 21247, 23170, 25267, 27554, 30048};
+ int qn, qb;
+ int N2 = 2*N-1;
+ if (stereo && N==2)
+ N2--;
+ /* The upper limit ensures that in a stereo split with itheta==16384, we'll
+ always have enough bits left over to code at least one pulse in the
+ side; otherwise it would collapse, since it doesn't get folded. */
+ qb = celt_sudiv(b+N2*offset, N2);
+ qb = IMIN(b-pulse_cap-(4<<BITRES), qb);
+
+ qb = IMIN(8<<BITRES, qb);
+
+ if (qb<(1<<BITRES>>1)) {
+ qn = 1;
+ } else {
+ qn = exp2_table8[qb&0x7]>>(14-(qb>>BITRES));
+ qn = (qn+1)>>1<<1;
+ }
+ celt_assert(qn <= 256);
+ return qn;
+}
+
+struct band_ctx {
+ int encode;
+ int resynth;
+ const CELTMode *m;
+ int i;
+ int intensity;
+ int spread;
+ int tf_change;
+ ec_ctx *ec;
+ opus_int32 remaining_bits;
+ const celt_ener *bandE;
+ opus_uint32 seed;
+ int arch;
+ int theta_round;
+ int disable_inv;
+ int avoid_split_noise;
+#ifdef ENABLE_QEXT
+ ec_ctx *ext_ec;
+ int extra_bits;
+ opus_int32 ext_total_bits;
+ int extra_bands;
+#endif
+};
+
+struct split_ctx {
+ int inv;
+ int imid;
+ int iside;
+ int delta;
+ int itheta;
+#ifdef ENABLE_QEXT
+ int itheta_q30;
+#endif
+ int qalloc;
+};
+
+static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
+ celt_norm *X, celt_norm *Y, int N, int *b, int B, int B0,
+ int LM,
+ int stereo, int *fill ARG_QEXT(int *ext_b))
+{
+ int qn;
+ int itheta=0;
+ int itheta_q30=0;
+ int delta;
+ int imid, iside;
+ int qalloc;
+ int pulse_cap;
+ int offset;
+ opus_int32 tell;
+ int inv=0;
+ int encode;
+ const CELTMode *m;
+ int i;
+ int intensity;
+ ec_ctx *ec;
+ const celt_ener *bandE;
+
+ encode = ctx->encode;
+ m = ctx->m;
+ i = ctx->i;
+ intensity = ctx->intensity;
+ ec = ctx->ec;
+ bandE = ctx->bandE;
+
+ /* Decide on the resolution to give to the split parameter theta */
+ pulse_cap = m->logN[i]+LM*(1<<BITRES);
+ offset = (pulse_cap>>1) - (stereo&&N==2 ? QTHETA_OFFSET_TWOPHASE : QTHETA_OFFSET);
+ qn = compute_qn(N, *b, offset, pulse_cap, stereo);
+ if (stereo && i>=intensity)
+ qn = 1;
+ if (encode)
+ {
+ /* theta is the atan() of the ratio between the (normalized)
+ side and mid. With just that parameter, we can re-scale both
+ mid and side because we know that 1) they have unit norm and
+ 2) they are orthogonal. */
+ itheta_q30 = stereo_itheta(X, Y, stereo, N, ctx->arch);
+ itheta = itheta_q30>>16;
+ }
+ tell = ec_tell_frac(ec);
+ if (qn!=1)
+ {
+ if (encode)
+ {
+ if (!stereo || ctx->theta_round == 0)
+ {
+ itheta = (itheta*(opus_int32)qn+8192)>>14;
+ if (!stereo && ctx->avoid_split_noise && itheta > 0 && itheta < qn)
+ {
+ /* Check if the selected value of theta will cause the bit allocation
+ to inject noise on one side. If so, make sure the energy of that side
+ is zero. */
+ int unquantized = celt_udiv((opus_int32)itheta*16384, qn);
+ imid = bitexact_cos((opus_int16)unquantized);
+ iside = bitexact_cos((opus_int16)(16384-unquantized));
+ delta = FRAC_MUL16((N-1)<<7,bitexact_log2tan(iside,imid));
+ if (delta > *b)
+ itheta = qn;
+ else if (delta < -*b)
+ itheta = 0;
+ }
+ } else {
+ int down;
+ /* Bias quantization towards itheta=0 and itheta=16384. */
+ int bias = itheta > 8192 ? 32767/qn : -32767/qn;
+ down = IMIN(qn-1, IMAX(0, (itheta*(opus_int32)qn + bias)>>14));
+ if (ctx->theta_round < 0)
+ itheta = down;
+ else
+ itheta = down+1;
+ }
+ }
+ /* Entropy coding of the angle. We use a uniform pdf for the
+ time split, a step for stereo, and a triangular one for the rest. */
+ if (stereo && N>2)
+ {
+ int p0 = 3;
+ int x = itheta;
+ int x0 = qn/2;
+ int ft = p0*(x0+1) + x0;
+ /* Use a probability of p0 up to itheta=8192 and then use 1 after */
+ if (encode)
+ {
+ ec_encode(ec,x<=x0?p0*x:(x-1-x0)+(x0+1)*p0,x<=x0?p0*(x+1):(x-x0)+(x0+1)*p0,ft);
+ } else {
+ int fs;
+ fs=ec_decode(ec,ft);
+ if (fs<(x0+1)*p0)
+ x=fs/p0;
+ else
+ x=x0+1+(fs-(x0+1)*p0);
+ ec_dec_update(ec,x<=x0?p0*x:(x-1-x0)+(x0+1)*p0,x<=x0?p0*(x+1):(x-x0)+(x0+1)*p0,ft);
+ itheta = x;
+ }
+ } else if (B0>1 || stereo) {
+ /* Uniform pdf */
+ if (encode)
+ ec_enc_uint(ec, itheta, qn+1);
+ else
+ itheta = ec_dec_uint(ec, qn+1);
+ } else {
+ int fs=1, ft;
+ ft = ((qn>>1)+1)*((qn>>1)+1);
+ if (encode)
+ {
+ int fl;
+
+ fs = itheta <= (qn>>1) ? itheta + 1 : qn + 1 - itheta;
+ fl = itheta <= (qn>>1) ? itheta*(itheta + 1)>>1 :
+ ft - ((qn + 1 - itheta)*(qn + 2 - itheta)>>1);
+
+ ec_encode(ec, fl, fl+fs, ft);
+ } else {
+ /* Triangular pdf */
+ int fl=0;
+ int fm;
+ fm = ec_decode(ec, ft);
+
+ if (fm < ((qn>>1)*((qn>>1) + 1)>>1))
+ {
+ itheta = (isqrt32(8*(opus_uint32)fm + 1) - 1)>>1;
+ fs = itheta + 1;
+ fl = itheta*(itheta + 1)>>1;
+ }
+ else
+ {
+ itheta = (2*(qn + 1)
+ - isqrt32(8*(opus_uint32)(ft - fm - 1) + 1))>>1;
+ fs = qn + 1 - itheta;
+ fl = ft - ((qn + 1 - itheta)*(qn + 2 - itheta)>>1);
+ }
+
+ ec_dec_update(ec, fl, fl+fs, ft);
+ }
+ }
+ celt_assert(itheta>=0);
+ itheta = celt_udiv((opus_int32)itheta*16384, qn);
+#ifdef ENABLE_QEXT
+ *ext_b = IMIN(*ext_b, ctx->ext_total_bits - (opus_int32)ec_tell_frac(ctx->ext_ec));
+ if (*ext_b >= 2*N<<BITRES && ctx->ext_total_bits-ec_tell_frac(ctx->ext_ec)-1 > 2<<BITRES) {
+ int extra_bits;
+ int ext_tell = ec_tell_frac(ctx->ext_ec);
+ extra_bits = IMIN(12, IMAX(2, celt_sudiv(*ext_b, (2*N-1)<<BITRES)));
+ if (encode) {
+ itheta_q30 = itheta_q30 - (itheta<<16);
+ itheta_q30 = (itheta_q30*(opus_int64)qn*((1<<extra_bits)-1)+(1<<29))>>30;
+ itheta_q30 += (1<<(extra_bits-1))-1;
+ itheta_q30 = IMAX(0, IMIN((1<<extra_bits)-2, itheta_q30));
+ ec_enc_uint(ctx->ext_ec, itheta_q30, (1<<extra_bits)-1);
+ } else {
+ itheta_q30 = ec_dec_uint(ctx->ext_ec, (1<<extra_bits)-1);
+ }
+ itheta_q30 -= (1<<(extra_bits-1))-1;
+ itheta_q30 = (itheta<<16) + itheta_q30*(opus_int64)(1<<30)/(qn*((1<<extra_bits)-1));
+ /* Hard bounds on itheta (can only trigger on corrupted bitstreams). */
+ itheta_q30 = IMAX(0, IMIN(itheta_q30, 1073741824));
+ *ext_b -= ec_tell_frac(ctx->ext_ec) - ext_tell;
+ } else {
+ itheta_q30 = (opus_int32)itheta<<16;
+ }
+#endif
+ if (encode && stereo)
+ {
+ if (itheta==0)
+ intensity_stereo(m, X, Y, bandE, i, N);
+ else
+ stereo_split(X, Y, N);
+ }
+ /* NOTE: Renormalising X and Y *may* help fixed-point a bit at very high rate.
+ Let's do that at higher complexity */
+ } else if (stereo) {
+ if (encode)
+ {
+ inv = itheta > 8192 && !ctx->disable_inv;
+ if (inv)
+ {
+ int j;
+ for (j=0;j<N;j++)
+ Y[j] = -Y[j];
+ }
+ intensity_stereo(m, X, Y, bandE, i, N);
+ }
+ if (*b>2<<BITRES && ctx->remaining_bits > 2<<BITRES)
+ {
+ if (encode)
+ ec_enc_bit_logp(ec, inv, 2);
+ else
+ inv = ec_dec_bit_logp(ec, 2);
+ } else
+ inv = 0;
+ /* inv flag override to avoid problems with downmixing. */
+ if (ctx->disable_inv)
+ inv = 0;
+ itheta = 0;
+ itheta_q30 = 0;
+ }
+ qalloc = ec_tell_frac(ec) - tell;
+ *b -= qalloc;
+
+ if (itheta == 0)
+ {
+ imid = 32767;
+ iside = 0;
+ *fill &= (1<<B)-1;
+ delta = -16384;
+ } else if (itheta == 16384)
+ {
+ imid = 0;
+ iside = 32767;
+ *fill &= ((1<<B)-1)<<B;
+ delta = 16384;
+ } else {
+ imid = bitexact_cos((opus_int16)itheta);
+ iside = bitexact_cos((opus_int16)(16384-itheta));
+ /* This is the mid vs side allocation that minimizes squared error
+ in that band. */
+ delta = FRAC_MUL16((N-1)<<7,bitexact_log2tan(iside,imid));
+ }
+
+ sctx->inv = inv;
+ sctx->imid = imid;
+ sctx->iside = iside;
+ sctx->delta = delta;
+ sctx->itheta = itheta;
+#ifdef ENABLE_QEXT
+ sctx->itheta_q30 = itheta_q30;
+#endif
+ sctx->qalloc = qalloc;
+}
+static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y,
+ celt_norm *lowband_out)
+{
+ int c;
+ int stereo;
+ celt_norm *x = X;
+ int encode;
+ ec_ctx *ec;
+
+ encode = ctx->encode;
+ ec = ctx->ec;
+
+ stereo = Y != NULL;
+ c=0; do {
+ int sign=0;
+ if (ctx->remaining_bits>=1<<BITRES)
+ {
+ if (encode)
+ {
+ sign = x[0]<0;
+ ec_enc_bits(ec, sign, 1);
+ } else {
+ sign = ec_dec_bits(ec, 1);
+ }
+ ctx->remaining_bits -= 1<<BITRES;
+ }
+ if (ctx->resynth)
+ x[0] = sign ? -NORM_SCALING : NORM_SCALING;
+ x = Y;
+ } while (++c<1+stereo);
+ if (lowband_out)
+ lowband_out[0] = SHR32(X[0],4);
+ return 1;
+}
+
+/* This function is responsible for encoding and decoding a mono partition.
+ It can split the band in two and transmit the energy difference with
+ the two half-bands. It can be called recursively so bands can end up being
+ split in 8 parts. */
+static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
+ int N, int b, int B, celt_norm *lowband,
+ int LM,
+ opus_val32 gain, int fill
+ ARG_QEXT(int ext_b))
+{
+ const unsigned char *cache;
+ int q;
+ int curr_bits;
+ int imid=0, iside=0;
+ int B0=B;
+ opus_val32 mid=0, side=0;
+ unsigned cm=0;
+ celt_norm *Y=NULL;
+ int encode;
+ const CELTMode *m;
+ int i;
+ int spread;
+ ec_ctx *ec;
+
+ encode = ctx->encode;
+ m = ctx->m;
+ i = ctx->i;
+ spread = ctx->spread;
+ ec = ctx->ec;
+
+ /* If we need 1.5 more bit than we can produce, split the band in two. */
+ cache = m->cache.bits + m->cache.index[(LM+1)*m->nbEBands+i];
+ if (LM != -1 && b > cache[cache[0]]+12 && N>2)
+ {
+ int mbits, sbits, delta;
+ int itheta;
+ int qalloc;
+ struct split_ctx sctx;
+ celt_norm *next_lowband2=NULL;
+ opus_int32 rebalance;
+
+ N >>= 1;
+ Y = X+N;
+ LM -= 1;
+ if (B==1)
+ fill = (fill&1)|(fill<<1);
+ B = (B+1)>>1;
+
+ compute_theta(ctx, &sctx, X, Y, N, &b, B, B0, LM, 0, &fill ARG_QEXT(&ext_b));
+ imid = sctx.imid;
+ iside = sctx.iside;
+ delta = sctx.delta;
+ itheta = sctx.itheta;
+ qalloc = sctx.qalloc;
+#ifdef FIXED_POINT
+# ifdef ENABLE_QEXT
+ (void)imid;
+ (void)iside;
+ mid = celt_cos_norm32(sctx.itheta_q30);
+ side = celt_cos_norm32((1<<30)-sctx.itheta_q30);
+# else
+ mid = SHL32(EXTEND32(imid), 16);
+ side = SHL32(EXTEND32(iside), 16);
+# endif
+#else
+# ifdef ENABLE_QEXT
+ (void)imid;
+ (void)iside;
+ mid = celt_cos_norm2(sctx.itheta_q30*(1.f/(1<<30)));
+ side = celt_cos_norm2(1.f-sctx.itheta_q30*(1.f/(1<<30)));
+# else
+ mid = (1.f/32768)*imid;
+ side = (1.f/32768)*iside;
+# endif
+#endif
+
+ /* Give more bits to low-energy MDCTs than they would otherwise deserve */
+ if (B0>1 && (itheta&0x3fff))
+ {
+ if (itheta > 8192)
+ /* Rough approximation for pre-echo masking */
+ delta -= delta>>(4-LM);
+ else
+ /* Corresponds to a forward-masking slope of 1.5 dB per 10 ms */
+ delta = IMIN(0, delta + (N<<BITRES>>(5-LM)));
+ }
+ mbits = IMAX(0, IMIN(b, (b-delta)/2));
+ sbits = b-mbits;
+ ctx->remaining_bits -= qalloc;
+
+ if (lowband)
+ next_lowband2 = lowband+N; /* >32-bit split case */
+
+ rebalance = ctx->remaining_bits;
+ if (mbits >= sbits)
+ {
+ cm = quant_partition(ctx, X, N, mbits, B, lowband, LM,
+ MULT32_32_Q31(gain,mid), fill ARG_QEXT(ext_b/2));
+ rebalance = mbits - (rebalance-ctx->remaining_bits);
+ if (rebalance > 3<<BITRES && itheta!=0)
+ sbits += rebalance - (3<<BITRES);
+ cm |= quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
+ MULT32_32_Q31(gain,side), fill>>B ARG_QEXT(ext_b/2))<<(B0>>1);
+ } else {
+ cm = quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
+ MULT32_32_Q31(gain,side), fill>>B ARG_QEXT(ext_b/2))<<(B0>>1);
+ rebalance = sbits - (rebalance-ctx->remaining_bits);
+ if (rebalance > 3<<BITRES && itheta!=16384)
+ mbits += rebalance - (3<<BITRES);
+ cm |= quant_partition(ctx, X, N, mbits, B, lowband, LM,
+ MULT32_32_Q31(gain,mid), fill ARG_QEXT(ext_b/2));
+ }
+ } else {
+#ifdef ENABLE_QEXT
+ int extra_bits;
+ int ext_remaining_bits;
+ extra_bits = ext_b/(N-1)>>BITRES;
+ ext_remaining_bits = ctx->ext_total_bits-(opus_int32)ec_tell_frac(ctx->ext_ec);
+ if (ext_remaining_bits < ((extra_bits+1)*(N-1)+N)<<BITRES) {
+ extra_bits = (ext_remaining_bits-(N<<BITRES))/(N-1)>>BITRES;
+ extra_bits = IMAX(extra_bits-1, 0);
+ }
+ extra_bits = IMIN(12, extra_bits);
+#endif
+ /* This is the basic no-split case */
+ q = bits2pulses(m, i, LM, b);
+ curr_bits = pulses2bits(m, i, LM, q);
+ ctx->remaining_bits -= curr_bits;
+
+ /* Ensures we can never bust the budget */
+ while (ctx->remaining_bits < 0 && q > 0)
+ {
+ ctx->remaining_bits += curr_bits;
+ q--;
+ curr_bits = pulses2bits(m, i, LM, q);
+ ctx->remaining_bits -= curr_bits;
+ }
+
+ if (q!=0)
+ {
+ int K = get_pulses(q);
+
+ /* Finally do the actual quantization */
+ if (encode)
+ {
+ cm = alg_quant(X, N, K, spread, B, ec, gain, ctx->resynth
+ ARG_QEXT(ctx->ext_ec) ARG_QEXT(extra_bits),
+ ctx->arch);
+ } else {
+ cm = alg_unquant(X, N, K, spread, B, ec, gain
+ ARG_QEXT(ctx->ext_ec) ARG_QEXT(extra_bits));
+ }
+#ifdef ENABLE_QEXT
+ } else if (ext_b > 2*N<<BITRES)
+ {
+ extra_bits = ext_b/(N-1)>>BITRES;
+ ext_remaining_bits = ctx->ext_total_bits-ec_tell_frac(ctx->ext_ec);
+ if (ext_remaining_bits < ((extra_bits+1)*(N-1)+N)<<BITRES) {
+ extra_bits = (ext_remaining_bits-(N<<BITRES))/(N-1)>>BITRES;
+ extra_bits = IMAX(extra_bits-1, 0);
+ }
+ extra_bits = IMIN(14, extra_bits);
+ if (encode) cm = cubic_quant(X, N, extra_bits, B, ctx->ext_ec, gain, ctx->resynth);
+ else cm = cubic_unquant(X, N, extra_bits, B, ctx->ext_ec, gain);
+#endif
+ } else {
+ /* If there's no pulse, fill the band anyway */
+ int j;
+ if (ctx->resynth)
+ {
+ unsigned cm_mask;
+ /* B can be as large as 16, so this shift might overflow an int on a
+ 16-bit platform; use a long to get defined behavior.*/
+ cm_mask = (unsigned)(1UL<<B)-1;
+ fill &= cm_mask;
+ if (!fill)
+ {
+ OPUS_CLEAR(X, N);
+ } else {
+ if (lowband == NULL)
+ {
+ /* Noise */
+ for (j=0;j<N;j++)
+ {
+ ctx->seed = celt_lcg_rand(ctx->seed);
+ X[j] = SHL32((celt_norm)((opus_int32)ctx->seed>>20), NORM_SHIFT-14);
+ }
+ cm = cm_mask;
+ } else {
+ /* Folded spectrum */
+ for (j=0;j<N;j++)
+ {
+ opus_val16 tmp;
+ ctx->seed = celt_lcg_rand(ctx->seed);
+ /* About 48 dB below the "normal" folding level */
+ tmp = QCONST16(1.0f/256, NORM_SHIFT-4);
+ tmp = (ctx->seed)&0x8000 ? tmp : -tmp;
+ X[j] = lowband[j]+tmp;
+ }
+ cm = fill;
+ }
+ renormalise_vector(X, N, gain, ctx->arch);
+ }
+ }
+ }
+ }
+
+ return cm;
+}
+
+#ifdef ENABLE_QEXT
+static unsigned cubic_quant_partition(struct band_ctx *ctx, celt_norm *X, int N, int b, int B, ec_ctx *ec, int LM, opus_val32 gain, int resynth, int encode)
+{
+ celt_assert(LM>=0);
+ ctx->remaining_bits = ctx->ec->storage*8*8 - ec_tell_frac(ctx->ec);
+ b = IMIN(b, ctx->remaining_bits);
+ /* As long as we have at least two bits of depth, split all the way to LM=0 (not -1 like PVQ). */
+ if (LM==0 || b<=2*N<<BITRES) {
+ int res, ret;
+ b = IMIN(b + ((N-1)<<BITRES)/2, ctx->remaining_bits);
+ /* Resolution left after taking into account coding the cube face. */
+ res = (b-(1<<BITRES)-ctx->m->logN[ctx->i]-(LM<<BITRES)-1)/(N-1)>>BITRES;
+ res = IMIN(14, IMAX(0, res));
+ if (encode) ret = cubic_quant(X, N, res, B, ec, gain, resynth);
+ else ret = cubic_unquant(X, N, res, B, ec, gain);
+ ctx->remaining_bits = ctx->ec->storage*8*8 - ec_tell_frac(ctx->ec);
+ return ret;
+ } else {
+ celt_norm *Y;
+ opus_int32 itheta_q30;
+ opus_val32 g1, g2;
+ opus_int32 theta_res;
+ opus_int32 qtheta;
+ int delta;
+ int b1, b2;
+ int cm;
+ int N0;
+ N0 = N;
+ N >>= 1;
+ Y = X+N;
+ LM -= 1;
+ B = (B+1)>>1;
+ theta_res = IMIN(16, (b>>BITRES)/(N0-1) + 1);
+ if (encode) {
+ itheta_q30 = stereo_itheta(X, Y, 0, N, ctx->arch);
+ qtheta = (itheta_q30+(1<<(29-theta_res)))>>(30-theta_res);
+ ec_enc_uint(ec, qtheta, (1<<theta_res)+1);
+ } else {
+ qtheta = ec_dec_uint(ec, (1<<theta_res)+1);
+ }
+ itheta_q30 = qtheta<<(30-theta_res);
+ b -= theta_res<<BITRES;
+ delta = (N0-1) * 23 * ((itheta_q30>>16)-8192) >> (17-BITRES);
+
+#ifdef FIXED_POINT
+ g1 = celt_cos_norm32(itheta_q30);
+ g2 = celt_cos_norm32((1<<30)-itheta_q30);
+#else
+ g1 = celt_cos_norm2(itheta_q30*(1.f/(1<<30)));
+ g2 = celt_cos_norm2(1.f-itheta_q30*(1.f/(1<<30)));
+#endif
+ if (itheta_q30 == 0) {
+ b1=b;
+ b2=0;
+ } else if (itheta_q30==1073741824) {
+ b1=0;
+ b2=b;
+ } else {
+ b1 = IMIN(b, IMAX(0, (b-delta)/2));
+ b2 = b-b1;
+ }
+ cm = cubic_quant_partition(ctx, X, N, b1, B, ec, LM, MULT32_32_Q31(gain, g1), resynth, encode);
+ cm |= cubic_quant_partition(ctx, Y, N, b2, B, ec, LM, MULT32_32_Q31(gain, g2), resynth, encode);
+ return cm;
+ }
+}
+#endif
+
+/* This function is responsible for encoding and decoding a band for the mono case. */
+static unsigned quant_band(struct band_ctx *ctx, celt_norm *X,
+ int N, int b, int B, celt_norm *lowband,
+ int LM, celt_norm *lowband_out,
+ opus_val32 gain, celt_norm *lowband_scratch, int fill
+ ARG_QEXT(int ext_b))
+{
+ int N0=N;
+ int N_B=N;
+ int N_B0;
+ int B0=B;
+ int time_divide=0;
+ int recombine=0;
+ int longBlocks;
+ unsigned cm=0;
+ int k;
+ int encode;
+ int tf_change;
+
+ encode = ctx->encode;
+ tf_change = ctx->tf_change;
+
+ longBlocks = B0==1;
+
+ N_B = celt_udiv(N_B, B);
+
+ /* Special case for one sample */
+ if (N==1)
+ {
+ return quant_band_n1(ctx, X, NULL, lowband_out);
+ }
+
+ if (tf_change>0)
+ recombine = tf_change;
+ /* Band recombining to increase frequency resolution */
+
+ if (lowband_scratch && lowband && (recombine || ((N_B&1) == 0 && tf_change<0) || B0>1))
+ {
+ OPUS_COPY(lowband_scratch, lowband, N);
+ lowband = lowband_scratch;
+ }
+
+ for (k=0;k<recombine;k++)
+ {
+ static const unsigned char bit_interleave_table[16]={
+ 0,1,1,1,2,3,3,3,2,3,3,3,2,3,3,3
+ };
+ if (encode)
+ haar1(X, N>>k, 1<<k);
+ if (lowband)
+ haar1(lowband, N>>k, 1<<k);
+ fill = bit_interleave_table[fill&0xF]|bit_interleave_table[fill>>4]<<2;
+ }
+ B>>=recombine;
+ N_B<<=recombine;
+
+ /* Increasing the time resolution */
+ while ((N_B&1) == 0 && tf_change<0)
+ {
+ if (encode)
+ haar1(X, N_B, B);
+ if (lowband)
+ haar1(lowband, N_B, B);
+ fill |= fill<<B;
+ B <<= 1;
+ N_B >>= 1;
+ time_divide++;
+ tf_change++;
+ }
+ B0=B;
+ N_B0 = N_B;
+
+ /* Reorganize the samples in time order instead of frequency order */
+ if (B0>1)
+ {
+ if (encode)
+ deinterleave_hadamard(X, N_B>>recombine, B0<<recombine, longBlocks);
+ if (lowband)
+ deinterleave_hadamard(lowband, N_B>>recombine, B0<<recombine, longBlocks);
+ }
+
+#ifdef ENABLE_QEXT
+ if (ctx->extra_bands && b > (3*N<<BITRES)+(ctx->m->logN[ctx->i]+8+8*LM)) {
+ cm = cubic_quant_partition(ctx, X, N, b, B, ctx->ec, LM, gain, ctx->resynth, encode);
+ } else
+#endif
+ {
+ cm = quant_partition(ctx, X, N, b, B, lowband, LM, gain, fill ARG_QEXT(ext_b));
+ }
+
+ /* This code is used by the decoder and by the resynthesis-enabled encoder */
+ if (ctx->resynth)
+ {
+ /* Undo the sample reorganization going from time order to frequency order */
+ if (B0>1)
+ interleave_hadamard(X, N_B>>recombine, B0<<recombine, longBlocks);
+
+ /* Undo time-freq changes that we did earlier */
+ N_B = N_B0;
+ B = B0;
+ for (k=0;k<time_divide;k++)
+ {
+ B >>= 1;
+ N_B <<= 1;
+ cm |= cm>>B;
+ haar1(X, N_B, B);
+ }
+
+ for (k=0;k<recombine;k++)
+ {
+ static const unsigned char bit_deinterleave_table[16]={
+ 0x00,0x03,0x0C,0x0F,0x30,0x33,0x3C,0x3F,
+ 0xC0,0xC3,0xCC,0xCF,0xF0,0xF3,0xFC,0xFF
+ };
+ cm = bit_deinterleave_table[cm];
+ haar1(X, N0>>k, 1<<k);
+ }
+ B<<=recombine;
+
+ /* Scale output for later folding */
+ if (lowband_out)
+ {
+ int j;
+ opus_val16 n;
+ n = celt_sqrt(SHL32(EXTEND32(N0),22));
+ for (j=0;j<N0;j++)
+ lowband_out[j] = MULT16_32_Q15(n,X[j]);
+ }
+ cm &= (1<<B)-1;
+ }
+ return cm;
+}
+
+#ifdef FIXED_POINT
+#define MIN_STEREO_ENERGY 2
+#else
+#define MIN_STEREO_ENERGY 1e-10f
+#endif
+
+/* This function is responsible for encoding and decoding a band for the stereo case. */
+static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm *Y,
+ int N, int b, int B, celt_norm *lowband,
+ int LM, celt_norm *lowband_out,
+ celt_norm *lowband_scratch, int fill
+ ARG_QEXT(int ext_b) ARG_QEXT(const int *cap))
+{
+ int imid=0, iside=0;
+ int inv = 0;
+ opus_val32 mid=0, side=0;
+ unsigned cm=0;
+ int mbits, sbits, delta;
+ int itheta;
+ int qalloc;
+ struct split_ctx sctx;
+ int orig_fill;
+ int encode;
+ ec_ctx *ec;
+
+ encode = ctx->encode;
+ ec = ctx->ec;
+
+ /* Special case for one sample */
+ if (N==1)
+ {
+ return quant_band_n1(ctx, X, Y, lowband_out);
+ }
+
+ orig_fill = fill;
+
+ if (encode) {
+ if (ctx->bandE[ctx->i] < MIN_STEREO_ENERGY || ctx->bandE[ctx->m->nbEBands+ctx->i] < MIN_STEREO_ENERGY) {
+ if (ctx->bandE[ctx->i] > ctx->bandE[ctx->m->nbEBands+ctx->i]) OPUS_COPY(Y, X, N);
+ else OPUS_COPY(X, Y, N);
+ }
+ }
+ compute_theta(ctx, &sctx, X, Y, N, &b, B, B, LM, 1, &fill ARG_QEXT(&ext_b));
+ inv = sctx.inv;
+ imid = sctx.imid;
+ iside = sctx.iside;
+ delta = sctx.delta;
+ itheta = sctx.itheta;
+ qalloc = sctx.qalloc;
+#ifdef FIXED_POINT
+# ifdef ENABLE_QEXT
+ (void)imid;
+ (void)iside;
+ mid = celt_cos_norm32(sctx.itheta_q30);
+ side = celt_cos_norm32((1<<30)-sctx.itheta_q30);
+# else
+ mid = SHL32(EXTEND32(imid), 16);
+ side = SHL32(EXTEND32(iside), 16);
+# endif
+#else
+# ifdef ENABLE_QEXT
+ (void)imid;
+ (void)iside;
+ mid = celt_cos_norm2(sctx.itheta_q30*(1.f/(1<<30)));
+ side = celt_cos_norm2(1.f-sctx.itheta_q30*(1.f/(1<<30)));
+# else
+ mid = (1.f/32768)*imid;
+ side = (1.f/32768)*iside;
+# endif
+#endif
+
+ /* This is a special case for N=2 that only works for stereo and takes
+ advantage of the fact that mid and side are orthogonal to encode
+ the side with just one bit. */
+ if (N==2)
+ {
+ int c;
+ int sign=0;
+ celt_norm *x2, *y2;
+ mbits = b;
+ sbits = 0;
+ /* Only need one bit for the side. */
+ if (itheta != 0 && itheta != 16384)
+ sbits = 1<<BITRES;
+ mbits -= sbits;
+ c = itheta > 8192;
+ ctx->remaining_bits -= qalloc+sbits;
+
+ x2 = c ? Y : X;
+ y2 = c ? X : Y;
+ if (sbits)
+ {
+ if (encode)
+ {
+ /* Here we only need to encode a sign for the side. */
+ /* FIXME: Need to increase fixed-point precision? */
+ sign = MULT32_32_Q31(x2[0],y2[1]) - MULT32_32_Q31(x2[1],y2[0]) < 0;
+ ec_enc_bits(ec, sign, 1);
+ } else {
+ sign = ec_dec_bits(ec, 1);
+ }
+ }
+ sign = 1-2*sign;
+ /* We use orig_fill here because we want to fold the side, but if
+ itheta==16384, we'll have cleared the low bits of fill. */
+ cm = quant_band(ctx, x2, N, mbits, B, lowband, LM, lowband_out, Q31ONE,
+ lowband_scratch, orig_fill ARG_QEXT(ext_b));
+ /* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse),
+ and there's no need to worry about mixing with the other channel. */
+ y2[0] = -sign*x2[1];
+ y2[1] = sign*x2[0];
+ if (ctx->resynth)
+ {
+ celt_norm tmp;
+ X[0] = MULT32_32_Q31(mid, X[0]);
+ X[1] = MULT32_32_Q31(mid, X[1]);
+ Y[0] = MULT32_32_Q31(side, Y[0]);
+ Y[1] = MULT32_32_Q31(side, Y[1]);
+ tmp = X[0];
+ X[0] = SUB32(tmp,Y[0]);
+ Y[0] = ADD32(tmp,Y[0]);
+ tmp = X[1];
+ X[1] = SUB32(tmp,Y[1]);
+ Y[1] = ADD32(tmp,Y[1]);
+ }
+ } else {
+ /* "Normal" split code */
+ opus_int32 rebalance;
+
+ mbits = IMAX(0, IMIN(b, (b-delta)/2));
+ sbits = b-mbits;
+ ctx->remaining_bits -= qalloc;
+
+ rebalance = ctx->remaining_bits;
+ if (mbits >= sbits)
+ {
+#ifdef ENABLE_QEXT
+ int qext_extra = 0;
+ /* Reallocate any mid bits that cannot be used to extra mid bits. */
+ if (cap != NULL && ext_b != 0) qext_extra = IMAX(0, IMIN(ext_b/2, mbits - cap[ctx->i]/2));
+#endif
+ /* In stereo mode, we do not apply a scaling to the mid because we need the normalized
+ mid for folding later. */
+ cm = quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q31ONE,
+ lowband_scratch, fill ARG_QEXT(ext_b/2+qext_extra));
+ rebalance = mbits - (rebalance-ctx->remaining_bits);
+ if (rebalance > 3<<BITRES && itheta!=0)
+ sbits += rebalance - (3<<BITRES);
+#ifdef ENABLE_QEXT
+ /* Guard against overflowing the EC with the angle if the cubic quant used too many bits for the mid. */
+ if (ctx->extra_bands) sbits = IMIN(sbits, ctx->remaining_bits);
+#endif
+ /* For a stereo split, the high bits of fill are always zero, so no
+ folding will be done to the side. */
+ cm |= quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B ARG_QEXT(ext_b/2-qext_extra));
+ } else {
+#ifdef ENABLE_QEXT
+ int qext_extra = 0;
+ /* Reallocate any side bits that cannot be used to extra side bits. */
+ if (cap != NULL && ext_b != 0) qext_extra = IMAX(0, IMIN(ext_b/2, sbits - cap[ctx->i]/2));
+#endif
+ /* For a stereo split, the high bits of fill are always zero, so no
+ folding will be done to the side. */
+ cm = quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B ARG_QEXT(ext_b/2+qext_extra));
+ rebalance = sbits - (rebalance-ctx->remaining_bits);
+ if (rebalance > 3<<BITRES && itheta!=16384)
+ mbits += rebalance - (3<<BITRES);
+#ifdef ENABLE_QEXT
+ /* Guard against overflowing the EC with the angle if the cubic quant used too many bits for the side. */
+ if (ctx->extra_bands) mbits = IMIN(mbits, ctx->remaining_bits);
+#endif
+ /* In stereo mode, we do not apply a scaling to the mid because we need the normalized
+ mid for folding later. */
+ cm |= quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q31ONE,
+ lowband_scratch, fill ARG_QEXT(ext_b/2-qext_extra));
+ }
+ }
+
+
+ /* This code is used by the decoder and by the resynthesis-enabled encoder */
+ if (ctx->resynth)
+ {
+ if (N!=2)
+ stereo_merge(X, Y, mid, N, ctx->arch);
+ if (inv)
+ {
+ int j;
+ for (j=0;j<N;j++)
+ Y[j] = -Y[j];
+ }
+ }
+ return cm;
+}
+
+#ifndef DISABLE_UPDATE_DRAFT
+static void special_hybrid_folding(const CELTMode *m, celt_norm *norm, celt_norm *norm2, int start, int M, int dual_stereo)
+{
+ int n1, n2;
+ const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
+ n1 = M*(eBands[start+1]-eBands[start]);
+ n2 = M*(eBands[start+2]-eBands[start+1]);
+ /* Duplicate enough of the first band folding data to be able to fold the second band.
+ Copies no data for CELT-only mode. */
+ OPUS_COPY(&norm[n1], &norm[2*n1 - n2], n2-n1);
+ if (dual_stereo)
+ OPUS_COPY(&norm2[n1], &norm2[2*n1 - n2], n2-n1);
+}
+#endif
+
+void quant_all_bands(int encode, const CELTMode *m, int start, int end,
+ celt_norm *X_, celt_norm *Y_, unsigned char *collapse_masks,
+ const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
+ int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
+ opus_int32 balance, ec_ctx *ec, int LM, int codedBands,
+ opus_uint32 *seed, int complexity, int arch, int disable_inv
+ ARG_QEXT(ec_ctx *ext_ec) ARG_QEXT(int *extra_pulses)
+ ARG_QEXT(opus_int32 ext_total_bits) ARG_QEXT(const int *cap))
+{
+ int i;
+ opus_int32 remaining_bits;
+ const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
+ celt_norm * OPUS_RESTRICT norm, * OPUS_RESTRICT norm2;
+ VARDECL(celt_norm, _norm);
+ VARDECL(celt_norm, _lowband_scratch);
+ VARDECL(celt_norm, X_save);
+ VARDECL(celt_norm, Y_save);
+ VARDECL(celt_norm, X_save2);
+ VARDECL(celt_norm, Y_save2);
+ VARDECL(celt_norm, norm_save2);
+ VARDECL(unsigned char, bytes_save);
+ int resynth_alloc;
+ celt_norm *lowband_scratch;
+ int B;
+ int M;
+ int lowband_offset;
+ int update_lowband = 1;
+ int C = Y_ != NULL ? 2 : 1;
+ int norm_offset;
+ int theta_rdo = encode && Y_!=NULL && !dual_stereo && complexity>=8;
+#ifdef RESYNTH
+ int resynth = 1;
+#else
+ int resynth = !encode || theta_rdo;
+#endif
+ struct band_ctx ctx;
+#ifdef ENABLE_QEXT
+ int ext_b;
+ opus_int32 ext_balance=0;
+ opus_int32 ext_tell=0;
+ VARDECL(unsigned char, ext_bytes_save);
+#endif
+ SAVE_STACK;
+
+ M = 1<<LM;
+ B = shortBlocks ? M : 1;
+ norm_offset = M*eBands[start];
+ /* No need to allocate norm for the last band because we don't need an
+ output in that band. */
+ ALLOC(_norm, C*(M*eBands[m->nbEBands-1]-norm_offset), celt_norm);
+ norm = _norm;
+ norm2 = norm + M*eBands[m->nbEBands-1]-norm_offset;
+
+ /* For decoding, we can use the last band as scratch space because we don't need that
+ scratch space for the last band and we don't care about the data there until we're
+ decoding the last band. */
+ if (encode && resynth)
+ resynth_alloc = M*(eBands[m->nbEBands]-eBands[m->nbEBands-1]);
+ else
+ resynth_alloc = ALLOC_NONE;
+ ALLOC(_lowband_scratch, resynth_alloc, celt_norm);
+ if (encode && resynth)
+ lowband_scratch = _lowband_scratch;
+ else
+ lowband_scratch = X_+M*eBands[m->effEBands-1];
+ ALLOC(X_save, resynth_alloc, celt_norm);
+ ALLOC(Y_save, resynth_alloc, celt_norm);
+ ALLOC(X_save2, resynth_alloc, celt_norm);
+ ALLOC(Y_save2, resynth_alloc, celt_norm);
+ ALLOC(norm_save2, resynth_alloc, celt_norm);
+
+ lowband_offset = 0;
+ ctx.bandE = bandE;
+ ctx.ec = ec;
+ ctx.encode = encode;
+ ctx.intensity = intensity;
+ ctx.m = m;
+ ctx.seed = *seed;
+ ctx.spread = spread;
+ ctx.arch = arch;
+ ctx.disable_inv = disable_inv;
+ ctx.resynth = resynth;
+ ctx.theta_round = 0;
+#ifdef ENABLE_QEXT
+ ctx.ext_ec = ext_ec;
+ ctx.ext_total_bits = ext_total_bits;
+ ctx.extra_bands = end == NB_QEXT_BANDS || end == 2;
+ if (ctx.extra_bands) theta_rdo = 0;
+ ALLOC(ext_bytes_save, theta_rdo ? QEXT_PACKET_SIZE_CAP : ALLOC_NONE, unsigned char);
+#endif
+ ALLOC(bytes_save, theta_rdo ? 1275 : ALLOC_NONE, unsigned char);
+
+ /* Avoid injecting noise in the first band on transients. */
+ ctx.avoid_split_noise = B > 1;
+ for (i=start;i<end;i++)
+ {
+ opus_int32 tell;
+ int b;
+ int N;
+ opus_int32 curr_balance;
+ int effective_lowband=-1;
+ celt_norm * OPUS_RESTRICT X, * OPUS_RESTRICT Y;
+ int tf_change=0;
+ unsigned x_cm;
+ unsigned y_cm;
+ int last;
+
+ ctx.i = i;
+ last = (i==end-1);
+
+ X = X_+M*eBands[i];
+ if (Y_!=NULL)
+ Y = Y_+M*eBands[i];
+ else
+ Y = NULL;
+ N = M*eBands[i+1]-M*eBands[i];
+ celt_assert(N > 0);
+ tell = ec_tell_frac(ec);
+
+ /* Compute how many bits we want to allocate to this band */
+ if (i != start)
+ balance -= tell;
+ remaining_bits = total_bits-tell-1;
+ ctx.remaining_bits = remaining_bits;
+#ifdef ENABLE_QEXT
+ if (i != start) {
+ ext_balance += extra_pulses[i-1] + ext_tell;
+ }
+ ext_tell = ec_tell_frac(ext_ec);
+ ctx.extra_bits = extra_pulses[i];
+ if (i != start)
+ ext_balance -= ext_tell;
+ if (i <= codedBands-1)
+ {
+ opus_int32 ext_curr_balance = celt_sudiv(ext_balance, IMIN(3, codedBands-i));
+ ext_b = IMAX(0, IMIN(16383, IMIN(ext_total_bits-ext_tell,extra_pulses[i]+ext_curr_balance)));
+ } else {
+ ext_b = 0;
+ }
+#endif
+ if (i <= codedBands-1)
+ {
+ curr_balance = celt_sudiv(balance, IMIN(3, codedBands-i));
+ b = IMAX(0, IMIN(16383, IMIN(remaining_bits+1,pulses[i]+curr_balance)));
+ } else {
+ b = 0;
+ }
+
+#ifndef DISABLE_UPDATE_DRAFT
+ if (resynth && (M*eBands[i]-N >= M*eBands[start] || i==start+1) && (update_lowband || lowband_offset==0))
+ lowband_offset = i;
+ if (i == start+1)
+ special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
+#else
+ if (resynth && M*eBands[i]-N >= M*eBands[start] && (update_lowband || lowband_offset==0))
+ lowband_offset = i;
+#endif
+
+ tf_change = tf_res[i];
+ ctx.tf_change = tf_change;
+ if (i>=m->effEBands)
+ {
+ X=norm;
+ if (Y_!=NULL)
+ Y = norm;
+ lowband_scratch = NULL;
+ }
+ if (last && !theta_rdo)
+ lowband_scratch = NULL;
+
+ /* Get a conservative estimate of the collapse_mask's for the bands we're
+ going to be folding from. */
+ if (lowband_offset != 0 && (spread!=SPREAD_AGGRESSIVE || B>1 || tf_change<0))
+ {
+ int fold_start;
+ int fold_end;
+ int fold_i;
+ /* This ensures we never repeat spectral content within one band */
+ effective_lowband = IMAX(0, M*eBands[lowband_offset]-norm_offset-N);
+ fold_start = lowband_offset;
+ while(M*eBands[--fold_start] > effective_lowband+norm_offset);
+ fold_end = lowband_offset-1;
+#ifndef DISABLE_UPDATE_DRAFT
+ while(++fold_end < i && M*eBands[fold_end] < effective_lowband+norm_offset+N);
+#else
+ while(M*eBands[++fold_end] < effective_lowband+norm_offset+N);
+#endif
+ x_cm = y_cm = 0;
+ fold_i = fold_start; do {
+ x_cm |= collapse_masks[fold_i*C+0];
+ y_cm |= collapse_masks[fold_i*C+C-1];
+ } while (++fold_i<fold_end);
+ }
+ /* Otherwise, we'll be using the LCG to fold, so all blocks will (almost
+ always) be non-zero. */
+ else
+ x_cm = y_cm = (1<<B)-1;
+
+ if (dual_stereo && i==intensity)
+ {
+ int j;
+
+ /* Switch off dual stereo to do intensity. */
+ dual_stereo = 0;
+ if (resynth)
+ for (j=0;j<M*eBands[i]-norm_offset;j++)
+ norm[j] = HALF32(norm[j]+norm2[j]);
+ }
+ if (dual_stereo)
+ {
+ x_cm = quant_band(&ctx, X, N, b/2, B,
+ effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+ last?NULL:norm+M*eBands[i]-norm_offset, Q31ONE, lowband_scratch, x_cm ARG_QEXT(ext_b/2));
+ y_cm = quant_band(&ctx, Y, N, b/2, B,
+ effective_lowband != -1 ? norm2+effective_lowband : NULL, LM,
+ last?NULL:norm2+M*eBands[i]-norm_offset, Q31ONE, lowband_scratch, y_cm ARG_QEXT(ext_b/2));
+ } else {
+ if (Y!=NULL)
+ {
+ if (theta_rdo && i < intensity)
+ {
+ ec_ctx ec_save, ec_save2;
+ struct band_ctx ctx_save, ctx_save2;
+ opus_val32 dist0, dist1;
+ unsigned cm, cm2;
+ int nstart_bytes, nend_bytes, save_bytes;
+ unsigned char *bytes_buf;
+#ifdef ENABLE_QEXT
+ ec_ctx ext_ec_save, ext_ec_save2;
+ unsigned char *ext_bytes_buf;
+ int ext_nstart_bytes, ext_nend_bytes, ext_save_bytes;
+#endif
+ opus_val16 w[2];
+ compute_channel_weights(bandE[i], bandE[i+m->nbEBands], w);
+ /* Make a copy. */
+ cm = x_cm|y_cm;
+ ec_save = *ec;
+#ifdef ENABLE_QEXT
+ ext_ec_save = *ext_ec;
+#endif
+ ctx_save = ctx;
+ OPUS_COPY(X_save, X, N);
+ OPUS_COPY(Y_save, Y, N);
+ /* Encode and round down. */
+ ctx.theta_round = -1;
+ x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+ effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+ last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm ARG_QEXT(ext_b) ARG_QEXT(cap));
+ dist0 = MULT16_32_Q15(w[0], celt_inner_prod_norm_shift(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod_norm_shift(Y_save, Y, N, arch));
+
+ /* Save first result. */
+ cm2 = x_cm;
+ ec_save2 = *ec;
+#ifdef ENABLE_QEXT
+ ext_ec_save2 = *ext_ec;
+#endif
+ ctx_save2 = ctx;
+ OPUS_COPY(X_save2, X, N);
+ OPUS_COPY(Y_save2, Y, N);
+ if (!last)
+ OPUS_COPY(norm_save2, norm+M*eBands[i]-norm_offset, N);
+ nstart_bytes = ec_save.offs;
+ nend_bytes = ec_save.storage;
+ bytes_buf = ec_save.buf+nstart_bytes;
+ save_bytes = nend_bytes-nstart_bytes;
+ OPUS_COPY(bytes_save, bytes_buf, save_bytes);
+#ifdef ENABLE_QEXT
+ ext_nstart_bytes = ext_ec_save.offs;
+ ext_nend_bytes = ext_ec_save.storage;
+ ext_bytes_buf = ext_ec_save.buf!=NULL ? ext_ec_save.buf+ext_nstart_bytes : NULL;
+ ext_save_bytes = ext_nend_bytes-ext_nstart_bytes;
+ if (ext_save_bytes) OPUS_COPY(ext_bytes_save, ext_bytes_buf, ext_save_bytes);
+#endif
+ /* Restore */
+ *ec = ec_save;
+#ifdef ENABLE_QEXT
+ *ext_ec = ext_ec_save;
+#endif
+ ctx = ctx_save;
+ OPUS_COPY(X, X_save, N);
+ OPUS_COPY(Y, Y_save, N);
+#ifndef DISABLE_UPDATE_DRAFT
+ if (i == start+1)
+ special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
+#endif
+ /* Encode and round up. */
+ ctx.theta_round = 1;
+ x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+ effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+ last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm ARG_QEXT(ext_b) ARG_QEXT(cap));
+ dist1 = MULT16_32_Q15(w[0], celt_inner_prod_norm_shift(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod_norm_shift(Y_save, Y, N, arch));
+ if (dist0 >= dist1) {
+ x_cm = cm2;
+ *ec = ec_save2;
+#ifdef ENABLE_QEXT
+ *ext_ec = ext_ec_save2;
+#endif
+ ctx = ctx_save2;
+ OPUS_COPY(X, X_save2, N);
+ OPUS_COPY(Y, Y_save2, N);
+ if (!last)
+ OPUS_COPY(norm+M*eBands[i]-norm_offset, norm_save2, N);
+ OPUS_COPY(bytes_buf, bytes_save, save_bytes);
+#ifdef ENABLE_QEXT
+ if (ext_save_bytes) OPUS_COPY(ext_bytes_buf, ext_bytes_save, ext_save_bytes);
+#endif
+ }
+ } else {
+ ctx.theta_round = 0;
+ x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+ effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+ last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, x_cm|y_cm ARG_QEXT(ext_b) ARG_QEXT(cap));
+ }
+ } else {
+ x_cm = quant_band(&ctx, X, N, b, B,
+ effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+ last?NULL:norm+M*eBands[i]-norm_offset, Q31ONE, lowband_scratch, x_cm|y_cm ARG_QEXT(ext_b));
+ }
+ y_cm = x_cm;
+ }
+ collapse_masks[i*C+0] = (unsigned char)x_cm;
+ collapse_masks[i*C+C-1] = (unsigned char)y_cm;
+ balance += pulses[i] + tell;
+
+ /* Update the folding position only as long as we have 1 bit/sample depth. */
+ update_lowband = b>(N<<BITRES);
+ /* We only need to avoid noise on a split for the first band. After that, we
+ have folding. */
+ ctx.avoid_split_noise = 0;
+ }
+ *seed = ctx.seed;
+
+ RESTORE_STACK;
+}
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Copyright (c) 2008-2009 Gregory Maxwell
+ Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 BANDS_H
+#define BANDS_H
+
+#include "arch.h"
+#include "modes.h"
+#include "entenc.h"
+#include "entdec.h"
+#include "rate.h"
+
+opus_int16 bitexact_cos(opus_int16 x);
+int bitexact_log2tan(int isin,int icos);
+
+/** Compute the amplitude (sqrt energy) in each of the bands
+ * @param m Mode data
+ * @param X Spectrum
+ * @param bandE Square root of the energy for each band (returned)
+ */
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch);
+
+/*void compute_noise_energies(const CELTMode *m, const celt_sig *X, const opus_val16 *tonality, celt_ener *bandE);*/
+
+/** Normalise each band of X such that the energy in each band is
+ equal to 1
+ * @param m Mode data
+ * @param X Spectrum (returned normalised)
+ * @param bandE Square root of the energy for each band
+ */
+void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M);
+
+/** Denormalise each band of X to restore full amplitude
+ * @param m Mode data
+ * @param X Spectrum (returned de-normalised)
+ * @param bandE Square root of the energy for each band
+ */
+void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
+ celt_sig * OPUS_RESTRICT freq, const celt_glog *bandE, int start,
+ int end, int M, int downsample, int silence);
+
+#define SPREAD_NONE (0)
+#define SPREAD_LIGHT (1)
+#define SPREAD_NORMAL (2)
+#define SPREAD_AGGRESSIVE (3)
+
+int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
+ int last_decision, int *hf_average, int *tapset_decision, int update_hf,
+ int end, int C, int M, const int *spread_weight);
+
+#ifdef MEASURE_NORM_MSE
+void measure_norm_mse(const CELTMode *m, float *X, float *X0, float *bandE, float *bandE0, int M, int N, int C);
+#endif
+
+void haar1(celt_norm *X, int N0, int stride);
+
+/** Quantisation/encoding of the residual spectrum
+ * @param encode flag that indicates whether we're encoding (1) or decoding (0)
+ * @param m Mode data
+ * @param start First band to process
+ * @param end Last band to process + 1
+ * @param X Residual (normalised)
+ * @param Y Residual (normalised) for second channel (or NULL for mono)
+ * @param collapse_masks Anti-collapse tracking mask
+ * @param bandE Square root of the energy for each band
+ * @param pulses Bit allocation (per band) for PVQ
+ * @param shortBlocks Zero for long blocks, non-zero for short blocks
+ * @param spread Amount of spreading to use
+ * @param dual_stereo Zero for MS stereo, non-zero for dual stereo
+ * @param intensity First band to use intensity stereo
+ * @param tf_res Time-frequency resolution change
+ * @param total_bits Total number of bits that can be used for the frame (including the ones already spent)
+ * @param balance Number of unallocated bits
+ * @param en Entropy coder state
+ * @param LM log2() of the number of 2.5 subframes in the frame
+ * @param codedBands Last band to receive bits + 1
+ * @param seed Random generator seed
+ * @param arch Run-time architecture (see opus_select_arch())
+ */
+void quant_all_bands(int encode, const CELTMode *m, int start, int end,
+ celt_norm * X, celt_norm * Y, unsigned char *collapse_masks,
+ const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
+ int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
+ opus_int32 balance, ec_ctx *ec, int M, int codedBands, opus_uint32 *seed,
+ int complexity, int arch, int disable_inv
+ ARG_QEXT(ec_ctx *ext_ec) ARG_QEXT(int *extra_pulses)
+ ARG_QEXT(opus_int32 total_ext_bits) ARG_QEXT(const int *cap));
+
+void anti_collapse(const CELTMode *m, celt_norm *X_,
+ unsigned char *collapse_masks, int LM, int C, int size, int start,
+ int end, const celt_glog *logE, const celt_glog *prev1logE,
+ const celt_glog *prev2logE, const int *pulses, opus_uint32 seed,
+ int encode, int arch);
+
+opus_uint32 celt_lcg_rand(opus_uint32 seed);
+
+int hysteresis_decision(opus_val16 val, const opus_val16 *thresholds, const opus_val16 *hysteresis, int N, int prev);
+
+#endif /* BANDS_H */
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2010 Xiph.Org Foundation
+ Copyright (c) 2008 Gregory Maxwell
+ Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define CELT_C
+
+#include "os_support.h"
+#include "mdct.h"
+#include <math.h>
+#include "celt.h"
+#include "pitch.h"
+#include "bands.h"
+#include "modes.h"
+#include "entcode.h"
+#include "quant_bands.h"
+#include "rate.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "float_cast.h"
+#include <stdarg.h>
+#include "celt_lpc.h"
+#include "vq.h"
+
+#ifndef PACKAGE_VERSION
+#define PACKAGE_VERSION "unknown"
+#endif
+
+#if defined(FIXED_POINT) && defined(__mips)
+#include "mips/celt_mipsr1.h"
+#endif
+
+
+int resampling_factor(opus_int32 rate)
+{
+ int ret;
+ switch (rate)
+ {
+#ifdef ENABLE_QEXT
+ case 96000:
+#endif
+ case 48000:
+ ret = 1;
+ break;
+ case 24000:
+ ret = 2;
+ break;
+ case 16000:
+ ret = 3;
+ break;
+ case 12000:
+ ret = 4;
+ break;
+ case 8000:
+ ret = 6;
+ break;
+ default:
+#ifndef CUSTOM_MODES
+ celt_assert(0);
+#endif
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+
+#if !defined(OVERRIDE_COMB_FILTER_CONST) || defined(NON_STATIC_COMB_FILTER_CONST_C)
+/* This version should be faster on ARM */
+#ifdef OPUS_ARM_ASM
+#ifndef NON_STATIC_COMB_FILTER_CONST_C
+static
+#endif
+void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
+ celt_coef g10, celt_coef g11, celt_coef g12)
+{
+ opus_val32 x0, x1, x2, x3, x4;
+ int i;
+ x4 = SHL32(x[-T-2], 1);
+ x3 = SHL32(x[-T-1], 1);
+ x2 = SHL32(x[-T], 1);
+ x1 = SHL32(x[-T+1], 1);
+ for (i=0;i<N-4;i+=5)
+ {
+ opus_val32 t;
+ x0=SHL32(x[i-T+2],1);
+ t = MAC_COEF_32_ARM(x[i], g10, x2);
+ t = MAC_COEF_32_ARM(t, g11, ADD32(x1,x3));
+ t = MAC_COEF_32_ARM(t, g12, ADD32(x0,x4));
+ t = SATURATE(t, SIG_SAT);
+ y[i] = t;
+ x4=SHL32(x[i-T+3],1);
+ t = MAC_COEF_32_ARM(x[i+1], g10, x1);
+ t = MAC_COEF_32_ARM(t, g11, ADD32(x0,x2));
+ t = MAC_COEF_32_ARM(t, g12, ADD32(x4,x3));
+ t = SATURATE(t, SIG_SAT);
+ y[i+1] = t;
+ x3=SHL32(x[i-T+4],1);
+ t = MAC_COEF_32_ARM(x[i+2], g10, x0);
+ t = MAC_COEF_32_ARM(t, g11, ADD32(x4,x1));
+ t = MAC_COEF_32_ARM(t, g12, ADD32(x3,x2));
+ t = SATURATE(t, SIG_SAT);
+ y[i+2] = t;
+ x2=SHL32(x[i-T+5],1);
+ t = MAC_COEF_32_ARM(x[i+3], g10, x4);
+ t = MAC_COEF_32_ARM(t, g11, ADD32(x3,x0));
+ t = MAC_COEF_32_ARM(t, g12, ADD32(x2,x1));
+ t = SATURATE(t, SIG_SAT);
+ y[i+3] = t;
+ x1=SHL32(x[i-T+6],1);
+ t = MAC_COEF_32_ARM(x[i+4], g10, x3);
+ t = MAC_COEF_32_ARM(t, g11, ADD32(x2,x4));
+ t = MAC_COEF_32_ARM(t, g12, ADD32(x1,x0));
+ t = SATURATE(t, SIG_SAT);
+ y[i+4] = t;
+ }
+#ifdef CUSTOM_MODES
+ for (;i<N;i++)
+ {
+ opus_val32 t;
+ x0=SHL32(x[i-T+2],1);
+ t = MAC_COEF_32_ARM(x[i], g10, x2);
+ t = MAC_COEF_32_ARM(t, g11, ADD32(x1,x3));
+ t = MAC_COEF_32_ARM(t, g12, ADD32(x0,x4));
+ t = SATURATE(t, SIG_SAT);
+ y[i] = t;
+ x4=x3;
+ x3=x2;
+ x2=x1;
+ x1=x0;
+ }
+#endif
+}
+#else
+#ifndef NON_STATIC_COMB_FILTER_CONST_C
+static
+#endif
+void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
+ celt_coef g10, celt_coef g11, celt_coef g12)
+{
+ opus_val32 x0, x1, x2, x3, x4;
+ int i;
+ x4 = x[-T-2];
+ x3 = x[-T-1];
+ x2 = x[-T];
+ x1 = x[-T+1];
+ for (i=0;i<N;i++)
+ {
+ x0=x[i-T+2];
+ y[i] = x[i]
+ + MULT_COEF_32(g10,x2)
+ + MULT_COEF_32(g11,ADD32(x1,x3))
+ + MULT_COEF_32(g12,ADD32(x0,x4));
+#ifdef FIXED_POINT
+ /* A bit of bias seems to help here. */
+ y[i] = SUB32(y[i], 1);
+#endif
+ y[i] = SATURATE(y[i], SIG_SAT);
+ x4=x3;
+ x3=x2;
+ x2=x1;
+ x1=x0;
+ }
+
+}
+#endif
+#endif
+
+#ifdef ENABLE_QEXT
+void comb_filter_qext(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
+ opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
+ const celt_coef *window, int overlap, int arch)
+{
+ VARDECL(opus_val32, mem_buf);
+ VARDECL(opus_val32, buf);
+ celt_coef new_window[120];
+ int s;
+ int i;
+ int N2;
+ int overlap2;
+ SAVE_STACK;
+ /* Using ALLOC() instead of a regular stack allocation to minimize real stack use when using the pseudostack.
+ This is useful on some embedded systems. */
+ ALLOC(mem_buf, COMBFILTER_MAXPERIOD+960, opus_val32);
+ ALLOC(buf, COMBFILTER_MAXPERIOD+960, opus_val32);
+ N2 = N/2;
+ overlap2=overlap/2;
+ /* At 96 kHz, we double the period and the spacing between taps, which is equivalent
+ to creating a mirror image of the filter around 24 kHz. It also means we can process
+ the even and odd samples completely independently. */
+ for (s=0;s<2;s++) {
+ opus_val32 *yptr;
+ for (i=0;i<overlap2;i++) new_window[i] = window[2*i+s];
+ for (i=0;i<COMBFILTER_MAXPERIOD+N2;i++) mem_buf[i] = x[2*i+s-2*COMBFILTER_MAXPERIOD];
+ if (x==y) {
+ yptr = mem_buf+COMBFILTER_MAXPERIOD;
+ } else {
+ for (i=0;i<N2;i++) buf[i] = y[2*i+s];
+ yptr = buf;
+ }
+ comb_filter(yptr, mem_buf+COMBFILTER_MAXPERIOD, T0, T1, N2, g0, g1, tapset0, tapset1, new_window, overlap2, arch);
+ for (i=0;i<N2;i++) y[2*i+s] = yptr[i];
+ }
+ RESTORE_STACK;
+ return;
+}
+#endif
+
+#ifndef OVERRIDE_comb_filter
+void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
+ opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
+ const celt_coef *window, int overlap, int arch)
+{
+ int i;
+ /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */
+ celt_coef g00, g01, g02, g10, g11, g12;
+ opus_val32 x0, x1, x2, x3, x4;
+ static const opus_val16 gains[3][3] = {
+ {QCONST16(0.3066406250f, 15), QCONST16(0.2170410156f, 15), QCONST16(0.1296386719f, 15)},
+ {QCONST16(0.4638671875f, 15), QCONST16(0.2680664062f, 15), QCONST16(0.f, 15)},
+ {QCONST16(0.7998046875f, 15), QCONST16(0.1000976562f, 15), QCONST16(0.f, 15)}};
+#ifdef ENABLE_QEXT
+ if (overlap==240) {
+ comb_filter_qext(y, x, T0, T1, N, g0, g1, tapset0, tapset1, window, overlap, arch);
+ return;
+ }
+#endif
+ if (g0==0 && g1==0)
+ {
+ /* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */
+ if (x!=y)
+ OPUS_MOVE(y, x, N);
+ return;
+ }
+ /* When the gain is zero, T0 and/or T1 is set to zero. We need
+ to have then be at least 2 to avoid processing garbage data. */
+ T0 = IMAX(T0, COMBFILTER_MINPERIOD);
+ T1 = IMAX(T1, COMBFILTER_MINPERIOD);
+ g00 = MULT_COEF_TAPS(g0, gains[tapset0][0]);
+ g01 = MULT_COEF_TAPS(g0, gains[tapset0][1]);
+ g02 = MULT_COEF_TAPS(g0, gains[tapset0][2]);
+ g10 = MULT_COEF_TAPS(g1, gains[tapset1][0]);
+ g11 = MULT_COEF_TAPS(g1, gains[tapset1][1]);
+ g12 = MULT_COEF_TAPS(g1, gains[tapset1][2]);
+ x1 = x[-T1+1];
+ x2 = x[-T1 ];
+ x3 = x[-T1-1];
+ x4 = x[-T1-2];
+ /* If the filter didn't change, we don't need the overlap */
+ if (g0==g1 && T0==T1 && tapset0==tapset1)
+ overlap=0;
+ for (i=0;i<overlap;i++)
+ {
+ celt_coef f;
+ x0=x[i-T1+2];
+ f = MULT_COEF(window[i],window[i]);
+ y[i] = x[i]
+ + MULT_COEF_32(MULT_COEF((COEF_ONE-f),g00),x[i-T0])
+ + MULT_COEF_32(MULT_COEF((COEF_ONE-f),g01),ADD32(x[i-T0+1],x[i-T0-1]))
+ + MULT_COEF_32(MULT_COEF((COEF_ONE-f),g02),ADD32(x[i-T0+2],x[i-T0-2]))
+ + MULT_COEF_32(MULT_COEF(f,g10),x2)
+ + MULT_COEF_32(MULT_COEF(f,g11),ADD32(x1,x3))
+ + MULT_COEF_32(MULT_COEF(f,g12),ADD32(x0,x4));
+#ifdef FIXED_POINT
+ /* A bit of bias seems to help here. */
+ y[i] = SUB32(y[i], 3);
+#endif
+ y[i] = SATURATE(y[i], SIG_SAT);
+ x4=x3;
+ x3=x2;
+ x2=x1;
+ x1=x0;
+
+ }
+ if (g1==0)
+ {
+ /* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */
+ if (x!=y)
+ OPUS_MOVE(y+overlap, x+overlap, N-overlap);
+ return;
+ }
+
+ /* Compute the part with the constant filter. */
+ comb_filter_const(y+i, x+i, T1, N-i, g10, g11, g12, arch);
+}
+#endif /* OVERRIDE_comb_filter */
+
+/* TF change table. Positive values mean better frequency resolution (longer
+ effective window), whereas negative values mean better time resolution
+ (shorter effective window). The second index is computed as:
+ 4*isTransient + 2*tf_select + per_band_flag */
+const signed char tf_select_table[4][8] = {
+ /*isTransient=0 isTransient=1 */
+ {0, -1, 0, -1, 0,-1, 0,-1}, /* 2.5 ms */
+ {0, -1, 0, -2, 1, 0, 1,-1}, /* 5 ms */
+ {0, -2, 0, -3, 2, 0, 1,-1}, /* 10 ms */
+ {0, -2, 0, -3, 3, 0, 1,-1}, /* 20 ms */
+};
+
+
+void init_caps(const CELTMode *m,int *cap,int LM,int C)
+{
+ int i;
+ for (i=0;i<m->nbEBands;i++)
+ {
+ int N;
+ N=(m->eBands[i+1]-m->eBands[i])<<LM;
+ cap[i] = (m->cache.caps[m->nbEBands*(2*LM+C-1)+i]+64)*C*N>>2;
+ }
+}
+
+
+
+const char *opus_strerror(int error)
+{
+ static const char * const error_strings[8] = {
+ "success",
+ "invalid argument",
+ "buffer too small",
+ "internal error",
+ "corrupted stream",
+ "request not implemented",
+ "invalid state",
+ "memory allocation failed"
+ };
+ if (error > 0 || error < -7)
+ return "unknown error";
+ else
+ return error_strings[-error];
+}
+
+const char *opus_get_version_string(void)
+{
+ return "libopus " PACKAGE_VERSION
+ /* Applications may rely on the presence of this substring in the version
+ string to determine if they have a fixed-point or floating-point build
+ at runtime. */
+#ifdef FIXED_POINT
+ "-fixed"
+#endif
+#ifdef FUZZING
+ "-fuzzing"
+#endif
+ ;
+}
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Copyright (c) 2008 Gregory Maxwell
+ Written by Jean-Marc Valin and Gregory Maxwell */
+/**
+ @file celt.h
+ @brief Contains all the functions for encoding and decoding audio
+ */
+
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 CELT_H
+#define CELT_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+#include "opus_custom.h"
+#include "entenc.h"
+#include "entdec.h"
+#include "arch.h"
+#include "kiss_fft.h"
+
+#ifdef ENABLE_QEXT
+#define ARG_QEXT(arg) , arg
+#else
+#define ARG_QEXT(arg)
+#endif
+
+
+#ifdef ENABLE_DEEP_PLC
+#include "lpcnet.h"
+#endif
+
+#define CELTEncoder OpusCustomEncoder
+#define CELTDecoder OpusCustomDecoder
+#define CELTMode OpusCustomMode
+
+#define QEXT_EXTENSION_ID 124
+
+#define LEAK_BANDS 19
+
+typedef struct {
+ int valid;
+ float tonality;
+ float tonality_slope;
+ float noisiness;
+ float activity;
+ float music_prob;
+ float music_prob_min;
+ float music_prob_max;
+ int bandwidth;
+ float activity_probability;
+ float max_pitch_ratio;
+ /* Store as Q6 char to save space. */
+ unsigned char leak_boost[LEAK_BANDS];
+} AnalysisInfo;
+
+typedef struct {
+ int signalType;
+ int offset;
+} SILKInfo;
+
+#define celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
+
+#define celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr)))
+
+#define celt_check_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr)))
+
+#define celt_check_glog_ptr(ptr) ((ptr) + ((ptr) - (celt_glog*)(ptr)))
+
+/* Encoder/decoder Requests */
+
+
+#define CELT_SET_PREDICTION_REQUEST 10002
+/** Controls the use of interframe prediction.
+ 0=Independent frames
+ 1=Short term interframe prediction allowed
+ 2=Long term prediction allowed
+ */
+#define CELT_SET_PREDICTION(x) CELT_SET_PREDICTION_REQUEST, opus_check_int(x)
+
+#define CELT_SET_INPUT_CLIPPING_REQUEST 10004
+#define CELT_SET_INPUT_CLIPPING(x) CELT_SET_INPUT_CLIPPING_REQUEST, opus_check_int(x)
+
+#define CELT_GET_AND_CLEAR_ERROR_REQUEST 10007
+#define CELT_GET_AND_CLEAR_ERROR(x) CELT_GET_AND_CLEAR_ERROR_REQUEST, opus_check_int_ptr(x)
+
+#define CELT_SET_CHANNELS_REQUEST 10008
+#define CELT_SET_CHANNELS(x) CELT_SET_CHANNELS_REQUEST, opus_check_int(x)
+
+
+/* Internal */
+#define CELT_SET_START_BAND_REQUEST 10010
+#define CELT_SET_START_BAND(x) CELT_SET_START_BAND_REQUEST, opus_check_int(x)
+
+#define CELT_SET_END_BAND_REQUEST 10012
+#define CELT_SET_END_BAND(x) CELT_SET_END_BAND_REQUEST, opus_check_int(x)
+
+#define CELT_GET_MODE_REQUEST 10015
+/** Get the CELTMode used by an encoder or decoder */
+#define CELT_GET_MODE(x) CELT_GET_MODE_REQUEST, celt_check_mode_ptr_ptr(x)
+
+#define CELT_SET_SIGNALLING_REQUEST 10016
+#define CELT_SET_SIGNALLING(x) CELT_SET_SIGNALLING_REQUEST, opus_check_int(x)
+
+#define CELT_SET_TONALITY_REQUEST 10018
+#define CELT_SET_TONALITY(x) CELT_SET_TONALITY_REQUEST, opus_check_int(x)
+#define CELT_SET_TONALITY_SLOPE_REQUEST 10020
+#define CELT_SET_TONALITY_SLOPE(x) CELT_SET_TONALITY_SLOPE_REQUEST, opus_check_int(x)
+
+#define CELT_SET_ANALYSIS_REQUEST 10022
+#define CELT_SET_ANALYSIS(x) CELT_SET_ANALYSIS_REQUEST, celt_check_analysis_ptr(x)
+
+#define OPUS_SET_LFE_REQUEST 10024
+#define OPUS_SET_LFE(x) OPUS_SET_LFE_REQUEST, opus_check_int(x)
+
+#define OPUS_SET_ENERGY_MASK_REQUEST 10026
+#define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, celt_check_glog_ptr(x)
+
+#define CELT_SET_SILK_INFO_REQUEST 10028
+#define CELT_SET_SILK_INFO(x) CELT_SET_SILK_INFO_REQUEST, celt_check_silkinfo_ptr(x)
+
+
+static OPUS_INLINE opus_int32 bits_to_bitrate(opus_int32 bits, opus_int32 Fs, opus_int32 frame_size) {
+ return bits*(6*Fs/frame_size)/6;
+}
+
+static OPUS_INLINE opus_int32 bitrate_to_bits(opus_int32 bitrate, opus_int32 Fs, opus_int32 frame_size) {
+ return bitrate*6/(6*Fs/frame_size);
+}
+
+/* Encoder stuff */
+
+int celt_encoder_get_size(int channels);
+
+int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_res * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
+
+int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels,
+ int arch);
+
+
+
+/* Decoder stuff */
+
+int celt_decoder_get_size(int channels);
+
+
+int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels);
+
+int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
+ int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum
+#ifdef ENABLE_DEEP_PLC
+ ,LPCNetPLCState *lpcnet
+#endif
+ ARG_QEXT(const unsigned char *qext_payload) ARG_QEXT(int qext_payload_len)
+ );
+
+int celt_decode_with_ec(OpusCustomDecoder * OPUS_RESTRICT st, const unsigned char *data,
+ int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum);
+
+#define celt_encoder_ctl opus_custom_encoder_ctl
+#define celt_decoder_ctl opus_custom_decoder_ctl
+
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+#define OPUS_CUSTOM_NOSTATIC
+#else
+#define OPUS_CUSTOM_NOSTATIC static OPUS_INLINE
+#endif
+
+static const unsigned char trim_icdf[11] = {126, 124, 119, 109, 87, 41, 19, 9, 4, 2, 0};
+/* Probs: NONE: 21.875%, LIGHT: 6.25%, NORMAL: 65.625%, AGGRESSIVE: 6.25% */
+static const unsigned char spread_icdf[4] = {25, 23, 2, 0};
+
+static const unsigned char tapset_icdf[3]={2,1,0};
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+static const unsigned char toOpusTable[20] = {
+ 0xE0, 0xE8, 0xF0, 0xF8,
+ 0xC0, 0xC8, 0xD0, 0xD8,
+ 0xA0, 0xA8, 0xB0, 0xB8,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x88, 0x90, 0x98,
+};
+
+static const unsigned char fromOpusTable[16] = {
+ 0x80, 0x88, 0x90, 0x98,
+ 0x40, 0x48, 0x50, 0x58,
+ 0x20, 0x28, 0x30, 0x38,
+ 0x00, 0x08, 0x10, 0x18
+};
+
+static OPUS_INLINE int toOpus(unsigned char c)
+{
+ int ret=0;
+ if (c<0xA0)
+ ret = toOpusTable[c>>3];
+ if (ret == 0)
+ return -1;
+ else
+ return ret|(c&0x7);
+}
+
+static OPUS_INLINE int fromOpus(unsigned char c)
+{
+ if (c<0x80)
+ return -1;
+ else
+ return fromOpusTable[(c>>3)-16] | (c&0x7);
+}
+#endif /* CUSTOM_MODES */
+
+#define COMBFILTER_MAXPERIOD 1024
+#define COMBFILTER_MINPERIOD 15
+
+extern const signed char tf_select_table[4][8];
+
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+void validate_celt_decoder(CELTDecoder *st);
+#define VALIDATE_CELT_DECODER(st) validate_celt_decoder(st)
+#else
+#define VALIDATE_CELT_DECODER(st)
+#endif
+
+int resampling_factor(opus_int32 rate);
+
+void celt_preemphasis(const opus_res * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
+ int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip);
+
+void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
+ opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
+ const celt_coef *window, int overlap, int arch);
+
+void init_caps(const CELTMode *m,int *cap,int LM,int C);
+
+#ifdef RESYNTH
+void deemphasis(celt_sig *in[], opus_res *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem, int accum);
+void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
+ celt_glog *oldBandE, int start, int effEnd, int C, int CC, int isTransient,
+ int LM, int downsample, int silence, int arch ARG_QEXT(const CELTMode *qext_mode) ARG_QEXT(const celt_glog *qext_bandLogE) ARG_QEXT(int qext_end));
+#endif
+
+#ifdef ENABLE_QEXT
+#define QEXT_SCALE(x) ((qext_scale)*(x))
+#define QEXT_SCALE2(x, qext_scale) ((qext_scale)*(x))
+#else
+#define QEXT_SCALE(x) (x)
+#define QEXT_SCALE2(x, qext_scale) (x)
+#endif
+
+#endif /* CELT_H */
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2010 Xiph.Org Foundation
+ Copyright (c) 2008 Gregory Maxwell
+ Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define CELT_DECODER_C
+
+#include "cpu_support.h"
+#include "os_support.h"
+#include "mdct.h"
+#include <math.h>
+#include "celt.h"
+#include "pitch.h"
+#include "bands.h"
+#include "modes.h"
+#include "entcode.h"
+#include "quant_bands.h"
+#include "rate.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "float_cast.h"
+#include <stdarg.h>
+#include "celt_lpc.h"
+#include "vq.h"
+
+#ifdef ENABLE_DEEP_PLC
+#include "lpcnet.h"
+#include "lpcnet_private.h"
+#endif
+
+/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
+ CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
+ current value corresponds to a pitch of 66.67 Hz. */
+#define PLC_PITCH_LAG_MAX (720)
+/* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
+ pitch of 480 Hz. */
+#define PLC_PITCH_LAG_MIN (100)
+
+#define FRAME_NONE 0
+#define FRAME_NORMAL 1
+#define FRAME_PLC_NOISE 2
+#define FRAME_PLC_PERIODIC 3
+#define FRAME_PLC_NEURAL 4
+#define FRAME_DRED 5
+
+/**********************************************************************/
+/* */
+/* DECODER */
+/* */
+/**********************************************************************/
+#define DECODE_BUFFER_SIZE DEC_PITCH_BUF_SIZE
+
+#define PLC_UPDATE_FRAMES 4
+#define PLC_UPDATE_SAMPLES (PLC_UPDATE_FRAMES*FRAME_SIZE)
+
+/** Decoder state
+ @brief Decoder state
+ */
+struct OpusCustomDecoder {
+ const OpusCustomMode *mode;
+ int overlap;
+ int channels;
+ int stream_channels;
+
+ int downsample;
+ int start, end;
+ int signalling;
+ int disable_inv;
+ int complexity;
+ int arch;
+#ifdef ENABLE_QEXT
+ int qext_scale;
+#endif
+
+ /* Everything beyond this point gets cleared on a reset */
+#define DECODER_RESET_START rng
+
+ opus_uint32 rng;
+ int error;
+ int last_pitch_index;
+ int loss_duration;
+ int plc_duration;
+ int last_frame_type;
+ int skip_plc;
+ int postfilter_period;
+ int postfilter_period_old;
+ opus_val16 postfilter_gain;
+ opus_val16 postfilter_gain_old;
+ int postfilter_tapset;
+ int postfilter_tapset_old;
+ int prefilter_and_fold;
+
+ celt_sig preemph_memD[2];
+
+#ifdef ENABLE_DEEP_PLC
+ opus_int16 plc_pcm[PLC_UPDATE_SAMPLES];
+ int plc_fill;
+ float plc_preemphasis_mem;
+#endif
+
+#ifdef ENABLE_QEXT
+ celt_glog qext_oldBandE[2*NB_QEXT_BANDS];
+#endif
+
+ celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */
+ /* celt_glog oldEBands[], Size = 2*mode->nbEBands */
+ /* celt_glog oldLogE[], Size = 2*mode->nbEBands */
+ /* celt_glog oldLogE2[], Size = 2*mode->nbEBands */
+ /* celt_glog backgroundLogE[], Size = 2*mode->nbEBands */
+ /* opus_val16 lpc[], Size = channels*CELT_LPC_ORDER */
+};
+
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+/* Make basic checks on the CELT state to ensure we don't end
+ up writing all over memory. */
+void validate_celt_decoder(CELTDecoder *st)
+{
+#if !defined(CUSTOM_MODES) && !defined(ENABLE_OPUS_CUSTOM_API) && !defined(ENABLE_QEXT)
+ celt_assert(st->mode == opus_custom_mode_create(48000, 960, NULL));
+ celt_assert(st->overlap == 120);
+ celt_assert(st->end <= 21);
+#else
+/* From Section 4.3 in the spec: "The normal CELT layer uses 21 of those bands,
+ though Opus Custom (see Section 6.2) may use a different number of bands"
+
+ Check if it's within the maximum number of Bark frequency bands instead */
+ celt_assert(st->end <= 25);
+#endif
+ celt_assert(st->channels == 1 || st->channels == 2);
+ celt_assert(st->stream_channels == 1 || st->stream_channels == 2);
+ celt_assert(st->downsample > 0);
+ celt_assert(st->start == 0 || st->start == 17);
+ celt_assert(st->start < st->end);
+#ifdef OPUS_ARCHMASK
+ celt_assert(st->arch >= 0);
+ celt_assert(st->arch <= OPUS_ARCHMASK);
+#endif
+#ifndef ENABLE_QEXT
+ celt_assert(st->last_pitch_index <= PLC_PITCH_LAG_MAX);
+ celt_assert(st->last_pitch_index >= PLC_PITCH_LAG_MIN || st->last_pitch_index == 0);
+#endif
+ celt_assert(st->postfilter_period < MAX_PERIOD);
+ celt_assert(st->postfilter_period >= COMBFILTER_MINPERIOD || st->postfilter_period == 0);
+ celt_assert(st->postfilter_period_old < MAX_PERIOD);
+ celt_assert(st->postfilter_period_old >= COMBFILTER_MINPERIOD || st->postfilter_period_old == 0);
+ celt_assert(st->postfilter_tapset <= 2);
+ celt_assert(st->postfilter_tapset >= 0);
+ celt_assert(st->postfilter_tapset_old <= 2);
+ celt_assert(st->postfilter_tapset_old >= 0);
+}
+#endif
+
+int celt_decoder_get_size(int channels)
+{
+#ifdef ENABLE_QEXT
+ const CELTMode *mode = opus_custom_mode_create(96000, 960, NULL);
+#else
+ const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
+#endif
+ return opus_custom_decoder_get_size(mode, channels);
+}
+
+OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int channels)
+{
+ int size;
+#ifdef ENABLE_QEXT
+ int qext_scale;
+ if (mode->Fs == 96000 && (mode->shortMdctSize==240 || mode->shortMdctSize==180)) {
+ qext_scale = 2;
+ } else qext_scale = 1;
+#endif
+ size = sizeof(struct CELTDecoder)
+ + (channels*(QEXT_SCALE(DECODE_BUFFER_SIZE)+mode->overlap)-1)*sizeof(celt_sig)
+ + 4*2*mode->nbEBands*sizeof(celt_glog)
+ + channels*CELT_LPC_ORDER*sizeof(opus_val16);
+ return size;
+}
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+CELTDecoder *opus_custom_decoder_create(const CELTMode *mode, int channels, int *error)
+{
+ int ret;
+ CELTDecoder *st = (CELTDecoder *)opus_alloc(opus_custom_decoder_get_size(mode, channels));
+ ret = opus_custom_decoder_init(st, mode, channels);
+ if (ret != OPUS_OK)
+ {
+ opus_custom_decoder_destroy(st);
+ st = NULL;
+ }
+ if (error)
+ *error = ret;
+ return st;
+}
+#endif /* CUSTOM_MODES */
+
+int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels)
+{
+ int ret;
+#ifdef ENABLE_QEXT
+ if (sampling_rate == 96000) {
+ return opus_custom_decoder_init(st, opus_custom_mode_create(96000, 960, NULL), channels);
+ }
+#endif
+ ret = opus_custom_decoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels);
+ if (ret != OPUS_OK)
+ return ret;
+ st->downsample = resampling_factor(sampling_rate);
+ if (st->downsample==0)
+ return OPUS_BAD_ARG;
+ else
+ return OPUS_OK;
+}
+
+OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels)
+{
+ if (channels < 0 || channels > 2)
+ return OPUS_BAD_ARG;
+
+ if (st==NULL)
+ return OPUS_ALLOC_FAIL;
+
+ OPUS_CLEAR((char*)st, opus_custom_decoder_get_size(mode, channels));
+
+ st->mode = mode;
+ st->overlap = mode->overlap;
+ st->stream_channels = st->channels = channels;
+
+ st->downsample = 1;
+ st->start = 0;
+ st->end = st->mode->effEBands;
+ st->signalling = 1;
+#ifndef DISABLE_UPDATE_DRAFT
+ st->disable_inv = channels == 1;
+#else
+ st->disable_inv = 0;
+#endif
+ st->arch = opus_select_arch();
+
+#ifdef ENABLE_QEXT
+ if (st->mode->Fs == 96000 && (mode->shortMdctSize==240 || mode->shortMdctSize==180)) st->qext_scale = 2;
+ else st->qext_scale = 1;
+#endif
+
+ opus_custom_decoder_ctl(st, OPUS_RESET_STATE);
+
+ return OPUS_OK;
+}
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+void opus_custom_decoder_destroy(CELTDecoder *st)
+{
+ opus_free(st);
+}
+#endif /* CUSTOM_MODES */
+
+#if !defined(CUSTOM_MODES) && !defined(ENABLE_OPUS_CUSTOM_API) && !defined(ENABLE_QEXT)
+/* Special case for stereo with no downsampling and no accumulation. This is
+ quite common and we can make it faster by processing both channels in the
+ same loop, reducing overhead due to the dependency loop in the IIR filter. */
+static void deemphasis_stereo_simple(celt_sig *in[], opus_res *pcm, int N, const opus_val16 coef0,
+ celt_sig *mem)
+{
+ celt_sig * OPUS_RESTRICT x0;
+ celt_sig * OPUS_RESTRICT x1;
+ celt_sig m0, m1;
+ int j;
+ x0=in[0];
+ x1=in[1];
+ m0 = mem[0];
+ m1 = mem[1];
+ for (j=0;j<N;j++)
+ {
+ celt_sig tmp0, tmp1;
+ /* Add VERY_SMALL to x[] first to reduce dependency chain. */
+ tmp0 = SATURATE(x0[j] + VERY_SMALL + m0, SIG_SAT);
+ tmp1 = SATURATE(x1[j] + VERY_SMALL + m1, SIG_SAT);
+ m0 = MULT16_32_Q15(coef0, tmp0);
+ m1 = MULT16_32_Q15(coef0, tmp1);
+ pcm[2*j ] = SIG2RES(tmp0);
+ pcm[2*j+1] = SIG2RES(tmp1);
+ }
+ mem[0] = m0;
+ mem[1] = m1;
+}
+#endif
+
+#ifndef RESYNTH
+static
+#endif
+void deemphasis(celt_sig *in[], opus_res *pcm, int N, int C, int downsample, const opus_val16 *coef,
+ celt_sig *mem, int accum)
+{
+ int c;
+ int Nd;
+ int apply_downsampling=0;
+ opus_val16 coef0;
+ VARDECL(celt_sig, scratch);
+ SAVE_STACK;
+#if !defined(CUSTOM_MODES) && !defined(ENABLE_OPUS_CUSTOM_API) && !defined(ENABLE_QEXT)
+ /* Short version for common case. */
+ if (downsample == 1 && C == 2 && !accum)
+ {
+ deemphasis_stereo_simple(in, pcm, N, coef[0], mem);
+ return;
+ }
+#endif
+ ALLOC(scratch, N, celt_sig);
+ coef0 = coef[0];
+ Nd = N/downsample;
+ c=0; do {
+ int j;
+ celt_sig * OPUS_RESTRICT x;
+ opus_res * OPUS_RESTRICT y;
+ celt_sig m = mem[c];
+ x =in[c];
+ y = pcm+c;
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) || defined(ENABLE_QEXT)
+ if (coef[1] != 0)
+ {
+ opus_val16 coef1 = coef[1];
+ opus_val16 coef3 = coef[3];
+ for (j=0;j<N;j++)
+ {
+ celt_sig tmp = SATURATE(x[j] + m + VERY_SMALL, SIG_SAT);
+ m = MULT16_32_Q15(coef0, tmp)
+ - MULT16_32_Q15(coef1, x[j]);
+ tmp = SHL32(MULT16_32_Q15(coef3, tmp), 2);
+ scratch[j] = tmp;
+ }
+ apply_downsampling=1;
+ } else
+#endif
+ if (downsample>1)
+ {
+ /* Shortcut for the standard (non-custom modes) case */
+ for (j=0;j<N;j++)
+ {
+ celt_sig tmp = SATURATE(x[j] + VERY_SMALL + m, SIG_SAT);
+ m = MULT16_32_Q15(coef0, tmp);
+ scratch[j] = tmp;
+ }
+ apply_downsampling=1;
+ } else {
+ /* Shortcut for the standard (non-custom modes) case */
+ if (accum)
+ {
+ for (j=0;j<N;j++)
+ {
+ celt_sig tmp = SATURATE(x[j] + m + VERY_SMALL, SIG_SAT);
+ m = MULT16_32_Q15(coef0, tmp);
+ y[j*C] = ADD_RES(y[j*C], SIG2RES(tmp));
+ }
+ } else
+ {
+ for (j=0;j<N;j++)
+ {
+ celt_sig tmp = SATURATE(x[j] + VERY_SMALL + m, SIG_SAT);
+ m = MULT16_32_Q15(coef0, tmp);
+ y[j*C] = SIG2RES(tmp);
+ }
+ }
+ }
+ mem[c] = m;
+
+ if (apply_downsampling)
+ {
+ /* Perform down-sampling */
+ if (accum)
+ {
+ for (j=0;j<Nd;j++)
+ y[j*C] = ADD_RES(y[j*C], SIG2RES(scratch[j*downsample]));
+ } else
+ {
+ for (j=0;j<Nd;j++)
+ y[j*C] = SIG2RES(scratch[j*downsample]);
+ }
+ }
+ } while (++c<C);
+ RESTORE_STACK;
+}
+
+#ifndef RESYNTH
+static
+#endif
+void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
+ celt_glog *oldBandE, int start, int effEnd, int C, int CC,
+ int isTransient, int LM, int downsample,
+ int silence, int arch ARG_QEXT(const CELTMode *qext_mode) ARG_QEXT(const celt_glog *qext_bandLogE) ARG_QEXT(int qext_end))
+{
+ int c, i;
+ int M;
+ int b;
+ int B;
+ int N, NB;
+ int shift;
+ int nbEBands;
+ int overlap;
+ VARDECL(celt_sig, freq);
+ SAVE_STACK;
+
+ overlap = mode->overlap;
+ nbEBands = mode->nbEBands;
+ N = mode->shortMdctSize<<LM;
+ ALLOC(freq, N, celt_sig); /**< Interleaved signal MDCTs */
+ M = 1<<LM;
+#ifdef ENABLE_QEXT
+ if (mode->Fs != 96000) qext_end=2;
+#endif
+
+ if (isTransient)
+ {
+ B = M;
+ NB = mode->shortMdctSize;
+ shift = mode->maxLM;
+ } else {
+ B = 1;
+ NB = mode->shortMdctSize<<LM;
+ shift = mode->maxLM-LM;
+ }
+
+ if (CC==2&&C==1)
+ {
+ /* Copying a mono streams to two channels */
+ celt_sig *freq2;
+ denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
+ downsample, silence);
+#ifdef ENABLE_QEXT
+ if (qext_mode)
+ denormalise_bands(qext_mode, X, freq, qext_bandLogE, 0, qext_end, M,
+ downsample, silence);
+#endif
+ /* Store a temporary copy in the output buffer because the IMDCT destroys its input. */
+ freq2 = out_syn[1]+overlap/2;
+ OPUS_COPY(freq2, freq, N);
+ for (b=0;b<B;b++)
+ clt_mdct_backward(&mode->mdct, &freq2[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
+ for (b=0;b<B;b++)
+ clt_mdct_backward(&mode->mdct, &freq[b], out_syn[1]+NB*b, mode->window, overlap, shift, B, arch);
+ } else if (CC==1&&C==2)
+ {
+ /* Downmixing a stereo stream to mono */
+ celt_sig *freq2;
+ freq2 = out_syn[0]+overlap/2;
+ denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
+ downsample, silence);
+ /* Use the output buffer as temp array before downmixing. */
+ denormalise_bands(mode, X+N, freq2, oldBandE+nbEBands, start, effEnd, M,
+ downsample, silence);
+#ifdef ENABLE_QEXT
+ if (qext_mode)
+ {
+ denormalise_bands(qext_mode, X, freq, qext_bandLogE, 0, qext_end, M,
+ downsample, silence);
+ denormalise_bands(qext_mode, X+N, freq2, qext_bandLogE+NB_QEXT_BANDS, 0, qext_end, M,
+ downsample, silence);
+ }
+#endif
+ for (i=0;i<N;i++)
+ freq[i] = ADD32(HALF32(freq[i]), HALF32(freq2[i]));
+ for (b=0;b<B;b++)
+ clt_mdct_backward(&mode->mdct, &freq[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
+ } else {
+ /* Normal case (mono or stereo) */
+ c=0; do {
+ denormalise_bands(mode, X+c*N, freq, oldBandE+c*nbEBands, start, effEnd, M,
+ downsample, silence);
+#ifdef ENABLE_QEXT
+ if (qext_mode)
+ denormalise_bands(qext_mode, X+c*N, freq, qext_bandLogE+c*NB_QEXT_BANDS, 0, qext_end, M,
+ downsample, silence);
+#endif
+ for (b=0;b<B;b++)
+ clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B, arch);
+ } while (++c<CC);
+ }
+ /* Saturate IMDCT output so that we can't overflow in the pitch postfilter
+ or in the */
+ c=0; do {
+ for (i=0;i<N;i++)
+ out_syn[c][i] = SATURATE(out_syn[c][i], SIG_SAT);
+ } while (++c<CC);
+ RESTORE_STACK;
+}
+
+static void tf_decode(int start, int end, int isTransient, int *tf_res, int LM, ec_dec *dec)
+{
+ int i, curr, tf_select;
+ int tf_select_rsv;
+ int tf_changed;
+ int logp;
+ opus_uint32 budget;
+ opus_uint32 tell;
+
+ budget = dec->storage*8;
+ tell = ec_tell(dec);
+ logp = isTransient ? 2 : 4;
+ tf_select_rsv = LM>0 && tell+logp+1<=budget;
+ budget -= tf_select_rsv;
+ tf_changed = curr = 0;
+ for (i=start;i<end;i++)
+ {
+ if (tell+logp<=budget)
+ {
+ curr ^= ec_dec_bit_logp(dec, logp);
+ tell = ec_tell(dec);
+ tf_changed |= curr;
+ }
+ tf_res[i] = curr;
+ logp = isTransient ? 4 : 5;
+ }
+ tf_select = 0;
+ if (tf_select_rsv &&
+ tf_select_table[LM][4*isTransient+0+tf_changed] !=
+ tf_select_table[LM][4*isTransient+2+tf_changed])
+ {
+ tf_select = ec_dec_bit_logp(dec, 1);
+ }
+ for (i=start;i<end;i++)
+ {
+ tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
+ }
+}
+
+static int celt_plc_pitch_search(CELTDecoder *st, celt_sig *decode_mem[2], int C, int arch)
+{
+ int pitch_index;
+#ifdef ENABLE_QEXT
+ int qext_scale;
+#endif
+ VARDECL( opus_val16, lp_pitch_buf );
+ SAVE_STACK;
+#ifdef ENABLE_QEXT
+ qext_scale = st->qext_scale;
+#else
+ (void)st;
+#endif
+ ALLOC( lp_pitch_buf, DECODE_BUFFER_SIZE>>1, opus_val16 );
+ pitch_downsample(decode_mem, lp_pitch_buf,
+ DECODE_BUFFER_SIZE>>1, C, QEXT_SCALE(2), arch);
+ pitch_search(lp_pitch_buf+(PLC_PITCH_LAG_MAX>>1), lp_pitch_buf,
+ DECODE_BUFFER_SIZE-PLC_PITCH_LAG_MAX,
+ PLC_PITCH_LAG_MAX-PLC_PITCH_LAG_MIN, &pitch_index, arch);
+ pitch_index = PLC_PITCH_LAG_MAX-pitch_index;
+ RESTORE_STACK;
+ return QEXT_SCALE(pitch_index);
+}
+
+static void prefilter_and_fold(CELTDecoder * OPUS_RESTRICT st, int N)
+{
+ int c;
+ int CC;
+ int i;
+ int overlap;
+ celt_sig *decode_mem[2];
+ const OpusCustomMode *mode;
+ int decode_buffer_size;
+#ifdef ENABLE_QEXT
+ int qext_scale;
+#endif
+ VARDECL(opus_val32, etmp);
+ SAVE_STACK
+#ifdef ENABLE_QEXT
+ qext_scale = st->qext_scale;
+#endif
+ decode_buffer_size = QEXT_SCALE(DECODE_BUFFER_SIZE);
+ mode = st->mode;
+ overlap = st->overlap;
+ CC = st->channels;
+ ALLOC(etmp, overlap, opus_val32);
+ c=0; do {
+ decode_mem[c] = st->_decode_mem + c*(decode_buffer_size+overlap);
+ } while (++c<CC);
+
+ c=0; do {
+ /* Apply the pre-filter to the MDCT overlap for the next frame because
+ the post-filter will be re-applied in the decoder after the MDCT
+ overlap. */
+ comb_filter(etmp, decode_mem[c]+decode_buffer_size-N,
+ st->postfilter_period_old, st->postfilter_period, overlap,
+ -st->postfilter_gain_old, -st->postfilter_gain,
+ st->postfilter_tapset_old, st->postfilter_tapset, NULL, 0, st->arch);
+
+ /* Simulate TDAC on the concealed audio so that it blends with the
+ MDCT of the next frame. */
+ for (i=0;i<overlap/2;i++)
+ {
+ decode_mem[c][decode_buffer_size-N+i] =
+ MULT16_32_Q15(COEF2VAL16(mode->window[i]), etmp[overlap-1-i])
+ + MULT16_32_Q15 (COEF2VAL16(mode->window[overlap-i-1]), etmp[i]);
+ }
+ } while (++c<CC);
+ RESTORE_STACK;
+}
+
+#ifdef ENABLE_DEEP_PLC
+
+#define SINC_ORDER 48
+/* h=cos(pi/2*abs(sin([-24:24]/48*pi*23./24)).^2);
+ b=sinc([-24:24]/3*1.02).*h;
+ b=b/sum(b); */
+static const float sinc_filter[SINC_ORDER+1] = {
+ 4.2931e-05f, -0.000190293f, -0.000816132f, -0.000637162f, 0.00141662f, 0.00354764f, 0.00184368f, -0.00428274f,
+ -0.00856105f, -0.0034003f, 0.00930201f, 0.0159616f, 0.00489785f, -0.0169649f, -0.0259484f, -0.00596856f,
+ 0.0286551f, 0.0405872f, 0.00649994f, -0.0509284f, -0.0716655f, -0.00665212f, 0.134336f, 0.278927f,
+ 0.339995f, 0.278927f, 0.134336f, -0.00665212f, -0.0716655f, -0.0509284f, 0.00649994f, 0.0405872f,
+ 0.0286551f, -0.00596856f, -0.0259484f, -0.0169649f, 0.00489785f, 0.0159616f, 0.00930201f, -0.0034003f,
+ -0.00856105f, -0.00428274f, 0.00184368f, 0.00354764f, 0.00141662f, -0.000637162f, -0.000816132f, -0.000190293f,
+ 4.2931e-05f
+};
+
+void update_plc_state(LPCNetPLCState *lpcnet, celt_sig *decode_mem[2], float *plc_preemphasis_mem, int CC)
+{
+ int i;
+ int tmp_read_post, tmp_fec_skip;
+ int offset;
+ celt_sig buf48k[DECODE_BUFFER_SIZE];
+ opus_int16 buf16k[PLC_UPDATE_SAMPLES];
+ if (CC == 1) OPUS_COPY(buf48k, decode_mem[0], DECODE_BUFFER_SIZE);
+ else {
+ for (i=0;i<DECODE_BUFFER_SIZE;i++) {
+ buf48k[i] = .5*(decode_mem[0][i] + decode_mem[1][i]);
+ }
+ }
+ /* Down-sample the last 40 ms. */
+ for (i=1;i<DECODE_BUFFER_SIZE;i++) buf48k[i] += PREEMPHASIS*buf48k[i-1];
+ *plc_preemphasis_mem = buf48k[DECODE_BUFFER_SIZE-1];
+ offset = DECODE_BUFFER_SIZE-SINC_ORDER-1 - 3*(PLC_UPDATE_SAMPLES-1);
+ celt_assert(3*(PLC_UPDATE_SAMPLES-1) + SINC_ORDER + offset == DECODE_BUFFER_SIZE-1);
+ for (i=0;i<PLC_UPDATE_SAMPLES;i++) {
+ int j;
+ float sum = 0;
+ for (j=0;j<SINC_ORDER+1;j++) {
+ sum += buf48k[3*i + j + offset]*sinc_filter[j];
+ }
+ buf16k[i] = float2int(MIN32(32767.f, MAX32(-32767.f, sum)));
+ }
+ tmp_read_post = lpcnet->fec_read_pos;
+ tmp_fec_skip = lpcnet->fec_skip;
+ for (i=0;i<PLC_UPDATE_FRAMES;i++) {
+ lpcnet_plc_update(lpcnet, &buf16k[FRAME_SIZE*i]);
+ }
+ lpcnet->fec_read_pos = tmp_read_post;
+ lpcnet->fec_skip = tmp_fec_skip;
+}
+#endif
+
+static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
+#ifdef ENABLE_DEEP_PLC
+ ,LPCNetPLCState *lpcnet
+#endif
+ )
+{
+ int c;
+ int i;
+ const int C = st->channels;
+ celt_sig *decode_mem[2];
+ celt_sig *out_syn[2];
+ opus_val16 *lpc;
+ celt_glog *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
+ const OpusCustomMode *mode;
+ int nbEBands;
+ int overlap;
+ int start;
+ int loss_duration;
+ int curr_frame_type;
+ const opus_int16 *eBands;
+ int decode_buffer_size;
+ int max_period;
+#ifdef ENABLE_QEXT
+ int qext_scale;
+#endif
+ SAVE_STACK;
+#ifdef ENABLE_QEXT
+ qext_scale = st->qext_scale;
+#endif
+ decode_buffer_size = QEXT_SCALE(DECODE_BUFFER_SIZE);
+ max_period = QEXT_SCALE(MAX_PERIOD);
+ mode = st->mode;
+ nbEBands = mode->nbEBands;
+ overlap = mode->overlap;
+ eBands = mode->eBands;
+
+ c=0; do {
+ decode_mem[c] = st->_decode_mem + c*(decode_buffer_size+overlap);
+ out_syn[c] = decode_mem[c]+decode_buffer_size-N;
+ } while (++c<C);
+ oldBandE = (celt_glog*)(st->_decode_mem+(decode_buffer_size+overlap)*C);
+ oldLogE = oldBandE + 2*nbEBands;
+ oldLogE2 = oldLogE + 2*nbEBands;
+ backgroundLogE = oldLogE2 + 2*nbEBands;
+ lpc = (opus_val16*)(backgroundLogE + 2*nbEBands);
+
+ loss_duration = st->loss_duration;
+ start = st->start;
+ curr_frame_type = FRAME_PLC_PERIODIC;
+ if (st->plc_duration >= 40 || start != 0 || st->skip_plc)
+ curr_frame_type = FRAME_PLC_NOISE;
+#ifdef ENABLE_DEEP_PLC
+ if (start == 0 && lpcnet != NULL && st->mode->Fs != 96000 && lpcnet->loaded)
+ {
+ if (st->complexity >= 5 && st->plc_duration < 80 && !st->skip_plc)
+ curr_frame_type = FRAME_PLC_NEURAL;
+#ifdef ENABLE_DRED
+ if (lpcnet->fec_fill_pos > lpcnet->fec_read_pos)
+ curr_frame_type = FRAME_DRED;
+#endif
+ }
+#endif
+
+ if (curr_frame_type == FRAME_PLC_NOISE)
+ {
+ /* Noise-based PLC/CNG */
+ VARDECL(celt_norm, X);
+ opus_uint32 seed;
+ int end;
+ int effEnd;
+ celt_glog decay;
+ end = st->end;
+ effEnd = IMAX(start, IMIN(end, mode->effEBands));
+
+ ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
+ c=0; do {
+ OPUS_MOVE(decode_mem[c], decode_mem[c]+N,
+ decode_buffer_size-N+overlap);
+ } while (++c<C);
+
+ if (st->prefilter_and_fold) {
+ prefilter_and_fold(st, N);
+ }
+
+ /* Energy decay */
+ decay = loss_duration==0 ? GCONST(1.5f) : GCONST(.5f);
+ c=0; do
+ {
+ for (i=start;i<end;i++)
+ oldBandE[c*nbEBands+i] = MAXG(backgroundLogE[c*nbEBands+i], oldBandE[c*nbEBands+i] - decay);
+ } while (++c<C);
+ seed = st->rng;
+ for (c=0;c<C;c++)
+ {
+ for (i=start;i<effEnd;i++)
+ {
+ int j;
+ int boffs;
+ int blen;
+ boffs = N*c+(eBands[i]<<LM);
+ blen = (eBands[i+1]-eBands[i])<<LM;
+ for (j=0;j<blen;j++)
+ {
+ seed = celt_lcg_rand(seed);
+ X[boffs+j] = SHL32((celt_norm)((opus_int32)seed>>20), NORM_SHIFT-14);
+ }
+ renormalise_vector(X+boffs, blen, Q31ONE, st->arch);
+ }
+ }
+ st->rng = seed;
+
+ celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, C, 0, LM, st->downsample, 0, st->arch ARG_QEXT(NULL) ARG_QEXT(NULL) ARG_QEXT(0));
+
+ /* Run the postfilter with the last parameters. */
+ c=0; do {
+ st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD);
+ st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD);
+ comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, mode->shortMdctSize,
+ st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset,
+ mode->window, overlap, st->arch);
+ if (LM!=0)
+ comb_filter(out_syn[c]+mode->shortMdctSize, out_syn[c]+mode->shortMdctSize, st->postfilter_period, st->postfilter_period, N-mode->shortMdctSize,
+ st->postfilter_gain, st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset,
+ mode->window, overlap, st->arch);
+
+ } while (++c<C);
+ st->postfilter_period_old = st->postfilter_period;
+ st->postfilter_gain_old = st->postfilter_gain;
+ st->postfilter_tapset_old = st->postfilter_tapset;
+
+ st->prefilter_and_fold = 0;
+ /* Skip regular PLC until we get two consecutive packets. */
+ st->skip_plc = 1;
+ } else {
+ int exc_length;
+ /* Pitch-based PLC */
+ const celt_coef *window;
+ opus_val16 *exc;
+ opus_val16 fade = Q15ONE;
+ int pitch_index;
+ int curr_neural;
+ int last_neural;
+ VARDECL(opus_val16, _exc);
+ VARDECL(opus_val16, fir_tmp);
+
+ curr_neural = curr_frame_type == FRAME_PLC_NEURAL || curr_frame_type == FRAME_DRED;
+ last_neural = st->last_frame_type == FRAME_PLC_NEURAL || st->last_frame_type == FRAME_DRED;
+ if (st->last_frame_type != FRAME_PLC_PERIODIC && !(last_neural && curr_neural))
+ {
+ st->last_pitch_index = pitch_index = celt_plc_pitch_search(st, decode_mem, C, st->arch);
+ } else {
+ pitch_index = st->last_pitch_index;
+ fade = QCONST16(.8f,15);
+ }
+#ifdef ENABLE_DEEP_PLC
+ if (curr_neural && !last_neural) update_plc_state(lpcnet, decode_mem, &st->plc_preemphasis_mem, C);
+#endif
+
+ /* We want the excitation for 2 pitch periods in order to look for a
+ decaying signal, but we can't get more than MAX_PERIOD. */
+ exc_length = IMIN(2*pitch_index, max_period);
+
+ ALLOC(_exc, max_period+CELT_LPC_ORDER, opus_val16);
+ ALLOC(fir_tmp, exc_length, opus_val16);
+ exc = _exc+CELT_LPC_ORDER;
+ window = mode->window;
+ c=0; do {
+ opus_val16 decay;
+ opus_val16 attenuation;
+ opus_val32 S1=0;
+ celt_sig *buf;
+ int extrapolation_offset;
+ int extrapolation_len;
+ int j;
+
+ buf = decode_mem[c];
+ for (i=0;i<max_period+CELT_LPC_ORDER;i++)
+ exc[i-CELT_LPC_ORDER] = SROUND16(buf[decode_buffer_size-max_period-CELT_LPC_ORDER+i], SIG_SHIFT);
+
+ if (st->last_frame_type != FRAME_PLC_PERIODIC && !(last_neural && curr_neural))
+ {
+ opus_val32 ac[CELT_LPC_ORDER+1];
+ /* Compute LPC coefficients for the last MAX_PERIOD samples before
+ the first loss so we can work in the excitation-filter domain. */
+ _celt_autocorr(exc, ac, window, overlap,
+ CELT_LPC_ORDER, max_period, st->arch);
+ /* Add a noise floor of -40 dB. */
+#ifdef FIXED_POINT
+ ac[0] += SHR32(ac[0],13);
+#else
+ ac[0] *= 1.0001f;
+#endif
+ /* Use lag windowing to stabilize the Levinson-Durbin recursion. */
+ for (i=1;i<=CELT_LPC_ORDER;i++)
+ {
+ /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
+#ifdef FIXED_POINT
+ ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
+#else
+ ac[i] -= ac[i]*(0.008f*0.008f)*i*i;
+#endif
+ }
+ _celt_lpc(lpc+c*CELT_LPC_ORDER, ac, CELT_LPC_ORDER);
+#ifdef FIXED_POINT
+ /* For fixed-point, apply bandwidth expansion until we can guarantee that
+ no overflow can happen in the IIR filter. This means:
+ 32768*sum(abs(filter)) < 2^31 */
+ while (1) {
+ opus_val16 tmp=Q15ONE;
+ opus_val32 sum=QCONST16(1., SIG_SHIFT);
+ for (i=0;i<CELT_LPC_ORDER;i++)
+ sum += ABS16(lpc[c*CELT_LPC_ORDER+i]);
+ if (sum < 65535) break;
+ for (i=0;i<CELT_LPC_ORDER;i++)
+ {
+ tmp = MULT16_16_Q15(QCONST16(.99f,15), tmp);
+ lpc[c*CELT_LPC_ORDER+i] = MULT16_16_Q15(lpc[c*CELT_LPC_ORDER+i], tmp);
+ }
+ }
+#endif
+ }
+ /* Initialize the LPC history with the samples just before the start
+ of the region for which we're computing the excitation. */
+ {
+ /* Compute the excitation for exc_length samples before the loss. We need the copy
+ because celt_fir() cannot filter in-place. */
+ celt_fir(exc+max_period-exc_length, lpc+c*CELT_LPC_ORDER,
+ fir_tmp, exc_length, CELT_LPC_ORDER, st->arch);
+ OPUS_COPY(exc+max_period-exc_length, fir_tmp, exc_length);
+ }
+
+ /* Check if the waveform is decaying, and if so how fast.
+ We do this to avoid adding energy when concealing in a segment
+ with decaying energy. */
+ {
+ opus_val32 E1=1, E2=1;
+ int decay_length;
+#ifdef FIXED_POINT
+ int shift = IMAX(0,2*celt_zlog2(celt_maxabs16(&exc[max_period-exc_length], exc_length))-20);
+#ifdef ENABLE_QEXT
+ if (st->qext_scale==2) shift++;
+#endif
+#endif
+ decay_length = exc_length>>1;
+ for (i=0;i<decay_length;i++)
+ {
+ opus_val16 e;
+ e = exc[max_period-decay_length+i];
+ E1 += SHR32(MULT16_16(e, e), shift);
+ e = exc[max_period-2*decay_length+i];
+ E2 += SHR32(MULT16_16(e, e), shift);
+ }
+ E1 = MIN32(E1, E2);
+ decay = celt_sqrt(frac_div32(SHR32(E1, 1), E2));
+ }
+
+ /* Move the decoder memory one frame to the left to give us room to
+ add the data for the new frame. We ignore the overlap that extends
+ past the end of the buffer, because we aren't going to use it. */
+ OPUS_MOVE(buf, buf+N, decode_buffer_size-N);
+
+ /* Extrapolate from the end of the excitation with a period of
+ "pitch_index", scaling down each period by an additional factor of
+ "decay". */
+ extrapolation_offset = max_period-pitch_index;
+ /* We need to extrapolate enough samples to cover a complete MDCT
+ window (including overlap/2 samples on both sides). */
+ extrapolation_len = N+overlap;
+ /* We also apply fading if this is not the first loss. */
+ attenuation = MULT16_16_Q15(fade, decay);
+ for (i=j=0;i<extrapolation_len;i++,j++)
+ {
+ opus_val16 tmp;
+ if (j >= pitch_index) {
+ j -= pitch_index;
+ attenuation = MULT16_16_Q15(attenuation, decay);
+ }
+ buf[decode_buffer_size-N+i] =
+ SHL32(EXTEND32(MULT16_16_Q15(attenuation,
+ exc[extrapolation_offset+j])), SIG_SHIFT);
+ /* Compute the energy of the previously decoded signal whose
+ excitation we're copying. */
+ tmp = SROUND16(
+ buf[decode_buffer_size-max_period-N+extrapolation_offset+j],
+ SIG_SHIFT);
+ S1 += SHR32(MULT16_16(tmp, tmp), 11);
+ }
+ {
+ opus_val16 lpc_mem[CELT_LPC_ORDER];
+ /* Copy the last decoded samples (prior to the overlap region) to
+ synthesis filter memory so we can have a continuous signal. */
+ for (i=0;i<CELT_LPC_ORDER;i++)
+ lpc_mem[i] = SROUND16(buf[decode_buffer_size-N-1-i], SIG_SHIFT);
+ /* Apply the synthesis filter to convert the excitation back into
+ the signal domain. */
+ celt_iir(buf+decode_buffer_size-N, lpc+c*CELT_LPC_ORDER,
+ buf+decode_buffer_size-N, extrapolation_len, CELT_LPC_ORDER,
+ lpc_mem, st->arch);
+#ifdef FIXED_POINT
+ for (i=0; i < extrapolation_len; i++)
+ buf[decode_buffer_size-N+i] = SATURATE(buf[decode_buffer_size-N+i], SIG_SAT);
+#endif
+ }
+
+ /* Check if the synthesis energy is higher than expected, which can
+ happen with the signal changes during our window. If so,
+ attenuate. */
+ {
+ opus_val32 S2=0;
+ for (i=0;i<extrapolation_len;i++)
+ {
+ opus_val16 tmp = SROUND16(buf[decode_buffer_size-N+i], SIG_SHIFT);
+ S2 += SHR32(MULT16_16(tmp, tmp), 11);
+ }
+ /* This checks for an "explosion" in the synthesis. */
+#ifdef FIXED_POINT
+ if (!(S1 > SHR32(S2,2)))
+#else
+ /* The float test is written this way to catch NaNs in the output
+ of the IIR filter at the same time. */
+ if (!(S1 > 0.2f*S2))
+#endif
+ {
+ for (i=0;i<extrapolation_len;i++)
+ buf[decode_buffer_size-N+i] = 0;
+ } else if (S1 < S2)
+ {
+ opus_val16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1));
+ for (i=0;i<overlap;i++)
+ {
+ opus_val16 tmp_g = Q15ONE
+ - MULT16_16_Q15(COEF2VAL16(window[i]), Q15ONE-ratio);
+ buf[decode_buffer_size-N+i] =
+ MULT16_32_Q15(tmp_g, buf[decode_buffer_size-N+i]);
+ }
+ for (i=overlap;i<extrapolation_len;i++)
+ {
+ buf[decode_buffer_size-N+i] =
+ MULT16_32_Q15(ratio, buf[decode_buffer_size-N+i]);
+ }
+ }
+ }
+
+ } while (++c<C);
+
+#ifdef ENABLE_DEEP_PLC
+ if (curr_neural) {
+ float overlap_mem;
+ int samples_needed16k;
+ celt_sig *buf;
+ VARDECL(float, buf_copy);
+ buf = decode_mem[0];
+ ALLOC(buf_copy, C*overlap, float);
+ c=0; do {
+ OPUS_COPY(buf_copy+c*overlap, &decode_mem[c][decode_buffer_size-N], overlap);
+ } while (++c<C);
+
+ /* Need enough samples from the PLC to cover the frame size, resampling delay,
+ and the overlap at the end. */
+ samples_needed16k = (N+SINC_ORDER+overlap)/3;
+ if (!last_neural) {
+ st->plc_fill = 0;
+ }
+ while (st->plc_fill < samples_needed16k) {
+ lpcnet_plc_conceal(lpcnet, &st->plc_pcm[st->plc_fill]);
+ st->plc_fill += FRAME_SIZE;
+ }
+ /* Resample to 48 kHz. */
+ for (i=0;i<(N+overlap)/3;i++) {
+ int j;
+ float sum;
+ for (sum=0, j=0;j<17;j++) sum += 3*st->plc_pcm[i+j]*sinc_filter[3*j];
+ buf[decode_buffer_size-N+3*i] = sum;
+ for (sum=0, j=0;j<16;j++) sum += 3*st->plc_pcm[i+j+1]*sinc_filter[3*j+2];
+ buf[decode_buffer_size-N+3*i+1] = sum;
+ for (sum=0, j=0;j<16;j++) sum += 3*st->plc_pcm[i+j+1]*sinc_filter[3*j+1];
+ buf[decode_buffer_size-N+3*i+2] = sum;
+ }
+ OPUS_MOVE(st->plc_pcm, &st->plc_pcm[N/3], st->plc_fill-N/3);
+ st->plc_fill -= N/3;
+ for (i=0;i<N;i++) {
+ float tmp = buf[decode_buffer_size-N+i];
+ buf[decode_buffer_size-N+i] -= PREEMPHASIS*st->plc_preemphasis_mem;
+ st->plc_preemphasis_mem = tmp;
+ }
+ overlap_mem = st->plc_preemphasis_mem;
+ for (i=0;i<overlap;i++) {
+ float tmp = buf[decode_buffer_size+i];
+ buf[decode_buffer_size+i] -= PREEMPHASIS*overlap_mem;
+ overlap_mem = tmp;
+ }
+ /* For now, we just do mono PLC. */
+ if (C==2) OPUS_COPY(decode_mem[1], decode_mem[0], decode_buffer_size+overlap);
+ c=0; do {
+ /* Cross-fade with 48-kHz non-neural PLC for the first 2.5 ms to avoid a discontinuity. */
+ if (!last_neural) {
+ for (i=0;i<overlap;i++) decode_mem[c][decode_buffer_size-N+i] = (1-window[i])*buf_copy[c*overlap+i] + (window[i])*decode_mem[c][decode_buffer_size-N+i];
+ }
+ } while (++c<C);
+ }
+#endif
+ st->prefilter_and_fold = 1;
+ }
+
+ /* Saturate to something large to avoid wrap-around. */
+ st->loss_duration = IMIN(10000, loss_duration+(1<<LM));
+ st->plc_duration = IMIN(10000, st->plc_duration+(1<<LM));
+#ifdef ENABLE_DRED
+ if (curr_frame_type == FRAME_DRED) {
+ st->plc_duration = 0;
+ st->skip_plc = 0;
+ }
+#endif
+ st->last_frame_type = curr_frame_type;
+ RESTORE_STACK;
+}
+
+#ifdef ENABLE_QEXT
+static void decode_qext_stereo_params(ec_dec *ec, int qext_end, int *qext_intensity, int *qext_dual_stereo) {
+ *qext_intensity = ec_dec_uint(ec, qext_end+1);
+ if (*qext_intensity != 0) *qext_dual_stereo = ec_dec_bit_logp(ec, 1);
+ else *qext_dual_stereo = 0;
+}
+#endif
+
+int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
+ int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum
+#ifdef ENABLE_DEEP_PLC
+ ,LPCNetPLCState *lpcnet
+#endif
+ ARG_QEXT(const unsigned char *qext_payload) ARG_QEXT(int qext_payload_len)
+ )
+{
+ int c, i, N;
+ int spread_decision;
+ opus_int32 bits;
+ ec_dec _dec;
+ VARDECL(celt_norm, X);
+ VARDECL(int, fine_quant);
+ VARDECL(int, pulses);
+ VARDECL(int, cap);
+ VARDECL(int, offsets);
+ VARDECL(int, fine_priority);
+ VARDECL(int, tf_res);
+ VARDECL(unsigned char, collapse_masks);
+ celt_sig *decode_mem[2];
+ celt_sig *out_syn[2];
+ celt_glog *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
+
+ int shortBlocks;
+ int isTransient;
+ int intra_ener;
+ const int CC = st->channels;
+ int LM, M;
+ int start;
+ int end;
+ int effEnd;
+ int codedBands;
+ int alloc_trim;
+ int postfilter_pitch;
+ opus_val16 postfilter_gain;
+ int intensity=0;
+ int dual_stereo=0;
+ opus_int32 total_bits;
+ opus_int32 balance;
+ opus_int32 tell;
+ int dynalloc_logp;
+ int postfilter_tapset;
+ int anti_collapse_rsv;
+ int anti_collapse_on=0;
+ int silence;
+ int C = st->stream_channels;
+ const OpusCustomMode *mode;
+ int nbEBands;
+ int overlap;
+ const opus_int16 *eBands;
+ celt_glog max_background_increase;
+ int decode_buffer_size;
+#ifdef ENABLE_QEXT
+ opus_int32 qext_bits;
+ ec_dec ext_dec;
+ int qext_bytes=0;
+ int qext_end=0;
+ int qext_intensity=0;
+ int qext_dual_stereo=0;
+ VARDECL(int, extra_quant);
+ VARDECL(int, extra_pulses);
+ const CELTMode *qext_mode = NULL;
+ CELTMode qext_mode_struct;
+ int qext_scale;
+#else
+# define qext_bytes 0
+#endif
+ ALLOC_STACK;
+#ifdef ENABLE_QEXT
+ qext_scale = st->qext_scale;
+#endif
+ decode_buffer_size = QEXT_SCALE(DECODE_BUFFER_SIZE);
+
+ VALIDATE_CELT_DECODER(st);
+ mode = st->mode;
+ nbEBands = mode->nbEBands;
+ overlap = mode->overlap;
+ eBands = mode->eBands;
+ start = st->start;
+ end = st->end;
+ frame_size *= st->downsample;
+
+ oldBandE = (celt_glog*)(st->_decode_mem+(decode_buffer_size+overlap)*CC);
+ oldLogE = oldBandE + 2*nbEBands;
+ oldLogE2 = oldLogE + 2*nbEBands;
+ backgroundLogE = oldLogE2 + 2*nbEBands;
+
+#ifdef ENABLE_QEXT
+ if (qext_payload) {
+ ec_dec_init(&ext_dec, (unsigned char*)qext_payload, qext_payload_len);
+ qext_bytes = qext_payload_len;
+ } else {
+ ec_dec_init(&ext_dec, NULL, 0);
+ }
+#endif
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+ if (st->signalling && data!=NULL)
+ {
+ int data0=data[0];
+ /* Convert "standard mode" to Opus header */
+# ifndef ENABLE_QEXT
+ if (mode->Fs==48000 && mode->shortMdctSize==120)
+# endif
+ {
+ data0 = fromOpus(data0);
+ if (data0<0)
+ return OPUS_INVALID_PACKET;
+ }
+ st->end = end = IMAX(1, mode->effEBands-2*(data0>>5));
+ LM = (data0>>3)&0x3;
+ C = 1 + ((data0>>2)&0x1);
+ if ((data[0] & 0x03) == 0x03) {
+ data++;
+ len--;
+ if (len<=0)
+ return OPUS_INVALID_PACKET;
+ if (data[0] & 0x40) {
+ int p;
+ int padding=0;
+ data++;
+ len--;
+ do {
+ int tmp;
+ if (len<=0)
+ return OPUS_INVALID_PACKET;
+ p = *data++;
+ len--;
+ tmp = p==255 ? 254: p;
+ len -= tmp;
+ padding += tmp;
+ } while (p==255);
+ padding--;
+ if (len <= 0 || padding<0) return OPUS_INVALID_PACKET;
+#ifdef ENABLE_QEXT
+ qext_bytes = padding;
+ if (data[len] != QEXT_EXTENSION_ID<<1)
+ qext_bytes=0;
+ ec_dec_init(&ext_dec, (unsigned char*)data+len+1, qext_bytes);
+#endif
+ }
+ } else
+ {
+ data++;
+ len--;
+ }
+ if (LM>mode->maxLM)
+ return OPUS_INVALID_PACKET;
+ if (frame_size < mode->shortMdctSize<<LM)
+ return OPUS_BUFFER_TOO_SMALL;
+ else
+ frame_size = mode->shortMdctSize<<LM;
+ } else {
+#else
+ {
+#endif
+ for (LM=0;LM<=mode->maxLM;LM++)
+ if (mode->shortMdctSize<<LM==frame_size)
+ break;
+ if (LM>mode->maxLM)
+ return OPUS_BAD_ARG;
+ }
+ M=1<<LM;
+
+ if (len<0 || len>1275 || pcm==NULL)
+ return OPUS_BAD_ARG;
+
+ N = M*mode->shortMdctSize;
+ c=0; do {
+ decode_mem[c] = st->_decode_mem + c*(decode_buffer_size+overlap);
+ out_syn[c] = decode_mem[c]+decode_buffer_size-N;
+ } while (++c<CC);
+
+ effEnd = end;
+ if (effEnd > mode->effEBands)
+ effEnd = mode->effEBands;
+
+ if (data == NULL || len<=1)
+ {
+ celt_decode_lost(st, N, LM
+#ifdef ENABLE_DEEP_PLC
+ , lpcnet
+#endif
+ );
+ deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
+ RESTORE_STACK;
+ return frame_size/st->downsample;
+ }
+#ifdef ENABLE_DEEP_PLC
+ else {
+ /* FIXME: This is a bit of a hack just to make sure opus_decode_native() knows we're no longer in PLC. */
+ if (lpcnet) lpcnet->blend = 0;
+ }
+#endif
+
+ /* Check if there are at least two packets received consecutively before
+ * turning on the pitch-based PLC */
+ if (st->loss_duration == 0) st->skip_plc = 0;
+
+ if (dec == NULL)
+ {
+ ec_dec_init(&_dec,(unsigned char*)data,len);
+ dec = &_dec;
+ }
+
+ if (C==1)
+ {
+ for (i=0;i<nbEBands;i++)
+ oldBandE[i]=MAXG(oldBandE[i],oldBandE[nbEBands+i]);
+ }
+
+ total_bits = len*8;
+ tell = ec_tell(dec);
+
+ if (tell >= total_bits)
+ silence = 1;
+ else if (tell==1)
+ silence = ec_dec_bit_logp(dec, 15);
+ else
+ silence = 0;
+ if (silence)
+ {
+ /* Pretend we've read all the remaining bits */
+ tell = len*8;
+ dec->nbits_total+=tell-ec_tell(dec);
+ }
+
+ postfilter_gain = 0;
+ postfilter_pitch = 0;
+ postfilter_tapset = 0;
+ if (start==0 && tell+16 <= total_bits)
+ {
+ if(ec_dec_bit_logp(dec, 1))
+ {
+ int qg, octave;
+ octave = ec_dec_uint(dec, 6);
+ postfilter_pitch = (16<<octave)+ec_dec_bits(dec, 4+octave)-1;
+ qg = ec_dec_bits(dec, 3);
+ if (ec_tell(dec)+2<=total_bits)
+ postfilter_tapset = ec_dec_icdf(dec, tapset_icdf, 2);
+ postfilter_gain = QCONST16(.09375f,15)*(qg+1);
+ }
+ tell = ec_tell(dec);
+ }
+
+ if (LM > 0 && tell+3 <= total_bits)
+ {
+ isTransient = ec_dec_bit_logp(dec, 3);
+ tell = ec_tell(dec);
+ }
+ else
+ isTransient = 0;
+
+ if (isTransient)
+ shortBlocks = M;
+ else
+ shortBlocks = 0;
+
+ /* Decode the global flags (first symbols in the stream) */
+ intra_ener = tell+3<=total_bits ? ec_dec_bit_logp(dec, 3) : 0;
+ /* If recovering from packet loss, make sure we make the energy prediction safe to reduce the
+ risk of getting loud artifacts. */
+ if (!intra_ener && st->loss_duration != 0) {
+ c=0; do
+ {
+ celt_glog safety = 0;
+ int missing = IMIN(10, st->loss_duration>>LM);
+ if (LM==0) safety = GCONST(1.5f);
+ else if (LM==1) safety = GCONST(.5f);
+ for (i=start;i<end;i++)
+ {
+ if (oldBandE[c*nbEBands+i] < MAXG(oldLogE[c*nbEBands+i], oldLogE2[c*nbEBands+i])) {
+ /* If energy is going down already, continue the trend. */
+ opus_val32 slope;
+ opus_val32 E0, E1, E2;
+ E0 = oldBandE[c*nbEBands+i];
+ E1 = oldLogE[c*nbEBands+i];
+ E2 = oldLogE2[c*nbEBands+i];
+ slope = MAX32(E1 - E0, HALF32(E2 - E0));
+ slope = MING(slope, GCONST(2.f));
+ E0 -= MAX32(0, (1+missing)*slope);
+ oldBandE[c*nbEBands+i] = MAX32(-GCONST(20.f), E0);
+ } else {
+ /* Otherwise take the min of the last frames. */
+ oldBandE[c*nbEBands+i] = MING(MING(oldBandE[c*nbEBands+i], oldLogE[c*nbEBands+i]), oldLogE2[c*nbEBands+i]);
+ }
+ /* Shorter frames have more natural fluctuations -- play it safe. */
+ oldBandE[c*nbEBands+i] -= safety;
+ }
+ } while (++c<2);
+ }
+ /* Get band energies */
+ unquant_coarse_energy(mode, start, end, oldBandE,
+ intra_ener, dec, C, LM);
+
+ ALLOC(tf_res, nbEBands, int);
+ tf_decode(start, end, isTransient, tf_res, LM, dec);
+
+ tell = ec_tell(dec);
+ spread_decision = SPREAD_NORMAL;
+ if (tell+4 <= total_bits)
+ spread_decision = ec_dec_icdf(dec, spread_icdf, 5);
+
+ ALLOC(cap, nbEBands, int);
+
+ init_caps(mode,cap,LM,C);
+
+ ALLOC(offsets, nbEBands, int);
+
+ dynalloc_logp = 6;
+ total_bits<<=BITRES;
+ tell = ec_tell_frac(dec);
+ for (i=start;i<end;i++)
+ {
+ int width, quanta;
+ int dynalloc_loop_logp;
+ int boost;
+ width = C*(eBands[i+1]-eBands[i])<<LM;
+ /* quanta is 6 bits, but no more than 1 bit/sample
+ and no less than 1/8 bit/sample */
+ quanta = IMIN(width<<BITRES, IMAX(6<<BITRES, width));
+ dynalloc_loop_logp = dynalloc_logp;
+ boost = 0;
+ while (tell+(dynalloc_loop_logp<<BITRES) < total_bits && boost < cap[i])
+ {
+ int flag;
+ flag = ec_dec_bit_logp(dec, dynalloc_loop_logp);
+ tell = ec_tell_frac(dec);
+ if (!flag)
+ break;
+ boost += quanta;
+ total_bits -= quanta;
+ dynalloc_loop_logp = 1;
+ }
+ offsets[i] = boost;
+ /* Making dynalloc more likely */
+ if (boost>0)
+ dynalloc_logp = IMAX(2, dynalloc_logp-1);
+ }
+
+ ALLOC(fine_quant, nbEBands, int);
+ alloc_trim = tell+(6<<BITRES) <= total_bits ?
+ ec_dec_icdf(dec, trim_icdf, 7) : 5;
+
+ bits = (((opus_int32)len*8)<<BITRES) - (opus_int32)ec_tell_frac(dec) - 1;
+ anti_collapse_rsv = isTransient&&LM>=2&&bits>=((LM+2)<<BITRES) ? (1<<BITRES) : 0;
+ bits -= anti_collapse_rsv;
+
+ ALLOC(pulses, nbEBands, int);
+ ALLOC(fine_priority, nbEBands, int);
+
+ codedBands = clt_compute_allocation(mode, start, end, offsets, cap,
+ alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses,
+ fine_quant, fine_priority, C, LM, dec, 0, 0, 0);
+
+ unquant_fine_energy(mode, start, end, oldBandE, NULL, fine_quant, dec, C);
+
+ ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
+
+#ifdef ENABLE_QEXT
+ if (qext_bytes && end == nbEBands &&
+ ((mode->Fs == 48000 && (mode->shortMdctSize==120 || mode->shortMdctSize==90))
+ || (mode->Fs == 96000 && (mode->shortMdctSize==240 || mode->shortMdctSize==180)))) {
+ int qext_intra_ener;
+ compute_qext_mode(&qext_mode_struct, mode);
+ qext_mode = &qext_mode_struct;
+ qext_end = ec_dec_bit_logp(&ext_dec, 1) ? NB_QEXT_BANDS : 2;
+ if (C==2) decode_qext_stereo_params(&ext_dec, qext_end, &qext_intensity, &qext_dual_stereo);
+ qext_intra_ener = ec_tell(&ext_dec)+3<=qext_bytes*8 ? ec_dec_bit_logp(&ext_dec, 3) : 0;
+ unquant_coarse_energy(qext_mode, 0, qext_end, st->qext_oldBandE,
+ qext_intra_ener, &ext_dec, C, LM);
+ }
+ ALLOC(extra_quant, nbEBands+NB_QEXT_BANDS, int);
+ ALLOC(extra_pulses, nbEBands+NB_QEXT_BANDS, int);
+ qext_bits = ((opus_int32)qext_bytes*8<<BITRES) - (opus_int32)ec_tell_frac(dec) - 1;
+ clt_compute_extra_allocation(mode, qext_mode, start, end, qext_end, NULL, NULL,
+ qext_bits, extra_pulses, extra_quant, C, LM, &ext_dec, 0, 0, 0);
+ if (qext_bytes > 0) {
+ unquant_fine_energy(mode, start, end, oldBandE, fine_quant, extra_quant, &ext_dec, C);
+ }
+#endif
+
+ c=0; do {
+ OPUS_MOVE(decode_mem[c], decode_mem[c]+N, decode_buffer_size-N+overlap);
+ } while (++c<CC);
+
+ /* Decode fixed codebook */
+ ALLOC(collapse_masks, C*nbEBands, unsigned char);
+
+ quant_all_bands(0, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
+ NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res,
+ len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, 0,
+ st->arch, st->disable_inv
+ ARG_QEXT(&ext_dec) ARG_QEXT(extra_pulses)
+ ARG_QEXT(qext_bytes*(8<<BITRES)) ARG_QEXT(cap));
+
+#ifdef ENABLE_QEXT
+ if (qext_mode) {
+ VARDECL(int, zeros);
+ VARDECL(unsigned char, qext_collapse_masks);
+ ec_dec dummy_dec;
+ int ext_balance;
+ ALLOC(zeros, nbEBands, int);
+ ALLOC(qext_collapse_masks, C*NB_QEXT_BANDS, unsigned char);
+ ec_dec_init(&dummy_dec, NULL, 0);
+ OPUS_CLEAR(zeros, end);
+ ext_balance = qext_bytes*(8<<BITRES) - ec_tell_frac(&ext_dec);
+ for (i=0;i<qext_end;i++) ext_balance -= extra_pulses[nbEBands+i] + C*(extra_quant[nbEBands+1]<<BITRES);
+ unquant_fine_energy(qext_mode, 0, qext_end, st->qext_oldBandE, NULL, &extra_quant[nbEBands], &ext_dec, C);
+ quant_all_bands(0, qext_mode, 0, qext_end, X, C==2 ? X+N : NULL, qext_collapse_masks,
+ NULL, &extra_pulses[nbEBands], shortBlocks, spread_decision, qext_dual_stereo, qext_intensity, zeros,
+ qext_bytes*(8<<BITRES), ext_balance, &ext_dec, LM, qext_end, &st->rng, 0,
+ st->arch, st->disable_inv, &dummy_dec, zeros, 0, NULL);
+ }
+#endif
+
+ if (anti_collapse_rsv > 0)
+ {
+ anti_collapse_on = ec_dec_bits(dec, 1);
+ }
+ unquant_energy_finalise(mode, start, end, (qext_bytes > 0) ? NULL : oldBandE,
+ fine_quant, fine_priority, len*8-ec_tell(dec), dec, C);
+ if (anti_collapse_on)
+ anti_collapse(mode, X, collapse_masks, LM, C, N,
+ start, end, oldBandE, oldLogE, oldLogE2, pulses, st->rng, 0, st->arch);
+
+ if (silence)
+ {
+ for (i=0;i<C*nbEBands;i++)
+ oldBandE[i] = -GCONST(28.f);
+ }
+ if (st->prefilter_and_fold) {
+ prefilter_and_fold(st, N);
+ }
+ celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd,
+ C, CC, isTransient, LM, st->downsample, silence, st->arch ARG_QEXT(qext_mode) ARG_QEXT(st->qext_oldBandE) ARG_QEXT(qext_end));
+
+ c=0; do {
+ st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD);
+ st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD);
+ comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, mode->shortMdctSize,
+ st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset,
+ mode->window, overlap, st->arch);
+ if (LM!=0)
+ comb_filter(out_syn[c]+mode->shortMdctSize, out_syn[c]+mode->shortMdctSize, st->postfilter_period, postfilter_pitch, N-mode->shortMdctSize,
+ st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset,
+ mode->window, overlap, st->arch);
+
+ } while (++c<CC);
+ st->postfilter_period_old = st->postfilter_period;
+ st->postfilter_gain_old = st->postfilter_gain;
+ st->postfilter_tapset_old = st->postfilter_tapset;
+ st->postfilter_period = postfilter_pitch;
+ st->postfilter_gain = postfilter_gain;
+ st->postfilter_tapset = postfilter_tapset;
+ if (LM!=0)
+ {
+ st->postfilter_period_old = st->postfilter_period;
+ st->postfilter_gain_old = st->postfilter_gain;
+ st->postfilter_tapset_old = st->postfilter_tapset;
+ }
+
+ if (C==1)
+ OPUS_COPY(&oldBandE[nbEBands], oldBandE, nbEBands);
+
+ if (!isTransient)
+ {
+ OPUS_COPY(oldLogE2, oldLogE, 2*nbEBands);
+ OPUS_COPY(oldLogE, oldBandE, 2*nbEBands);
+ } else {
+ for (i=0;i<2*nbEBands;i++)
+ oldLogE[i] = MING(oldLogE[i], oldBandE[i]);
+ }
+ /* In normal circumstances, we only allow the noise floor to increase by
+ up to 2.4 dB/second, but when we're in DTX we give the weight of
+ all missing packets to the update packet. */
+ max_background_increase = IMIN(160, st->loss_duration+M)*GCONST(0.001f);
+ for (i=0;i<2*nbEBands;i++)
+ backgroundLogE[i] = MING(backgroundLogE[i] + max_background_increase, oldBandE[i]);
+ /* In case start or end were to change */
+ c=0; do
+ {
+ for (i=0;i<start;i++)
+ {
+ oldBandE[c*nbEBands+i]=0;
+ oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-GCONST(28.f);
+ }
+ for (i=end;i<nbEBands;i++)
+ {
+ oldBandE[c*nbEBands+i]=0;
+ oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-GCONST(28.f);
+ }
+ } while (++c<2);
+ st->rng = dec->rng;
+#ifdef ENABLE_QEXT
+ if (qext_bytes) st->rng = st->rng ^ ext_dec.rng;
+#endif
+
+ deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
+ st->loss_duration = 0;
+ st->plc_duration = 0;
+ st->last_frame_type = FRAME_NORMAL;
+ st->prefilter_and_fold = 0;
+ RESTORE_STACK;
+ if (ec_tell(dec) > 8*len)
+ return OPUS_INTERNAL_ERROR;
+#ifdef ENABLE_QEXT
+ if (qext_bytes != 0 && ec_tell(&ext_dec) > 8*qext_bytes)
+ return OPUS_INTERNAL_ERROR;
+#endif
+ if(ec_get_error(dec))
+ st->error = 1;
+ return frame_size/st->downsample;
+}
+
+int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
+ int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum)
+{
+ return celt_decode_with_ec_dred(st, data, len, pcm, frame_size, dec, accum
+#ifdef ENABLE_DEEP_PLC
+ , NULL
+#endif
+ ARG_QEXT(NULL) ARG_QEXT(0)
+ );
+}
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+
+#if defined(FIXED_POINT) && !defined(ENABLE_RES24)
+int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
+{
+ return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
+}
+#else
+int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
+{
+ int j, ret, C, N;
+ VARDECL(opus_res, out);
+ ALLOC_STACK;
+
+ if (pcm==NULL)
+ return OPUS_BAD_ARG;
+
+ C = st->channels;
+ N = frame_size;
+
+ ALLOC(out, C*N, opus_res);
+ ret = celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
+ if (ret>0)
+ for (j=0;j<C*ret;j++)
+ pcm[j]=RES2INT16(out[j]);
+
+ RESTORE_STACK;
+ return ret;
+}
+#endif
+
+#if defined(FIXED_POINT) && defined(ENABLE_RES24)
+int opus_custom_decode24(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int32 * OPUS_RESTRICT pcm, int frame_size)
+{
+ return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
+}
+#else
+int opus_custom_decode24(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int32 * OPUS_RESTRICT pcm, int frame_size)
+{
+ int j, ret, C, N;
+ VARDECL(opus_res, out);
+ ALLOC_STACK;
+
+ if (pcm==NULL)
+ return OPUS_BAD_ARG;
+
+ C = st->channels;
+ N = frame_size;
+
+ ALLOC(out, C*N, opus_res);
+ ret = celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
+ if (ret>0)
+ for (j=0;j<C*ret;j++)
+ pcm[j]=RES2INT24(out[j]);
+
+ RESTORE_STACK;
+ return ret;
+}
+#endif
+
+
+#ifndef DISABLE_FLOAT_API
+
+# if !defined(FIXED_POINT)
+int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
+{
+ return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
+}
+# else
+int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
+{
+ int j, ret, C, N;
+ VARDECL(opus_res, out);
+ ALLOC_STACK;
+
+ if (pcm==NULL)
+ return OPUS_BAD_ARG;
+
+ C = st->channels;
+ N = frame_size;
+
+ ALLOC(out, C*N, opus_res);
+ ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
+ if (ret>0)
+ for (j=0;j<C*ret;j++)
+ pcm[j]=RES2FLOAT(out[j]);
+
+ RESTORE_STACK;
+ return ret;
+}
+# endif
+
+#endif
+
+#endif /* CUSTOM_MODES */
+
+int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
+{
+ va_list ap;
+
+ va_start(ap, request);
+ switch (request)
+ {
+ case OPUS_SET_COMPLEXITY_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ if(value<0 || value>10)
+ {
+ goto bad_arg;
+ }
+ st->complexity = value;
+ }
+ break;
+ case OPUS_GET_COMPLEXITY_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = st->complexity;
+ }
+ break;
+ case CELT_SET_START_BAND_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ if (value<0 || value>=st->mode->nbEBands)
+ goto bad_arg;
+ st->start = value;
+ }
+ break;
+ case CELT_SET_END_BAND_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ if (value<1 || value>st->mode->nbEBands)
+ goto bad_arg;
+ st->end = value;
+ }
+ break;
+ case CELT_SET_CHANNELS_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ if (value<1 || value>2)
+ goto bad_arg;
+ st->stream_channels = value;
+ }
+ break;
+ case CELT_GET_AND_CLEAR_ERROR_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (value==NULL)
+ goto bad_arg;
+ *value=st->error;
+ st->error = 0;
+ }
+ break;
+ case OPUS_GET_LOOKAHEAD_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (value==NULL)
+ goto bad_arg;
+ *value = st->overlap/st->downsample;
+ }
+ break;
+ case OPUS_RESET_STATE:
+ {
+ int i;
+ celt_glog *oldBandE, *oldLogE, *oldLogE2;
+ int decode_buffer_size;
+#ifdef ENABLE_QEXT
+ int qext_scale = st->qext_scale;
+#endif
+ decode_buffer_size = QEXT_SCALE(DECODE_BUFFER_SIZE);
+ oldBandE = (celt_glog*)(st->_decode_mem+(decode_buffer_size+st->overlap)*st->channels);
+ oldLogE = oldBandE + 2*st->mode->nbEBands;
+ oldLogE2 = oldLogE + 2*st->mode->nbEBands;
+ OPUS_CLEAR((char*)&st->DECODER_RESET_START,
+ opus_custom_decoder_get_size(st->mode, st->channels)-
+ ((char*)&st->DECODER_RESET_START - (char*)st));
+ for (i=0;i<2*st->mode->nbEBands;i++)
+ oldLogE[i]=oldLogE2[i]=-GCONST(28.f);
+ st->skip_plc = 1;
+ st->last_frame_type = FRAME_NONE;
+ }
+ break;
+ case OPUS_GET_PITCH_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (value==NULL)
+ goto bad_arg;
+ *value = st->postfilter_period;
+ }
+ break;
+ case CELT_GET_MODE_REQUEST:
+ {
+ const CELTMode ** value = va_arg(ap, const CELTMode**);
+ if (value==0)
+ goto bad_arg;
+ *value=st->mode;
+ }
+ break;
+ case CELT_SET_SIGNALLING_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ st->signalling = value;
+ }
+ break;
+ case OPUS_GET_FINAL_RANGE_REQUEST:
+ {
+ opus_uint32 * value = va_arg(ap, opus_uint32 *);
+ if (value==0)
+ goto bad_arg;
+ *value=st->rng;
+ }
+ break;
+ case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ if(value<0 || value>1)
+ {
+ goto bad_arg;
+ }
+ st->disable_inv = value;
+ }
+ break;
+ case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = st->disable_inv;
+ }
+ break;
+ default:
+ goto bad_request;
+ }
+ va_end(ap);
+ return OPUS_OK;
+bad_arg:
+ va_end(ap);
+ return OPUS_BAD_ARG;
+bad_request:
+ va_end(ap);
+ return OPUS_UNIMPLEMENTED;
+}
--- /dev/null
+/* Copyright (c) 2009-2010 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "pitch.h"
+
+void _celt_lpc(
+ opus_val16 *_lpc, /* out: [0...p-1] LPC coefficients */
+const opus_val32 *ac, /* in: [0...p] autocorrelation values */
+int p
+)
+{
+ int i, j;
+ opus_val32 r;
+ opus_val32 error = ac[0];
+#ifdef FIXED_POINT
+ opus_val32 lpc[CELT_LPC_ORDER];
+#else
+ float *lpc = _lpc;
+#endif
+
+ OPUS_CLEAR(lpc, p);
+#ifdef FIXED_POINT
+ if (ac[0] != 0)
+#else
+ if (ac[0] > 1e-10f)
+#endif
+ {
+ for (i = 0; i < p; i++) {
+ /* Sum up this iteration's reflection coefficient */
+ opus_val32 rr = 0;
+#if defined (FIXED_POINT) && OPUS_FAST_INT64
+ opus_int64 acc = 0;
+ for (j = 0; j < i; j++)
+ acc += (opus_int64)(lpc[j]) * (opus_int64)(ac[i - j]);
+ rr = (opus_val32)SHR64(acc, 31);
+#else
+ for (j = 0; j < i; j++)
+ rr += MULT32_32_Q31(lpc[j],ac[i - j]);
+#endif
+ rr += SHR32(ac[i + 1],6);
+ r = -frac_div32(SHL32(rr,6), error);
+ /* Update LPC coefficients and total error */
+ lpc[i] = SHR32(r,6);
+ for (j = 0; j < (i+1)>>1; j++)
+ {
+ opus_val32 tmp1, tmp2;
+ tmp1 = lpc[j];
+ tmp2 = lpc[i-1-j];
+ lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2);
+ lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1);
+ }
+
+ error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error);
+ /* Bail out once we get 30 dB gain */
+#ifdef FIXED_POINT
+ if (error<=SHR32(ac[0],10))
+ break;
+#else
+ if (error<=.001f*ac[0])
+ break;
+#endif
+ }
+ }
+#ifdef FIXED_POINT
+ {
+ /* Convert the int32 lpcs to int16 and ensure there are no wrap-arounds.
+ This reuses the logic in silk_LPC_fit() and silk_bwexpander_32(). Any bug
+ fixes should also be applied there. */
+ int iter, idx = 0;
+ opus_val32 maxabs, absval, chirp_Q16, chirp_minus_one_Q16;
+
+ for (iter = 0; iter < 10; iter++) {
+ maxabs = 0;
+ for (i = 0; i < p; i++) {
+ absval = ABS32(lpc[i]);
+ if (absval > maxabs) {
+ maxabs = absval;
+ idx = i;
+ }
+ }
+ maxabs = PSHR32(maxabs, 13); /* Q25->Q12 */
+
+ if (maxabs > 32767) {
+ maxabs = MIN32(maxabs, 163838);
+ chirp_Q16 = QCONST32(0.999, 16) - DIV32(SHL32(maxabs - 32767, 14),
+ SHR32(MULT32_32_32(maxabs, idx + 1), 2));
+ chirp_minus_one_Q16 = chirp_Q16 - 65536;
+
+ /* Apply bandwidth expansion. */
+ for (i = 0; i < p - 1; i++) {
+ lpc[i] = MULT32_32_Q16(chirp_Q16, lpc[i]);
+ chirp_Q16 += PSHR32(MULT32_32_32(chirp_Q16, chirp_minus_one_Q16), 16);
+ }
+ lpc[p - 1] = MULT32_32_Q16(chirp_Q16, lpc[p - 1]);
+ } else {
+ break;
+ }
+ }
+
+ if (iter == 10) {
+ /* If the coeffs still do not fit into the 16 bit range after 10 iterations,
+ fall back to the A(z)=1 filter. */
+ OPUS_CLEAR(lpc, p);
+ _lpc[0] = 4096; /* Q12 */
+ } else {
+ for (i = 0; i < p; i++) {
+ _lpc[i] = EXTRACT16(PSHR32(lpc[i], 13)); /* Q25->Q12 */
+ }
+ }
+ }
+#endif
+}
+
+
+void celt_fir_c(
+ const opus_val16 *x,
+ const opus_val16 *num,
+ opus_val16 *y,
+ int N,
+ int ord,
+ int arch)
+{
+ int i,j;
+ VARDECL(opus_val16, rnum);
+ SAVE_STACK;
+ celt_assert(x != y);
+ ALLOC(rnum, ord, opus_val16);
+ for(i=0;i<ord;i++)
+ rnum[i] = num[ord-i-1];
+ for (i=0;i<N-3;i+=4)
+ {
+ opus_val32 sum[4];
+ sum[0] = SHL32(EXTEND32(x[i ]), SIG_SHIFT);
+ sum[1] = SHL32(EXTEND32(x[i+1]), SIG_SHIFT);
+ sum[2] = SHL32(EXTEND32(x[i+2]), SIG_SHIFT);
+ sum[3] = SHL32(EXTEND32(x[i+3]), SIG_SHIFT);
+#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
+ {
+ opus_val32 sum_c[4];
+ memcpy(sum_c, sum, sizeof(sum_c));
+ xcorr_kernel_c(rnum, x+i-ord, sum_c, ord);
+#endif
+ xcorr_kernel(rnum, x+i-ord, sum, ord, arch);
+#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
+ celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0);
+ }
+#endif
+ y[i ] = SROUND16(sum[0], SIG_SHIFT);
+ y[i+1] = SROUND16(sum[1], SIG_SHIFT);
+ y[i+2] = SROUND16(sum[2], SIG_SHIFT);
+ y[i+3] = SROUND16(sum[3], SIG_SHIFT);
+ }
+ for (;i<N;i++)
+ {
+ opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
+ for (j=0;j<ord;j++)
+ sum = MAC16_16(sum,rnum[j],x[i+j-ord]);
+ y[i] = SROUND16(sum, SIG_SHIFT);
+ }
+ RESTORE_STACK;
+}
+
+void celt_iir(const opus_val32 *_x,
+ const opus_val16 *den,
+ opus_val32 *_y,
+ int N,
+ int ord,
+ opus_val16 *mem,
+ int arch)
+{
+#ifdef SMALL_FOOTPRINT
+ int i,j;
+ (void)arch;
+ for (i=0;i<N;i++)
+ {
+ opus_val32 sum = _x[i];
+ for (j=0;j<ord;j++)
+ {
+ sum -= MULT16_16(den[j],mem[j]);
+ }
+ for (j=ord-1;j>=1;j--)
+ {
+ mem[j]=mem[j-1];
+ }
+ mem[0] = SROUND16(sum, SIG_SHIFT);
+ _y[i] = sum;
+ }
+#else
+ int i,j;
+ VARDECL(opus_val16, rden);
+ VARDECL(opus_val16, y);
+ SAVE_STACK;
+
+ celt_assert((ord&3)==0);
+ ALLOC(rden, ord, opus_val16);
+ ALLOC(y, N+ord, opus_val16);
+ for(i=0;i<ord;i++)
+ rden[i] = den[ord-i-1];
+ for(i=0;i<ord;i++)
+ y[i] = -mem[ord-i-1];
+ for(;i<N+ord;i++)
+ y[i]=0;
+ for (i=0;i<N-3;i+=4)
+ {
+ /* Unroll by 4 as if it were an FIR filter */
+ opus_val32 sum[4];
+ sum[0]=_x[i];
+ sum[1]=_x[i+1];
+ sum[2]=_x[i+2];
+ sum[3]=_x[i+3];
+#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
+ {
+ opus_val32 sum_c[4];
+ memcpy(sum_c, sum, sizeof(sum_c));
+ xcorr_kernel_c(rden, y+i, sum_c, ord);
+#endif
+ xcorr_kernel(rden, y+i, sum, ord, arch);
+#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
+ celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0);
+ }
+#endif
+ /* Patch up the result to compensate for the fact that this is an IIR */
+ y[i+ord ] = -SROUND16(sum[0],SIG_SHIFT);
+ _y[i ] = sum[0];
+ sum[1] = MAC16_16(sum[1], y[i+ord ], den[0]);
+ y[i+ord+1] = -SROUND16(sum[1],SIG_SHIFT);
+ _y[i+1] = sum[1];
+ sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]);
+ sum[2] = MAC16_16(sum[2], y[i+ord ], den[1]);
+ y[i+ord+2] = -SROUND16(sum[2],SIG_SHIFT);
+ _y[i+2] = sum[2];
+
+ sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]);
+ sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]);
+ sum[3] = MAC16_16(sum[3], y[i+ord ], den[2]);
+ y[i+ord+3] = -SROUND16(sum[3],SIG_SHIFT);
+ _y[i+3] = sum[3];
+ }
+ for (;i<N;i++)
+ {
+ opus_val32 sum = _x[i];
+ for (j=0;j<ord;j++)
+ sum -= MULT16_16(rden[j],y[i+j]);
+ y[i+ord] = SROUND16(sum,SIG_SHIFT);
+ _y[i] = sum;
+ }
+ for(i=0;i<ord;i++)
+ mem[i] = _y[N-i-1];
+ RESTORE_STACK;
+#endif
+}
+
+int _celt_autocorr(
+ const opus_val16 *x, /* in: [0...n-1] samples x */
+ opus_val32 *ac, /* out: [0...lag-1] ac values */
+ const celt_coef *window,
+ int overlap,
+ int lag,
+ int n,
+ int arch
+ )
+{
+ opus_val32 d;
+ int i, k;
+ int fastN=n-lag;
+ int shift;
+ const opus_val16 *xptr;
+ VARDECL(opus_val16, xx);
+ SAVE_STACK;
+ ALLOC(xx, n, opus_val16);
+ celt_assert(n>0);
+ celt_assert(overlap>=0);
+ if (overlap == 0)
+ {
+ xptr = x;
+ } else {
+ for (i=0;i<n;i++)
+ xx[i] = x[i];
+ for (i=0;i<overlap;i++)
+ {
+ opus_val16 w = COEF2VAL16(window[i]);
+ xx[i] = MULT16_16_Q15(x[i],w);
+ xx[n-i-1] = MULT16_16_Q15(x[n-i-1],w);
+ }
+ xptr = xx;
+ }
+ shift=0;
+#ifdef FIXED_POINT
+ {
+ opus_val32 ac0;
+ int ac0_shift = celt_ilog2(n + (n>>4));
+ ac0 = 1+(n<<7);
+ if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),ac0_shift);
+ for(i=(n&1);i<n;i+=2)
+ {
+ ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),ac0_shift);
+ ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),ac0_shift);
+ }
+ /* Consider the effect of rounding-to-nearest when scaling the signal. */
+ ac0 += SHR32(ac0,7);
+
+ shift = celt_ilog2(ac0)-30+ac0_shift+1;
+ shift = (shift)/2;
+ if (shift>0)
+ {
+ for(i=0;i<n;i++)
+ xx[i] = PSHR32(xptr[i], shift);
+ xptr = xx;
+ } else
+ shift = 0;
+ }
+#endif
+ celt_pitch_xcorr(xptr, xptr, ac, fastN, lag+1, arch);
+ for (k=0;k<=lag;k++)
+ {
+ for (i = k+fastN, d = 0; i < n; i++)
+ d = MAC16_16(d, xptr[i], xptr[i-k]);
+ ac[k] += d;
+ }
+#ifdef FIXED_POINT
+ shift = 2*shift;
+ if (shift<=0)
+ ac[0] += SHL32((opus_int32)1, -shift);
+ if (ac[0] < 268435456)
+ {
+ int shift2 = 29 - EC_ILOG(ac[0]);
+ for (i=0;i<=lag;i++)
+ ac[i] = SHL32(ac[i], shift2);
+ shift -= shift2;
+ } else if (ac[0] >= 536870912)
+ {
+ int shift2=1;
+ if (ac[0] >= 1073741824)
+ shift2++;
+ for (i=0;i<=lag;i++)
+ ac[i] = SHR32(ac[i], shift2);
+ shift += shift2;
+ }
+#endif
+
+ RESTORE_STACK;
+ return shift;
+}
--- /dev/null
+/* Copyright (c) 2009-2010 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 CELT_LPC_H
+#define CELT_LPC_H
+
+#include "arch.h"
+#include "cpu_support.h"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+#include "x86/celt_lpc_sse.h"
+#endif
+
+#define CELT_LPC_ORDER 24
+
+void _celt_lpc(opus_val16 *_lpc, const opus_val32 *ac, int p);
+
+void celt_fir_c(
+ const opus_val16 *x,
+ const opus_val16 *num,
+ opus_val16 *y,
+ int N,
+ int ord,
+ int arch);
+
+#if !defined(OVERRIDE_CELT_FIR)
+#define celt_fir(x, num, y, N, ord, arch) \
+ (celt_fir_c(x, num, y, N, ord, arch))
+#endif
+
+void celt_iir(const opus_val32 *x,
+ const opus_val16 *den,
+ opus_val32 *y,
+ int N,
+ int ord,
+ opus_val16 *mem,
+ int arch);
+
+int _celt_autocorr(const opus_val16 *x, opus_val32 *ac,
+ const celt_coef *window, int overlap, int lag, int n, int arch);
+
+#endif /* CELT_LPC_H */
--- /dev/null
+/* Copyright (c) 2010 Xiph.Org Foundation
+ * Copyright (c) 2013 Parrot */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 CPU_SUPPORT_H
+#define CPU_SUPPORT_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#if defined(OPUS_HAVE_RTCD) && \
+ (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "arm/armcpu.h"
+
+/* We currently support 5 ARM variants:
+ * arch[0] -> ARMv4
+ * arch[1] -> ARMv5E
+ * arch[2] -> ARMv6
+ * arch[3] -> NEON
+ * arch[4] -> NEON+DOTPROD
+ */
+#define OPUS_ARCHMASK 7
+
+#elif defined(OPUS_HAVE_RTCD) && \
+ ((defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)) || \
+ (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) || \
+ (defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
+ (defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2)))
+
+#include "x86/x86cpu.h"
+/* We currently support 5 x86 variants:
+ * arch[0] -> non-sse
+ * arch[1] -> sse
+ * arch[2] -> sse2
+ * arch[3] -> sse4.1
+ * arch[4] -> avx
+ */
+#define OPUS_ARCHMASK 7
+int opus_select_arch(void);
+
+#else
+#define OPUS_ARCHMASK 0
+
+static OPUS_INLINE int opus_select_arch(void)
+{
+ return 0;
+}
+#endif
+#endif
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Copyright (c) 2007-2009 Timothy B. Terriberry
+ Written by Timothy B. Terriberry and Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "os_support.h"
+#include "cwrs.h"
+#include "mathops.h"
+#include "arch.h"
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_QEXT)
+#define CWRS_EXTRA_ROWS
+#endif
+
+#if defined(CUSTOM_MODES)
+
+/*Guaranteed to return a conservatively large estimate of the binary logarithm
+ with frac bits of fractional precision.
+ Tested for all possible 32-bit inputs with frac=4, where the maximum
+ overestimation is 0.06254243 bits.*/
+int log2_frac(opus_uint32 val, int frac)
+{
+ int l;
+ l=EC_ILOG(val);
+ if(val&(val-1)){
+ /*This is (val>>l-16), but guaranteed to round up, even if adding a bias
+ before the shift would cause overflow (e.g., for 0xFFFFxxxx).
+ Doesn't work for val=0, but that case fails the test above.*/
+ if(l>16)val=((val-1)>>(l-16))+1;
+ else val<<=16-l;
+ l=(l-1)<<frac;
+ /*Note that we always need one iteration, since the rounding up above means
+ that we might need to adjust the integer part of the logarithm.*/
+ do{
+ int b;
+ b=(int)(val>>16);
+ l+=b<<frac;
+ val=(val+b)>>b;
+ val=(val*val+0x7FFF)>>15;
+ }
+ while(frac-->0);
+ /*If val is not exactly 0x8000, then we have to round up the remainder.*/
+ return l+(val>0x8000);
+ }
+ /*Exact powers of two require no rounding.*/
+ else return (l-1)<<frac;
+}
+#endif
+
+/*Although derived separately, the pulse vector coding scheme is equivalent to
+ a Pyramid Vector Quantizer \cite{Fis86}.
+ Some additional notes about an early version appear at
+ https://people.xiph.org/~tterribe/notes/cwrs.html, but the codebook ordering
+ and the definitions of some terms have evolved since that was written.
+
+ The conversion from a pulse vector to an integer index (encoding) and back
+ (decoding) is governed by two related functions, V(N,K) and U(N,K).
+
+ V(N,K) = the number of combinations, with replacement, of N items, taken K
+ at a time, when a sign bit is added to each item taken at least once (i.e.,
+ the number of N-dimensional unit pulse vectors with K pulses).
+ One way to compute this is via
+ V(N,K) = K>0 ? sum(k=1...K,2**k*choose(N,k)*choose(K-1,k-1)) : 1,
+ where choose() is the binomial function.
+ A table of values for N<10 and K<10 looks like:
+ V[10][10] = {
+ {1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {1, 2, 2, 2, 2, 2, 2, 2, 2, 2},
+ {1, 4, 8, 12, 16, 20, 24, 28, 32, 36},
+ {1, 6, 18, 38, 66, 102, 146, 198, 258, 326},
+ {1, 8, 32, 88, 192, 360, 608, 952, 1408, 1992},
+ {1, 10, 50, 170, 450, 1002, 1970, 3530, 5890, 9290},
+ {1, 12, 72, 292, 912, 2364, 5336, 10836, 20256, 35436},
+ {1, 14, 98, 462, 1666, 4942, 12642, 28814, 59906, 115598},
+ {1, 16, 128, 688, 2816, 9424, 27008, 68464, 157184, 332688},
+ {1, 18, 162, 978, 4482, 16722, 53154, 148626, 374274, 864146}
+ };
+
+ U(N,K) = the number of such combinations wherein N-1 objects are taken at
+ most K-1 at a time.
+ This is given by
+ U(N,K) = sum(k=0...K-1,V(N-1,k))
+ = K>0 ? (V(N-1,K-1) + V(N,K-1))/2 : 0.
+ The latter expression also makes clear that U(N,K) is half the number of such
+ combinations wherein the first object is taken at least once.
+ Although it may not be clear from either of these definitions, U(N,K) is the
+ natural function to work with when enumerating the pulse vector codebooks,
+ not V(N,K).
+ U(N,K) is not well-defined for N=0, but with the extension
+ U(0,K) = K>0 ? 0 : 1,
+ the function becomes symmetric: U(N,K) = U(K,N), with a similar table:
+ U[10][10] = {
+ {1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ {0, 1, 3, 5, 7, 9, 11, 13, 15, 17},
+ {0, 1, 5, 13, 25, 41, 61, 85, 113, 145},
+ {0, 1, 7, 25, 63, 129, 231, 377, 575, 833},
+ {0, 1, 9, 41, 129, 321, 681, 1289, 2241, 3649},
+ {0, 1, 11, 61, 231, 681, 1683, 3653, 7183, 13073},
+ {0, 1, 13, 85, 377, 1289, 3653, 8989, 19825, 40081},
+ {0, 1, 15, 113, 575, 2241, 7183, 19825, 48639, 108545},
+ {0, 1, 17, 145, 833, 3649, 13073, 40081, 108545, 265729}
+ };
+
+ With this extension, V(N,K) may be written in terms of U(N,K):
+ V(N,K) = U(N,K) + U(N,K+1)
+ for all N>=0, K>=0.
+ Thus U(N,K+1) represents the number of combinations where the first element
+ is positive or zero, and U(N,K) represents the number of combinations where
+ it is negative.
+ With a large enough table of U(N,K) values, we could write O(N) encoding
+ and O(min(N*log(K),N+K)) decoding routines, but such a table would be
+ prohibitively large for small embedded devices (K may be as large as 32767
+ for small N, and N may be as large as 200).
+
+ Both functions obey the same recurrence relation:
+ V(N,K) = V(N-1,K) + V(N,K-1) + V(N-1,K-1),
+ U(N,K) = U(N-1,K) + U(N,K-1) + U(N-1,K-1),
+ for all N>0, K>0, with different initial conditions at N=0 or K=0.
+ This allows us to construct a row of one of the tables above given the
+ previous row or the next row.
+ Thus we can derive O(NK) encoding and decoding routines with O(K) memory
+ using only addition and subtraction.
+
+ When encoding, we build up from the U(2,K) row and work our way forwards.
+ When decoding, we need to start at the U(N,K) row and work our way backwards,
+ which requires a means of computing U(N,K).
+ U(N,K) may be computed from two previous values with the same N:
+ U(N,K) = ((2*N-1)*U(N,K-1) - U(N,K-2))/(K-1) + U(N,K-2)
+ for all N>1, and since U(N,K) is symmetric, a similar relation holds for two
+ previous values with the same K:
+ U(N,K>1) = ((2*K-1)*U(N-1,K) - U(N-2,K))/(N-1) + U(N-2,K)
+ for all K>1.
+ This allows us to construct an arbitrary row of the U(N,K) table by starting
+ with the first two values, which are constants.
+ This saves roughly 2/3 the work in our O(NK) decoding routine, but costs O(K)
+ multiplications.
+ Similar relations can be derived for V(N,K), but are not used here.
+
+ For N>0 and K>0, U(N,K) and V(N,K) take on the form of an (N-1)-degree
+ polynomial for fixed N.
+ The first few are
+ U(1,K) = 1,
+ U(2,K) = 2*K-1,
+ U(3,K) = (2*K-2)*K+1,
+ U(4,K) = (((4*K-6)*K+8)*K-3)/3,
+ U(5,K) = ((((2*K-4)*K+10)*K-8)*K+3)/3,
+ and
+ V(1,K) = 2,
+ V(2,K) = 4*K,
+ V(3,K) = 4*K*K+2,
+ V(4,K) = 8*(K*K+2)*K/3,
+ V(5,K) = ((4*K*K+20)*K*K+6)/3,
+ for all K>0.
+ This allows us to derive O(N) encoding and O(N*log(K)) decoding routines for
+ small N (and indeed decoding is also O(N) for N<3).
+
+ @ARTICLE{Fis86,
+ author="Thomas R. Fischer",
+ title="A Pyramid Vector Quantizer",
+ journal="IEEE Transactions on Information Theory",
+ volume="IT-32",
+ number=4,
+ pages="568--583",
+ month=Jul,
+ year=1986
+ }*/
+
+#if !defined(SMALL_FOOTPRINT)
+
+/*U(N,K) = U(K,N) := N>0?K>0?U(N-1,K)+U(N,K-1)+U(N-1,K-1):0:K>0?1:0*/
+# define CELT_PVQ_U(_n,_k) (CELT_PVQ_U_ROW[IMIN(_n,_k)][IMAX(_n,_k)])
+/*V(N,K) := U(N,K)+U(N,K+1) = the number of PVQ codewords for a band of size N
+ with K pulses allocated to it.*/
+# define CELT_PVQ_V(_n,_k) (CELT_PVQ_U(_n,_k)+CELT_PVQ_U(_n,(_k)+1))
+
+/*For each V(N,K) supported, we will access element U(min(N,K+1),max(N,K+1)).
+ Thus, the number of entries in row I is the larger of the maximum number of
+ pulses we will ever allocate for a given N=I (K=128, or however many fit in
+ 32 bits, whichever is smaller), plus one, and the maximum N for which
+ K=I-1 pulses fit in 32 bits.
+ The largest band size in an Opus Custom mode is 208.
+ Otherwise, we can limit things to the set of N which can be achieved by
+ splitting a band from a standard Opus mode: 176, 144, 96, 88, 72, 64, 48,
+ 44, 36, 32, 24, 22, 18, 16, 8, 4, 2).*/
+#if defined(CWRS_EXTRA_ROWS)
+static const opus_uint32 CELT_PVQ_U_DATA[1488]={
+#else
+static const opus_uint32 CELT_PVQ_U_DATA[1272]={
+#endif
+ /*N=0, K=0...176:*/
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#if defined(CWRS_EXTRA_ROWS)
+ /*...208:*/
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+#endif
+ /*N=1, K=1...176:*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+#if defined(CWRS_EXTRA_ROWS)
+ /*...208:*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1,
+#endif
+ /*N=2, K=2...176:*/
+ 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41,
+ 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79,
+ 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113,
+ 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143,
+ 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173,
+ 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203,
+ 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233,
+ 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263,
+ 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293,
+ 295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323,
+ 325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351,
+#if defined(CWRS_EXTRA_ROWS)
+ /*...208:*/
+ 353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381,
+ 383, 385, 387, 389, 391, 393, 395, 397, 399, 401, 403, 405, 407, 409, 411,
+ 413, 415,
+#endif
+ /*N=3, K=3...176:*/
+ 13, 25, 41, 61, 85, 113, 145, 181, 221, 265, 313, 365, 421, 481, 545, 613,
+ 685, 761, 841, 925, 1013, 1105, 1201, 1301, 1405, 1513, 1625, 1741, 1861,
+ 1985, 2113, 2245, 2381, 2521, 2665, 2813, 2965, 3121, 3281, 3445, 3613, 3785,
+ 3961, 4141, 4325, 4513, 4705, 4901, 5101, 5305, 5513, 5725, 5941, 6161, 6385,
+ 6613, 6845, 7081, 7321, 7565, 7813, 8065, 8321, 8581, 8845, 9113, 9385, 9661,
+ 9941, 10225, 10513, 10805, 11101, 11401, 11705, 12013, 12325, 12641, 12961,
+ 13285, 13613, 13945, 14281, 14621, 14965, 15313, 15665, 16021, 16381, 16745,
+ 17113, 17485, 17861, 18241, 18625, 19013, 19405, 19801, 20201, 20605, 21013,
+ 21425, 21841, 22261, 22685, 23113, 23545, 23981, 24421, 24865, 25313, 25765,
+ 26221, 26681, 27145, 27613, 28085, 28561, 29041, 29525, 30013, 30505, 31001,
+ 31501, 32005, 32513, 33025, 33541, 34061, 34585, 35113, 35645, 36181, 36721,
+ 37265, 37813, 38365, 38921, 39481, 40045, 40613, 41185, 41761, 42341, 42925,
+ 43513, 44105, 44701, 45301, 45905, 46513, 47125, 47741, 48361, 48985, 49613,
+ 50245, 50881, 51521, 52165, 52813, 53465, 54121, 54781, 55445, 56113, 56785,
+ 57461, 58141, 58825, 59513, 60205, 60901, 61601,
+#if defined(CWRS_EXTRA_ROWS)
+ /*...208:*/
+ 62305, 63013, 63725, 64441, 65161, 65885, 66613, 67345, 68081, 68821, 69565,
+ 70313, 71065, 71821, 72581, 73345, 74113, 74885, 75661, 76441, 77225, 78013,
+ 78805, 79601, 80401, 81205, 82013, 82825, 83641, 84461, 85285, 86113,
+#endif
+ /*N=4, K=4...176:*/
+ 63, 129, 231, 377, 575, 833, 1159, 1561, 2047, 2625, 3303, 4089, 4991, 6017,
+ 7175, 8473, 9919, 11521, 13287, 15225, 17343, 19649, 22151, 24857, 27775,
+ 30913, 34279, 37881, 41727, 45825, 50183, 54809, 59711, 64897, 70375, 76153,
+ 82239, 88641, 95367, 102425, 109823, 117569, 125671, 134137, 142975, 152193,
+ 161799, 171801, 182207, 193025, 204263, 215929, 228031, 240577, 253575,
+ 267033, 280959, 295361, 310247, 325625, 341503, 357889, 374791, 392217,
+ 410175, 428673, 447719, 467321, 487487, 508225, 529543, 551449, 573951,
+ 597057, 620775, 645113, 670079, 695681, 721927, 748825, 776383, 804609,
+ 833511, 863097, 893375, 924353, 956039, 988441, 1021567, 1055425, 1090023,
+ 1125369, 1161471, 1198337, 1235975, 1274393, 1313599, 1353601, 1394407,
+ 1436025, 1478463, 1521729, 1565831, 1610777, 1656575, 1703233, 1750759,
+ 1799161, 1848447, 1898625, 1949703, 2001689, 2054591, 2108417, 2163175,
+ 2218873, 2275519, 2333121, 2391687, 2451225, 2511743, 2573249, 2635751,
+ 2699257, 2763775, 2829313, 2895879, 2963481, 3032127, 3101825, 3172583,
+ 3244409, 3317311, 3391297, 3466375, 3542553, 3619839, 3698241, 3777767,
+ 3858425, 3940223, 4023169, 4107271, 4192537, 4278975, 4366593, 4455399,
+ 4545401, 4636607, 4729025, 4822663, 4917529, 5013631, 5110977, 5209575,
+ 5309433, 5410559, 5512961, 5616647, 5721625, 5827903, 5935489, 6044391,
+ 6154617, 6266175, 6379073, 6493319, 6608921, 6725887, 6844225, 6963943,
+ 7085049, 7207551,
+#if defined(CWRS_EXTRA_ROWS)
+ /*...208:*/
+ 7331457, 7456775, 7583513, 7711679, 7841281, 7972327, 8104825, 8238783,
+ 8374209, 8511111, 8649497, 8789375, 8930753, 9073639, 9218041, 9363967,
+ 9511425, 9660423, 9810969, 9963071, 10116737, 10271975, 10428793, 10587199,
+ 10747201, 10908807, 11072025, 11236863, 11403329, 11571431, 11741177,
+ 11912575,
+#endif
+ /*N=5, K=5...176:*/
+ 321, 681, 1289, 2241, 3649, 5641, 8361, 11969, 16641, 22569, 29961, 39041,
+ 50049, 63241, 78889, 97281, 118721, 143529, 172041, 204609, 241601, 283401,
+ 330409, 383041, 441729, 506921, 579081, 658689, 746241, 842249, 947241,
+ 1061761, 1186369, 1321641, 1468169, 1626561, 1797441, 1981449, 2179241,
+ 2391489, 2618881, 2862121, 3121929, 3399041, 3694209, 4008201, 4341801,
+ 4695809, 5071041, 5468329, 5888521, 6332481, 6801089, 7295241, 7815849,
+ 8363841, 8940161, 9545769, 10181641, 10848769, 11548161, 12280841, 13047849,
+ 13850241, 14689089, 15565481, 16480521, 17435329, 18431041, 19468809,
+ 20549801, 21675201, 22846209, 24064041, 25329929, 26645121, 28010881,
+ 29428489, 30899241, 32424449, 34005441, 35643561, 37340169, 39096641,
+ 40914369, 42794761, 44739241, 46749249, 48826241, 50971689, 53187081,
+ 55473921, 57833729, 60268041, 62778409, 65366401, 68033601, 70781609,
+ 73612041, 76526529, 79526721, 82614281, 85790889, 89058241, 92418049,
+ 95872041, 99421961, 103069569, 106816641, 110664969, 114616361, 118672641,
+ 122835649, 127107241, 131489289, 135983681, 140592321, 145317129, 150160041,
+ 155123009, 160208001, 165417001, 170752009, 176215041, 181808129, 187533321,
+ 193392681, 199388289, 205522241, 211796649, 218213641, 224775361, 231483969,
+ 238341641, 245350569, 252512961, 259831041, 267307049, 274943241, 282741889,
+ 290705281, 298835721, 307135529, 315607041, 324252609, 333074601, 342075401,
+ 351257409, 360623041, 370174729, 379914921, 389846081, 399970689, 410291241,
+ 420810249, 431530241, 442453761, 453583369, 464921641, 476471169, 488234561,
+ 500214441, 512413449, 524834241, 537479489, 550351881, 563454121, 576788929,
+ 590359041, 604167209, 618216201, 632508801,
+#if defined(CWRS_EXTRA_ROWS)
+ /*...208:*/
+ 647047809, 661836041, 676876329, 692171521, 707724481, 723538089, 739615241,
+ 755958849, 772571841, 789457161, 806617769, 824056641, 841776769, 859781161,
+ 878072841, 896654849, 915530241, 934702089, 954173481, 973947521, 994027329,
+ 1014416041, 1035116809, 1056132801, 1077467201, 1099123209, 1121104041,
+ 1143412929, 1166053121, 1189027881, 1212340489, 1235994241,
+#endif
+ /*N=6, K=6...96:*/
+ 1683, 3653, 7183, 13073, 22363, 36365, 56695, 85305, 124515, 177045, 246047,
+ 335137, 448427, 590557, 766727, 982729, 1244979, 1560549, 1937199, 2383409,
+ 2908411, 3522221, 4235671, 5060441, 6009091, 7095093, 8332863, 9737793,
+ 11326283, 13115773, 15124775, 17372905, 19880915, 22670725, 25765455,
+ 29189457, 32968347, 37129037, 41699767, 46710137, 52191139, 58175189,
+ 64696159, 71789409, 79491819, 87841821, 96879431, 106646281, 117185651,
+ 128542501, 140763503, 153897073, 167993403, 183104493, 199284183, 216588185,
+ 235074115, 254801525, 275831935, 298228865, 322057867, 347386557, 374284647,
+ 402823977, 433078547, 465124549, 499040399, 534906769, 572806619, 612825229,
+ 655050231, 699571641, 746481891, 795875861, 847850911, 902506913, 959946283,
+ 1020274013, 1083597703, 1150027593, 1219676595, 1292660325, 1369097135,
+ 1449108145, 1532817275, 1620351277, 1711839767, 1807415257, 1907213187,
+ 2011371957, 2120032959,
+#if defined(CWRS_EXTRA_ROWS)
+ /*...109:*/
+ 2233340609U, 2351442379U, 2474488829U, 2602633639U, 2736033641U, 2874848851U,
+ 3019242501U, 3169381071U, 3325434321U, 3487575323U, 3655980493U, 3830829623U,
+ 4012305913U,
+#endif
+ /*N=7, K=7...54*/
+ 8989, 19825, 40081, 75517, 134245, 227305, 369305, 579125, 880685, 1303777,
+ 1884961, 2668525, 3707509, 5064793, 6814249, 9041957, 11847485, 15345233,
+ 19665841, 24957661, 31388293, 39146185, 48442297, 59511829, 72616013,
+ 88043969, 106114625, 127178701, 151620757, 179861305, 212358985, 249612805,
+ 292164445, 340600625, 395555537, 457713341, 527810725, 606639529, 695049433,
+ 793950709, 904317037, 1027188385, 1163673953, 1314955181, 1482288821,
+ 1667010073, 1870535785, 2094367717,
+#if defined(CWRS_EXTRA_ROWS)
+ /*...60:*/
+ 2340095869U, 2609401873U, 2904062449U, 3225952925U, 3577050821U, 3959439497U,
+#endif
+ /*N=8, K=8...37*/
+ 48639, 108545, 224143, 433905, 795455, 1392065, 2340495, 3800305, 5984767,
+ 9173505, 13726991, 20103025, 28875327, 40754369, 56610575, 77500017,
+ 104692735, 139703809, 184327311, 240673265, 311207743, 398796225, 506750351,
+ 638878193, 799538175, 993696769, 1226990095, 1505789553, 1837271615,
+ 2229491905U,
+#if defined(CWRS_EXTRA_ROWS)
+ /*...40:*/
+ 2691463695U, 3233240945U, 3866006015U,
+#endif
+ /*N=9, K=9...28:*/
+ 265729, 598417, 1256465, 2485825, 4673345, 8405905, 14546705, 24331777,
+ 39490049, 62390545, 96220561, 145198913, 214828609, 312193553, 446304145,
+ 628496897, 872893441, 1196924561, 1621925137, 2173806145U,
+#if defined(CWRS_EXTRA_ROWS)
+ /*...29:*/
+ 2883810113U,
+#endif
+ /*N=10, K=10...24:*/
+ 1462563, 3317445, 7059735, 14218905, 27298155, 50250765, 89129247, 152951073,
+ 254831667, 413442773, 654862247, 1014889769, 1541911931, 2300409629U,
+ 3375210671U,
+ /*N=11, K=11...19:*/
+ 8097453, 18474633, 39753273, 81270333, 158819253, 298199265, 540279585,
+ 948062325, 1616336765,
+#if defined(CWRS_EXTRA_ROWS)
+ /*...20:*/
+ 2684641785U,
+#endif
+ /*N=12, K=12...18:*/
+ 45046719, 103274625, 224298231, 464387817, 921406335, 1759885185,
+ 3248227095U,
+ /*N=13, K=13...16:*/
+ 251595969, 579168825, 1267854873, 2653649025U,
+ /*N=14, K=14:*/
+ 1409933619
+};
+
+#if defined(CWRS_EXTRA_ROWS)
+static const opus_uint32 *const CELT_PVQ_U_ROW[15]={
+ CELT_PVQ_U_DATA+ 0,CELT_PVQ_U_DATA+ 208,CELT_PVQ_U_DATA+ 415,
+ CELT_PVQ_U_DATA+ 621,CELT_PVQ_U_DATA+ 826,CELT_PVQ_U_DATA+1030,
+ CELT_PVQ_U_DATA+1233,CELT_PVQ_U_DATA+1336,CELT_PVQ_U_DATA+1389,
+ CELT_PVQ_U_DATA+1421,CELT_PVQ_U_DATA+1441,CELT_PVQ_U_DATA+1455,
+ CELT_PVQ_U_DATA+1464,CELT_PVQ_U_DATA+1470,CELT_PVQ_U_DATA+1473
+};
+#else
+static const opus_uint32 *const CELT_PVQ_U_ROW[15]={
+ CELT_PVQ_U_DATA+ 0,CELT_PVQ_U_DATA+ 176,CELT_PVQ_U_DATA+ 351,
+ CELT_PVQ_U_DATA+ 525,CELT_PVQ_U_DATA+ 698,CELT_PVQ_U_DATA+ 870,
+ CELT_PVQ_U_DATA+1041,CELT_PVQ_U_DATA+1131,CELT_PVQ_U_DATA+1178,
+ CELT_PVQ_U_DATA+1207,CELT_PVQ_U_DATA+1226,CELT_PVQ_U_DATA+1240,
+ CELT_PVQ_U_DATA+1248,CELT_PVQ_U_DATA+1254,CELT_PVQ_U_DATA+1257
+};
+#endif
+
+#if defined(CUSTOM_MODES)
+void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){
+ int k;
+ /*_maxk==0 => there's nothing to do.*/
+ celt_assert(_maxk>0);
+ _bits[0]=0;
+ for(k=1;k<=_maxk;k++)_bits[k]=log2_frac(CELT_PVQ_V(_n,k),_frac);
+}
+#endif
+
+static opus_uint32 icwrs(int _n,const int *_y){
+ opus_uint32 i;
+ int j;
+ int k;
+ celt_assert(_n>=2);
+ j=_n-1;
+ i=_y[j]<0;
+ k=abs(_y[j]);
+ do{
+ j--;
+ i+=CELT_PVQ_U(_n-j,k);
+ k+=abs(_y[j]);
+ if(_y[j]<0)i+=CELT_PVQ_U(_n-j,k+1);
+ }
+ while(j>0);
+ return i;
+}
+
+void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){
+ celt_assert(_k>0);
+ ec_enc_uint(_enc,icwrs(_n,_y),CELT_PVQ_V(_n,_k));
+}
+
+static opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y){
+ opus_uint32 p;
+ int s;
+ int k0;
+ opus_int16 val;
+ opus_val32 yy=0;
+ celt_assert(_k>0);
+ celt_assert(_n>1);
+ while(_n>2){
+ opus_uint32 q;
+ /*Lots of pulses case:*/
+ if(_k>=_n){
+ const opus_uint32 *row;
+ row=CELT_PVQ_U_ROW[_n];
+ /*Are the pulses in this dimension negative?*/
+ p=row[_k+1];
+ s=-(_i>=p);
+ _i-=p&s;
+ /*Count how many pulses were placed in this dimension.*/
+ k0=_k;
+ q=row[_n];
+ if(q>_i){
+ celt_sig_assert(p>q);
+ _k=_n;
+ do p=CELT_PVQ_U_ROW[--_k][_n];
+ while(p>_i);
+ }
+ else for(p=row[_k];p>_i;p=row[_k])_k--;
+ _i-=p;
+ val=(k0-_k+s)^s;
+ *_y++=val;
+ yy=MAC16_16(yy,val,val);
+ }
+ /*Lots of dimensions case:*/
+ else{
+ /*Are there any pulses in this dimension at all?*/
+ p=CELT_PVQ_U_ROW[_k][_n];
+ q=CELT_PVQ_U_ROW[_k+1][_n];
+ if(p<=_i&&_i<q){
+ _i-=p;
+ *_y++=0;
+ }
+ else{
+ /*Are the pulses in this dimension negative?*/
+ s=-(_i>=q);
+ _i-=q&s;
+ /*Count how many pulses were placed in this dimension.*/
+ k0=_k;
+ do p=CELT_PVQ_U_ROW[--_k][_n];
+ while(p>_i);
+ _i-=p;
+ val=(k0-_k+s)^s;
+ *_y++=val;
+ yy=MAC16_16(yy,val,val);
+ }
+ }
+ _n--;
+ }
+ /*_n==2*/
+ p=2*_k+1;
+ s=-(_i>=p);
+ _i-=p&s;
+ k0=_k;
+ _k=(_i+1)>>1;
+ if(_k)_i-=2*_k-1;
+ val=(k0-_k+s)^s;
+ *_y++=val;
+ yy=MAC16_16(yy,val,val);
+ /*_n==1*/
+ s=-(int)_i;
+ val=(_k+s)^s;
+ *_y=val;
+ yy=MAC16_16(yy,val,val);
+ return yy;
+}
+
+opus_val32 decode_pulses(int *_y,int _n,int _k,ec_dec *_dec){
+ return cwrsi(_n,_k,ec_dec_uint(_dec,CELT_PVQ_V(_n,_k)),_y);
+}
+
+#else /* SMALL_FOOTPRINT */
+
+/*Computes the next row/column of any recurrence that obeys the relation
+ u[i][j]=u[i-1][j]+u[i][j-1]+u[i-1][j-1].
+ _ui0 is the base case for the new row/column.*/
+static OPUS_INLINE void unext(opus_uint32 *_ui,unsigned _len,opus_uint32 _ui0){
+ opus_uint32 ui1;
+ unsigned j;
+ /*This do-while will overrun the array if we don't have storage for at least
+ 2 values.*/
+ j=1; do {
+ ui1=UADD32(UADD32(_ui[j],_ui[j-1]),_ui0);
+ _ui[j-1]=_ui0;
+ _ui0=ui1;
+ } while (++j<_len);
+ _ui[j-1]=_ui0;
+}
+
+/*Computes the previous row/column of any recurrence that obeys the relation
+ u[i-1][j]=u[i][j]-u[i][j-1]-u[i-1][j-1].
+ _ui0 is the base case for the new row/column.*/
+static OPUS_INLINE void uprev(opus_uint32 *_ui,unsigned _n,opus_uint32 _ui0){
+ opus_uint32 ui1;
+ unsigned j;
+ /*This do-while will overrun the array if we don't have storage for at least
+ 2 values.*/
+ j=1; do {
+ ui1=USUB32(USUB32(_ui[j],_ui[j-1]),_ui0);
+ _ui[j-1]=_ui0;
+ _ui0=ui1;
+ } while (++j<_n);
+ _ui[j-1]=_ui0;
+}
+
+/*Compute V(_n,_k), as well as U(_n,0..._k+1).
+ _u: On exit, _u[i] contains U(_n,i) for i in [0..._k+1].*/
+static opus_uint32 ncwrs_urow(unsigned _n,unsigned _k,opus_uint32 *_u){
+ opus_uint32 um2;
+ unsigned len;
+ unsigned k;
+ len=_k+2;
+ /*We require storage at least 3 values (e.g., _k>0).*/
+ celt_assert(len>=3);
+ _u[0]=0;
+ _u[1]=um2=1;
+ /*If _n==0, _u[0] should be 1 and the rest should be 0.*/
+ /*If _n==1, _u[i] should be 1 for i>1.*/
+ celt_assert(_n>=2);
+ /*If _k==0, the following do-while loop will overflow the buffer.*/
+ celt_assert(_k>0);
+ k=2;
+ do _u[k]=(k<<1)-1;
+ while(++k<len);
+ for(k=2;k<_n;k++)unext(_u+1,_k+1,1);
+ return _u[_k]+_u[_k+1];
+}
+
+/*Returns the _i'th combination of _k elements chosen from a set of size _n
+ with associated sign bits.
+ _y: Returns the vector of pulses.
+ _u: Must contain entries [0..._k+1] of row _n of U() on input.
+ Its contents will be destructively modified.*/
+static opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y,opus_uint32 *_u){
+ int j;
+ opus_int16 val;
+ opus_val32 yy=0;
+ celt_assert(_n>0);
+ j=0;
+ do{
+ opus_uint32 p;
+ int s;
+ int yj;
+ p=_u[_k+1];
+ s=-(_i>=p);
+ _i-=p&s;
+ yj=_k;
+ p=_u[_k];
+ while(p>_i)p=_u[--_k];
+ _i-=p;
+ yj-=_k;
+ val=(yj+s)^s;
+ _y[j]=val;
+ yy=MAC16_16(yy,val,val);
+ uprev(_u,_k+2,0);
+ }
+ while(++j<_n);
+ return yy;
+}
+
+/*Returns the index of the given combination of K elements chosen from a set
+ of size 1 with associated sign bits.
+ _y: The vector of pulses, whose sum of absolute values is K.
+ _k: Returns K.*/
+static OPUS_INLINE opus_uint32 icwrs1(const int *_y,int *_k){
+ *_k=abs(_y[0]);
+ return _y[0]<0;
+}
+
+/*Returns the index of the given combination of K elements chosen from a set
+ of size _n with associated sign bits.
+ _y: The vector of pulses, whose sum of absolute values must be _k.
+ _nc: Returns V(_n,_k).*/
+static OPUS_INLINE opus_uint32 icwrs(int _n,int _k,opus_uint32 *_nc,const int *_y,
+ opus_uint32 *_u){
+ opus_uint32 i;
+ int j;
+ int k;
+ /*We can't unroll the first two iterations of the loop unless _n>=2.*/
+ celt_assert(_n>=2);
+ _u[0]=0;
+ for(k=1;k<=_k+1;k++)_u[k]=(k<<1)-1;
+ i=icwrs1(_y+_n-1,&k);
+ j=_n-2;
+ i+=_u[k];
+ k+=abs(_y[j]);
+ if(_y[j]<0)i+=_u[k+1];
+ while(j-->0){
+ unext(_u,_k+2,0);
+ i+=_u[k];
+ k+=abs(_y[j]);
+ if(_y[j]<0)i+=_u[k+1];
+ }
+ *_nc=_u[k]+_u[k+1];
+ return i;
+}
+
+#if defined(CUSTOM_MODES)
+void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){
+ int k;
+ /*_maxk==0 => there's nothing to do.*/
+ celt_assert(_maxk>0);
+ _bits[0]=0;
+ if (_n==1)
+ {
+ for (k=1;k<=_maxk;k++)
+ _bits[k] = 1<<_frac;
+ }
+ else {
+ VARDECL(opus_uint32,u);
+ SAVE_STACK;
+ ALLOC(u,_maxk+2U,opus_uint32);
+ ncwrs_urow(_n,_maxk,u);
+ for(k=1;k<=_maxk;k++)
+ _bits[k]=log2_frac(u[k]+u[k+1],_frac);
+ RESTORE_STACK;
+ }
+}
+#endif /* CUSTOM_MODES */
+
+void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){
+ opus_uint32 i;
+ VARDECL(opus_uint32,u);
+ opus_uint32 nc;
+ SAVE_STACK;
+ celt_assert(_k>0);
+ ALLOC(u,_k+2U,opus_uint32);
+ i=icwrs(_n,_k,&nc,_y,u);
+ ec_enc_uint(_enc,i,nc);
+ RESTORE_STACK;
+}
+
+opus_val32 decode_pulses(int *_y,int _n,int _k,ec_dec *_dec){
+ VARDECL(opus_uint32,u);
+ int ret;
+ SAVE_STACK;
+ celt_assert(_k>0);
+ ALLOC(u,_k+2U,opus_uint32);
+ ret = cwrsi(_n,_k,ec_dec_uint(_dec,ncwrs_urow(_n,_k,u)),_y,u);
+ RESTORE_STACK;
+ return ret;
+}
+
+#endif /* SMALL_FOOTPRINT */
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Copyright (c) 2007-2009 Timothy B. Terriberry
+ Written by Timothy B. Terriberry and Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 CWRS_H
+#define CWRS_H
+
+#include "arch.h"
+#include "stack_alloc.h"
+#include "entenc.h"
+#include "entdec.h"
+
+#ifdef CUSTOM_MODES
+int log2_frac(opus_uint32 val, int frac);
+#endif
+
+void get_required_bits(opus_int16 *bits, int N, int K, int frac);
+
+void encode_pulses(const int *_y, int N, int K, ec_enc *enc);
+
+opus_val32 decode_pulses(int *_y, int N, int K, ec_dec *dec);
+
+#endif /* CWRS_H */
--- /dev/null
+/* Copyright (c) 2003-2008 Timothy B. Terriberry
+ Copyright (c) 2008 Xiph.Org Foundation */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+/*Some common macros for potential platform-specific optimization.*/
+#include "opus_types.h"
+#include <math.h>
+#include <limits.h>
+#include "arch.h"
+#if !defined(_ecintrin_H)
+# define _ecintrin_H (1)
+
+/*Some specific platforms may have optimized intrinsic or OPUS_INLINE assembly
+ versions of these functions which can substantially improve performance.
+ We define macros for them to allow easy incorporation of these non-ANSI
+ features.*/
+
+/*Modern gcc (4.x) can compile the naive versions of min and max with cmov if
+ given an appropriate architecture, but the branchless bit-twiddling versions
+ are just as fast, and do not require any special target architecture.
+ Earlier gcc versions (3.x) compiled both code to the same assembly
+ instructions, because of the way they represented ((_b)>(_a)) internally.*/
+# define EC_MINI(_a,_b) ((_a)+(((_b)-(_a))&-((_b)<(_a))))
+
+/*Count leading zeros.
+ This macro should only be used for implementing ec_ilog(), if it is defined.
+ All other code should use EC_ILOG() instead.*/
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#if defined(_MSC_VER) && (_MSC_VER >= 1910)
+# include <intrin0.h> /* Improve compiler throughput. */
+#else
+# include <intrin.h>
+#endif
+/*In _DEBUG mode this is not an intrinsic by default.*/
+# pragma intrinsic(_BitScanReverse)
+
+static __inline int ec_bsr(unsigned long _x){
+ unsigned long ret;
+ _BitScanReverse(&ret,_x);
+ return (int)ret;
+}
+# define EC_CLZ0 (1)
+# define EC_CLZ(_x) (-ec_bsr(_x))
+#elif defined(ENABLE_TI_DSPLIB)
+# include "dsplib.h"
+# define EC_CLZ0 (31)
+# define EC_CLZ(_x) (_lnorm(_x))
+#elif __GNUC_PREREQ(3,4)
+# if INT_MAX>=2147483647
+# define EC_CLZ0 ((int)sizeof(unsigned)*CHAR_BIT)
+# define EC_CLZ(_x) (__builtin_clz(_x))
+# elif LONG_MAX>=2147483647L
+# define EC_CLZ0 ((int)sizeof(unsigned long)*CHAR_BIT)
+# define EC_CLZ(_x) (__builtin_clzl(_x))
+# endif
+#endif
+
+#if defined(EC_CLZ)
+/*Note that __builtin_clz is not defined when _x==0, according to the gcc
+ documentation (and that of the BSR instruction that implements it on x86).
+ The majority of the time we can never pass it zero.
+ When we need to, it can be special cased.*/
+# define EC_ILOG(_x) (EC_CLZ0-EC_CLZ(_x))
+#else
+int ec_ilog(opus_uint32 _v);
+# define EC_ILOG(_x) (ec_ilog(_x))
+#endif
+#endif
--- /dev/null
+/* Copyright (c) 2001-2011 Timothy B. Terriberry
+*/
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "entcode.h"
+#include "arch.h"
+
+#if !defined(EC_CLZ)
+/*This is a fallback for systems where we don't know how to access
+ a BSR or CLZ instruction (see ecintrin.h).
+ If you are optimizing Opus on a new platform and it has a native CLZ or
+ BZR (e.g. cell, MIPS, x86, etc) then making it available to Opus will be
+ an easy performance win.*/
+int ec_ilog(opus_uint32 _v){
+ /*On a Pentium M, this branchless version tested as the fastest on
+ 1,000,000,000 random 32-bit integers, edging out a similar version with
+ branches, and a 256-entry LUT version.*/
+ int ret;
+ int m;
+ ret=!!_v;
+ m=!!(_v&0xFFFF0000)<<4;
+ _v>>=m;
+ ret|=m;
+ m=!!(_v&0xFF00)<<3;
+ _v>>=m;
+ ret|=m;
+ m=!!(_v&0xF0)<<2;
+ _v>>=m;
+ ret|=m;
+ m=!!(_v&0xC)<<1;
+ _v>>=m;
+ ret|=m;
+ ret+=!!(_v&0x2);
+ return ret;
+}
+#endif
+
+#if 1
+/* This is a faster version of ec_tell_frac() that takes advantage
+ of the low (1/8 bit) resolution to use just a linear function
+ followed by a lookup to determine the exact transition thresholds. */
+opus_uint32 ec_tell_frac(ec_ctx *_this){
+ static const unsigned correction[8] =
+ {35733, 38967, 42495, 46340,
+ 50535, 55109, 60097, 65535};
+ opus_uint32 nbits;
+ opus_uint32 r;
+ int l;
+ unsigned b;
+ nbits=_this->nbits_total<<BITRES;
+ l=EC_ILOG(_this->rng);
+ r=_this->rng>>(l-16);
+ b = (r>>12)-8;
+ b += r>correction[b];
+ l = (l<<3)+b;
+ return nbits-l;
+}
+#else
+opus_uint32 ec_tell_frac(ec_ctx *_this){
+ opus_uint32 nbits;
+ opus_uint32 r;
+ int l;
+ int i;
+ /*To handle the non-integral number of bits still left in the encoder/decoder
+ state, we compute the worst-case number of bits of val that must be
+ encoded to ensure that the value is inside the range for any possible
+ subsequent bits.
+ The computation here is independent of val itself (the decoder does not
+ even track that value), even though the real number of bits used after
+ ec_enc_done() may be 1 smaller if rng is a power of two and the
+ corresponding trailing bits of val are all zeros.
+ If we did try to track that special case, then coding a value with a
+ probability of 1/(1<<n) might sometimes appear to use more than n bits.
+ This may help explain the surprising result that a newly initialized
+ encoder or decoder claims to have used 1 bit.*/
+ nbits=_this->nbits_total<<BITRES;
+ l=EC_ILOG(_this->rng);
+ r=_this->rng>>(l-16);
+ for(i=BITRES;i-->0;){
+ int b;
+ r=r*r>>15;
+ b=(int)(r>>16);
+ l=l<<1|b;
+ r>>=b;
+ }
+ return nbits-l;
+}
+#endif
+
+#ifdef USE_SMALL_DIV_TABLE
+/* Result of 2^32/(2*i+1), except for i=0. */
+const opus_uint32 SMALL_DIV_TABLE[129] = {
+ 0xFFFFFFFF, 0x55555555, 0x33333333, 0x24924924,
+ 0x1C71C71C, 0x1745D174, 0x13B13B13, 0x11111111,
+ 0x0F0F0F0F, 0x0D79435E, 0x0C30C30C, 0x0B21642C,
+ 0x0A3D70A3, 0x097B425E, 0x08D3DCB0, 0x08421084,
+ 0x07C1F07C, 0x07507507, 0x06EB3E45, 0x06906906,
+ 0x063E7063, 0x05F417D0, 0x05B05B05, 0x0572620A,
+ 0x05397829, 0x05050505, 0x04D4873E, 0x04A7904A,
+ 0x047DC11F, 0x0456C797, 0x04325C53, 0x04104104,
+ 0x03F03F03, 0x03D22635, 0x03B5CC0E, 0x039B0AD1,
+ 0x0381C0E0, 0x0369D036, 0x03531DEC, 0x033D91D2,
+ 0x0329161F, 0x03159721, 0x03030303, 0x02F14990,
+ 0x02E05C0B, 0x02D02D02, 0x02C0B02C, 0x02B1DA46,
+ 0x02A3A0FD, 0x0295FAD4, 0x0288DF0C, 0x027C4597,
+ 0x02702702, 0x02647C69, 0x02593F69, 0x024E6A17,
+ 0x0243F6F0, 0x0239E0D5, 0x02302302, 0x0226B902,
+ 0x021D9EAD, 0x0214D021, 0x020C49BA, 0x02040810,
+ 0x01FC07F0, 0x01F44659, 0x01ECC07B, 0x01E573AC,
+ 0x01DE5D6E, 0x01D77B65, 0x01D0CB58, 0x01CA4B30,
+ 0x01C3F8F0, 0x01BDD2B8, 0x01B7D6C3, 0x01B20364,
+ 0x01AC5701, 0x01A6D01A, 0x01A16D3F, 0x019C2D14,
+ 0x01970E4F, 0x01920FB4, 0x018D3018, 0x01886E5F,
+ 0x0183C977, 0x017F405F, 0x017AD220, 0x01767DCE,
+ 0x01724287, 0x016E1F76, 0x016A13CD, 0x01661EC6,
+ 0x01623FA7, 0x015E75BB, 0x015AC056, 0x01571ED3,
+ 0x01539094, 0x01501501, 0x014CAB88, 0x0149539E,
+ 0x01460CBC, 0x0142D662, 0x013FB013, 0x013C995A,
+ 0x013991C2, 0x013698DF, 0x0133AE45, 0x0130D190,
+ 0x012E025C, 0x012B404A, 0x01288B01, 0x0125E227,
+ 0x01234567, 0x0120B470, 0x011E2EF3, 0x011BB4A4,
+ 0x01194538, 0x0116E068, 0x011485F0, 0x0112358E,
+ 0x010FEF01, 0x010DB20A, 0x010B7E6E, 0x010953F3,
+ 0x01073260, 0x0105197F, 0x0103091B, 0x01010101
+};
+#endif
--- /dev/null
+/* Copyright (c) 2001-2011 Timothy B. Terriberry
+ Copyright (c) 2008-2009 Xiph.Org Foundation */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#if !defined(_entcode_H)
+# define _entcode_H (1)
+# include <limits.h>
+# include <stddef.h>
+# include "ecintrin.h"
+
+extern const opus_uint32 SMALL_DIV_TABLE[129];
+
+#ifdef OPUS_ARM_ASM
+#define USE_SMALL_DIV_TABLE
+#endif
+
+/*OPT: ec_window must be at least 32 bits, but if you have fast arithmetic on a
+ larger type, you can speed up the decoder by using it here.*/
+typedef opus_uint32 ec_window;
+typedef struct ec_ctx ec_ctx;
+typedef struct ec_ctx ec_enc;
+typedef struct ec_ctx ec_dec;
+
+# define EC_WINDOW_SIZE ((int)sizeof(ec_window)*CHAR_BIT)
+
+/*The number of bits to use for the range-coded part of unsigned integers.*/
+# define EC_UINT_BITS (8)
+
+/*The resolution of fractional-precision bit usage measurements, i.e.,
+ 3 => 1/8th bits.*/
+# define BITRES 3
+
+/*The entropy encoder/decoder context.
+ We use the same structure for both, so that common functions like ec_tell()
+ can be used on either one.*/
+struct ec_ctx{
+ /*Buffered input/output.*/
+ unsigned char *buf;
+ /*The size of the buffer.*/
+ opus_uint32 storage;
+ /*The offset at which the last byte containing raw bits was read/written.*/
+ opus_uint32 end_offs;
+ /*Bits that will be read from/written at the end.*/
+ ec_window end_window;
+ /*Number of valid bits in end_window.*/
+ int nend_bits;
+ /*The total number of whole bits read/written.
+ This does not include partial bits currently in the range coder.*/
+ int nbits_total;
+ /*The offset at which the next range coder byte will be read/written.*/
+ opus_uint32 offs;
+ /*The number of values in the current range.*/
+ opus_uint32 rng;
+ /*In the decoder: the difference between the top of the current range and
+ the input value, minus one.
+ In the encoder: the low end of the current range.*/
+ opus_uint32 val;
+ /*In the decoder: the saved normalization factor from ec_decode().
+ In the encoder: the number of outstanding carry propagating symbols.*/
+ opus_uint32 ext;
+ /*A buffered input/output symbol, awaiting carry propagation.*/
+ int rem;
+ /*Nonzero if an error occurred.*/
+ int error;
+};
+
+static OPUS_INLINE opus_uint32 ec_range_bytes(ec_ctx *_this){
+ return _this->offs;
+}
+
+static OPUS_INLINE unsigned char *ec_get_buffer(ec_ctx *_this){
+ return _this->buf;
+}
+
+static OPUS_INLINE int ec_get_error(ec_ctx *_this){
+ return _this->error;
+}
+
+/*Returns the number of bits "used" by the encoded or decoded symbols so far.
+ This same number can be computed in either the encoder or the decoder, and is
+ suitable for making coding decisions.
+ Return: The number of bits.
+ This will always be slightly larger than the exact value (e.g., all
+ rounding error is in the positive direction).*/
+static OPUS_INLINE int ec_tell(ec_ctx *_this){
+ return _this->nbits_total-EC_ILOG(_this->rng);
+}
+
+/*Returns the number of bits "used" by the encoded or decoded symbols so far.
+ This same number can be computed in either the encoder or the decoder, and is
+ suitable for making coding decisions.
+ Return: The number of bits scaled by 2**BITRES.
+ This will always be slightly larger than the exact value (e.g., all
+ rounding error is in the positive direction).*/
+opus_uint32 ec_tell_frac(ec_ctx *_this);
+
+/* Tested exhaustively for all n and for 1<=d<=256 */
+static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) {
+ celt_sig_assert(d>0);
+#ifdef USE_SMALL_DIV_TABLE
+ if (d>256)
+ return n/d;
+ else {
+ opus_uint32 t, q;
+ t = EC_ILOG(d&-d);
+ q = (opus_uint64)SMALL_DIV_TABLE[d>>t]*(n>>(t-1))>>32;
+ return q+(n-q*d >= d);
+ }
+#else
+ return n/d;
+#endif
+}
+
+static OPUS_INLINE opus_int32 celt_sudiv(opus_int32 n, opus_int32 d) {
+ celt_sig_assert(d>0);
+#ifdef USE_SMALL_DIV_TABLE
+ if (n<0)
+ return -(opus_int32)celt_udiv(-n, d);
+ else
+ return celt_udiv(n, d);
+#else
+ return n/d;
+#endif
+}
+
+#endif
--- /dev/null
+/* Copyright (c) 2001-2011 Timothy B. Terriberry
+ Copyright (c) 2008-2009 Xiph.Org Foundation */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stddef.h>
+#include "os_support.h"
+#include "arch.h"
+#include "entdec.h"
+#include "mfrngcod.h"
+
+/*A range decoder.
+ This is an entropy decoder based upon \cite{Mar79}, which is itself a
+ rediscovery of the FIFO arithmetic code introduced by \cite{Pas76}.
+ It is very similar to arithmetic encoding, except that encoding is done with
+ digits in any base, instead of with bits, and so it is faster when using
+ larger bases (i.e.: a byte).
+ The author claims an average waste of $\frac{1}{2}\log_b(2b)$ bits, where $b$
+ is the base, longer than the theoretical optimum, but to my knowledge there
+ is no published justification for this claim.
+ This only seems true when using near-infinite precision arithmetic so that
+ the process is carried out with no rounding errors.
+
+ An excellent description of implementation details is available at
+ http://www.arturocampos.com/ac_range.html
+ A recent work \cite{MNW98} which proposes several changes to arithmetic
+ encoding for efficiency actually re-discovers many of the principles
+ behind range encoding, and presents a good theoretical analysis of them.
+
+ End of stream is handled by writing out the smallest number of bits that
+ ensures that the stream will be correctly decoded regardless of the value of
+ any subsequent bits.
+ ec_tell() can be used to determine how many bits were needed to decode
+ all the symbols thus far; other data can be packed in the remaining bits of
+ the input buffer.
+ @PHDTHESIS{Pas76,
+ author="Richard Clark Pasco",
+ title="Source coding algorithms for fast data compression",
+ school="Dept. of Electrical Engineering, Stanford University",
+ address="Stanford, CA",
+ month=May,
+ year=1976
+ }
+ @INPROCEEDINGS{Mar79,
+ author="Martin, G.N.N.",
+ title="Range encoding: an algorithm for removing redundancy from a digitised
+ message",
+ booktitle="Video & Data Recording Conference",
+ year=1979,
+ address="Southampton",
+ month=Jul
+ }
+ @ARTICLE{MNW98,
+ author="Alistair Moffat and Radford Neal and Ian H. Witten",
+ title="Arithmetic Coding Revisited",
+ journal="{ACM} Transactions on Information Systems",
+ year=1998,
+ volume=16,
+ number=3,
+ pages="256--294",
+ month=Jul,
+ URL="http://www.stanford.edu/class/ee398a/handouts/papers/Moffat98ArithmCoding.pdf"
+ }*/
+
+static int ec_read_byte(ec_dec *_this){
+ return _this->offs<_this->storage?_this->buf[_this->offs++]:0;
+}
+
+static int ec_read_byte_from_end(ec_dec *_this){
+ return _this->end_offs<_this->storage?
+ _this->buf[_this->storage-++(_this->end_offs)]:0;
+}
+
+/*Normalizes the contents of val and rng so that rng lies entirely in the
+ high-order symbol.*/
+static void ec_dec_normalize(ec_dec *_this){
+ /*If the range is too small, rescale it and input some bits.*/
+ while(_this->rng<=EC_CODE_BOT){
+ int sym;
+ _this->nbits_total+=EC_SYM_BITS;
+ _this->rng<<=EC_SYM_BITS;
+ /*Use up the remaining bits from our last symbol.*/
+ sym=_this->rem;
+ /*Read the next value from the input.*/
+ _this->rem=ec_read_byte(_this);
+ /*Take the rest of the bits we need from this new symbol.*/
+ sym=(sym<<EC_SYM_BITS|_this->rem)>>(EC_SYM_BITS-EC_CODE_EXTRA);
+ /*And subtract them from val, capped to be less than EC_CODE_TOP.*/
+ _this->val=((_this->val<<EC_SYM_BITS)+(EC_SYM_MAX&~sym))&(EC_CODE_TOP-1);
+ }
+}
+
+void ec_dec_init(ec_dec *_this,unsigned char *_buf,opus_uint32 _storage){
+ _this->buf=_buf;
+ _this->storage=_storage;
+ _this->end_offs=0;
+ _this->end_window=0;
+ _this->nend_bits=0;
+ /*This is the offset from which ec_tell() will subtract partial bits.
+ The final value after the ec_dec_normalize() call will be the same as in
+ the encoder, but we have to compensate for the bits that are added there.*/
+ _this->nbits_total=EC_CODE_BITS+1
+ -((EC_CODE_BITS-EC_CODE_EXTRA)/EC_SYM_BITS)*EC_SYM_BITS;
+ _this->offs=0;
+ _this->rng=1U<<EC_CODE_EXTRA;
+ _this->rem=ec_read_byte(_this);
+ _this->val=_this->rng-1-(_this->rem>>(EC_SYM_BITS-EC_CODE_EXTRA));
+ _this->error=0;
+ /*Normalize the interval.*/
+ ec_dec_normalize(_this);
+}
+
+unsigned ec_decode(ec_dec *_this,unsigned _ft){
+ unsigned s;
+ _this->ext=celt_udiv(_this->rng,_ft);
+ s=(unsigned)(_this->val/_this->ext);
+ return _ft-EC_MINI(s+1,_ft);
+}
+
+unsigned ec_decode_bin(ec_dec *_this,unsigned _bits){
+ unsigned s;
+ _this->ext=_this->rng>>_bits;
+ s=(unsigned)(_this->val/_this->ext);
+ return (1U<<_bits)-EC_MINI(s+1U,1U<<_bits);
+}
+
+void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft){
+ opus_uint32 s;
+ s=IMUL32(_this->ext,_ft-_fh);
+ _this->val-=s;
+ _this->rng=_fl>0?IMUL32(_this->ext,_fh-_fl):_this->rng-s;
+ ec_dec_normalize(_this);
+}
+
+/*The probability of having a "one" is 1/(1<<_logp).*/
+int ec_dec_bit_logp(ec_dec *_this,unsigned _logp){
+ opus_uint32 r;
+ opus_uint32 d;
+ opus_uint32 s;
+ int ret;
+ r=_this->rng;
+ d=_this->val;
+ s=r>>_logp;
+ ret=d<s;
+ if(!ret)_this->val=d-s;
+ _this->rng=ret?s:r-s;
+ ec_dec_normalize(_this);
+ return ret;
+}
+
+int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb){
+ opus_uint32 r;
+ opus_uint32 d;
+ opus_uint32 s;
+ opus_uint32 t;
+ int ret;
+ s=_this->rng;
+ d=_this->val;
+ r=s>>_ftb;
+ ret=-1;
+ do{
+ t=s;
+ s=IMUL32(r,_icdf[++ret]);
+ }
+ while(d<s);
+ _this->val=d-s;
+ _this->rng=t-s;
+ ec_dec_normalize(_this);
+ return ret;
+}
+
+int ec_dec_icdf16(ec_dec *_this,const opus_uint16 *_icdf,unsigned _ftb){
+ opus_uint32 r;
+ opus_uint32 d;
+ opus_uint32 s;
+ opus_uint32 t;
+ int ret;
+ s=_this->rng;
+ d=_this->val;
+ r=s>>_ftb;
+ ret=-1;
+ do{
+ t=s;
+ s=IMUL32(r,_icdf[++ret]);
+ }
+ while(d<s);
+ _this->val=d-s;
+ _this->rng=t-s;
+ ec_dec_normalize(_this);
+ return ret;
+}
+
+opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft){
+ unsigned ft;
+ unsigned s;
+ int ftb;
+ /*In order to optimize EC_ILOG(), it is undefined for the value 0.*/
+ celt_assert(_ft>1);
+ _ft--;
+ ftb=EC_ILOG(_ft);
+ if(ftb>EC_UINT_BITS){
+ opus_uint32 t;
+ ftb-=EC_UINT_BITS;
+ ft=(unsigned)(_ft>>ftb)+1;
+ s=ec_decode(_this,ft);
+ ec_dec_update(_this,s,s+1,ft);
+ t=(opus_uint32)s<<ftb|ec_dec_bits(_this,ftb);
+ if(t<=_ft)return t;
+ _this->error=1;
+ return _ft;
+ }
+ else{
+ _ft++;
+ s=ec_decode(_this,(unsigned)_ft);
+ ec_dec_update(_this,s,s+1,(unsigned)_ft);
+ return s;
+ }
+}
+
+opus_uint32 ec_dec_bits(ec_dec *_this,unsigned _bits){
+ ec_window window;
+ int available;
+ opus_uint32 ret;
+ window=_this->end_window;
+ available=_this->nend_bits;
+ if((unsigned)available<_bits){
+ do{
+ window|=(ec_window)ec_read_byte_from_end(_this)<<available;
+ available+=EC_SYM_BITS;
+ }
+ while(available<=EC_WINDOW_SIZE-EC_SYM_BITS);
+ }
+ ret=(opus_uint32)window&(((opus_uint32)1<<_bits)-1U);
+ window>>=_bits;
+ available-=_bits;
+ _this->end_window=window;
+ _this->nend_bits=available;
+ _this->nbits_total+=_bits;
+ return ret;
+}
--- /dev/null
+/* Copyright (c) 2001-2011 Timothy B. Terriberry
+ Copyright (c) 2008-2009 Xiph.Org Foundation */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#if !defined(_entdec_H)
+# define _entdec_H (1)
+# include <limits.h>
+# include "entcode.h"
+
+/*Initializes the decoder.
+ _buf: The input buffer to use.
+ Return: 0 on success, or a negative value on error.*/
+void ec_dec_init(ec_dec *_this,unsigned char *_buf,opus_uint32 _storage);
+
+/*Calculates the cumulative frequency for the next symbol.
+ This can then be fed into the probability model to determine what that
+ symbol is, and the additional frequency information required to advance to
+ the next symbol.
+ This function cannot be called more than once without a corresponding call to
+ ec_dec_update(), or decoding will not proceed correctly.
+ _ft: The total frequency of the symbols in the alphabet the next symbol was
+ encoded with.
+ Return: A cumulative frequency representing the encoded symbol.
+ If the cumulative frequency of all the symbols before the one that
+ was encoded was fl, and the cumulative frequency of all the symbols
+ up to and including the one encoded is fh, then the returned value
+ will fall in the range [fl,fh).*/
+unsigned ec_decode(ec_dec *_this,unsigned _ft);
+
+/*Equivalent to ec_decode() with _ft==1<<_bits.*/
+unsigned ec_decode_bin(ec_dec *_this,unsigned _bits);
+
+/*Advance the decoder past the next symbol using the frequency information the
+ symbol was encoded with.
+ Exactly one call to ec_decode() must have been made so that all necessary
+ intermediate calculations are performed.
+ _fl: The cumulative frequency of all symbols that come before the symbol
+ decoded.
+ _fh: The cumulative frequency of all symbols up to and including the symbol
+ decoded.
+ Together with _fl, this defines the range [_fl,_fh) in which the value
+ returned above must fall.
+ _ft: The total frequency of the symbols in the alphabet the symbol decoded
+ was encoded in.
+ This must be the same as passed to the preceding call to ec_decode().*/
+void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft);
+
+/* Decode a bit that has a 1/(1<<_logp) probability of being a one */
+int ec_dec_bit_logp(ec_dec *_this,unsigned _logp);
+
+/*Decodes a symbol given an "inverse" CDF table.
+ No call to ec_dec_update() is necessary after this call.
+ _icdf: The "inverse" CDF, such that symbol s falls in the range
+ [s>0?ft-_icdf[s-1]:0,ft-_icdf[s]), where ft=1<<_ftb.
+ The values must be monotonically non-increasing, and the last value
+ must be 0.
+ _ftb: The number of bits of precision in the cumulative distribution.
+ Return: The decoded symbol s.*/
+int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb);
+
+/*Decodes a symbol given an "inverse" CDF table.
+ No call to ec_dec_update() is necessary after this call.
+ _icdf: The "inverse" CDF, such that symbol s falls in the range
+ [s>0?ft-_icdf[s-1]:0,ft-_icdf[s]), where ft=1<<_ftb.
+ The values must be monotonically non-increasing, and the last value
+ must be 0.
+ _ftb: The number of bits of precision in the cumulative distribution.
+ Return: The decoded symbol s.*/
+int ec_dec_icdf16(ec_dec *_this,const opus_uint16 *_icdf,unsigned _ftb);
+
+/*Extracts a raw unsigned integer with a non-power-of-2 range from the stream.
+ The bits must have been encoded with ec_enc_uint().
+ No call to ec_dec_update() is necessary after this call.
+ _ft: The number of integers that can be decoded (one more than the max).
+ This must be at least 2, and no more than 2**32-1.
+ Return: The decoded bits.*/
+opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft);
+
+/*Extracts a sequence of raw bits from the stream.
+ The bits must have been encoded with ec_enc_bits().
+ No call to ec_dec_update() is necessary after this call.
+ _ftb: The number of bits to extract.
+ This must be between 0 and 25, inclusive.
+ Return: The decoded bits.*/
+opus_uint32 ec_dec_bits(ec_dec *_this,unsigned _ftb);
+
+#endif
--- /dev/null
+/* Copyright (c) 2001-2011 Timothy B. Terriberry
+ Copyright (c) 2008-2009 Xiph.Org Foundation */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#if defined(HAVE_CONFIG_H)
+# include "config.h"
+#endif
+#include "os_support.h"
+#include "arch.h"
+#include "entenc.h"
+#include "mfrngcod.h"
+
+/*A range encoder.
+ See entdec.c and the references for implementation details \cite{Mar79,MNW98}.
+
+ @INPROCEEDINGS{Mar79,
+ author="Martin, G.N.N.",
+ title="Range encoding: an algorithm for removing redundancy from a digitised
+ message",
+ booktitle="Video \& Data Recording Conference",
+ year=1979,
+ address="Southampton",
+ month=Jul
+ }
+ @ARTICLE{MNW98,
+ author="Alistair Moffat and Radford Neal and Ian H. Witten",
+ title="Arithmetic Coding Revisited",
+ journal="{ACM} Transactions on Information Systems",
+ year=1998,
+ volume=16,
+ number=3,
+ pages="256--294",
+ month=Jul,
+ URL="http://www.stanford.edu/class/ee398/handouts/papers/Moffat98ArithmCoding.pdf"
+ }*/
+
+static int ec_write_byte(ec_enc *_this,unsigned _value){
+ if(_this->offs+_this->end_offs>=_this->storage)return -1;
+ _this->buf[_this->offs++]=(unsigned char)_value;
+ return 0;
+}
+
+static int ec_write_byte_at_end(ec_enc *_this,unsigned _value){
+ if(_this->offs+_this->end_offs>=_this->storage)return -1;
+ _this->buf[_this->storage-++(_this->end_offs)]=(unsigned char)_value;
+ return 0;
+}
+
+/*Outputs a symbol, with a carry bit.
+ If there is a potential to propagate a carry over several symbols, they are
+ buffered until it can be determined whether or not an actual carry will
+ occur.
+ If the counter for the buffered symbols overflows, then the stream becomes
+ undecodable.
+ This gives a theoretical limit of a few billion symbols in a single packet on
+ 32-bit systems.
+ The alternative is to truncate the range in order to force a carry, but
+ requires similar carry tracking in the decoder, needlessly slowing it down.*/
+static void ec_enc_carry_out(ec_enc *_this,int _c){
+ if(_c!=EC_SYM_MAX){
+ /*No further carry propagation possible, flush buffer.*/
+ int carry;
+ carry=_c>>EC_SYM_BITS;
+ /*Don't output a byte on the first write.
+ This compare should be taken care of by branch-prediction thereafter.*/
+ if(_this->rem>=0)_this->error|=ec_write_byte(_this,_this->rem+carry);
+ if(_this->ext>0){
+ unsigned sym;
+ sym=(EC_SYM_MAX+carry)&EC_SYM_MAX;
+ do _this->error|=ec_write_byte(_this,sym);
+ while(--(_this->ext)>0);
+ }
+ _this->rem=_c&EC_SYM_MAX;
+ }
+ else _this->ext++;
+}
+
+static OPUS_INLINE void ec_enc_normalize(ec_enc *_this){
+ /*If the range is too small, output some bits and rescale it.*/
+ while(_this->rng<=EC_CODE_BOT){
+ ec_enc_carry_out(_this,(int)(_this->val>>EC_CODE_SHIFT));
+ /*Move the next-to-high-order symbol into the high-order position.*/
+ _this->val=(_this->val<<EC_SYM_BITS)&(EC_CODE_TOP-1);
+ _this->rng<<=EC_SYM_BITS;
+ _this->nbits_total+=EC_SYM_BITS;
+ }
+}
+
+void ec_enc_init(ec_enc *_this,unsigned char *_buf,opus_uint32 _size){
+ _this->buf=_buf;
+ _this->end_offs=0;
+ _this->end_window=0;
+ _this->nend_bits=0;
+ /*This is the offset from which ec_tell() will subtract partial bits.*/
+ _this->nbits_total=EC_CODE_BITS+1;
+ _this->offs=0;
+ _this->rng=EC_CODE_TOP;
+ _this->rem=-1;
+ _this->val=0;
+ _this->ext=0;
+ _this->storage=_size;
+ _this->error=0;
+}
+
+void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
+ opus_uint32 r;
+ r=celt_udiv(_this->rng,_ft);
+ if(_fl>0){
+ _this->val+=_this->rng-IMUL32(r,(_ft-_fl));
+ _this->rng=IMUL32(r,(_fh-_fl));
+ }
+ else _this->rng-=IMUL32(r,(_ft-_fh));
+ ec_enc_normalize(_this);
+}
+
+void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _bits){
+ opus_uint32 r;
+ r=_this->rng>>_bits;
+ if(_fl>0){
+ _this->val+=_this->rng-IMUL32(r,((1U<<_bits)-_fl));
+ _this->rng=IMUL32(r,(_fh-_fl));
+ }
+ else _this->rng-=IMUL32(r,((1U<<_bits)-_fh));
+ ec_enc_normalize(_this);
+}
+
+/*The probability of having a "one" is 1/(1<<_logp).*/
+void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp){
+ opus_uint32 r;
+ opus_uint32 s;
+ opus_uint32 l;
+ r=_this->rng;
+ l=_this->val;
+ s=r>>_logp;
+ r-=s;
+ if(_val)_this->val=l+r;
+ _this->rng=_val?s:r;
+ ec_enc_normalize(_this);
+}
+
+void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb){
+ opus_uint32 r;
+ r=_this->rng>>_ftb;
+ if(_s>0){
+ _this->val+=_this->rng-IMUL32(r,_icdf[_s-1]);
+ _this->rng=IMUL32(r,_icdf[_s-1]-_icdf[_s]);
+ }
+ else _this->rng-=IMUL32(r,_icdf[_s]);
+ ec_enc_normalize(_this);
+}
+
+void ec_enc_icdf16(ec_enc *_this,int _s,const opus_uint16 *_icdf,unsigned _ftb){
+ opus_uint32 r;
+ r=_this->rng>>_ftb;
+ if(_s>0){
+ _this->val+=_this->rng-IMUL32(r,_icdf[_s-1]);
+ _this->rng=IMUL32(r,_icdf[_s-1]-_icdf[_s]);
+ }
+ else _this->rng-=IMUL32(r,_icdf[_s]);
+ ec_enc_normalize(_this);
+}
+
+void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft){
+ unsigned ft;
+ unsigned fl;
+ int ftb;
+ /*In order to optimize EC_ILOG(), it is undefined for the value 0.*/
+ celt_assert(_ft>1);
+ _ft--;
+ ftb=EC_ILOG(_ft);
+ if(ftb>EC_UINT_BITS){
+ ftb-=EC_UINT_BITS;
+ ft=(_ft>>ftb)+1;
+ fl=(unsigned)(_fl>>ftb);
+ ec_encode(_this,fl,fl+1,ft);
+ ec_enc_bits(_this,_fl&(((opus_uint32)1<<ftb)-1U),ftb);
+ }
+ else ec_encode(_this,_fl,_fl+1,_ft+1);
+}
+
+void ec_enc_bits(ec_enc *_this,opus_uint32 _fl,unsigned _bits){
+ ec_window window;
+ int used;
+ window=_this->end_window;
+ used=_this->nend_bits;
+ celt_assert(_bits>0);
+ if(used+_bits>EC_WINDOW_SIZE){
+ do{
+ _this->error|=ec_write_byte_at_end(_this,(unsigned)window&EC_SYM_MAX);
+ window>>=EC_SYM_BITS;
+ used-=EC_SYM_BITS;
+ }
+ while(used>=EC_SYM_BITS);
+ }
+ window|=(ec_window)_fl<<used;
+ used+=_bits;
+ _this->end_window=window;
+ _this->nend_bits=used;
+ _this->nbits_total+=_bits;
+}
+
+void ec_enc_patch_initial_bits(ec_enc *_this,unsigned _val,unsigned _nbits){
+ int shift;
+ unsigned mask;
+ celt_assert(_nbits<=EC_SYM_BITS);
+ shift=EC_SYM_BITS-_nbits;
+ mask=((1<<_nbits)-1)<<shift;
+ if(_this->offs>0){
+ /*The first byte has been finalized.*/
+ _this->buf[0]=(unsigned char)((_this->buf[0]&~mask)|_val<<shift);
+ }
+ else if(_this->rem>=0){
+ /*The first byte is still awaiting carry propagation.*/
+ _this->rem=(_this->rem&~mask)|_val<<shift;
+ }
+ else if(_this->rng<=(EC_CODE_TOP>>_nbits)){
+ /*The renormalization loop has never been run.*/
+ _this->val=(_this->val&~((opus_uint32)mask<<EC_CODE_SHIFT))|
+ (opus_uint32)_val<<(EC_CODE_SHIFT+shift);
+ }
+ /*The encoder hasn't even encoded _nbits of data yet.*/
+ else _this->error=-1;
+}
+
+void ec_enc_shrink(ec_enc *_this,opus_uint32 _size){
+ celt_assert(_this->offs+_this->end_offs<=_size);
+ OPUS_MOVE(_this->buf+_size-_this->end_offs,
+ _this->buf+_this->storage-_this->end_offs,_this->end_offs);
+ _this->storage=_size;
+}
+
+void ec_enc_done(ec_enc *_this){
+ ec_window window;
+ int used;
+ opus_uint32 msk;
+ opus_uint32 end;
+ int l;
+ /*We output the minimum number of bits that ensures that the symbols encoded
+ thus far will be decoded correctly regardless of the bits that follow.*/
+ l=EC_CODE_BITS-EC_ILOG(_this->rng);
+ msk=(EC_CODE_TOP-1)>>l;
+ end=(_this->val+msk)&~msk;
+ if((end|msk)>=_this->val+_this->rng){
+ l++;
+ msk>>=1;
+ end=(_this->val+msk)&~msk;
+ }
+ while(l>0){
+ ec_enc_carry_out(_this,(int)(end>>EC_CODE_SHIFT));
+ end=(end<<EC_SYM_BITS)&(EC_CODE_TOP-1);
+ l-=EC_SYM_BITS;
+ }
+ /*If we have a buffered byte flush it into the output buffer.*/
+ if(_this->rem>=0||_this->ext>0)ec_enc_carry_out(_this,0);
+ /*If we have buffered extra bits, flush them as well.*/
+ window=_this->end_window;
+ used=_this->nend_bits;
+ while(used>=EC_SYM_BITS){
+ _this->error|=ec_write_byte_at_end(_this,(unsigned)window&EC_SYM_MAX);
+ window>>=EC_SYM_BITS;
+ used-=EC_SYM_BITS;
+ }
+ /*Clear any excess space and add any remaining extra bits to the last byte.*/
+ if(!_this->error){
+ if (_this->buf) OPUS_CLEAR(_this->buf+_this->offs,
+ _this->storage-_this->offs-_this->end_offs);
+ if(used>0){
+ /*If there's no range coder data at all, give up.*/
+ if(_this->end_offs>=_this->storage)_this->error=-1;
+ else{
+ l=-l;
+ /*If we've busted, don't add too many extra bits to the last byte; it
+ would corrupt the range coder data, and that's more important.*/
+ if(_this->offs+_this->end_offs>=_this->storage&&l<used){
+ window&=(1<<l)-1;
+ _this->error=-1;
+ }
+ _this->buf[_this->storage-_this->end_offs-1]|=(unsigned char)window;
+ }
+ }
+ }
+}
--- /dev/null
+/* Copyright (c) 2001-2011 Timothy B. Terriberry
+ Copyright (c) 2008-2009 Xiph.Org Foundation */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#if !defined(_entenc_H)
+# define _entenc_H (1)
+# include <stddef.h>
+# include "entcode.h"
+
+/*Initializes the encoder.
+ _buf: The buffer to store output bytes in.
+ _size: The size of the buffer, in chars.*/
+void ec_enc_init(ec_enc *_this,unsigned char *_buf,opus_uint32 _size);
+/*Encodes a symbol given its frequency information.
+ The frequency information must be discernible by the decoder, assuming it
+ has read only the previous symbols from the stream.
+ It is allowable to change the frequency information, or even the entire
+ source alphabet, so long as the decoder can tell from the context of the
+ previously encoded information that it is supposed to do so as well.
+ _fl: The cumulative frequency of all symbols that come before the one to be
+ encoded.
+ _fh: The cumulative frequency of all symbols up to and including the one to
+ be encoded.
+ Together with _fl, this defines the range [_fl,_fh) in which the
+ decoded value will fall.
+ _ft: The sum of the frequencies of all the symbols*/
+void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft);
+
+/*Equivalent to ec_encode() with _ft==1<<_bits.*/
+void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _bits);
+
+/* Encode a bit that has a 1/(1<<_logp) probability of being a one */
+void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp);
+
+/*Encodes a symbol given an "inverse" CDF table.
+ _s: The index of the symbol to encode.
+ _icdf: The "inverse" CDF, such that symbol _s falls in the range
+ [_s>0?ft-_icdf[_s-1]:0,ft-_icdf[_s]), where ft=1<<_ftb.
+ The values must be monotonically non-increasing, and the last value
+ must be 0.
+ _ftb: The number of bits of precision in the cumulative distribution.*/
+void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb);
+
+/*Encodes a symbol given an "inverse" CDF table.
+ _s: The index of the symbol to encode.
+ _icdf: The "inverse" CDF, such that symbol _s falls in the range
+ [_s>0?ft-_icdf[_s-1]:0,ft-_icdf[_s]), where ft=1<<_ftb.
+ The values must be monotonically non-increasing, and the last value
+ must be 0.
+ _ftb: The number of bits of precision in the cumulative distribution.*/
+void ec_enc_icdf16(ec_enc *_this,int _s,const opus_uint16 *_icdf,unsigned _ftb);
+
+/*Encodes a raw unsigned integer in the stream.
+ _fl: The integer to encode.
+ _ft: The number of integers that can be encoded (one more than the max).
+ This must be at least 2, and no more than 2**32-1.*/
+void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft);
+
+/*Encodes a sequence of raw bits in the stream.
+ _fl: The bits to encode.
+ _ftb: The number of bits to encode.
+ This must be between 1 and 25, inclusive.*/
+void ec_enc_bits(ec_enc *_this,opus_uint32 _fl,unsigned _ftb);
+
+/*Overwrites a few bits at the very start of an existing stream, after they
+ have already been encoded.
+ This makes it possible to have a few flags up front, where it is easy for
+ decoders to access them without parsing the whole stream, even if their
+ values are not determined until late in the encoding process, without having
+ to buffer all the intermediate symbols in the encoder.
+ In order for this to work, at least _nbits bits must have already been
+ encoded using probabilities that are an exact power of two.
+ The encoder can verify the number of encoded bits is sufficient, but cannot
+ check this latter condition.
+ _val: The bits to encode (in the least _nbits significant bits).
+ They will be decoded in order from most-significant to least.
+ _nbits: The number of bits to overwrite.
+ This must be no more than 8.*/
+void ec_enc_patch_initial_bits(ec_enc *_this,unsigned _val,unsigned _nbits);
+
+/*Compacts the data to fit in the target size.
+ This moves up the raw bits at the end of the current buffer so they are at
+ the end of the new buffer size.
+ The caller must ensure that the amount of data that's already been written
+ will fit in the new size.
+ _size: The number of bytes in the new buffer.
+ This must be large enough to contain the bits already written, and
+ must be no larger than the existing size.*/
+void ec_enc_shrink(ec_enc *_this,opus_uint32 _size);
+
+/*Indicates that there are no more symbols to encode.
+ All remaining output bytes are flushed to the output buffer.
+ ec_enc_init() must be called before the encoder can be used again.*/
+void ec_enc_done(ec_enc *_this);
+
+#endif
--- /dev/null
+/* Copyright (C) 2003-2008 Jean-Marc Valin
+ Copyright (C) 2007-2012 Xiph.Org Foundation */
+/**
+ @file fixed_debug.h
+ @brief Fixed-point operations with debugging
+*/
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 FIXED_DEBUG_H
+#define FIXED_DEBUG_H
+
+#include <stdio.h>
+#include "opus_defines.h"
+
+#ifdef CELT_C
+OPUS_EXPORT opus_int64 celt_mips=0;
+#else
+extern opus_int64 celt_mips;
+#endif
+
+#define MULT16_16U(a,b) ((opus_uint32)(a)*(opus_uint32)(b))
+#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b))
+#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL32(MULT16_16(SHR32((a),16),SHR((b),16)),1), SHR32(MULT16_16SU(SHR32((a),16),((b)&0x0000ffff)),15)), SHR32(MULT16_16SU(SHR32((b),16),((a)&0x0000ffff)),15))
+#define MULT32_32_P31(a,b) ADD32(SHL32(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR32(128+(opus_int32)(MULT16_16U(((a)&0x0000ffff),((b)&0x0000ffff))>>(16+7)) + SHR32(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),7) + SHR32(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),7), 8) )
+#define MULT32_32_P31_ovflw(a,b) ADD32_ovflw(SHL32(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR32(128+(opus_int32)(MULT16_16U(((a)&0x0000ffff),((b)&0x0000ffff))>>(16+7)) + SHR32(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),7) + SHR32(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),7), 8) )
+#define MULT32_32_Q32(a,b) ADD32(ADD32(MULT16_16(SHR((a),16),SHR((b),16)), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),16)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),16))
+
+/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
+#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR32((b),16)), SHR32(MULT16_16SU((a),((b)&0x0000ffff)),16))
+
+#define MULT16_32_P16(a,b) MULT16_32_PX(a,b,16)
+
+#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
+#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val64)1)<<(bits))))
+#define GCONST2(x,bits) ((celt_glog)(.5+(x)*(((celt_glog)1)<<(bits))))
+#define GCONST(x) GCONST2((x),DB_SHIFT)
+
+#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
+#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
+#define VERIFY_UINT(x) ((x)<=(2147483647LLU<<1))
+
+#define SHR(a,b) SHR32(a,b)
+#define PSHR(a,b) PSHR32(a,b)
+
+/** Add two 32-bit values, ignore any overflows */
+#define ADD32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
+/** Subtract two 32-bit values, ignore any overflows */
+#define SUB32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
+/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
+/** Negate 32-bit value, ignore any overflows */
+#define NEG32_ovflw(a) (celt_mips+=2,(opus_val32)(0-(opus_uint32)(a)))
+/** 32-bit shift left, ignoring overflows */
+#define SHL32_ovflw(a,shift) ((opus_int32)((opus_uint32)(a)<<(shift)))
+/** 32-bit arithmetic shift right with rounding-to-nearest, ignoring overflows */
+#define PSHR32_ovflw(a,shift) (SHR32(ADD32_ovflw(a, (EXTEND32(1)<<(shift)>>1)),shift))
+
+static OPUS_INLINE short NEG16(int x)
+{
+ int res;
+ if (!VERIFY_SHORT(x))
+ {
+ fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = -x;
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips++;
+ return res;
+}
+static OPUS_INLINE int NEG32(opus_int64 x)
+{
+ opus_int64 res;
+ if (!VERIFY_INT(x))
+ {
+ fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = -x;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=2;
+ return res;
+}
+
+#define EXTRACT16(x) EXTRACT16_(x, __FILE__, __LINE__)
+static OPUS_INLINE short EXTRACT16_(int x, char *file, int line)
+{
+ int res;
+ if (!VERIFY_SHORT(x))
+ {
+ fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = x;
+ celt_mips++;
+ return res;
+}
+
+#define EXTEND32(x) EXTEND32_(x, __FILE__, __LINE__)
+static OPUS_INLINE int EXTEND32_(int x, char *file, int line)
+{
+ int res;
+ if (!VERIFY_SHORT(x))
+ {
+ fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = x;
+ celt_mips++;
+ return res;
+}
+
+#define SHR16(a, shift) SHR16_(a, shift, __FILE__, __LINE__)
+static OPUS_INLINE short SHR16_(int a, int shift, char *file, int line)
+{
+ int res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
+ {
+ fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = a>>shift;
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips++;
+ return res;
+}
+#define SHL16(a, shift) SHL16_(a, shift, __FILE__, __LINE__)
+static OPUS_INLINE short SHL16_(int a, int shift, char *file, int line)
+{
+ opus_int32 res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
+ {
+ fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = (opus_int32)((opus_uint32)a<<shift);
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips++;
+ return res;
+}
+
+static OPUS_INLINE int SHR32(opus_int64 a, int shift)
+{
+ opus_int64 res;
+ if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
+ {
+ fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = a>>shift;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=2;
+ return res;
+}
+#define SHL32(a, shift) SHL32_(a, shift, __FILE__, __LINE__)
+static OPUS_INLINE int SHL32_(opus_int64 a, int shift, char *file, int line)
+{
+ opus_int64 res;
+ if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
+ {
+ fprintf (stderr, "SHL32: inputs are not int: %lld %d in %s: line %d\n", (long long)a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = (opus_int64)((opus_uint64)a<<shift);
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", (long long)a, shift, (long long)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=2;
+ return res;
+}
+
+#define PSHR32(a,shift) (celt_mips--,SHR32(ADD32((a),(((opus_val32)(1)<<((shift))>>1))),shift))
+#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
+
+#define SHR64(a,shift) (celt_mips++,(a) >> (shift))
+
+#define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
+#define SROUND16(x,a) (celt_mips--,EXTRACT16(SATURATE(PSHR32(x,a), 32767)));
+
+#define HALF16(x) (SHR16(x,1))
+#define HALF32(x) (SHR32(x,1))
+
+#define ADD16(a, b) ADD16_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE short ADD16_(int a, int b, char *file, int line)
+{
+ int res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+ {
+ fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = a+b;
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips++;
+ return res;
+}
+
+#define SUB16(a, b) SUB16_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE short SUB16_(int a, int b, char *file, int line)
+{
+ int res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+ {
+ fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = a-b;
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips++;
+ return res;
+}
+
+#define ADD32(a, b) ADD32_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE int ADD32_(opus_int64 a, opus_int64 b, char *file, int line)
+{
+ opus_int64 res;
+ if (!VERIFY_INT(a) || !VERIFY_INT(b))
+ {
+ fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = a+b;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=2;
+ return res;
+}
+
+#define SUB32(a, b) SUB32_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE int SUB32_(opus_int64 a, opus_int64 b, char *file, int line)
+{
+ opus_int64 res;
+ if (!VERIFY_INT(a) || !VERIFY_INT(b))
+ {
+ fprintf (stderr, "SUB32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = a-b;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "SUB32: output is not int: %d in %s: line %d\n", (int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=2;
+ return res;
+}
+
+#undef UADD32
+#define UADD32(a, b) UADD32_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE unsigned int UADD32_(opus_uint64 a, opus_uint64 b, char *file, int line)
+{
+ opus_uint64 res;
+ if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
+ {
+ fprintf (stderr, "UADD32: inputs are not uint32: %llu %llu in %s: line %d\n", (unsigned long long)a, (unsigned long long)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = a+b;
+ if (!VERIFY_UINT(res))
+ {
+ fprintf (stderr, "UADD32: output is not uint32: %llu in %s: line %d\n", (unsigned long long)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=2;
+ return res;
+}
+
+#undef USUB32
+#define USUB32(a, b) USUB32_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE unsigned int USUB32_(opus_uint64 a, opus_uint64 b, char *file, int line)
+{
+ opus_uint64 res;
+ if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
+ {
+ fprintf (stderr, "USUB32: inputs are not uint32: %llu %llu in %s: line %d\n", (unsigned long long)a, (unsigned long long)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ if (a<b)
+ {
+ fprintf (stderr, "USUB32: inputs underflow: %llu < %llu in %s: line %d\n", (unsigned long long)a, (unsigned long long)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = a-b;
+ if (!VERIFY_UINT(res))
+ {
+ fprintf (stderr, "USUB32: output is not uint32: %llu - %llu = %llu in %s: line %d\n", (unsigned long long)a, (unsigned long long)b, (unsigned long long)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=2;
+ return res;
+}
+
+/* result fits in 16 bits */
+static OPUS_INLINE short MULT16_16_16(int a, int b)
+{
+ int res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+ {
+ fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = a*b;
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips++;
+ return res;
+}
+
+/* result fits in 32 bits */
+static OPUS_INLINE int MULT32_32_32(opus_int64 a, opus_int64 b)
+{
+ opus_int64 res;
+ if (!VERIFY_INT(a) || !VERIFY_INT(b))
+ {
+ fprintf (stderr, "MULT32_32_32: inputs are not int: %lld %lld\n", (long long)a, (long long)b);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = a*b;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "MULT32_32_32: output is not int: %lld\n", (long long)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=5;
+ return res;
+}
+
+static OPUS_INLINE int MULT32_32_Q16(opus_int64 a, opus_int64 b)
+{
+ opus_int64 res;
+ if (!VERIFY_INT(a) || !VERIFY_INT(b))
+ {
+ fprintf (stderr, "MULT32_32_Q16: inputs are not int: %lld %lld\n", (long long)a, (long long)b);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = ((opus_int64)(a)*(opus_int64)(b)) >> 16;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "MULT32_32_Q16: output is not int: %lld*%lld=%lld\n", (long long)a, (long long)b, (long long)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=5;
+ return res;
+}
+
+#define MULT16_16(a, b) MULT16_16_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE int MULT16_16_(int a, int b, char *file, int line)
+{
+ opus_int64 res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+ {
+ fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = ((opus_int64)a)*b;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips++;
+ return res;
+}
+
+#define MAC16_16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
+
+#define MULT16_32_QX(a, b, Q) MULT16_32_QX_(a, b, Q, __FILE__, __LINE__)
+static OPUS_INLINE int MULT16_32_QX_(int a, opus_int64 b, int Q, char *file, int line)
+{
+ opus_int64 res;
+ if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
+ {
+ fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ if (ABS32(b)>=((opus_int64)(1)<<(16+Q)))
+ {
+ fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = (((opus_int64)a)*(opus_int64)b) >> Q;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ if (Q==15)
+ celt_mips+=3;
+ else
+ celt_mips+=4;
+ return res;
+}
+
+#define MULT16_32_PX(a, b, Q) MULT16_32_PX_(a, b, Q, __FILE__, __LINE__)
+static OPUS_INLINE int MULT16_32_PX_(int a, opus_int64 b, int Q, char *file, int line)
+{
+ opus_int64 res;
+ if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
+ {
+ fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d in %s: line %d\n\n", Q, (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ if (ABS32(b)>=((opus_int64)(1)<<(16+Q)))
+ {
+ fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n\n", Q, (int)a, (int)b,file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = ((((opus_int64)a)*(opus_int64)b) + (((opus_val32)(1)<<Q)>>1))>> Q;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d in %s: line %d\n\n", Q, (int)a, (int)b,(int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ if (Q==15)
+ celt_mips+=4;
+ else
+ celt_mips+=5;
+ return res;
+}
+
+#define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
+#define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
+#define MAC16_32_Q16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q16((a),(b))))
+
+static OPUS_INLINE int SATURATE(int a, int b)
+{
+ if (a>b)
+ a=b;
+ if (a<-b)
+ a = -b;
+ celt_mips+=3;
+ return a;
+}
+
+static OPUS_INLINE opus_int16 SATURATE16(opus_int32 a)
+{
+ celt_mips+=3;
+ if (a>32767)
+ return 32767;
+ else if (a<-32768)
+ return -32768;
+ else return a;
+}
+
+static OPUS_INLINE int MULT16_16_Q11_32(int a, int b)
+{
+ opus_int64 res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+ {
+ fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = ((opus_int64)a)*b;
+ res >>= 11;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=3;
+ return res;
+}
+static OPUS_INLINE short MULT16_16_Q13(int a, int b)
+{
+ opus_int64 res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+ {
+ fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = ((opus_int64)a)*b;
+ res >>= 13;
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=3;
+ return res;
+}
+static OPUS_INLINE short MULT16_16_Q14(int a, int b)
+{
+ opus_int64 res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+ {
+ fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = ((opus_int64)a)*b;
+ res >>= 14;
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=3;
+ return res;
+}
+
+#define MULT16_16_Q15(a, b) MULT16_16_Q15_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE short MULT16_16_Q15_(int a, int b, char *file, int line)
+{
+ opus_int64 res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+ {
+ fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = ((opus_int64)a)*b;
+ res >>= 15;
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "MULT16_16_Q15: output is not short: %d in %s: line %d\n", (int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=1;
+ return res;
+}
+
+static OPUS_INLINE short MULT16_16_P13(int a, int b)
+{
+ opus_int64 res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+ {
+ fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = ((opus_int64)a)*b;
+ res += 4096;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res >>= 13;
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=4;
+ return res;
+}
+static OPUS_INLINE short MULT16_16_P14(int a, int b)
+{
+ opus_int64 res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+ {
+ fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = ((opus_int64)a)*b;
+ res += 8192;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res >>= 14;
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=4;
+ return res;
+}
+static OPUS_INLINE short MULT16_16_P15(int a, int b)
+{
+ opus_int64 res;
+ if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
+ {
+ fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = ((opus_int64)a)*b;
+ res += 16384;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res >>= 15;
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=2;
+ return res;
+}
+
+#define DIV32_16(a, b) DIV32_16_(a, b, __FILE__, __LINE__)
+
+static OPUS_INLINE int DIV32_16_(opus_int64 a, opus_int64 b, char *file, int line)
+{
+ opus_int64 res;
+ if (b==0)
+ {
+ fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ return 0;
+ }
+ if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
+ {
+ fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = a/b;
+ if (!VERIFY_SHORT(res))
+ {
+ fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
+ if (res>32767)
+ res = 32767;
+ if (res<-32768)
+ res = -32768;
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=35;
+ return res;
+}
+
+#define DIV32(a, b) DIV32_(a, b, __FILE__, __LINE__)
+static OPUS_INLINE int DIV32_(opus_int64 a, opus_int64 b, char *file, int line)
+{
+ opus_int64 res;
+ if (b==0)
+ {
+ fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ return 0;
+ }
+
+ if (!VERIFY_INT(a) || !VERIFY_INT(b))
+ {
+ fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ res = a/b;
+ if (!VERIFY_INT(res))
+ {
+ fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ celt_assert(0);
+#endif
+ }
+ celt_mips+=70;
+ return res;
+}
+
+static OPUS_INLINE opus_val16 SIG2WORD16_generic(celt_sig x)
+{
+ x = PSHR32(x, SIG_SHIFT);
+ x = MAX32(x, -32768);
+ x = MIN32(x, 32767);
+ return EXTRACT16(x);
+}
+#define SIG2WORD16(x) (SIG2WORD16_generic(x))
+
+
+#undef PRINT_MIPS
+#define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", (unsigned long long)celt_mips);} while (0);
+
+#endif
--- /dev/null
+/* Copyright (C) 2007-2009 Xiph.Org Foundation
+ Copyright (C) 2003-2008 Jean-Marc Valin
+ Copyright (C) 2007-2008 CSIRO */
+/**
+ @file fixed_generic.h
+ @brief Generic fixed-point operations
+*/
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 FIXED_GENERIC_H
+#define FIXED_GENERIC_H
+
+/** Multiply a 16-bit signed value by a 16-bit unsigned value. The result is a 32-bit signed value */
+#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b))
+
+/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT16_32_Q16(a,b) ((opus_val32)SHR((opus_int64)((opus_val16)(a))*(b),16))
+#else
+#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16))
+#endif
+
+/** 16x32 multiplication, followed by a 16-bit shift right (round-to-nearest). Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT16_32_P16(a,b) ((opus_val32)PSHR((opus_int64)((opus_val16)(a))*(b),16))
+#else
+#define MULT16_32_P16(a,b) ADD32(MULT16_16((a),SHR((b),16)), PSHR(MULT16_16SU((a),((b)&0x0000ffff)),16))
+#endif
+
+/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT16_32_Q15(a,b) ((opus_val32)SHR((opus_int64)((opus_val16)(a))*(b),15))
+#else
+#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),((b)&0x0000ffff)),15))
+#endif
+
+/** 32x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT32_32_Q16(a,b) ((opus_val32)SHR((opus_int64)(a)*(opus_int64)(b),16))
+#else
+#define MULT32_32_Q16(a,b) (ADD32(ADD32(ADD32((opus_val32)(SHR32(((opus_uint32)((a)&0x0000ffff)*(opus_uint32)((b)&0x0000ffff)),16)), MULT16_16SU(SHR32(a,16),((b)&0x0000ffff))), MULT16_16SU(SHR32(b,16),((a)&0x0000ffff))), SHL32(MULT16_16(SHR32(a,16),SHR32(b,16)),16)))
+#endif
+
+/** 32x32 multiplication, followed by a 31-bit shift right. Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT32_32_Q31(a,b) ((opus_val32)SHR((opus_int64)(a)*(opus_int64)(b),31))
+#else
+#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),15)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),15))
+#endif
+
+/** 32x32 multiplication, followed by a 31-bit shift right (with rounding). Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT32_32_P31(a,b) ((opus_val32)SHR(1073741824+(opus_int64)(a)*(opus_int64)(b),31))
+#define MULT32_32_P31_ovflw(a,b) MULT32_32_P31(a,b)
+#else
+#define MULT16_16U(a,b) ((opus_uint32)(a)*(opus_uint32)(b))
+#define MULT32_32_P31(a,b) ADD32(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR32(128+(opus_int32)SHR(MULT16_16U(((a)&0x0000ffff),((b)&0x0000ffff)),16+7) + SHR32(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),7) + SHR32(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),7), 8) )
+#define MULT32_32_P31_ovflw(a,b) ADD32_ovflw(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR32(128+(opus_int32)SHR(MULT16_16U(((a)&0x0000ffff),((b)&0x0000ffff)),16+7) + SHR32(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),7) + SHR32(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),7), 8) )
+#endif
+
+/** 32x32 multiplication, followed by a 32-bit shift right. Results fits in 32 bits */
+#if OPUS_FAST_INT64
+#define MULT32_32_Q32(a,b) ((opus_val32)SHR((opus_int64)(a)*(opus_int64)(b),32))
+#else
+#define MULT32_32_Q32(a,b) ADD32(ADD32(MULT16_16(SHR((a),16),SHR((b),16)), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),16)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),16))
+#endif
+
+/** Compile-time conversion of float constant to 16-bit value */
+#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
+
+/** Compile-time conversion of float constant to 32-bit value */
+#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_int64)1)<<(bits))))
+
+/** Compile-time conversion of float constant to log gain value */
+#define GCONST2(x,bits) ((celt_glog)(.5+(x)*(((celt_glog)1)<<(bits))))
+
+/** Compile-time conversion of float constant to DB_SHIFT log gain value */
+#define GCONST(x) GCONST2((x),DB_SHIFT)
+
+/** Negate a 16-bit value */
+#define NEG16(x) (-(x))
+/** Negate a 32-bit value */
+#define NEG32(x) (-(x))
+
+/** Change a 32-bit value into a 16-bit value. The value is assumed to fit in 16-bit, otherwise the result is undefined */
+#define EXTRACT16(x) ((opus_val16)(x))
+/** Change a 16-bit value into a 32-bit value */
+#define EXTEND32(x) ((opus_val32)(x))
+
+/** Arithmetic shift-right of a 16-bit value */
+#define SHR16(a,shift) ((a) >> (shift))
+/** Arithmetic shift-left of a 16-bit value */
+#define SHL16(a,shift) ((opus_int16)((opus_uint16)(a)<<(shift)))
+/** Arithmetic shift-right of a 32-bit value */
+#define SHR32(a,shift) ((a) >> (shift))
+/** Arithmetic shift-left of a 32-bit value */
+#define SHL32(a,shift) ((opus_int32)((opus_uint32)(a)<<(shift)))
+
+/** 32-bit arithmetic shift right with rounding-to-nearest instead of rounding down */
+#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift))
+/** 32-bit arithmetic shift right where the argument can be negative */
+#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
+
+/** Arithmetic shift-right of a 64-bit value */
+#define SHR64(a,shift) ((a) >> (shift))
+
+/** "RAW" macros, should not be used outside of this header file */
+#define SHR(a,shift) ((a) >> (shift))
+#define SHL(a,shift) SHL32(a,shift)
+#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
+#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+
+#define SATURATE16(x) (EXTRACT16((x)>32767 ? 32767 : (x)<-32768 ? -32768 : (x)))
+
+/** Shift by a and round-to-nearest 32-bit value. Result is a 16-bit value */
+#define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a))))
+/** Shift by a and round-to-nearest 32-bit value. Result is a saturated 16-bit value */
+#define SROUND16(x,a) EXTRACT16(SATURATE(PSHR32(x,a), 32767));
+
+/** Divide by two */
+#define HALF16(x) (SHR16(x,1))
+#define HALF32(x) (SHR32(x,1))
+
+/** Add two 16-bit values */
+#define ADD16(a,b) ((opus_val16)((opus_val16)(a)+(opus_val16)(b)))
+/** Subtract two 16-bit values */
+#define SUB16(a,b) ((opus_val16)(a)-(opus_val16)(b))
+/** Add two 32-bit values */
+#define ADD32(a,b) ((opus_val32)(a)+(opus_val32)(b))
+/** Subtract two 32-bit values */
+#define SUB32(a,b) ((opus_val32)(a)-(opus_val32)(b))
+
+/** Add two 32-bit values, ignore any overflows */
+#define ADD32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
+/** Subtract two 32-bit values, ignore any overflows */
+#define SUB32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
+/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
+/** Negate 32-bit value, ignore any overflows */
+#define NEG32_ovflw(a) ((opus_val32)(0-(opus_uint32)(a)))
+/** 32-bit shift left, ignoring overflows */
+#define SHL32_ovflw(a,shift) SHL32(a,shift)
+/** 32-bit arithmetic shift right with rounding-to-nearest, ignoring overflows */
+#define PSHR32_ovflw(a,shift) (SHR32(ADD32_ovflw(a, (EXTEND32(1)<<(shift)>>1)),shift))
+
+/** 16x16 multiplication where the result fits in 16 bits */
+#define MULT16_16_16(a,b) ((((opus_val16)(a))*((opus_val16)(b))))
+
+/** 32x32 multiplication where the result fits in 32 bits */
+#define MULT32_32_32(a,b) ((((opus_val32)(a))*((opus_val32)(b))))
+
+/* (opus_val32)(opus_val16) gives TI compiler a hint that it's 16x16->32 multiply */
+/** 16x16 multiplication where the result fits in 32 bits */
+#define MULT16_16(a,b) (((opus_val32)(opus_val16)(a))*((opus_val32)(opus_val16)(b)))
+
+/** 16x16 multiply-add where the result fits in 32 bits */
+#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
+/** 16x32 multiply, followed by a 15-bit shift right and 32-bit add.
+ b must fit in 31 bits.
+ Result fits in 32 bits. */
+#define MAC16_32_Q15(c,a,b) ADD32((c),ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
+
+/** 16x32 multiplication, followed by a 16-bit shift right and 32-bit add.
+ Results fits in 32 bits */
+#define MAC16_32_Q16(c,a,b) ADD32((c),ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16)))
+
+#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11))
+#define MULT16_16_Q11(a,b) (SHR(MULT16_16((a),(b)),11))
+#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13))
+#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14))
+#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15))
+
+#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13))
+#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14))
+#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15))
+
+/** Divide a 32-bit value by a 16-bit value. Result fits in 16 bits */
+#define DIV32_16(a,b) ((opus_val16)(((opus_val32)(a))/((opus_val16)(b))))
+
+/** Divide a 32-bit value by a 32-bit value. Result fits in 32 bits */
+#define DIV32(a,b) (((opus_val32)(a))/((opus_val32)(b)))
+
+#if defined(__mips)
+#include "mips/fixed_generic_mipsr1.h"
+#endif
+
+static OPUS_INLINE opus_val16 SIG2WORD16_generic(celt_sig x)
+{
+ x = PSHR32(x, SIG_SHIFT);
+ x = MAX32(x, -32768);
+ x = MIN32(x, 32767);
+ return EXTRACT16(x);
+}
+#define SIG2WORD16(x) (SIG2WORD16_generic(x))
+
+#endif
--- /dev/null
+/* Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com> */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+/* Version 1.1 */
+
+#ifndef FLOAT_CAST_H
+#define FLOAT_CAST_H
+
+
+#include "arch.h"
+
+/*============================================================================
+** On Intel Pentium processors (especially PIII and probably P4), converting
+** from float to int is very slow. To meet the C specs, the code produced by
+** most C compilers targeting Pentium needs to change the FPU rounding mode
+** before the float to int conversion is performed.
+**
+** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
+** is this flushing of the pipeline which is so slow.
+**
+** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
+** llrint and llrintf which fix this problem as a side effect.
+**
+** On Unix-like systems, the configure process should have detected the
+** presence of these functions. If they weren't found we have to replace them
+** here with a standard C cast.
+*/
+
+/*
+** The C99 prototypes for lrint and lrintf are as follows:
+**
+** long int lrintf (float x) ;
+** long int lrint (double x) ;
+*/
+
+/* The presence of the required functions are detected during the configure
+** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
+** the config.h file.
+*/
+
+/* With GCC, when SSE is available, the fastest conversion is cvtss2si. */
+#if defined(__GNUC__) && defined(__SSE__)
+
+#include <xmmintrin.h>
+static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_ss(x));}
+
+#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1))
+
+ #include <xmmintrin.h>
+ static OPUS_INLINE opus_int32 float2int(float value)
+ {
+ /* _mm_load_ss will generate same code as _mm_set_ss
+ ** in _MSC_VER >= 1914 /02 so keep __mm_load__ss
+ ** for backward compatibility.
+ */
+ return _mm_cvtss_si32(_mm_load_ss(&value));
+ }
+
+#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_IX86)
+
+ #include <math.h>
+
+ /* Win32 doesn't seem to have these functions.
+ ** Therefore implement OPUS_INLINE versions of these functions here.
+ */
+
+ static OPUS_INLINE opus_int32
+ float2int (float flt)
+ { int intgr;
+
+ _asm
+ { fld flt
+ fistp intgr
+ } ;
+
+ return intgr ;
+ }
+#elif defined(__aarch64__)
+
+ #include <arm_neon.h>
+ static OPUS_INLINE opus_int32 float2int(float flt)
+ {
+ return vcvtns_s32_f32(flt);
+ }
+
+#elif defined(HAVE_LRINTF) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* These defines enable functionality introduced with the 1999 ISO C
+** standard. They must be defined before the inclusion of math.h to
+** engage them. If optimisation is enabled, these functions will be
+** inlined. With optimisation switched off, you have to link in the
+** maths library using -lm.
+*/
+
+#define _ISOC9X_SOURCE 1
+#define _ISOC99_SOURCE 1
+
+#define __USE_ISOC9X 1
+#define __USE_ISOC99 1
+
+#include <math.h>
+#define float2int(x) lrintf(x)
+
+#elif defined(HAVE_LRINT) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+#define _ISOC9X_SOURCE 1
+#define _ISOC99_SOURCE 1
+
+#define __USE_ISOC9X 1
+#define __USE_ISOC99 1
+
+#include <math.h>
+#define float2int(x) lrint(x)
+
+#else
+
+#if (defined(__GNUC__) && defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L)
+ /* supported by gcc in C99 mode, but not by all other compilers */
+ #warning "Don't have the functions lrint() and lrintf ()."
+ #warning "Replacing these functions with a standard C cast."
+#endif /* __STDC_VERSION__ >= 199901L */
+ #include <math.h>
+ #define float2int(flt) ((int)(floor(.5+flt)))
+#endif
+
+#ifndef DISABLE_FLOAT_API
+static OPUS_INLINE opus_int16 FLOAT2INT16(float x)
+{
+ x = x*CELT_SIG_SCALE;
+ x = MAX32(x, -32768);
+ x = MIN32(x, 32767);
+ return (opus_int16)float2int(x);
+}
+
+static OPUS_INLINE opus_int32 FLOAT2INT24(float x)
+{
+ x = x*(CELT_SIG_SCALE*256.f);
+ x = MAX32(x, -16777216);
+ x = MIN32(x, 16777216);
+ return float2int(x);
+}
+#ifdef FIXED_POINT
+static OPUS_INLINE opus_int32 FLOAT2SIG(float x)
+{
+ x = x*((opus_int32)32768<<SIG_SHIFT);
+ x = MAX32(x, -(65536<<SIG_SHIFT));
+ x = MIN32(x, 65536<<SIG_SHIFT);
+ return float2int(x);
+}
+#endif
+#endif /* DISABLE_FLOAT_API */
+
+#endif /* FLOAT_CAST_H */
--- /dev/null
+/*Copyright (c) 2003-2004, Mark Borgerding
+ Lots of modifications by Jean-Marc Valin
+ Copyright (c) 2005-2007, Xiph.Org Foundation
+ Copyright (c) 2008, Xiph.Org Foundation, CSIRO
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.*/
+
+/* This code is originally from Mark Borgerding's KISS-FFT but has been
+ heavily modified to better suit Opus */
+
+#ifndef SKIP_CONFIG_H
+# ifdef HAVE_CONFIG_H
+# include "config.h"
+# endif
+#endif
+
+#include "_kiss_fft_guts.h"
+#include "arch.h"
+#include "os_support.h"
+#include "mathops.h"
+#include "stack_alloc.h"
+
+#ifndef M_PI
+#define M_PI 3.141592653
+#endif
+
+/* The guts header contains all the multiplication and addition macros that are defined for
+ complex numbers. It also declares the kf_ internal functions.
+*/
+
+static void kf_bfly2(
+ kiss_fft_cpx * Fout,
+ int m,
+ int N
+ )
+{
+ kiss_fft_cpx * Fout2;
+ int i;
+ (void)m;
+#ifdef CUSTOM_MODES
+ if (m==1)
+ {
+ celt_assert(m==1);
+ for (i=0;i<N;i++)
+ {
+ kiss_fft_cpx t;
+ Fout2 = Fout + 1;
+ t = *Fout2;
+ C_SUB( *Fout2 , *Fout , t );
+ C_ADDTO( *Fout , t );
+ Fout += 2;
+ }
+ } else
+#endif
+ {
+ celt_coef tw;
+ tw = QCONST32(0.7071067812f, COEF_SHIFT-1);
+ /* We know that m==4 here because the radix-2 is just after a radix-4 */
+ celt_assert(m==4);
+ for (i=0;i<N;i++)
+ {
+ kiss_fft_cpx t;
+ Fout2 = Fout + 4;
+ t = Fout2[0];
+ C_SUB( Fout2[0] , Fout[0] , t );
+ C_ADDTO( Fout[0] , t );
+
+ t.r = S_MUL(ADD32_ovflw(Fout2[1].r, Fout2[1].i), tw);
+ t.i = S_MUL(SUB32_ovflw(Fout2[1].i, Fout2[1].r), tw);
+ C_SUB( Fout2[1] , Fout[1] , t );
+ C_ADDTO( Fout[1] , t );
+
+ t.r = Fout2[2].i;
+ t.i = NEG32_ovflw(Fout2[2].r);
+ C_SUB( Fout2[2] , Fout[2] , t );
+ C_ADDTO( Fout[2] , t );
+
+ t.r = S_MUL(SUB32_ovflw(Fout2[3].i, Fout2[3].r), tw);
+ t.i = S_MUL(NEG32_ovflw(ADD32_ovflw(Fout2[3].i, Fout2[3].r)), tw);
+ C_SUB( Fout2[3] , Fout[3] , t );
+ C_ADDTO( Fout[3] , t );
+ Fout += 8;
+ }
+ }
+}
+
+static void kf_bfly4(
+ kiss_fft_cpx * Fout,
+ const size_t fstride,
+ const kiss_fft_state *st,
+ int m,
+ int N,
+ int mm
+ )
+{
+ int i;
+
+ if (m==1)
+ {
+ /* Degenerate case where all the twiddles are 1. */
+ for (i=0;i<N;i++)
+ {
+ kiss_fft_cpx scratch0, scratch1;
+
+ C_SUB( scratch0 , *Fout, Fout[2] );
+ C_ADDTO(*Fout, Fout[2]);
+ C_ADD( scratch1 , Fout[1] , Fout[3] );
+ C_SUB( Fout[2], *Fout, scratch1 );
+ C_ADDTO( *Fout , scratch1 );
+ C_SUB( scratch1 , Fout[1] , Fout[3] );
+
+ Fout[1].r = ADD32_ovflw(scratch0.r, scratch1.i);
+ Fout[1].i = SUB32_ovflw(scratch0.i, scratch1.r);
+ Fout[3].r = SUB32_ovflw(scratch0.r, scratch1.i);
+ Fout[3].i = ADD32_ovflw(scratch0.i, scratch1.r);
+ Fout+=4;
+ }
+ } else {
+ int j;
+ kiss_fft_cpx scratch[6];
+ const kiss_twiddle_cpx *tw1,*tw2,*tw3;
+ const int m2=2*m;
+ const int m3=3*m;
+ kiss_fft_cpx * Fout_beg = Fout;
+ for (i=0;i<N;i++)
+ {
+ Fout = Fout_beg + i*mm;
+ tw3 = tw2 = tw1 = st->twiddles;
+ /* m is guaranteed to be a multiple of 4. */
+ for (j=0;j<m;j++)
+ {
+ C_MUL(scratch[0],Fout[m] , *tw1 );
+ C_MUL(scratch[1],Fout[m2] , *tw2 );
+ C_MUL(scratch[2],Fout[m3] , *tw3 );
+
+ C_SUB( scratch[5] , *Fout, scratch[1] );
+ C_ADDTO(*Fout, scratch[1]);
+ C_ADD( scratch[3] , scratch[0] , scratch[2] );
+ C_SUB( scratch[4] , scratch[0] , scratch[2] );
+ C_SUB( Fout[m2], *Fout, scratch[3] );
+ tw1 += fstride;
+ tw2 += fstride*2;
+ tw3 += fstride*3;
+ C_ADDTO( *Fout , scratch[3] );
+
+ Fout[m].r = ADD32_ovflw(scratch[5].r, scratch[4].i);
+ Fout[m].i = SUB32_ovflw(scratch[5].i, scratch[4].r);
+ Fout[m3].r = SUB32_ovflw(scratch[5].r, scratch[4].i);
+ Fout[m3].i = ADD32_ovflw(scratch[5].i, scratch[4].r);
+ ++Fout;
+ }
+ }
+ }
+}
+
+
+#ifndef RADIX_TWO_ONLY
+
+static void kf_bfly3(
+ kiss_fft_cpx * Fout,
+ const size_t fstride,
+ const kiss_fft_state *st,
+ int m,
+ int N,
+ int mm
+ )
+{
+ int i;
+ size_t k;
+ const size_t m2 = 2*m;
+ const kiss_twiddle_cpx *tw1,*tw2;
+ kiss_fft_cpx scratch[5];
+ kiss_twiddle_cpx epi3;
+
+ kiss_fft_cpx * Fout_beg = Fout;
+#ifdef FIXED_POINT
+ /*epi3.r = -16384;*/ /* Unused */
+ epi3.i = -QCONST32(0.86602540f, COEF_SHIFT-1);
+#else
+ epi3 = st->twiddles[fstride*m];
+#endif
+ for (i=0;i<N;i++)
+ {
+ Fout = Fout_beg + i*mm;
+ tw1=tw2=st->twiddles;
+ /* For non-custom modes, m is guaranteed to be a multiple of 4. */
+ k=m;
+ do {
+
+ C_MUL(scratch[1],Fout[m] , *tw1);
+ C_MUL(scratch[2],Fout[m2] , *tw2);
+
+ C_ADD(scratch[3],scratch[1],scratch[2]);
+ C_SUB(scratch[0],scratch[1],scratch[2]);
+ tw1 += fstride;
+ tw2 += fstride*2;
+
+ Fout[m].r = SUB32_ovflw(Fout->r, HALF_OF(scratch[3].r));
+ Fout[m].i = SUB32_ovflw(Fout->i, HALF_OF(scratch[3].i));
+
+ C_MULBYSCALAR( scratch[0] , epi3.i );
+
+ C_ADDTO(*Fout,scratch[3]);
+
+ Fout[m2].r = ADD32_ovflw(Fout[m].r, scratch[0].i);
+ Fout[m2].i = SUB32_ovflw(Fout[m].i, scratch[0].r);
+
+ Fout[m].r = SUB32_ovflw(Fout[m].r, scratch[0].i);
+ Fout[m].i = ADD32_ovflw(Fout[m].i, scratch[0].r);
+
+ ++Fout;
+ } while(--k);
+ }
+}
+
+
+#ifndef OVERRIDE_kf_bfly5
+static void kf_bfly5(
+ kiss_fft_cpx * Fout,
+ const size_t fstride,
+ const kiss_fft_state *st,
+ int m,
+ int N,
+ int mm
+ )
+{
+ kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
+ int i, u;
+ kiss_fft_cpx scratch[13];
+ const kiss_twiddle_cpx *tw;
+ kiss_twiddle_cpx ya,yb;
+ kiss_fft_cpx * Fout_beg = Fout;
+
+#ifdef FIXED_POINT
+ ya.r = QCONST32(0.30901699f, COEF_SHIFT-1);
+ ya.i = -QCONST32(0.95105652f, COEF_SHIFT-1);
+ yb.r = -QCONST32(0.80901699f, COEF_SHIFT-1);
+ yb.i = -QCONST32(0.58778525f, COEF_SHIFT-1);
+#else
+ ya = st->twiddles[fstride*m];
+ yb = st->twiddles[fstride*2*m];
+#endif
+ tw=st->twiddles;
+
+ for (i=0;i<N;i++)
+ {
+ Fout = Fout_beg + i*mm;
+ Fout0=Fout;
+ Fout1=Fout0+m;
+ Fout2=Fout0+2*m;
+ Fout3=Fout0+3*m;
+ Fout4=Fout0+4*m;
+
+ /* For non-custom modes, m is guaranteed to be a multiple of 4. */
+ for ( u=0; u<m; ++u ) {
+ scratch[0] = *Fout0;
+
+ C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
+ C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
+ C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
+ C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
+
+ C_ADD( scratch[7],scratch[1],scratch[4]);
+ C_SUB( scratch[10],scratch[1],scratch[4]);
+ C_ADD( scratch[8],scratch[2],scratch[3]);
+ C_SUB( scratch[9],scratch[2],scratch[3]);
+
+ Fout0->r = ADD32_ovflw(Fout0->r, ADD32_ovflw(scratch[7].r, scratch[8].r));
+ Fout0->i = ADD32_ovflw(Fout0->i, ADD32_ovflw(scratch[7].i, scratch[8].i));
+
+ scratch[5].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,ya.r), S_MUL(scratch[8].r,yb.r)));
+ scratch[5].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,ya.r), S_MUL(scratch[8].i,yb.r)));
+
+ scratch[6].r = ADD32_ovflw(S_MUL(scratch[10].i,ya.i), S_MUL(scratch[9].i,yb.i));
+ scratch[6].i = NEG32_ovflw(ADD32_ovflw(S_MUL(scratch[10].r,ya.i), S_MUL(scratch[9].r,yb.i)));
+
+ C_SUB(*Fout1,scratch[5],scratch[6]);
+ C_ADD(*Fout4,scratch[5],scratch[6]);
+
+ scratch[11].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,yb.r), S_MUL(scratch[8].r,ya.r)));
+ scratch[11].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,yb.r), S_MUL(scratch[8].i,ya.r)));
+ scratch[12].r = SUB32_ovflw(S_MUL(scratch[9].i,ya.i), S_MUL(scratch[10].i,yb.i));
+ scratch[12].i = SUB32_ovflw(S_MUL(scratch[10].r,yb.i), S_MUL(scratch[9].r,ya.i));
+
+ C_ADD(*Fout2,scratch[11],scratch[12]);
+ C_SUB(*Fout3,scratch[11],scratch[12]);
+
+ ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
+ }
+ }
+}
+#endif /* OVERRIDE_kf_bfly5 */
+
+
+#endif
+
+
+#ifdef CUSTOM_MODES
+
+static
+void compute_bitrev_table(
+ int Fout,
+ opus_int16 *f,
+ const size_t fstride,
+ int in_stride,
+ opus_int16 * factors,
+ const kiss_fft_state *st
+ )
+{
+ const int p=*factors++; /* the radix */
+ const int m=*factors++; /* stage's fft length/p */
+
+ /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/
+ if (m==1)
+ {
+ int j;
+ for (j=0;j<p;j++)
+ {
+ *f = Fout+j;
+ f += fstride*in_stride;
+ }
+ } else {
+ int j;
+ for (j=0;j<p;j++)
+ {
+ compute_bitrev_table( Fout , f, fstride*p, in_stride, factors,st);
+ f += fstride*in_stride;
+ Fout += m;
+ }
+ }
+}
+
+/* facbuf is populated by p1,m1,p2,m2, ...
+ where
+ p[i] * m[i] = m[i-1]
+ m0 = n */
+static
+int kf_factor(int n,opus_int16 * facbuf)
+{
+ int p=4;
+ int i;
+ int stages=0;
+ int nbak = n;
+
+ /*factor out powers of 4, powers of 2, then any remaining primes */
+ do {
+ while (n % p) {
+ switch (p) {
+ case 4: p = 2; break;
+ case 2: p = 3; break;
+ default: p += 2; break;
+ }
+ if (p>32000 || (opus_int32)p*(opus_int32)p > n)
+ p = n; /* no more factors, skip to end */
+ }
+ n /= p;
+#ifdef RADIX_TWO_ONLY
+ if (p!=2 && p != 4)
+#else
+ if (p>5)
+#endif
+ {
+ return 0;
+ }
+ facbuf[2*stages] = p;
+ if (p==2 && stages > 1)
+ {
+ facbuf[2*stages] = 4;
+ facbuf[2] = 2;
+ }
+ stages++;
+ } while (n > 1);
+ n = nbak;
+ /* Reverse the order to get the radix 4 at the end, so we can use the
+ fast degenerate case. It turns out that reversing the order also
+ improves the noise behaviour. */
+ for (i=0;i<stages/2;i++)
+ {
+ int tmp;
+ tmp = facbuf[2*i];
+ facbuf[2*i] = facbuf[2*(stages-i-1)];
+ facbuf[2*(stages-i-1)] = tmp;
+ }
+ for (i=0;i<stages;i++)
+ {
+ n /= facbuf[2*i];
+ facbuf[2*i+1] = n;
+ }
+ return 1;
+}
+
+static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
+{
+ int i;
+#ifdef FIXED_POINT
+ for (i=0;i<nfft;++i) {
+ opus_val32 phase = -i;
+#ifdef ENABLE_QEXT
+ twiddles[i].r = (int)MIN32(2147483647, floor(.5+2147483648*cos((2*M_PI/nfft)*phase)));
+ twiddles[i].i = (int)MIN32(2147483647, floor(.5+2147483648*sin((2*M_PI/nfft)*phase)));
+#else
+ kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft));
+#endif
+ }
+#else
+ for (i=0;i<nfft;++i) {
+ const double pi=3.14159265358979323846264338327;
+ double phase = ( -2*pi /nfft ) * i;
+ kf_cexp(twiddles+i, phase );
+ }
+#endif
+}
+
+int opus_fft_alloc_arch_c(kiss_fft_state *st) {
+ (void)st;
+ return 0;
+}
+
+/*
+ *
+ * Allocates all necessary storage space for the fft and ifft.
+ * The return value is a contiguous block of memory. As such,
+ * It can be freed with free().
+ * */
+kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,
+ const kiss_fft_state *base, int arch)
+{
+ kiss_fft_state *st=NULL;
+ size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/
+
+ if ( lenmem==NULL ) {
+ st = ( kiss_fft_state*)KISS_FFT_MALLOC( memneeded );
+ }else{
+ if (mem != NULL && *lenmem >= memneeded)
+ st = (kiss_fft_state*)mem;
+ *lenmem = memneeded;
+ }
+ if (st) {
+ opus_int16 *bitrev;
+ kiss_twiddle_cpx *twiddles;
+
+ st->nfft=nfft;
+#ifdef FIXED_POINT
+ st->scale_shift = celt_ilog2(st->nfft);
+# ifdef ENABLE_QEXT
+ if (st->nfft == 1<<st->scale_shift)
+ st->scale = QCONST32(1.0f, 30);
+ else
+ st->scale = (((opus_int64)1073741824<<st->scale_shift)+st->nfft/2)/st->nfft;
+# else
+ if (st->nfft == 1<<st->scale_shift)
+ st->scale = Q15ONE;
+ else
+ st->scale = (1073741824+st->nfft/2)/st->nfft>>(15-st->scale_shift);
+# endif
+#else
+ st->scale = 1.f/nfft;
+#endif
+ if (base != NULL)
+ {
+ st->twiddles = base->twiddles;
+ st->shift = 0;
+ while (st->shift < 32 && nfft<<st->shift != base->nfft)
+ st->shift++;
+ if (st->shift>=32)
+ goto fail;
+ } else {
+ st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft);
+ compute_twiddles(twiddles, nfft);
+ st->shift = -1;
+ }
+ if (!kf_factor(nfft,st->factors))
+ {
+ goto fail;
+ }
+
+ /* bitrev */
+ st->bitrev = bitrev = (opus_int16*)KISS_FFT_MALLOC(sizeof(opus_int16)*nfft);
+ if (st->bitrev==NULL)
+ goto fail;
+ compute_bitrev_table(0, bitrev, 1,1, st->factors,st);
+
+ /* Initialize architecture specific fft parameters */
+ if (opus_fft_alloc_arch(st, arch))
+ goto fail;
+ }
+ return st;
+fail:
+ opus_fft_free(st, arch);
+ return NULL;
+}
+
+kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch)
+{
+ return opus_fft_alloc_twiddles(nfft, mem, lenmem, NULL, arch);
+}
+
+void opus_fft_free_arch_c(kiss_fft_state *st) {
+ (void)st;
+}
+
+void opus_fft_free(const kiss_fft_state *cfg, int arch)
+{
+ if (cfg)
+ {
+ opus_fft_free_arch((kiss_fft_state *)cfg, arch);
+ opus_free((opus_int16*)cfg->bitrev);
+ if (cfg->shift < 0)
+ opus_free((kiss_twiddle_cpx*)cfg->twiddles);
+ opus_free((kiss_fft_state*)cfg);
+ }
+}
+
+#endif /* CUSTOM_MODES */
+
+#ifdef FIXED_POINT
+#ifndef OVERRIDE_fft_downshift
+static void fft_downshift(kiss_fft_cpx *x, int N, int *total, int step) {
+ int shift;
+ shift = IMIN(step, *total);
+ *total -= shift;
+ if (shift == 1) {
+ int i;
+ for (i=0;i<N;i++) {
+ x[i].r = SHR32(x[i].r, 1);
+ x[i].i = SHR32(x[i].i, 1);
+ }
+ } else if (shift>0) {
+ int i;
+ for (i=0;i<N;i++) {
+ x[i].r = PSHR32(x[i].r, shift);
+ x[i].i = PSHR32(x[i].i, shift);
+ }
+ }
+}
+#endif /* OVERRIDE_fft_downshift */
+#else
+#define fft_downshift(x, N, total, step)
+#endif
+
+void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout ARG_FIXED(int downshift))
+{
+ int m2, m;
+ int p;
+ int L;
+ int fstride[MAXFACTORS];
+ int i;
+ int shift;
+
+ /* st->shift can be -1 */
+ shift = st->shift>0 ? st->shift : 0;
+
+ fstride[0] = 1;
+ L=0;
+ do {
+ p = st->factors[2*L];
+ m = st->factors[2*L+1];
+ fstride[L+1] = fstride[L]*p;
+ L++;
+ } while(m!=1);
+ m = st->factors[2*L-1];
+ for (i=L-1;i>=0;i--)
+ {
+ if (i!=0)
+ m2 = st->factors[2*i-1];
+ else
+ m2 = 1;
+ switch (st->factors[2*i])
+ {
+ case 2:
+ fft_downshift(fout, st->nfft, &downshift, 1);
+ kf_bfly2(fout, m, fstride[i]);
+ break;
+ case 4:
+ fft_downshift(fout, st->nfft, &downshift, 2);
+ kf_bfly4(fout,fstride[i]<<shift,st,m, fstride[i], m2);
+ break;
+ #ifndef RADIX_TWO_ONLY
+ case 3:
+ fft_downshift(fout, st->nfft, &downshift, 2);
+ kf_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2);
+ break;
+ case 5:
+ fft_downshift(fout, st->nfft, &downshift, 3);
+ kf_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2);
+ break;
+ #endif
+ }
+ m = m2;
+ }
+ fft_downshift(fout, st->nfft, &downshift, downshift);
+}
+
+void opus_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
+{
+ int i;
+ celt_coef scale;
+#ifdef FIXED_POINT
+ /* Allows us to scale with MULT16_32_Q16(), which is faster than
+ MULT16_32_Q15() on ARM. */
+ int scale_shift = st->scale_shift-1;
+#endif
+ scale = st->scale;
+
+ celt_assert2 (fin != fout, "In-place FFT not supported");
+ /* Bit-reverse the input */
+ for (i=0;i<st->nfft;i++)
+ {
+ kiss_fft_cpx x = fin[i];
+ fout[st->bitrev[i]].r = S_MUL2(x.r, scale);
+ fout[st->bitrev[i]].i = S_MUL2(x.i, scale);
+ }
+ opus_fft_impl(st, fout ARG_FIXED(scale_shift));
+}
+
+
+void opus_ifft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
+{
+ int i;
+ celt_assert2 (fin != fout, "In-place FFT not supported");
+ /* Bit-reverse the input */
+ for (i=0;i<st->nfft;i++)
+ fout[st->bitrev[i]] = fin[i];
+ for (i=0;i<st->nfft;i++)
+ fout[i].i = -fout[i].i;
+ opus_fft_impl(st, fout ARG_FIXED(0));
+ for (i=0;i<st->nfft;i++)
+ fout[i].i = -fout[i].i;
+}
--- /dev/null
+/*Copyright (c) 2003-2004, Mark Borgerding
+ Lots of modifications by Jean-Marc Valin
+ Copyright (c) 2005-2007, Xiph.Org Foundation
+ Copyright (c) 2008, Xiph.Org Foundation, CSIRO
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 KISS_FFT_H
+#define KISS_FFT_H
+
+#include <stdlib.h>
+#include <math.h>
+#include "arch.h"
+#include "cpu_support.h"
+
+#ifdef USE_SIMD
+# include <xmmintrin.h>
+# define kiss_fft_scalar __m128
+#define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes)
+#else
+#define KISS_FFT_MALLOC opus_alloc
+#endif
+
+#ifdef FIXED_POINT
+#include "arch.h"
+
+# define kiss_fft_scalar opus_int32
+# ifdef ENABLE_QEXT
+# define COEF_SHIFT 32
+# else
+# define COEF_SHIFT 16
+# endif
+
+# define kiss_twiddle_scalar celt_coef
+
+/* Some 32-bit CPUs would load/store a kiss_twiddle_cpx with a single memory
+ * access, and could benefit from additional alignment.
+ */
+# define KISS_TWIDDLE_CPX_ALIGNMENT (sizeof(opus_int32))
+
+#else
+
+# ifndef kiss_fft_scalar
+/* default is float */
+# define kiss_fft_scalar float
+# define kiss_twiddle_scalar float
+# define KF_SUFFIX _celt_single
+# endif
+#endif
+
+#if defined(__GNUC__) && defined(KISS_TWIDDLE_CPX_ALIGNMENT)
+#define KISS_TWIDDLE_CPX_ALIGNED __attribute__((aligned(KISS_TWIDDLE_CPX_ALIGNMENT)))
+#else
+#define KISS_TWIDDLE_CPX_ALIGNED
+#endif
+
+typedef struct {
+ kiss_fft_scalar r;
+ kiss_fft_scalar i;
+}kiss_fft_cpx;
+
+typedef struct {
+ kiss_twiddle_scalar r;
+ kiss_twiddle_scalar i;
+} KISS_TWIDDLE_CPX_ALIGNED kiss_twiddle_cpx;
+
+#define MAXFACTORS 8
+/* e.g. an fft of length 128 has 4 factors
+ as far as kissfft is concerned
+ 4*4*4*2
+ */
+
+typedef struct arch_fft_state{
+ int is_supported;
+ void *priv;
+} arch_fft_state;
+
+typedef struct kiss_fft_state{
+ int nfft;
+ celt_coef scale;
+#ifdef FIXED_POINT
+ int scale_shift;
+#endif
+ int shift;
+ opus_int16 factors[2*MAXFACTORS];
+ const opus_int16 *bitrev;
+ const kiss_twiddle_cpx *twiddles;
+ arch_fft_state *arch_fft;
+} kiss_fft_state;
+
+#if defined(HAVE_ARM_NE10)
+#include "arm/fft_arm.h"
+#endif
+
+/*typedef struct kiss_fft_state* kiss_fft_cfg;*/
+
+/**
+ * opus_fft_alloc
+ *
+ * Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
+ *
+ * typical usage: kiss_fft_cfg mycfg=opus_fft_alloc(1024,0,NULL,NULL);
+ *
+ * The return value from fft_alloc is a cfg buffer used internally
+ * by the fft routine or NULL.
+ *
+ * If lenmem is NULL, then opus_fft_alloc will allocate a cfg buffer using malloc.
+ * The returned value should be free()d when done to avoid memory leaks.
+ *
+ * The state can be placed in a user supplied buffer 'mem':
+ * If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
+ * then the function places the cfg in mem and the size used in *lenmem
+ * and returns mem.
+ *
+ * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
+ * then the function returns NULL and places the minimum cfg
+ * buffer size in *lenmem.
+ * */
+
+kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base, int arch);
+
+kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch);
+
+/**
+ * opus_fft(cfg,in_out_buf)
+ *
+ * Perform an FFT on a complex input buffer.
+ * for a forward FFT,
+ * fin should be f[0] , f[1] , ... ,f[nfft-1]
+ * fout will be F[0] , F[1] , ... ,F[nfft-1]
+ * Note that each element is complex and can be accessed like
+ f[k].r and f[k].i
+ * */
+void opus_fft_c(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
+void opus_ifft_c(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
+
+void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout ARG_FIXED(int downshift));
+void opus_ifft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout);
+
+void opus_fft_free(const kiss_fft_state *cfg, int arch);
+
+
+void opus_fft_free_arch_c(kiss_fft_state *st);
+int opus_fft_alloc_arch_c(kiss_fft_state *st);
+
+#if !defined(OVERRIDE_OPUS_FFT)
+/* Is run-time CPU detection enabled on this platform? */
+#if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10))
+
+extern int (*const OPUS_FFT_ALLOC_ARCH_IMPL[OPUS_ARCHMASK+1])(
+ kiss_fft_state *st);
+
+#define opus_fft_alloc_arch(_st, arch) \
+ ((*OPUS_FFT_ALLOC_ARCH_IMPL[(arch)&OPUS_ARCHMASK])(_st))
+
+extern void (*const OPUS_FFT_FREE_ARCH_IMPL[OPUS_ARCHMASK+1])(
+ kiss_fft_state *st);
+#define opus_fft_free_arch(_st, arch) \
+ ((*OPUS_FFT_FREE_ARCH_IMPL[(arch)&OPUS_ARCHMASK])(_st))
+
+extern void (*const OPUS_FFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg,
+ const kiss_fft_cpx *fin, kiss_fft_cpx *fout);
+#define opus_fft(_cfg, _fin, _fout, arch) \
+ ((*OPUS_FFT[(arch)&OPUS_ARCHMASK])(_cfg, _fin, _fout))
+
+extern void (*const OPUS_IFFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg,
+ const kiss_fft_cpx *fin, kiss_fft_cpx *fout);
+#define opus_ifft(_cfg, _fin, _fout, arch) \
+ ((*OPUS_IFFT[(arch)&OPUS_ARCHMASK])(_cfg, _fin, _fout))
+
+#else /* else for if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) */
+
+#define opus_fft_alloc_arch(_st, arch) \
+ ((void)(arch), opus_fft_alloc_arch_c(_st))
+
+#define opus_fft_free_arch(_st, arch) \
+ ((void)(arch), opus_fft_free_arch_c(_st))
+
+#define opus_fft(_cfg, _fin, _fout, arch) \
+ ((void)(arch), opus_fft_c(_cfg, _fin, _fout))
+
+#define opus_ifft(_cfg, _fin, _fout, arch) \
+ ((void)(arch), opus_ifft_c(_cfg, _fin, _fout))
+
+#endif /* end if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) */
+#endif /* end if !defined(OVERRIDE_OPUS_FFT) */
+
+#endif
--- /dev/null
+/* Copyright (c) 2007 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "laplace.h"
+#include "mathops.h"
+
+/* The minimum probability of an energy delta (out of 32768). */
+#define LAPLACE_LOG_MINP (0)
+#define LAPLACE_MINP (1<<LAPLACE_LOG_MINP)
+/* The minimum number of guaranteed representable energy deltas (in one
+ direction). */
+#define LAPLACE_NMIN (16)
+
+/* When called, decay is positive and at most 11456. */
+static unsigned ec_laplace_get_freq1(unsigned fs0, int decay)
+{
+ unsigned ft;
+ ft = 32768 - LAPLACE_MINP*(2*LAPLACE_NMIN) - fs0;
+ return ft*(opus_int32)(16384-decay)>>15;
+}
+
+void ec_laplace_encode(ec_enc *enc, int *value, unsigned fs, int decay)
+{
+ unsigned fl;
+ int val = *value;
+ fl = 0;
+ if (val)
+ {
+ int s;
+ int i;
+ s = -(val<0);
+ val = (val+s)^s;
+ fl = fs;
+ fs = ec_laplace_get_freq1(fs, decay);
+ /* Search the decaying part of the PDF.*/
+ for (i=1; fs > 0 && i < val; i++)
+ {
+ fs *= 2;
+ fl += fs+2*LAPLACE_MINP;
+ fs = (fs*(opus_int32)decay)>>15;
+ }
+ /* Everything beyond that has probability LAPLACE_MINP. */
+ if (!fs)
+ {
+ int di;
+ int ndi_max;
+ ndi_max = (32768-fl+LAPLACE_MINP-1)>>LAPLACE_LOG_MINP;
+ ndi_max = (ndi_max-s)>>1;
+ di = IMIN(val - i, ndi_max - 1);
+ fl += (2*di+1+s)*LAPLACE_MINP;
+ fs = IMIN(LAPLACE_MINP, 32768-fl);
+ *value = (i+di+s)^s;
+ }
+ else
+ {
+ fs += LAPLACE_MINP;
+ fl += fs&~s;
+ }
+ celt_assert(fl+fs<=32768);
+ celt_assert(fs>0);
+ }
+ ec_encode_bin(enc, fl, fl+fs, 15);
+}
+
+int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay)
+{
+ int val=0;
+ unsigned fl;
+ unsigned fm;
+ fm = ec_decode_bin(dec, 15);
+ fl = 0;
+ if (fm >= fs)
+ {
+ val++;
+ fl = fs;
+ fs = ec_laplace_get_freq1(fs, decay)+LAPLACE_MINP;
+ /* Search the decaying part of the PDF.*/
+ while(fs > LAPLACE_MINP && fm >= fl+2*fs)
+ {
+ fs *= 2;
+ fl += fs;
+ fs = ((fs-2*LAPLACE_MINP)*(opus_int32)decay)>>15;
+ fs += LAPLACE_MINP;
+ val++;
+ }
+ /* Everything beyond that has probability LAPLACE_MINP. */
+ if (fs <= LAPLACE_MINP)
+ {
+ int di;
+ di = (fm-fl)>>(LAPLACE_LOG_MINP+1);
+ val += di;
+ fl += 2*di*LAPLACE_MINP;
+ }
+ if (fm < fl+fs)
+ val = -val;
+ else
+ fl += fs;
+ }
+ celt_assert(fl<32768);
+ celt_assert(fs>0);
+ celt_assert(fl<=fm);
+ celt_assert(fm<IMIN(fl+fs,32768));
+ ec_dec_update(dec, fl, IMIN(fl+fs,32768), 32768);
+ return val;
+}
+
+void ec_laplace_encode_p0(ec_enc *enc, int value, opus_uint16 p0, opus_uint16 decay)
+{
+ int s;
+ opus_uint16 sign_icdf[3];
+ sign_icdf[0] = 32768-p0;
+ sign_icdf[1] = sign_icdf[0]/2;
+ sign_icdf[2] = 0;
+ s = value == 0 ? 0 : (value > 0 ? 1 : 2);
+ ec_enc_icdf16(enc, s, sign_icdf, 15);
+ value = abs(value);
+ if (value)
+ {
+ int i;
+ opus_uint16 icdf[8];
+ icdf[0] = IMAX(7, decay);
+ for (i=1;i<7;i++)
+ {
+ icdf[i] = IMAX(7-i, (icdf[i-1] * (opus_int32)decay) >> 15);
+ }
+ icdf[7] = 0;
+ value--;
+ do {
+ ec_enc_icdf16(enc, IMIN(value, 7), icdf, 15);
+ value -= 7;
+ } while (value >= 0);
+ }
+}
+
+int ec_laplace_decode_p0(ec_dec *dec, opus_uint16 p0, opus_uint16 decay)
+{
+ int s;
+ int value;
+ opus_uint16 sign_icdf[3];
+ sign_icdf[0] = 32768-p0;
+ sign_icdf[1] = sign_icdf[0]/2;
+ sign_icdf[2] = 0;
+ s = ec_dec_icdf16(dec, sign_icdf, 15);
+ if (s==2) s = -1;
+ if (s != 0)
+ {
+ int i;
+ int v;
+ opus_uint16 icdf[8];
+ icdf[0] = IMAX(7, decay);
+ for (i=1;i<7;i++)
+ {
+ icdf[i] = IMAX(7-i, (icdf[i-1] * (opus_int32)decay) >> 15);
+ }
+ icdf[7] = 0;
+ value = 1;
+ do {
+ v = ec_dec_icdf16(dec, icdf, 15);
+ value += v;
+ } while (v == 7);
+ return s*value;
+ } else return 0;
+}
+
+#if 0
+
+#include <stdio.h>
+#define NB_VALS 10
+#define DATA_SIZE 10000
+int main() {
+ ec_enc enc;
+ ec_dec dec;
+ unsigned char *ptr;
+ int i;
+ int decay, p0;
+ int val[NB_VALS] = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+ /*for (i=0;i<NB_VALS;i++) {
+ val[i] = -log(rand()/(float)RAND_MAX);
+ if (rand()%2) val[i] = -val[i];
+ }*/
+ p0 = 16000;
+ decay = 16000;
+ ptr = (unsigned char *)malloc(DATA_SIZE);
+ ec_enc_init(&enc,ptr,DATA_SIZE);
+ for (i=0;i<NB_VALS;i++) {
+ printf("%d ", val[i]);
+ }
+ printf("\n");
+ for (i=0;i<NB_VALS;i++) {
+ ec_laplace_encode_p0(&enc, val[i], p0, decay);
+ }
+
+ ec_enc_done(&enc);
+
+ ec_dec_init(&dec,ec_get_buffer(&enc),ec_range_bytes(&enc));
+
+ for (i=0;i<NB_VALS;i++) {
+ val[i] = ec_laplace_decode_p0(&dec, p0, decay);
+ }
+ for (i=0;i<NB_VALS;i++) {
+ printf("%d ", val[i]);
+ }
+ printf("\n");
+}
+
+#endif
--- /dev/null
+/* Copyright (c) 2007 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 LAPLACE_H
+#define LAPLACE_H
+
+#include "entenc.h"
+#include "entdec.h"
+
+/** Encode a value that is assumed to be the realisation of a
+ Laplace-distributed random process
+ @param enc Entropy encoder state
+ @param value Value to encode
+ @param fs Probability of 0, multiplied by 32768
+ @param decay Probability of the value +/- 1, multiplied by 16384
+*/
+void ec_laplace_encode(ec_enc *enc, int *value, unsigned fs, int decay);
+
+/** Decode a value that is assumed to be the realisation of a
+ Laplace-distributed random process
+ @param dec Entropy decoder state
+ @param fs Probability of 0, multiplied by 32768
+ @param decay Probability of the value +/- 1, multiplied by 16384
+ @return Value decoded
+ */
+int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay);
+
+
+int ec_laplace_decode_p0(ec_dec *dec, opus_uint16 p0, opus_uint16 decay);
+void ec_laplace_encode_p0(ec_enc *enc, int value, opus_uint16 p0, opus_uint16 decay);
+
+#endif
--- /dev/null
+/* Copyright (c) 2002-2008 Jean-Marc Valin
+ Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Copyright (c) 2024 Arm Limited
+ Written by Jean-Marc Valin */
+/**
+ @file mathops.h
+ @brief Various math functions
+*/
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "float_cast.h"
+#include "mathops.h"
+
+/*Compute floor(sqrt(_val)) with exact arithmetic.
+ _val must be greater than 0.
+ This has been tested on all possible 32-bit inputs greater than 0.*/
+unsigned isqrt32(opus_uint32 _val){
+ unsigned b;
+ unsigned g;
+ int bshift;
+ /*Uses the second method from
+ http://www.azillionmonkeys.com/qed/sqroot.html
+ The main idea is to search for the largest binary digit b such that
+ (g+b)*(g+b) <= _val, and add it to the solution g.*/
+ g=0;
+ bshift=(EC_ILOG(_val)-1)>>1;
+ b=1U<<bshift;
+ do{
+ opus_uint32 t;
+ t=(((opus_uint32)g<<1)+b)<<bshift;
+ if(t<=_val){
+ g+=b;
+ _val-=t;
+ }
+ b>>=1;
+ bshift--;
+ }
+ while(bshift>=0);
+ return g;
+}
+
+#ifdef FIXED_POINT
+
+opus_val32 frac_div32_q29(opus_val32 a, opus_val32 b)
+{
+ opus_val16 rcp;
+ opus_val32 result, rem;
+ int shift = celt_ilog2(b)-29;
+ a = VSHR32(a,shift);
+ b = VSHR32(b,shift);
+ /* 16-bit reciprocal */
+ rcp = ROUND16(celt_rcp(ROUND16(b,16)),3);
+ result = MULT16_32_Q15(rcp, a);
+ rem = PSHR32(a,2)-MULT32_32_Q31(result, b);
+ result = ADD32(result, SHL32(MULT16_32_Q15(rcp, rem),2));
+ return result;
+}
+
+opus_val32 frac_div32(opus_val32 a, opus_val32 b) {
+ opus_val32 result = frac_div32_q29(a,b);
+ if (result >= 536870912) /* 2^29 */
+ return 2147483647; /* 2^31 - 1 */
+ else if (result <= -536870912) /* -2^29 */
+ return -2147483647; /* -2^31 */
+ else
+ return SHL32(result, 2);
+}
+
+/** Reciprocal sqrt approximation in the range [0.25,1) (Q16 in, Q14 out) */
+opus_val16 celt_rsqrt_norm(opus_val32 x)
+{
+ opus_val16 n;
+ opus_val16 r;
+ opus_val16 r2;
+ opus_val16 y;
+ /* Range of n is [-16384,32767] ([-0.5,1) in Q15). */
+ n = x-32768;
+ /* Get a rough initial guess for the root.
+ The optimal minimax quadratic approximation (using relative error) is
+ r = 1.437799046117536+n*(-0.823394375837328+n*0.4096419668459485).
+ Coefficients here, and the final result r, are Q14.*/
+ r = ADD16(23557, MULT16_16_Q15(n, ADD16(-13490, MULT16_16_Q15(n, 6713))));
+ /* We want y = x*r*r-1 in Q15, but x is 32-bit Q16 and r is Q14.
+ We can compute the result from n and r using Q15 multiplies with some
+ adjustment, carefully done to avoid overflow.
+ Range of y is [-1564,1594]. */
+ r2 = MULT16_16_Q15(r, r);
+ y = SHL16(SUB16(ADD16(MULT16_16_Q15(r2, n), r2), 16384), 1);
+ /* Apply a 2nd-order Householder iteration: r += r*y*(y*0.375-0.5).
+ This yields the Q14 reciprocal square root of the Q16 x, with a maximum
+ relative error of 1.04956E-4, a (relative) RMSE of 2.80979E-5, and a
+ peak absolute error of 2.26591/16384. */
+ return ADD16(r, MULT16_16_Q15(r, MULT16_16_Q15(y,
+ SUB16(MULT16_16_Q15(y, 12288), 16384))));
+}
+
+/** Reciprocal sqrt approximation in the range [0.25,1) (Q31 in, Q29 out) */
+opus_val32 celt_rsqrt_norm32(opus_val32 x)
+{
+ opus_int32 tmp;
+ /* Use the first-order Newton-Raphson method to refine the root estimate.
+ * r = r * (1.5 - 0.5*x*r*r) */
+ opus_int32 r_q29 = SHL32(celt_rsqrt_norm(SHR32(x, 31-16)), 15);
+ /* Split evaluation in steps to avoid exploding macro expansion. */
+ tmp = MULT32_32_Q31(r_q29, r_q29);
+ tmp = MULT32_32_Q31(1073741824 /* Q31 */, tmp);
+ tmp = MULT32_32_Q31(x, tmp);
+ return SHL32(MULT32_32_Q31(r_q29, SUB32(201326592 /* Q27 */, tmp)), 4);
+}
+
+/** Sqrt approximation (QX input, QX/2 output) */
+opus_val32 celt_sqrt(opus_val32 x)
+{
+ int k;
+ opus_val16 n;
+ opus_val32 rt;
+ /* These coeffs are optimized in fixed-point to minimize both RMS and max error
+ of sqrt(x) over .25<x<1 without exceeding 32767.
+ The RMS error is 3.4e-5 and the max is 8.2e-5. */
+ static const opus_val16 C[6] = {23171, 11574, -2901, 1592, -1002, 336};
+ if (x==0)
+ return 0;
+ else if (x>=1073741824)
+ return 32767;
+ k = (celt_ilog2(x)>>1)-7;
+ x = VSHR32(x, 2*k);
+ n = x-32768;
+ rt = ADD32(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2],
+ MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, ADD16(C[4], MULT16_16_Q15(n, (C[5])))))))))));
+ rt = VSHR32(rt,7-k);
+ return rt;
+}
+
+/* Perform fixed-point arithmetic to approximate the square root. When the input
+ * is in Qx format, the output will be in Q(x/2 + 16) format. */
+opus_val32 celt_sqrt32(opus_val32 x)
+{
+ int k;
+ opus_int32 x_frac;
+ if (x==0)
+ return 0;
+ else if (x>=1073741824)
+ return 2147483647; /* 2^31 -1 */
+ k = (celt_ilog2(x)>>1);
+ x_frac = VSHR32(x, 2*(k-14)-1);
+ x_frac = MULT32_32_Q31(celt_rsqrt_norm32(x_frac), x_frac);
+ if (k < 12) return PSHR32(x_frac, 12-k);
+ else return SHL32(x_frac, k-12);
+}
+
+#define L1 32767
+#define L2 -7651
+#define L3 8277
+#define L4 -626
+
+static OPUS_INLINE opus_val16 _celt_cos_pi_2(opus_val16 x)
+{
+ opus_val16 x2;
+
+ x2 = MULT16_16_P15(x,x);
+ return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2
+ ))))))));
+}
+
+#undef L1
+#undef L2
+#undef L3
+#undef L4
+
+opus_val16 celt_cos_norm(opus_val32 x)
+{
+ x = x&0x0001ffff;
+ if (x>SHL32(EXTEND32(1), 16))
+ x = SUB32(SHL32(EXTEND32(1), 17),x);
+ if (x&0x00007fff)
+ {
+ if (x<SHL32(EXTEND32(1), 15))
+ {
+ return _celt_cos_pi_2(EXTRACT16(x));
+ } else {
+ return NEG16(_celt_cos_pi_2(EXTRACT16(65536-x)));
+ }
+ } else {
+ if (x&0x0000ffff)
+ return 0;
+ else if (x&0x0001ffff)
+ return -32767;
+ else
+ return 32767;
+ }
+}
+
+/* Calculates the cosine of (PI*0.5*x) where the input x ranges from -1 to 1 and
+ * is in Q30 format. The output will also be in Q31 format. */
+opus_val32 celt_cos_norm32(opus_val32 x)
+{
+ static const opus_val32 COS_NORM_COEFF_A0 = 134217720; /* Q27 */
+ static const opus_val32 COS_NORM_COEFF_A1 = -662336704; /* Q29 */
+ static const opus_val32 COS_NORM_COEFF_A2 = 544710848; /* Q31 */
+ static const opus_val32 COS_NORM_COEFF_A3 = -178761936; /* Q33 */
+ static const opus_val32 COS_NORM_COEFF_A4 = 29487206; /* Q35 */
+ opus_int32 x_sq_q29, tmp;
+ /* The expected x is in the range of [-1.0f, 1.0f] */
+ celt_sig_assert((x >= -1073741824) && (x <= 1073741824));
+ /* Make cos(+/- pi/2) exactly zero. */
+ if (ABS32(x) == 1<<30) return 0;
+ x_sq_q29 = MULT32_32_Q31(x, x);
+ /* Split evaluation in steps to avoid exploding macro expansion. */
+ tmp = ADD32(COS_NORM_COEFF_A3, MULT32_32_Q31(x_sq_q29, COS_NORM_COEFF_A4));
+ tmp = ADD32(COS_NORM_COEFF_A2, MULT32_32_Q31(x_sq_q29, tmp));
+ tmp = ADD32(COS_NORM_COEFF_A1, MULT32_32_Q31(x_sq_q29, tmp));
+ return SHL32(ADD32(COS_NORM_COEFF_A0, MULT32_32_Q31(x_sq_q29, tmp)), 4);
+}
+
+/* Computes a 16 bit approximate reciprocal (1/x) for a normalized Q15 input,
+ * resulting in a Q15 output. */
+opus_val16 celt_rcp_norm16(opus_val16 x)
+{
+ opus_val16 r;
+ /* Start with a linear approximation:
+ r = 1.8823529411764706-0.9411764705882353*n.
+ The coefficients and the result are Q14 in the range [15420,30840].*/
+ r = ADD16(30840, MULT16_16_Q15(-15420, x));
+ /* Perform two Newton iterations:
+ r -= r*((r*n)+(r-1.Q15))
+ = r*((r*n)+(r-1.Q15)). */
+ r = SUB16(r, MULT16_16_Q15(r,
+ ADD16(MULT16_16_Q15(r, x), ADD16(r, -32768))));
+ /* We subtract an extra 1 in the second iteration to avoid overflow; it also
+ neatly compensates for truncation error in the rest of the process. */
+ return SUB16(r, ADD16(1, MULT16_16_Q15(r,
+ ADD16(MULT16_16_Q15(r, x), ADD16(r, -32768)))));
+}
+
+/* Computes a 32 bit approximated reciprocal (1/x) for a normalized Q31 input,
+ * resulting in a Q30 output. The expected input range is [0.5f, 1.0f) in Q31
+ * and the expected output range is [1.0f, 2.0f) in Q30. */
+opus_val32 celt_rcp_norm32(opus_val32 x)
+{
+ opus_val32 r_q30;
+ celt_sig_assert(x >= 1073741824);
+ r_q30 = SHL32(EXTEND32(celt_rcp_norm16(SHR32(x, 15)-32768)), 16);
+ /* Solving f(y) = a - 1/y using the Newton Method
+ * Note: f(y)' = 1/y^2
+ * r = r - f(r)/f(r)' = r - (x * r*r - r)
+ * = r - r*(r*x - 1)
+ * where
+ * - r means 1/y's approximation.
+ * - x means a, the input of function.
+ * Please note that:
+ * - It adds 1 to avoid overflow
+ * - -1.0f in Q30 is -1073741824. */
+ return SUB32(r_q30, ADD32(SHL32(
+ MULT32_32_Q31(ADD32(MULT32_32_Q31(r_q30, x), -1073741824),
+ r_q30), 1), 1));
+}
+
+/** Reciprocal approximation (Q15 input, Q16 output) */
+opus_val32 celt_rcp(opus_val32 x)
+{
+ int i;
+ opus_val16 r;
+ celt_sig_assert(x>0);
+ i = celt_ilog2(x);
+
+ /* Compute the reciprocal of a Q15 number in the range [0, 1). */
+ r = celt_rcp_norm16(VSHR32(x,i-15)-32768);
+
+ /* r is now the Q15 solution to 2/(n+1), with a maximum relative error
+ of 7.05346E-5, a (relative) RMSE of 2.14418E-5, and a peak absolute
+ error of 1.24665/32768. */
+ return VSHR32(EXTEND32(r),i-16);
+}
+
+#endif
+
+#ifndef DISABLE_FLOAT_API
+
+void celt_float2int16_c(const float * OPUS_RESTRICT in, short * OPUS_RESTRICT out, int cnt)
+{
+ int i;
+ for (i = 0; i < cnt; i++)
+ {
+ out[i] = FLOAT2INT16(in[i]);
+ }
+}
+
+int opus_limit2_checkwithin1_c(float * samples, int cnt)
+{
+ int i;
+ if (cnt <= 0)
+ {
+ return 1;
+ }
+
+ for (i = 0; i < cnt; i++)
+ {
+ float clippedVal = samples[i];
+ clippedVal = FMAX(-2.0f, clippedVal);
+ clippedVal = FMIN(2.0f, clippedVal);
+ samples[i] = clippedVal;
+ }
+
+ /* C implementation can't provide quick hint. Assume it might exceed -1/+1. */
+ return 0;
+}
+
+#endif /* DISABLE_FLOAT_API */
--- /dev/null
+/* Copyright (c) 2002-2008 Jean-Marc Valin
+ Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Copyright (c) 2024 Arm Limited
+ Written by Jean-Marc Valin, and Yunho Huh */
+/**
+ @file mathops.h
+ @brief Various math functions
+*/
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 MATHOPS_H
+#define MATHOPS_H
+
+#include "arch.h"
+#include "entcode.h"
+#include "os_support.h"
+
+
+#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+#include "arm/mathops_arm.h"
+#endif
+
+#define PI 3.1415926535897931
+
+/* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */
+#define FRAC_MUL16(a,b) ((16384+((opus_int32)(opus_int16)(a)*(opus_int16)(b)))>>15)
+
+unsigned isqrt32(opus_uint32 _val);
+
+/* CELT doesn't need it for fixed-point, by analysis.c does. */
+#if !defined(FIXED_POINT) || defined(ANALYSIS_C)
+#define cA 0.43157974f
+#define cB 0.67848403f
+#define cC 0.08595542f
+#define cE ((float)PI/2)
+static OPUS_INLINE float fast_atan2f(float y, float x) {
+ float x2, y2;
+ x2 = x*x;
+ y2 = y*y;
+ /* For very small values, we don't care about the answer, so
+ we can just return 0. */
+ if (x2 + y2 < 1e-18f)
+ {
+ return 0;
+ }
+ if(x2<y2){
+ float den = (y2 + cB*x2) * (y2 + cC*x2);
+ return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE);
+ }else{
+ float den = (x2 + cB*y2) * (x2 + cC*y2);
+ return x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
+ }
+}
+#undef cA
+#undef cB
+#undef cC
+#undef cE
+#endif
+
+
+#ifndef OVERRIDE_CELT_MAXABS16
+static OPUS_INLINE opus_val32 celt_maxabs16(const opus_val16 *x, int len)
+{
+ int i;
+ opus_val16 maxval = 0;
+ opus_val16 minval = 0;
+ for (i=0;i<len;i++)
+ {
+ maxval = MAX16(maxval, x[i]);
+ minval = MIN16(minval, x[i]);
+ }
+ return MAX32(EXTEND32(maxval),-EXTEND32(minval));
+}
+#endif
+
+#if defined(ENABLE_RES24) && defined(FIXED_POINT)
+static OPUS_INLINE opus_res celt_maxabs_res(const opus_res *x, int len)
+{
+ int i;
+ opus_res maxval = 0;
+ opus_res minval = 0;
+ for (i=0;i<len;i++)
+ {
+ maxval = MAX32(maxval, x[i]);
+ minval = MIN32(minval, x[i]);
+ }
+ /* opus_res should never reach such amplitude, so we should be safe. */
+ celt_sig_assert(minval != -2147483648);
+ return MAX32(maxval,-minval);
+}
+#else
+#define celt_maxabs_res celt_maxabs16
+#endif
+
+
+#ifndef OVERRIDE_CELT_MAXABS32
+#ifdef FIXED_POINT
+static OPUS_INLINE opus_val32 celt_maxabs32(const opus_val32 *x, int len)
+{
+ int i;
+ opus_val32 maxval = 0;
+ opus_val32 minval = 0;
+ for (i=0;i<len;i++)
+ {
+ maxval = MAX32(maxval, x[i]);
+ minval = MIN32(minval, x[i]);
+ }
+ return MAX32(maxval, -minval);
+}
+#else
+#define celt_maxabs32(x,len) celt_maxabs16(x,len)
+#endif
+#endif
+
+#ifndef FIXED_POINT
+/* Calculates the arctangent of x using a Remez approximation of order 15,
+ * incorporating only odd-powered terms. */
+static OPUS_INLINE float celt_atan_norm(float x)
+{
+ #define ATAN2_2_OVER_PI 0.636619772367581f
+ float x_sq = x * x;
+
+ /* Polynomial coefficients approximated in the [0, 1] range.
+ * Lolremez command: lolremez --degree 6 --range "0:1"
+ * "(atan(sqrt(x))-sqrt(x))/(x*sqrt(x))" "1/(sqrt(x)*x)"
+ * Please note that ATAN2_COEFF_A01 is fixed to 1.0f. */
+ #define ATAN2_COEFF_A03 -3.3331659436225891113281250000e-01f
+ #define ATAN2_COEFF_A05 1.99627041816711425781250000000e-01f
+ #define ATAN2_COEFF_A07 -1.3976582884788513183593750000e-01f
+ #define ATAN2_COEFF_A09 9.79423448443412780761718750000e-02f
+ #define ATAN2_COEFF_A11 -5.7773590087890625000000000000e-02f
+ #define ATAN2_COEFF_A13 2.30401363223791122436523437500e-02f
+ #define ATAN2_COEFF_A15 -4.3554059229791164398193359375e-03f
+ return ATAN2_2_OVER_PI * (x + x * x_sq * (ATAN2_COEFF_A03
+ + x_sq * (ATAN2_COEFF_A05
+ + x_sq * (ATAN2_COEFF_A07
+ + x_sq * (ATAN2_COEFF_A09
+ + x_sq * (ATAN2_COEFF_A11
+ + x_sq * (ATAN2_COEFF_A13
+ + x_sq * (ATAN2_COEFF_A15))))))));
+}
+
+/* Calculates the arctangent of y/x, returning an approximate value in radians.
+ * Please refer to the linked wiki page (https://en.wikipedia.org/wiki/Atan2)
+ * to learn how atan2 results are computed. */
+static OPUS_INLINE float celt_atan2p_norm(float y, float x)
+{
+ celt_sig_assert(x>=0 && y>=0);
+
+ /* For very small values, we don't care about the answer. */
+ if ((x*x + y*y) < 1e-18f)
+ {
+ return 0;
+ }
+
+ if (y < x)
+ {
+ return celt_atan_norm(y / x);
+ } else {
+ return 1.f - celt_atan_norm(x / y);
+ }
+}
+#endif
+
+#if !defined(FIXED_POINT) || defined(ENABLE_QEXT)
+/* Computes estimated cosine values for (PI/2 * x) using only terms with even
+ * exponents. */
+static OPUS_INLINE float celt_cos_norm2(float x)
+{
+ float x_norm_sq;
+ int output_sign;
+ /* Restrict x to [-1, 3]. */
+ x -= 4*floor(.25*(x+1));
+ /* Negative sign for [1, 3]. */
+ output_sign = 1 - 2*(x>1);
+ /* Restrict to [-1, 1]. */
+ x -= 2*(x>1);
+
+ /* The cosine function, cos(x), has a Taylor series representation consisting
+ * exclusively of even-powered polynomial terms. */
+ x_norm_sq = x * x;
+
+ /* Polynomial coefficients approximated in the [0, 1] range using only terms
+ * with even exponents.
+ * Lolremez command: lolremez --degree 4 --range 0:1 "cos(sqrt(x)*pi*0.5)" */
+ #define COS_COEFF_A0 9.999999403953552246093750000000e-01f
+ #define COS_COEFF_A2 -1.233698248863220214843750000000000f
+ #define COS_COEFF_A4 2.536507546901702880859375000000e-01f
+ #define COS_COEFF_A6 -2.08106283098459243774414062500e-02f
+ #define COS_COEFF_A8 8.581906440667808055877685546875e-04f
+ return output_sign * (COS_COEFF_A0 + x_norm_sq * (COS_COEFF_A2 +
+ x_norm_sq * (COS_COEFF_A4 +
+ x_norm_sq * (COS_COEFF_A6 +
+ x_norm_sq * (COS_COEFF_A8)))));
+}
+
+#endif
+
+#ifndef FIXED_POINT
+
+#define celt_sqrt(x) ((float)sqrt(x))
+#define celt_sqrt32(x) ((float)sqrt(x))
+#define celt_rsqrt(x) (1.f/celt_sqrt(x))
+#define celt_rsqrt_norm(x) (celt_rsqrt(x))
+#define celt_rsqrt_norm32(x) (celt_rsqrt(x))
+#define celt_cos_norm(x) ((float)cos((.5f*PI)*(x)))
+#define celt_rcp(x) (1.f/(x))
+#define celt_div(a,b) ((a)/(b))
+#define frac_div32(a,b) ((float)(a)/(b))
+#define frac_div32_q29(a,b) frac_div32(a,b)
+
+#ifdef FLOAT_APPROX
+/* Calculates the base-2 logarithm (log2(x)) of a number. It is designed for
+ * systems using radix-2 floating-point representation, with the exponent
+ * located at bits 23 to 30 and an offset of 127. Note that special cases like
+ * denormalized numbers, positive/negative infinity, and NaN are not handled.
+ * log2(x) = log2(x^exponent * mantissa)
+ * = exponent + log2(mantissa) */
+
+/* Log2 x normalization single precision coefficients calculated by
+ * 1 / (1 + 0.125 * index).
+ * Coefficients in Double Precision
+ * double log2_x_norm_coeff[8] = {
+ * 1.0000000000000000000, 8.888888888888888e-01,
+ * 8.000000000000000e-01, 7.272727272727273e-01,
+ * 6.666666666666666e-01, 6.153846153846154e-01,
+ * 5.714285714285714e-01, 5.333333333333333e-01} */
+static const float log2_x_norm_coeff[8] = {
+ 1.000000000000000000000000000f, 8.88888895511627197265625e-01f,
+ 8.00000000000000000000000e-01f, 7.27272748947143554687500e-01f,
+ 6.66666686534881591796875e-01f, 6.15384638309478759765625e-01f,
+ 5.71428596973419189453125e-01f, 5.33333361148834228515625e-01f};
+
+/* Log2 y normalization single precision coefficients calculated by
+ * log2(1 + 0.125 * index).
+ * Coefficients in Double Precision
+ * double log2_y_norm_coeff[8] = {
+ * 0.0000000000000000000, 1.699250014423124e-01,
+ * 3.219280948873623e-01, 4.594316186372973e-01,
+ * 5.849625007211562e-01, 7.004397181410922e-01,
+ * 8.073549220576041e-01, 9.068905956085185e-01}; */
+static const float log2_y_norm_coeff[8] = {
+ 0.0000000000000000000000000000f, 1.699250042438507080078125e-01f,
+ 3.219280838966369628906250e-01f, 4.594316184520721435546875e-01f,
+ 5.849624872207641601562500e-01f, 7.004396915435791015625000e-01f,
+ 8.073549270629882812500000e-01f, 9.068905711174011230468750e-01f};
+
+static OPUS_INLINE float celt_log2(float x)
+{
+ opus_int32 integer;
+ opus_int32 range_idx;
+ union {
+ float f;
+ opus_uint32 i;
+ } in;
+ in.f = x;
+ integer = (opus_int32)(in.i>>23)-127;
+ in.i = (opus_int32)in.i - (opus_int32)((opus_uint32)integer<<23);
+
+ /* Normalize the mantissa range from [1, 2] to [1,1.125], and then shift x
+ * by 1.0625 to [-0.0625, 0.0625]. */
+ range_idx = (in.i >> 20) & 0x7;
+ in.f = in.f * log2_x_norm_coeff[range_idx] - 1.0625f;
+
+ /* Polynomial coefficients approximated in the [1, 1.125] range.
+ * Lolremez command: lolremez --degree 4 --range -0.0625:0.0625
+ * "log(x+1.0625)/log(2)"
+ * Coefficients in Double Precision
+ * A0: 8.7462840624502679e-2 A1: 1.3578296070972002
+ * A2: -6.3897703690210047e-1 A3: 4.0197125617419959e-1
+ * A4: -2.8415445877832832e-1 */
+ #define LOG2_COEFF_A0 8.74628424644470214843750000e-02f
+ #define LOG2_COEFF_A1 1.357829570770263671875000000000f
+ #define LOG2_COEFF_A2 -6.3897705078125000000000000e-01f
+ #define LOG2_COEFF_A3 4.01971250772476196289062500e-01f
+ #define LOG2_COEFF_A4 -2.8415444493293762207031250e-01f
+ in.f = LOG2_COEFF_A0 + in.f * (LOG2_COEFF_A1
+ + in.f * (LOG2_COEFF_A2
+ + in.f * (LOG2_COEFF_A3
+ + in.f * (LOG2_COEFF_A4))));
+ return integer + in.f + log2_y_norm_coeff[range_idx];
+}
+
+/* Calculates an approximation of 2^x. The approximation was achieved by
+ * employing a base-2 exponential function and utilizing a Remez approximation
+ * of order 5, ensuring a controlled relative error.
+ * exp2(x) = exp2(integer + fraction)
+ * = exp2(integer) * exp2(fraction) */
+static OPUS_INLINE float celt_exp2(float x)
+{
+ opus_int32 integer;
+ float frac;
+ union {
+ float f;
+ opus_uint32 i;
+ } res;
+ integer = (int)floor(x);
+ if (integer < -50)
+ return 0;
+ frac = x-integer;
+
+ /* Polynomial coefficients approximated in the [0, 1] range.
+ * Lolremez command: lolremez --degree 5 --range 0:1
+ * "exp(x*0.693147180559945)" "exp(x*0.693147180559945)"
+ * NOTE: log(2) ~ 0.693147180559945 */
+ #define EXP2_COEFF_A0 9.999999403953552246093750000000e-01f
+ #define EXP2_COEFF_A1 6.931530833244323730468750000000e-01f
+ #define EXP2_COEFF_A2 2.401536107063293457031250000000e-01f
+ #define EXP2_COEFF_A3 5.582631751894950866699218750000e-02f
+ #define EXP2_COEFF_A4 8.989339694380760192871093750000e-03f
+ #define EXP2_COEFF_A5 1.877576694823801517486572265625e-03f
+ res.f = EXP2_COEFF_A0 + frac * (EXP2_COEFF_A1
+ + frac * (EXP2_COEFF_A2
+ + frac * (EXP2_COEFF_A3
+ + frac * (EXP2_COEFF_A4
+ + frac * (EXP2_COEFF_A5)))));
+ res.i = (opus_uint32)((opus_int32)res.i + (opus_int32)((opus_uint32)integer<<23)) & 0x7fffffff;
+ return res.f;
+}
+
+#else
+#define celt_log2(x) ((float)(1.442695040888963387*log(x)))
+#define celt_exp2(x) ((float)exp(0.6931471805599453094*(x)))
+#endif
+
+#define celt_exp2_db celt_exp2
+#define celt_log2_db celt_log2
+
+#define celt_sin(x) celt_cos_norm2((0.5f*PI) * (x) - 1.0f)
+#define celt_log(x) (celt_log2(x) * 0.6931471805599453f)
+#define celt_exp(x) (celt_exp2((x) * 1.4426950408889634f))
+
+#endif
+
+#ifdef FIXED_POINT
+
+#include "os_support.h"
+
+#ifndef OVERRIDE_CELT_ILOG2
+/** Integer log in base2. Undefined for zero and negative numbers */
+static OPUS_INLINE opus_int16 celt_ilog2(opus_int32 x)
+{
+ celt_sig_assert(x>0);
+ return EC_ILOG(x)-1;
+}
+#endif
+
+
+/** Integer log in base2. Defined for zero, but not for negative numbers */
+static OPUS_INLINE opus_int16 celt_zlog2(opus_val32 x)
+{
+ return x <= 0 ? 0 : celt_ilog2(x);
+}
+
+opus_val16 celt_rsqrt_norm(opus_val32 x);
+
+opus_val32 celt_rsqrt_norm32(opus_val32 x);
+
+opus_val32 celt_sqrt(opus_val32 x);
+
+opus_val32 celt_sqrt32(opus_val32 x);
+
+opus_val16 celt_cos_norm(opus_val32 x);
+
+opus_val32 celt_cos_norm32(opus_val32 x);
+
+/** Base-2 logarithm approximation (log2(x)). (Q14 input, Q10 output) */
+static OPUS_INLINE opus_val16 celt_log2(opus_val32 x)
+{
+ int i;
+ opus_val16 n, frac;
+ /* -0.41509302963303146, 0.9609890551383969, -0.31836011537636605,
+ 0.15530808010959576, -0.08556153059057618 */
+ static const opus_val16 C[5] = {-6801+(1<<(13-10)), 15746, -5217, 2545, -1401};
+ if (x==0)
+ return -32767;
+ i = celt_ilog2(x);
+ n = VSHR32(x,i-15)-32768-16384;
+ frac = ADD16(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2], MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, C[4]))))))));
+ return SHL32(i-13,10)+SHR32(frac,14-10);
+}
+
+/*
+ K0 = 1
+ K1 = log(2)
+ K2 = 3-4*log(2)
+ K3 = 3*log(2) - 2
+*/
+#define D0 16383
+#define D1 22804
+#define D2 14819
+#define D3 10204
+
+static OPUS_INLINE opus_val32 celt_exp2_frac(opus_val16 x)
+{
+ opus_val16 frac;
+ frac = SHL16(x, 4);
+ return ADD16(D0, MULT16_16_Q15(frac, ADD16(D1, MULT16_16_Q15(frac, ADD16(D2 , MULT16_16_Q15(D3,frac))))));
+}
+
+#undef D0
+#undef D1
+#undef D2
+#undef D3
+
+/** Base-2 exponential approximation (2^x). (Q10 input, Q16 output) */
+static OPUS_INLINE opus_val32 celt_exp2(opus_val16 x)
+{
+ int integer;
+ opus_val16 frac;
+ integer = SHR16(x,10);
+ if (integer>14)
+ return 0x7f000000;
+ else if (integer < -15)
+ return 0;
+ frac = celt_exp2_frac(x-SHL16(integer,10));
+ return VSHR32(EXTEND32(frac), -integer-2);
+}
+
+#ifdef ENABLE_QEXT
+
+/* Calculates the base-2 logarithm of a Q14 input value. The result is returned
+ * in Q(DB_SHIFT). If the input value is 0, the function will output -32.0f. */
+static OPUS_INLINE opus_val32 celt_log2_db(opus_val32 x) {
+ /* Q30 */
+ static const opus_val32 log2_x_norm_coeff[8] = {
+ 1073741824, 954437184, 858993472, 780903168,
+ 715827904, 660764224, 613566784, 572662336};
+ /* Q24 */
+ static const opus_val32 log2_y_norm_coeff[8] = {
+ 0, 2850868, 5401057, 7707983,
+ 9814042, 11751428, 13545168, 15215099};
+ static const opus_val32 LOG2_COEFF_A0 = 1467383; /* Q24 */
+ static const opus_val32 LOG2_COEFF_A1 = 182244800; /* Q27 */
+ static const opus_val32 LOG2_COEFF_A2 = -21440512; /* Q25 */
+ static const opus_val32 LOG2_COEFF_A3 = 107903336; /* Q28 */
+ static const opus_val32 LOG2_COEFF_A4 = -610217024; /* Q31 */
+
+ opus_int32 integer, norm_coeff_idx, tmp;
+ opus_val32 mantissa;
+ if (x==0) {
+ return -536870912; /* -32.0f */
+ }
+ integer = SUB32(celt_ilog2(x), 14); /* Q0 */
+ mantissa = VSHR32(x, integer + 14 - 29); /* Q29 */
+ norm_coeff_idx = SHR32(mantissa, 29 - 3) & 0x7;
+ /* mantissa is in Q28 (29 + Q_NORM_CONST - 31 where Q_NORM_CONST is Q30)
+ * 285212672 (Q28) is 1.0625f. */
+ mantissa = SUB32(MULT32_32_Q31(mantissa, log2_x_norm_coeff[norm_coeff_idx]),
+ 285212672);
+
+ /* q_a3(Q28): q_mantissa + q_a4 - 31
+ * q_a2(Q25): q_mantissa + q_a3 - 31
+ * q_a1(Q27): q_mantissa + q_a2 - 31 + 5
+ * q_a0(Q24): q_mantissa + q_a1 - 31
+ * where q_mantissa is Q28 */
+ /* Split evaluation in steps to avoid exploding macro expansion. */
+ tmp = MULT32_32_Q31(mantissa, LOG2_COEFF_A4);
+ tmp = MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A3, tmp));
+ tmp = SHL32(MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A2, tmp)), 5 /* SHL32 for LOG2_COEFF_A1 */);
+ tmp = MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A1, tmp));
+ return ADD32(log2_y_norm_coeff[norm_coeff_idx],
+ ADD32(SHL32(integer, DB_SHIFT),
+ ADD32(LOG2_COEFF_A0, tmp)));
+}
+
+/* Calculates exp2 for Q28 within a specific range (0 to 1.0) using fixed-point
+ * arithmetic. The input number must be adjusted for Q DB_SHIFT. */
+static OPUS_INLINE opus_val32 celt_exp2_db_frac(opus_val32 x)
+{
+ /* Approximation constants. */
+ static const opus_int32 EXP2_COEFF_A0 = 268435440; /* Q28 */
+ static const opus_int32 EXP2_COEFF_A1 = 744267456; /* Q30 */
+ static const opus_int32 EXP2_COEFF_A2 = 1031451904; /* Q32 */
+ static const opus_int32 EXP2_COEFF_A3 = 959088832; /* Q34 */
+ static const opus_int32 EXP2_COEFF_A4 = 617742720; /* Q36 */
+ static const opus_int32 EXP2_COEFF_A5 = 516104352; /* Q38 */
+ opus_int32 tmp;
+ /* Converts input value from Q24 to Q29. */
+ opus_val32 x_q29 = SHL32(x, 29 - 24);
+ /* Split evaluation in steps to avoid exploding macro expansion. */
+ tmp = ADD32(EXP2_COEFF_A4, MULT32_32_Q31(x_q29, EXP2_COEFF_A5));
+ tmp = ADD32(EXP2_COEFF_A3, MULT32_32_Q31(x_q29, tmp));
+ tmp = ADD32(EXP2_COEFF_A2, MULT32_32_Q31(x_q29, tmp));
+ tmp = ADD32(EXP2_COEFF_A1, MULT32_32_Q31(x_q29, tmp));
+ return ADD32(EXP2_COEFF_A0, MULT32_32_Q31(x_q29, tmp));
+}
+
+/* Calculates exp2 for Q16 using fixed-point arithmetic. The input number must
+ * be adjusted for Q DB_SHIFT. */
+static OPUS_INLINE opus_val32 celt_exp2_db(opus_val32 x)
+{
+ int integer;
+ opus_val32 frac;
+ integer = SHR32(x,DB_SHIFT);
+ if (integer>14)
+ return 0x7f000000;
+ else if (integer <= -17)
+ return 0;
+ frac = celt_exp2_db_frac(x-SHL32(integer, DB_SHIFT)); /* Q28 */
+ return VSHR32(frac, -integer + 28 - 16); /* Q16 */
+}
+#else
+
+#define celt_log2_db(x) SHL32(EXTEND32(celt_log2(x)), DB_SHIFT-10)
+#define celt_exp2_db_frac(x) SHL32(celt_exp2_frac(PSHR32(x, DB_SHIFT-10)), 14)
+#define celt_exp2_db(x) celt_exp2(PSHR32(x, DB_SHIFT-10))
+
+#endif
+
+
+opus_val32 celt_rcp(opus_val32 x);
+opus_val32 celt_rcp_norm32(opus_val32 x);
+
+#define celt_div(a,b) MULT32_32_Q31((opus_val32)(a),celt_rcp(b))
+
+opus_val32 frac_div32_q29(opus_val32 a, opus_val32 b);
+opus_val32 frac_div32(opus_val32 a, opus_val32 b);
+
+/* Computes atan(x) multiplied by 2/PI. The input value (x) should be within the
+ * range of -1 to 1 and represented in Q30 format. The function will return the
+ * result in Q30 format. */
+static OPUS_INLINE opus_val32 celt_atan_norm(opus_val32 x)
+{
+ /* Approximation constants. */
+ static const opus_int32 ATAN_2_OVER_PI = 1367130551; /* Q31 */
+ static const opus_int32 ATAN_COEFF_A03 = -715791936; /* Q31 */
+ static const opus_int32 ATAN_COEFF_A05 = 857391616; /* Q32 */
+ static const opus_int32 ATAN_COEFF_A07 = -1200579328; /* Q33 */
+ static const opus_int32 ATAN_COEFF_A09 = 1682636672; /* Q34 */
+ static const opus_int32 ATAN_COEFF_A11 = -1985085440; /* Q35 */
+ static const opus_int32 ATAN_COEFF_A13 = 1583306112; /* Q36 */
+ static const opus_int32 ATAN_COEFF_A15 = -598602432; /* Q37 */
+ opus_int32 x_sq_q30;
+ opus_int32 x_q31;
+ opus_int32 tmp;
+ /* The expected x is in the range of [-1.0f, 1.0f] */
+ celt_sig_assert((x <= 1073741824) && (x >= -1073741824));
+
+ /* If x = 1.0f, returns 0.5f */
+ if (x == 1073741824)
+ {
+ return 536870912; /* 0.5f (Q30) */
+ }
+ /* If x = 1.0f, returns 0.5f */
+ if (x == -1073741824)
+ {
+ return -536870912; /* -0.5f (Q30) */
+ }
+ x_q31 = SHL32(x, 1);
+ x_sq_q30 = MULT32_32_Q31(x_q31, x);
+ /* Split evaluation in steps to avoid exploding macro expansion. */
+ tmp = MULT32_32_Q31(x_sq_q30, ATAN_COEFF_A15);
+ tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A13, tmp));
+ tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A11, tmp));
+ tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A09, tmp));
+ tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A07, tmp));
+ tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A05, tmp));
+ tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A03, tmp));
+ tmp = ADD32(x, MULT32_32_Q31(x_q31, tmp));
+ return MULT32_32_Q31(ATAN_2_OVER_PI, tmp);
+}
+
+/* Calculates the arctangent of y/x, multiplies the result by 2/pi, and returns
+ * the value in Q30 format. Both input values (x and y) must be within the range
+ * of 0 to 1 and represented in Q30 format. Inputs must be zero or greater, and
+ * at least one input must be non-zero. */
+static OPUS_INLINE opus_val32 celt_atan2p_norm(opus_val32 y, opus_val32 x)
+{
+ celt_sig_assert(x>=0 && y>=0);
+ if (y==0 && x==0) {
+ return 0;
+ } else if (y < x) {
+ return celt_atan_norm(SHR32(frac_div32(y, x), 1));
+ } else {
+ celt_sig_assert(y > 0);
+ return 1073741824 /* 1.0f Q30 */ -
+ celt_atan_norm(SHR32(frac_div32(x, y), 1));
+ }
+}
+
+#define M1 32767
+#define M2 -21
+#define M3 -11943
+#define M4 4936
+
+/* Atan approximation using a 4th order polynomial. Input is in Q15 format
+ and normalized by pi/4. Output is in Q15 format */
+static OPUS_INLINE opus_val16 celt_atan01(opus_val16 x)
+{
+ return MULT16_16_P15(x, ADD32(M1, MULT16_16_P15(x, ADD32(M2, MULT16_16_P15(x, ADD32(M3, MULT16_16_P15(M4, x)))))));
+}
+
+#undef M1
+#undef M2
+#undef M3
+#undef M4
+
+/* atan2() approximation valid for positive input values */
+static OPUS_INLINE opus_val16 celt_atan2p(opus_val16 y, opus_val16 x)
+{
+ if (x==0 && y==0) {
+ return 0;
+ } else if (y < x)
+ {
+ opus_val32 arg;
+ arg = celt_div(SHL32(EXTEND32(y),15),x);
+ if (arg >= 32767)
+ arg = 32767;
+ return SHR16(celt_atan01(EXTRACT16(arg)),1);
+ } else {
+ opus_val32 arg;
+ arg = celt_div(SHL32(EXTEND32(x),15),y);
+ if (arg >= 32767)
+ arg = 32767;
+ return 25736-SHR16(celt_atan01(EXTRACT16(arg)),1);
+ }
+}
+
+#endif /* FIXED_POINT */
+
+#ifndef DISABLE_FLOAT_API
+
+void celt_float2int16_c(const float * OPUS_RESTRICT in, short * OPUS_RESTRICT out, int cnt);
+
+#ifndef OVERRIDE_FLOAT2INT16
+#define celt_float2int16(in, out, cnt, arch) ((void)(arch), celt_float2int16_c(in, out, cnt))
+#endif
+
+int opus_limit2_checkwithin1_c(float *samples, int cnt);
+
+#ifndef OVERRIDE_LIMIT2_CHECKWITHIN1
+#define opus_limit2_checkwithin1(samples, cnt, arch) ((void)(arch), opus_limit2_checkwithin1_c(samples, cnt))
+#endif
+
+#endif /* DISABLE_FLOAT_API */
+
+#endif /* MATHOPS_H */
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2008 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+/* This is a simple MDCT implementation that uses a N/4 complex FFT
+ to do most of the work. It should be relatively straightforward to
+ plug in pretty much and FFT here.
+
+ This replaces the Vorbis FFT (and uses the exact same API), which
+ was a bit too messy and that was ending up duplicating code
+ (might as well use the same FFT everywhere).
+
+ The algorithm is similar to (and inspired from) Fabrice Bellard's
+ MDCT implementation in FFMPEG, but has differences in signs, ordering
+ and scaling in many places.
+*/
+
+#ifndef SKIP_CONFIG_H
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#endif
+
+#include "mdct.h"
+#include "kiss_fft.h"
+#include "_kiss_fft_guts.h"
+#include <math.h>
+#include "os_support.h"
+#include "mathops.h"
+#include "stack_alloc.h"
+
+#if defined(FIXED_POINT) && defined(__mips) && __mips == 32
+#include "mips/mdct_mipsr1.h"
+#endif
+
+#ifndef M_PI
+#define M_PI 3.141592653
+#endif
+
+#ifdef CUSTOM_MODES
+
+int clt_mdct_init(mdct_lookup *l,int N, int maxshift, int arch)
+{
+ int i;
+ kiss_twiddle_scalar *trig;
+ int shift;
+ int N2=N>>1;
+ l->n = N;
+ l->maxshift = maxshift;
+ for (i=0;i<=maxshift;i++)
+ {
+ if (i==0)
+ l->kfft[i] = opus_fft_alloc(N>>2>>i, 0, 0, arch);
+ else
+ l->kfft[i] = opus_fft_alloc_twiddles(N>>2>>i, 0, 0, l->kfft[0], arch);
+#ifndef ENABLE_TI_DSPLIB55
+ if (l->kfft[i]==NULL)
+ return 0;
+#endif
+ }
+ l->trig = trig = (kiss_twiddle_scalar*)opus_alloc((N-(N2>>maxshift))*sizeof(kiss_twiddle_scalar));
+ if (l->trig==NULL)
+ return 0;
+ for (shift=0;shift<=maxshift;shift++)
+ {
+ /* We have enough points that sine isn't necessary */
+#if defined(FIXED_POINT)
+#ifndef ENABLE_QEXT
+ for (i=0;i<N2;i++)
+ trig[i] = TRIG_UPSCALE*celt_cos_norm(DIV32(ADD32(SHL32(EXTEND32(i),17),N2+16384),N));
+#else
+ for (i=0;i<N2;i++)
+ trig[i] = (kiss_twiddle_scalar)MAX32(-2147483647,MIN32(2147483647,floor(.5+2147483648*cos(2*M_PI*(i+.125)/N))));
+#endif
+#else
+ for (i=0;i<N2;i++)
+ trig[i] = (kiss_twiddle_scalar)cos(2*PI*(i+.125)/N);
+#endif
+ trig += N2;
+ N2 >>= 1;
+ N >>= 1;
+ }
+ return 1;
+}
+
+void clt_mdct_clear(mdct_lookup *l, int arch)
+{
+ int i;
+ for (i=0;i<=l->maxshift;i++)
+ opus_fft_free(l->kfft[i], arch);
+ opus_free((kiss_twiddle_scalar*)l->trig);
+}
+
+#endif /* CUSTOM_MODES */
+
+/* Forward MDCT trashes the input array */
+#ifndef OVERRIDE_clt_mdct_forward
+void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
+ const celt_coef *window, int overlap, int shift, int stride, int arch)
+{
+ int i;
+ int N, N2, N4;
+ VARDECL(kiss_fft_scalar, f);
+ VARDECL(kiss_fft_cpx, f2);
+ const kiss_fft_state *st = l->kfft[shift];
+ const kiss_twiddle_scalar *trig;
+ celt_coef scale;
+#ifdef FIXED_POINT
+ /* Allows us to scale with MULT16_32_Q16(), which is faster than
+ MULT16_32_Q15() on ARM. */
+ int scale_shift = st->scale_shift-1;
+ int headroom;
+#endif
+ SAVE_STACK;
+ (void)arch;
+ scale = st->scale;
+
+ N = l->n;
+ trig = l->trig;
+ for (i=0;i<shift;i++)
+ {
+ N >>= 1;
+ trig += N;
+ }
+ N2 = N>>1;
+ N4 = N>>2;
+
+ ALLOC(f, N2, kiss_fft_scalar);
+ ALLOC(f2, N4, kiss_fft_cpx);
+
+ /* Consider the input to be composed of four blocks: [a, b, c, d] */
+ /* Window, shuffle, fold */
+ {
+ /* Temp pointers to make it really clear to the compiler what we're doing */
+ const kiss_fft_scalar * OPUS_RESTRICT xp1 = in+(overlap>>1);
+ const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+N2-1+(overlap>>1);
+ kiss_fft_scalar * OPUS_RESTRICT yp = f;
+ const celt_coef * OPUS_RESTRICT wp1 = window+(overlap>>1);
+ const celt_coef * OPUS_RESTRICT wp2 = window+(overlap>>1)-1;
+ for(i=0;i<((overlap+3)>>2);i++)
+ {
+ /* Real part arranged as -d-cR, Imag part arranged as -b+aR*/
+ *yp++ = S_MUL(xp1[N2], *wp2) + S_MUL(*xp2, *wp1);
+ *yp++ = S_MUL(*xp1, *wp1) - S_MUL(xp2[-N2], *wp2);
+ xp1+=2;
+ xp2-=2;
+ wp1+=2;
+ wp2-=2;
+ }
+ wp1 = window;
+ wp2 = window+overlap-1;
+ for(;i<N4-((overlap+3)>>2);i++)
+ {
+ /* Real part arranged as a-bR, Imag part arranged as -c-dR */
+ *yp++ = *xp2;
+ *yp++ = *xp1;
+ xp1+=2;
+ xp2-=2;
+ }
+ for(;i<N4;i++)
+ {
+ /* Real part arranged as a-bR, Imag part arranged as -c-dR */
+ *yp++ = -S_MUL(xp1[-N2], *wp1) + S_MUL(*xp2, *wp2);
+ *yp++ = S_MUL(*xp1, *wp2) + S_MUL(xp2[N2], *wp1);
+ xp1+=2;
+ xp2-=2;
+ wp1+=2;
+ wp2-=2;
+ }
+ }
+ /* Pre-rotation */
+ {
+ kiss_fft_scalar * OPUS_RESTRICT yp = f;
+ const kiss_twiddle_scalar *t = &trig[0];
+#ifdef FIXED_POINT
+ opus_val32 maxval=1;
+#endif
+ for(i=0;i<N4;i++)
+ {
+ kiss_fft_cpx yc;
+ kiss_twiddle_scalar t0, t1;
+ kiss_fft_scalar re, im, yr, yi;
+ t0 = t[i];
+ t1 = t[N4+i];
+ re = *yp++;
+ im = *yp++;
+ yr = S_MUL(re,t0) - S_MUL(im,t1);
+ yi = S_MUL(im,t0) + S_MUL(re,t1);
+ /* For QEXT, it's best to scale before the FFT, but otherwise it's best to scale after.
+ For floating-point it doesn't matter. */
+#ifdef ENABLE_QEXT
+ yc.r = yr;
+ yc.i = yi;
+#else
+ yc.r = S_MUL2(yr, scale);
+ yc.i = S_MUL2(yi, scale);
+#endif
+#ifdef FIXED_POINT
+ maxval = MAX32(maxval, MAX32(ABS32(yc.r), ABS32(yc.i)));
+#endif
+ f2[st->bitrev[i]] = yc;
+ }
+#ifdef FIXED_POINT
+ headroom = IMAX(0, IMIN(scale_shift, 28-celt_ilog2(maxval)));
+#endif
+ }
+
+ /* N/4 complex FFT, does not downscale anymore */
+ opus_fft_impl(st, f2 ARG_FIXED(scale_shift-headroom));
+
+ /* Post-rotate */
+ {
+ /* Temp pointers to make it really clear to the compiler what we're doing */
+ const kiss_fft_cpx * OPUS_RESTRICT fp = f2;
+ kiss_fft_scalar * OPUS_RESTRICT yp1 = out;
+ kiss_fft_scalar * OPUS_RESTRICT yp2 = out+stride*(N2-1);
+ const kiss_twiddle_scalar *t = &trig[0];
+ /* Temp pointers to make it really clear to the compiler what we're doing */
+ for(i=0;i<N4;i++)
+ {
+ kiss_fft_scalar yr, yi;
+ kiss_fft_scalar t0, t1;
+#ifdef ENABLE_QEXT
+ t0 = S_MUL2(t[i], scale);
+ t1 = S_MUL2(t[N4+i], scale);
+#else
+ t0 = t[i];
+ t1 = t[N4+i];
+#endif
+ yr = PSHR32(S_MUL(fp->i,t1) - S_MUL(fp->r,t0), headroom);
+ yi = PSHR32(S_MUL(fp->r,t1) + S_MUL(fp->i,t0), headroom);
+ *yp1 = yr;
+ *yp2 = yi;
+ fp++;
+ yp1 += 2*stride;
+ yp2 -= 2*stride;
+ }
+ }
+ RESTORE_STACK;
+}
+#endif /* OVERRIDE_clt_mdct_forward */
+
+#ifndef OVERRIDE_clt_mdct_backward
+void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
+ const celt_coef * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch)
+{
+ int i;
+ int N, N2, N4;
+ const kiss_twiddle_scalar *trig;
+#ifdef FIXED_POINT
+ int pre_shift, post_shift, fft_shift;
+#endif
+ (void) arch;
+
+ N = l->n;
+ trig = l->trig;
+ for (i=0;i<shift;i++)
+ {
+ N >>= 1;
+ trig += N;
+ }
+ N2 = N>>1;
+ N4 = N>>2;
+
+#ifdef FIXED_POINT
+ {
+ opus_val32 sumval=N2;
+ opus_val32 maxval=0;
+ for (i=0;i<N2;i++) {
+ maxval = MAX32(maxval, ABS32(in[i*stride]));
+ sumval = ADD32_ovflw(sumval, ABS32(SHR32(in[i*stride],11)));
+ }
+ pre_shift = IMAX(0, 29-celt_zlog2(1+maxval));
+ /* Worst-case where all the energy goes to a single sample. */
+ post_shift = IMAX(0, 19-celt_ilog2(ABS32(sumval)));
+ post_shift = IMIN(post_shift, pre_shift);
+ fft_shift = pre_shift - post_shift;
+ }
+#endif
+ /* Pre-rotate */
+ {
+ /* Temp pointers to make it really clear to the compiler what we're doing */
+ const kiss_fft_scalar * OPUS_RESTRICT xp1 = in;
+ const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+stride*(N2-1);
+ kiss_fft_scalar * OPUS_RESTRICT yp = out+(overlap>>1);
+ const kiss_twiddle_scalar * OPUS_RESTRICT t = &trig[0];
+ const opus_int16 * OPUS_RESTRICT bitrev = l->kfft[shift]->bitrev;
+ for(i=0;i<N4;i++)
+ {
+ int rev;
+ kiss_fft_scalar yr, yi;
+ opus_val32 x1, x2;
+ rev = *bitrev++;
+ x1 = SHL32_ovflw(*xp1, pre_shift);
+ x2 = SHL32_ovflw(*xp2, pre_shift);
+ yr = ADD32_ovflw(S_MUL(x2, t[i]), S_MUL(x1, t[N4+i]));
+ yi = SUB32_ovflw(S_MUL(x1, t[i]), S_MUL(x2, t[N4+i]));
+ /* We swap real and imag because we use an FFT instead of an IFFT. */
+ yp[2*rev+1] = yr;
+ yp[2*rev] = yi;
+ /* Storing the pre-rotation directly in the bitrev order. */
+ xp1+=2*stride;
+ xp2-=2*stride;
+ }
+ }
+
+ opus_fft_impl(l->kfft[shift], (kiss_fft_cpx*)(out+(overlap>>1)) ARG_FIXED(fft_shift));
+
+ /* Post-rotate and de-shuffle from both ends of the buffer at once to make
+ it in-place. */
+ {
+ kiss_fft_scalar * yp0 = out+(overlap>>1);
+ kiss_fft_scalar * yp1 = out+(overlap>>1)+N2-2;
+ const kiss_twiddle_scalar *t = &trig[0];
+ /* Loop to (N4+1)>>1 to handle odd N4. When N4 is odd, the
+ middle pair will be computed twice. */
+ for(i=0;i<(N4+1)>>1;i++)
+ {
+ kiss_fft_scalar re, im, yr, yi;
+ kiss_twiddle_scalar t0, t1;
+ /* We swap real and imag because we're using an FFT instead of an IFFT. */
+ re = yp0[1];
+ im = yp0[0];
+ t0 = t[i];
+ t1 = t[N4+i];
+ /* We'd scale up by 2 here, but instead it's done when mixing the windows */
+ yr = PSHR32_ovflw(ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)), post_shift);
+ yi = PSHR32_ovflw(SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)), post_shift);
+ /* We swap real and imag because we're using an FFT instead of an IFFT. */
+ re = yp1[1];
+ im = yp1[0];
+ yp0[0] = yr;
+ yp1[1] = yi;
+
+ t0 = t[(N4-i-1)];
+ t1 = t[(N2-i-1)];
+ /* We'd scale up by 2 here, but instead it's done when mixing the windows */
+ yr = PSHR32_ovflw(ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)), post_shift);
+ yi = PSHR32_ovflw(SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)), post_shift);
+ yp1[0] = yr;
+ yp0[1] = yi;
+ yp0 += 2;
+ yp1 -= 2;
+ }
+ }
+
+ /* Mirror on both sides for TDAC */
+ {
+ kiss_fft_scalar * OPUS_RESTRICT xp1 = out+overlap-1;
+ kiss_fft_scalar * OPUS_RESTRICT yp1 = out;
+ const celt_coef * OPUS_RESTRICT wp1 = window;
+ const celt_coef * OPUS_RESTRICT wp2 = window+overlap-1;
+
+ for(i = 0; i < overlap/2; i++)
+ {
+ kiss_fft_scalar x1, x2;
+ x1 = *xp1;
+ x2 = *yp1;
+ *yp1++ = SUB32_ovflw(S_MUL(x2, *wp2), S_MUL(x1, *wp1));
+ *xp1-- = ADD32_ovflw(S_MUL(x2, *wp1), S_MUL(x1, *wp2));
+ wp1++;
+ wp2--;
+ }
+ }
+}
+#endif /* OVERRIDE_clt_mdct_backward */
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2008 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+/* This is a simple MDCT implementation that uses a N/4 complex FFT
+ to do most of the work. It should be relatively straightforward to
+ plug in pretty much and FFT here.
+
+ This replaces the Vorbis FFT (and uses the exact same API), which
+ was a bit too messy and that was ending up duplicating code
+ (might as well use the same FFT everywhere).
+
+ The algorithm is similar to (and inspired from) Fabrice Bellard's
+ MDCT implementation in FFMPEG, but has differences in signs, ordering
+ and scaling in many places.
+*/
+
+#ifndef MDCT_H
+#define MDCT_H
+
+#include "opus_defines.h"
+#include "kiss_fft.h"
+#include "arch.h"
+
+typedef struct {
+ int n;
+ int maxshift;
+ const kiss_fft_state *kfft[4];
+ const kiss_twiddle_scalar * OPUS_RESTRICT trig;
+} mdct_lookup;
+
+#if defined(HAVE_ARM_NE10)
+#include "arm/mdct_arm.h"
+#endif
+
+int clt_mdct_init(mdct_lookup *l,int N, int maxshift, int arch);
+void clt_mdct_clear(mdct_lookup *l, int arch);
+
+/** Compute a forward MDCT and scale by 4/N, trashes the input array */
+void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in,
+ kiss_fft_scalar * OPUS_RESTRICT out,
+ const celt_coef *window, int overlap,
+ int shift, int stride, int arch);
+
+/** Compute a backward MDCT (no scaling) and performs weighted overlap-add
+ (scales implicitly by 1/2) */
+void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in,
+ kiss_fft_scalar * OPUS_RESTRICT out,
+ const celt_coef * OPUS_RESTRICT window,
+ int overlap, int shift, int stride, int arch);
+
+#if !defined(OVERRIDE_OPUS_MDCT)
+/* Is run-time CPU detection enabled on this platform? */
+#if defined(OPUS_HAVE_RTCD) && defined(HAVE_ARM_NE10)
+
+extern void (*const CLT_MDCT_FORWARD_IMPL[OPUS_ARCHMASK+1])(
+ const mdct_lookup *l, kiss_fft_scalar *in,
+ kiss_fft_scalar * OPUS_RESTRICT out, const celt_coef *window,
+ int overlap, int shift, int stride, int arch);
+
+#define clt_mdct_forward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
+ ((*CLT_MDCT_FORWARD_IMPL[(arch)&OPUS_ARCHMASK])(_l, _in, _out, \
+ _window, _overlap, _shift, \
+ _stride, _arch))
+
+extern void (*const CLT_MDCT_BACKWARD_IMPL[OPUS_ARCHMASK+1])(
+ const mdct_lookup *l, kiss_fft_scalar *in,
+ kiss_fft_scalar * OPUS_RESTRICT out, const celt_coef *window,
+ int overlap, int shift, int stride, int arch);
+
+#define clt_mdct_backward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
+ (*CLT_MDCT_BACKWARD_IMPL[(arch)&OPUS_ARCHMASK])(_l, _in, _out, \
+ _window, _overlap, _shift, \
+ _stride, _arch)
+
+#else /* if defined(OPUS_HAVE_RTCD) && defined(HAVE_ARM_NE10) */
+
+#define clt_mdct_forward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
+ clt_mdct_forward_c(_l, _in, _out, _window, _overlap, _shift, _stride, _arch)
+
+#define clt_mdct_backward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
+ clt_mdct_backward_c(_l, _in, _out, _window, _overlap, _shift, _stride, _arch)
+
+#endif /* end if defined(OPUS_HAVE_RTCD) && defined(HAVE_ARM_NE10) && !defined(FIXED_POINT) */
+#endif /* end if !defined(OVERRIDE_OPUS_MDCT) */
+
+#endif
--- /dev/null
+/* Copyright (c) 2001-2008 Timothy B. Terriberry
+ Copyright (c) 2008-2009 Xiph.Org Foundation */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#if !defined(_mfrngcode_H)
+# define _mfrngcode_H (1)
+# include "entcode.h"
+
+/*Constants used by the entropy encoder/decoder.*/
+
+/*The number of bits to output at a time.*/
+# define EC_SYM_BITS (8)
+/*The total number of bits in each of the state registers.*/
+# define EC_CODE_BITS (32)
+/*The maximum symbol value.*/
+# define EC_SYM_MAX ((1U<<EC_SYM_BITS)-1)
+/*Bits to shift by to move a symbol into the high-order position.*/
+# define EC_CODE_SHIFT (EC_CODE_BITS-EC_SYM_BITS-1)
+/*Carry bit of the high-order range symbol.*/
+# define EC_CODE_TOP (((opus_uint32)1U)<<(EC_CODE_BITS-1))
+/*Low-order bit of the high-order range symbol.*/
+# define EC_CODE_BOT (EC_CODE_TOP>>EC_SYM_BITS)
+/*The number of bits available for the last, partial symbol in the code field.*/
+# define EC_CODE_EXTRA ((EC_CODE_BITS-2)%EC_SYM_BITS+1)
+#endif
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Copyright (c) 2008 Gregory Maxwell
+ Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "celt.h"
+#include "modes.h"
+#include "rate.h"
+#include "os_support.h"
+#include "stack_alloc.h"
+#include "quant_bands.h"
+#include "cpu_support.h"
+
+static const opus_int16 eband5ms[] = {
+/*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 34, 40, 48, 60, 78, 100
+};
+
+/* Alternate tuning (partially derived from Vorbis) */
+#define BITALLOC_SIZE 11
+/* Bit allocation table in units of 1/32 bit/sample (0.1875 dB SNR) */
+static const unsigned char band_allocation[] = {
+/*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 90, 80, 75, 69, 63, 56, 49, 40, 34, 29, 20, 18, 10, 0, 0, 0, 0, 0, 0, 0, 0,
+110,100, 90, 84, 78, 71, 65, 58, 51, 45, 39, 32, 26, 20, 12, 0, 0, 0, 0, 0, 0,
+118,110,103, 93, 86, 80, 75, 70, 65, 59, 53, 47, 40, 31, 23, 15, 4, 0, 0, 0, 0,
+126,119,112,104, 95, 89, 83, 78, 72, 66, 60, 54, 47, 39, 32, 25, 17, 12, 1, 0, 0,
+134,127,120,114,103, 97, 91, 85, 78, 72, 66, 60, 54, 47, 41, 35, 29, 23, 16, 10, 1,
+144,137,130,124,113,107,101, 95, 88, 82, 76, 70, 64, 57, 51, 45, 39, 33, 26, 15, 1,
+152,145,138,132,123,117,111,105, 98, 92, 86, 80, 74, 67, 61, 55, 49, 43, 36, 20, 1,
+162,155,148,142,133,127,121,115,108,102, 96, 90, 84, 77, 71, 65, 59, 53, 46, 30, 1,
+172,165,158,152,143,137,131,125,118,112,106,100, 94, 87, 81, 75, 69, 63, 56, 45, 20,
+200,200,200,200,200,200,200,200,198,193,188,183,178,173,168,163,158,153,148,129,104,
+};
+
+#ifndef CUSTOM_MODES_ONLY
+ #ifdef FIXED_POINT
+ #include "static_modes_fixed.h"
+ #else
+ #include "static_modes_float.h"
+ #endif
+#endif /* CUSTOM_MODES_ONLY */
+
+#ifndef M_PI
+#define M_PI 3.1415926535897931
+#endif
+
+#ifdef CUSTOM_MODES
+
+/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
+ Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
+#define BARK_BANDS 25
+static const opus_int16 bark_freq[BARK_BANDS+1] = {
+ 0, 100, 200, 300, 400,
+ 510, 630, 770, 920, 1080,
+ 1270, 1480, 1720, 2000, 2320,
+ 2700, 3150, 3700, 4400, 5300,
+ 6400, 7700, 9500, 12000, 15500,
+ 20000};
+
+static opus_int16 *compute_ebands(opus_int32 Fs, int frame_size, int res, int *nbEBands)
+{
+ opus_int16 *eBands;
+ int i, j, lin, low, high, nBark, offset=0;
+
+ /* All modes that have 2.5 ms short blocks use the same definition */
+ if (Fs == 400*(opus_int32)frame_size)
+ {
+ *nbEBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
+ eBands = opus_alloc(sizeof(opus_int16)*(*nbEBands+1));
+ for (i=0;i<*nbEBands+1;i++)
+ eBands[i] = eband5ms[i];
+ return eBands;
+ }
+ /* Find the number of critical bands supported by our sampling rate */
+ for (nBark=1;nBark<BARK_BANDS;nBark++)
+ if (bark_freq[nBark+1]*2 >= Fs)
+ break;
+
+ /* Find where the linear part ends (i.e. where the spacing is more than min_width */
+ for (lin=0;lin<nBark;lin++)
+ if (bark_freq[lin+1]-bark_freq[lin] >= res)
+ break;
+
+ low = (bark_freq[lin]+res/2)/res;
+ high = nBark-lin;
+ *nbEBands = low+high;
+ eBands = opus_alloc(sizeof(opus_int16)*(*nbEBands+2));
+
+ if (eBands==NULL)
+ return NULL;
+
+ /* Linear spacing (min_width) */
+ for (i=0;i<low;i++)
+ eBands[i] = i;
+ if (low>0)
+ offset = eBands[low-1]*res - bark_freq[lin-1];
+ /* Spacing follows critical bands */
+ for (i=0;i<high;i++)
+ {
+ int target = bark_freq[lin+i];
+ /* Round to an even value */
+ eBands[i+low] = (target+offset/2+res)/(2*res)*2;
+ offset = eBands[i+low]*res - target;
+ }
+ /* Enforce the minimum spacing at the boundary */
+ for (i=0;i<*nbEBands;i++)
+ if (eBands[i] < i)
+ eBands[i] = i;
+ /* Round to an even value */
+ eBands[*nbEBands] = (bark_freq[nBark]+res)/(2*res)*2;
+ if (eBands[*nbEBands] > frame_size)
+ eBands[*nbEBands] = frame_size;
+ for (i=1;i<*nbEBands-1;i++)
+ {
+ if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1])
+ {
+ eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1])/2;
+ }
+ }
+ /* Remove any empty bands. */
+ for (i=j=0;i<*nbEBands;i++)
+ if(eBands[i+1]>eBands[j])
+ eBands[++j]=eBands[i+1];
+ *nbEBands=j;
+
+ for (i=1;i<*nbEBands;i++)
+ {
+ /* Every band must be smaller than the last band. */
+ celt_assert(eBands[i]-eBands[i-1]<=eBands[*nbEBands]-eBands[*nbEBands-1]);
+ /* Each band must be no larger than twice the size of the previous one. */
+ celt_assert(eBands[i+1]-eBands[i]<=2*(eBands[i]-eBands[i-1]));
+ }
+
+ return eBands;
+}
+
+static void compute_allocation_table(CELTMode *mode)
+{
+ int i, j;
+ unsigned char *allocVectors;
+ int maxBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
+
+ mode->nbAllocVectors = BITALLOC_SIZE;
+ allocVectors = opus_alloc(sizeof(unsigned char)*(BITALLOC_SIZE*mode->nbEBands));
+ if (allocVectors==NULL)
+ {
+ mode->allocVectors = NULL;
+ return;
+ }
+
+ /* Check for standard mode */
+ if (mode->Fs == 400*(opus_int32)mode->shortMdctSize)
+ {
+ for (i=0;i<BITALLOC_SIZE*mode->nbEBands;i++)
+ allocVectors[i] = band_allocation[i];
+ mode->allocVectors = allocVectors;
+ return;
+ }
+ /* If not the standard mode, interpolate */
+ /* Compute per-codec-band allocation from per-critical-band matrix */
+ for (i=0;i<BITALLOC_SIZE;i++)
+ {
+ for (j=0;j<mode->nbEBands;j++)
+ {
+ int k;
+ for (k=0;k<maxBands;k++)
+ {
+ if (400*(opus_int32)eband5ms[k] > mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize)
+ break;
+ }
+ if (k>maxBands-1)
+ allocVectors[i*mode->nbEBands+j] = band_allocation[i*maxBands + maxBands-1];
+ else {
+ opus_int32 a0, a1;
+ a1 = mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize - 400*(opus_int32)eband5ms[k-1];
+ a0 = 400*(opus_int32)eband5ms[k] - mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize;
+ allocVectors[i*mode->nbEBands+j] = (a0*band_allocation[i*maxBands+k-1]
+ + a1*band_allocation[i*maxBands+k])/(a0+a1);
+ }
+ }
+ }
+
+ /*printf ("\n");
+ for (i=0;i<BITALLOC_SIZE;i++)
+ {
+ for (j=0;j<mode->nbEBands;j++)
+ printf ("%d ", allocVectors[i*mode->nbEBands+j]);
+ printf ("\n");
+ }
+ exit(0);*/
+
+ mode->allocVectors = allocVectors;
+}
+
+#endif /* CUSTOM_MODES */
+
+CELTMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error)
+{
+ int i;
+#ifdef CUSTOM_MODES
+ CELTMode *mode=NULL;
+ int res;
+ celt_coef *window;
+ opus_int16 *logN;
+ int LM;
+ int arch = opus_select_arch();
+ ALLOC_STACK;
+#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
+ if (global_stack==NULL)
+ goto failure;
+#endif
+#endif
+
+#ifndef CUSTOM_MODES_ONLY
+ for (i=0;i<TOTAL_MODES;i++)
+ {
+ int j;
+ for (j=0;j<4;j++)
+ {
+ if (Fs == static_mode_list[i]->Fs &&
+ (frame_size<<j) == static_mode_list[i]->shortMdctSize*static_mode_list[i]->nbShortMdcts)
+ {
+ if (error)
+ *error = OPUS_OK;
+ return (CELTMode*)static_mode_list[i];
+ }
+ }
+ }
+#endif /* CUSTOM_MODES_ONLY */
+
+#ifndef CUSTOM_MODES
+ if (error)
+ *error = OPUS_BAD_ARG;
+ return NULL;
+#else
+
+ /* The good thing here is that permutation of the arguments will automatically be invalid */
+
+ if (Fs < 8000 || Fs > 96000)
+ {
+ if (error)
+ *error = OPUS_BAD_ARG;
+ return NULL;
+ }
+#ifdef ENABLE_QEXT
+ if (frame_size < 40 || frame_size > 2048 || frame_size%2!=0)
+#else
+ if (frame_size < 40 || frame_size > 1024 || frame_size%2!=0)
+#endif
+ {
+ if (error)
+ *error = OPUS_BAD_ARG;
+ return NULL;
+ }
+ /* Frames of less than 1ms are not supported. */
+ if ((opus_int32)frame_size*1000 < Fs)
+ {
+ if (error)
+ *error = OPUS_BAD_ARG;
+ return NULL;
+ }
+
+ if ((opus_int32)frame_size*75 >= Fs && (frame_size%16)==0)
+ {
+ LM = 3;
+ } else if ((opus_int32)frame_size*150 >= Fs && (frame_size%8)==0)
+ {
+ LM = 2;
+ } else if ((opus_int32)frame_size*300 >= Fs && (frame_size%4)==0)
+ {
+ LM = 1;
+ } else
+ {
+ LM = 0;
+ }
+
+ /* Shorts longer than 3.3ms are not supported. */
+ if ((opus_int32)(frame_size>>LM)*300 > Fs)
+ {
+ if (error)
+ *error = OPUS_BAD_ARG;
+ return NULL;
+ }
+
+ mode = opus_alloc(sizeof(CELTMode));
+ if (mode==NULL)
+ goto failure;
+ mode->Fs = Fs;
+
+ /* Pre/de-emphasis depends on sampling rate. The "standard" pre-emphasis
+ is defined as A(z) = 1 - 0.85*z^-1 at 48 kHz. Other rates should
+ approximate that. */
+#ifdef ENABLE_QEXT
+ if(Fs == 96000) /* 96 kHz */
+ {
+ mode->preemph[0] = QCONST16(0.9230041504f, 15);
+ mode->preemph[1] = QCONST16(0.2200012207f, 15);
+ mode->preemph[2] = QCONST16(1.5128347184f, SIG_SHIFT); /* exact 1/preemph[3] */
+ mode->preemph[3] = QCONST16(0.6610107422f, 13);
+ } else
+#endif
+ if(Fs < 12000) /* 8 kHz */
+ {
+ mode->preemph[0] = QCONST16(0.3500061035f, 15);
+ mode->preemph[1] = -QCONST16(0.1799926758f, 15);
+ mode->preemph[2] = QCONST16(0.2719968125f, SIG_SHIFT); /* exact 1/preemph[3] */
+ mode->preemph[3] = QCONST16(3.6765136719f, 13);
+ } else if(Fs < 24000) /* 16 kHz */
+ {
+ mode->preemph[0] = QCONST16(0.6000061035f, 15);
+ mode->preemph[1] = -QCONST16(0.1799926758f, 15);
+ mode->preemph[2] = QCONST16(0.4424998650f, SIG_SHIFT); /* exact 1/preemph[3] */
+ mode->preemph[3] = QCONST16(2.2598876953f, 13);
+ } else if(Fs < 40000) /* 32 kHz */
+ {
+ mode->preemph[0] = QCONST16(0.7799987793f, 15);
+ mode->preemph[1] = -QCONST16(0.1000061035f, 15);
+ mode->preemph[2] = QCONST16(0.7499771125f, SIG_SHIFT); /* exact 1/preemph[3] */
+ mode->preemph[3] = QCONST16(1.3333740234f, 13);
+ } else /* 48 kHz */
+ {
+ mode->preemph[0] = QCONST16(0.8500061035f, 15);
+ mode->preemph[1] = QCONST16(0.0f, 15);
+ mode->preemph[2] = QCONST16(1.f, SIG_SHIFT);
+ mode->preemph[3] = QCONST16(1.f, 13);
+ }
+
+ mode->maxLM = LM;
+ mode->nbShortMdcts = 1<<LM;
+ mode->shortMdctSize = frame_size/mode->nbShortMdcts;
+ res = (mode->Fs+mode->shortMdctSize)/(2*mode->shortMdctSize);
+
+ mode->eBands = compute_ebands(Fs, mode->shortMdctSize, res, &mode->nbEBands);
+ if (mode->eBands==NULL)
+ goto failure;
+#if !defined(SMALL_FOOTPRINT)
+ /* Make sure we don't allocate a band larger than our PVQ table.
+ 208 should be enough, but let's be paranoid. */
+ if ((mode->eBands[mode->nbEBands] - mode->eBands[mode->nbEBands-1])<<LM >
+ 208) {
+ goto failure;
+ }
+#endif
+
+ mode->effEBands = mode->nbEBands;
+ while (mode->eBands[mode->effEBands] > mode->shortMdctSize)
+ mode->effEBands--;
+
+ /* Overlap must be divisible by 4 */
+ mode->overlap = ((mode->shortMdctSize>>2)<<2);
+
+ compute_allocation_table(mode);
+ if (mode->allocVectors==NULL)
+ goto failure;
+
+ window = (celt_coef*)opus_alloc(mode->overlap*sizeof(*window));
+ if (window==NULL)
+ goto failure;
+
+#ifndef FIXED_POINT
+ for (i=0;i<mode->overlap;i++)
+ window[i] = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap));
+#else
+# ifdef ENABLE_QEXT
+ for (i=0;i<mode->overlap;i++)
+ window[i] = MIN32(2147483647, 2147483648*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap)));
+# else
+ for (i=0;i<mode->overlap;i++)
+ window[i] = MIN32(32767,floor(.5+32768.*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap))));
+# endif
+#endif
+ mode->window = window;
+
+ logN = (opus_int16*)opus_alloc(mode->nbEBands*sizeof(opus_int16));
+ if (logN==NULL)
+ goto failure;
+
+ for (i=0;i<mode->nbEBands;i++)
+ logN[i] = log2_frac(mode->eBands[i+1]-mode->eBands[i], BITRES);
+ mode->logN = logN;
+
+ compute_pulse_cache(mode, mode->maxLM);
+#ifdef ENABLE_QEXT
+ OPUS_CLEAR(&mode->qext_cache, 1);
+ if ( (mode->Fs == 48000 && (mode->shortMdctSize==120 || mode->shortMdctSize==90)) || (mode->Fs == 96000 && (mode->shortMdctSize==240 || mode->shortMdctSize==180)) ) {
+ CELTMode dummy;
+ compute_qext_mode(&dummy, mode);
+ compute_pulse_cache(&dummy, dummy.maxLM);
+ OPUS_COPY(&mode->qext_cache, &dummy.cache, 1);
+ }
+#endif
+
+ if (clt_mdct_init(&mode->mdct, 2*mode->shortMdctSize*mode->nbShortMdcts,
+ mode->maxLM, arch) == 0)
+ goto failure;
+
+ if (error)
+ *error = OPUS_OK;
+
+ return mode;
+failure:
+ if (error)
+ *error = OPUS_ALLOC_FAIL;
+ if (mode!=NULL)
+ opus_custom_mode_destroy(mode);
+ return NULL;
+#endif /* !CUSTOM_MODES */
+}
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+void opus_custom_mode_destroy(CELTMode *mode)
+{
+ int arch = opus_select_arch();
+
+ if (mode == NULL)
+ return;
+#ifndef CUSTOM_MODES_ONLY
+ {
+ int i;
+ for (i=0;i<TOTAL_MODES;i++)
+ {
+ if (mode == static_mode_list[i])
+ {
+ return;
+ }
+ }
+ }
+#endif /* CUSTOM_MODES_ONLY */
+#ifdef CUSTOM_MODES
+#ifdef ENABLE_QEXT
+ if (mode->qext_cache.index) opus_free((opus_int16*)mode->qext_cache.index);
+ if (mode->qext_cache.bits) opus_free((unsigned char*)mode->qext_cache.bits);
+ if (mode->qext_cache.caps) opus_free((unsigned char*)mode->qext_cache.caps);
+#endif
+ opus_free((opus_int16*)mode->eBands);
+ opus_free((unsigned char*)mode->allocVectors);
+
+ opus_free((opus_val16*)mode->window);
+ opus_free((opus_int16*)mode->logN);
+
+ opus_free((opus_int16*)mode->cache.index);
+ opus_free((unsigned char*)mode->cache.bits);
+ opus_free((unsigned char*)mode->cache.caps);
+ clt_mdct_clear(&mode->mdct, arch);
+
+ opus_free((CELTMode *)mode);
+#else
+ (void)arch;
+ celt_assert(0);
+#endif
+}
+#endif
+
+#ifdef ENABLE_QEXT
+
+static const opus_int16 qext_eBands_180[] = {
+/* 20k 22k 24k 26k 28k 30k 32k 34k 36k 38k 40k 42k 44k 47k 48k */
+ 74, 82, 90, 98, 106, 114, 122, 130, 138, 146, 154, 162, 168, 174, 180
+};
+
+static const opus_int16 qext_logN_180[] = {24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 21, 21, 21};
+
+/* Extra bands. */
+static const opus_int16 qext_eBands_240[] = {
+/* 20k 22k 24k 26k 28k 30k 32k 34k 36k 38k 40k 42k 44k 47k 48k */
+ 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240
+};
+
+static const opus_int16 qext_logN_240[] = {27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27};
+
+void compute_qext_mode(CELTMode *qext, const CELTMode *m)
+{
+ OPUS_COPY(qext, m, 1);
+ if (m->shortMdctSize*48000 == 120*m->Fs) {
+ qext->eBands = qext_eBands_240;
+ qext->logN = qext_logN_240;
+ } else if (m->shortMdctSize*48000 == 90*m->Fs) {
+ qext->eBands = qext_eBands_180;
+ qext->logN = qext_logN_180;
+ } else {
+ celt_assert(0);
+ }
+ qext->nbEBands = qext->effEBands = NB_QEXT_BANDS;
+ while (qext->eBands[qext->effEBands] > qext->shortMdctSize)
+ qext->effEBands--;
+ qext->nbAllocVectors = 0;
+ qext->allocVectors = NULL;
+ OPUS_COPY(&qext->cache, &m->qext_cache, 1);
+}
+#endif
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Copyright (c) 2008 Gregory Maxwell
+ Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 MODES_H
+#define MODES_H
+
+#include "opus_types.h"
+#include "celt.h"
+#include "arch.h"
+#include "mdct.h"
+#include "entenc.h"
+#include "entdec.h"
+
+#define MAX_PERIOD 1024
+
+#define DEC_PITCH_BUF_SIZE 2048
+
+typedef struct {
+ int size;
+ const opus_int16 *index;
+ const unsigned char *bits;
+ const unsigned char *caps;
+} PulseCache;
+
+/** Mode definition (opaque)
+ @brief Mode definition
+ */
+struct OpusCustomMode {
+ opus_int32 Fs;
+ int overlap;
+
+ int nbEBands;
+ int effEBands;
+ opus_val16 preemph[4];
+ const opus_int16 *eBands; /**< Definition for each "pseudo-critical band" */
+
+ int maxLM;
+ int nbShortMdcts;
+ int shortMdctSize;
+
+ int nbAllocVectors; /**< Number of lines in the matrix below */
+ const unsigned char *allocVectors; /**< Number of bits in each band for several rates */
+ const opus_int16 *logN;
+
+ const celt_coef *window;
+ mdct_lookup mdct;
+ PulseCache cache;
+#ifdef ENABLE_QEXT
+ PulseCache qext_cache;
+#endif
+};
+
+#ifdef ENABLE_QEXT
+#define QEXT_PACKET_SIZE_CAP 3825
+#define NB_QEXT_BANDS 14
+void compute_qext_mode(CELTMode *qext, const CELTMode *m);
+#endif
+
+#endif
--- /dev/null
+/* Copyright (C) 2007 Jean-Marc Valin
+
+ File: os_support.h
+ This is the (tiny) OS abstraction layer. Aside from math.h, this is the
+ only place where system headers are allowed.
+
+ 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.
+
+ 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 OS_SUPPORT_H
+#define OS_SUPPORT_H
+
+#ifdef CUSTOM_SUPPORT
+# include "custom_support.h"
+#endif
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+/** Opus wrapper for malloc(). To do your own dynamic allocation replace this function, opus_realloc, and opus_free */
+#ifndef OVERRIDE_OPUS_ALLOC
+static OPUS_INLINE void *opus_alloc (size_t size)
+{
+ return malloc(size);
+}
+#endif
+
+#ifndef OVERRIDE_OPUS_REALLOC
+static OPUS_INLINE void *opus_realloc (void *ptr, size_t size)
+{
+ return realloc(ptr, size);
+}
+#endif
+
+/** Used only for non-threadsafe pseudostack.
+ If desired, this can always return the same area of memory rather than allocating a new one every time. */
+#ifndef OVERRIDE_OPUS_ALLOC_SCRATCH
+static OPUS_INLINE void *opus_alloc_scratch (size_t size)
+{
+ /* Scratch space doesn't need to be cleared */
+ return opus_alloc(size);
+}
+#endif
+
+/** Opus wrapper for free(). To do your own dynamic allocation replace this function, opus_realloc, and opus_free */
+#ifndef OVERRIDE_OPUS_FREE
+static OPUS_INLINE void opus_free (void *ptr)
+{
+ free(ptr);
+}
+#endif
+
+/** Copy n elements from src to dst. The 0* term provides compile-time type checking */
+#ifndef OVERRIDE_OPUS_COPY
+#define OPUS_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
+#endif
+
+/** Copy n elements from src to dst, allowing overlapping regions. The 0* term
+ provides compile-time type checking */
+#ifndef OVERRIDE_OPUS_MOVE
+#define OPUS_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
+#endif
+
+/** Set n elements of dst to zero */
+#ifndef OVERRIDE_OPUS_CLEAR
+#define OPUS_CLEAR(dst, n) (memset((dst), 0, (n)*sizeof(*(dst))))
+#endif
+
+/*#ifdef __GNUC__
+#pragma GCC poison printf sprintf
+#pragma GCC poison malloc free realloc calloc
+#endif*/
+
+#endif /* OS_SUPPORT_H */
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/**
+ @file pitch.c
+ @brief Pitch analysis
+ */
+
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pitch.h"
+#include "os_support.h"
+#include "modes.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "celt_lpc.h"
+
+static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len,
+ int max_pitch, int *best_pitch
+#ifdef FIXED_POINT
+ , int yshift, opus_val32 maxcorr
+#endif
+ )
+{
+ int i, j;
+ opus_val32 Syy=1;
+ opus_val16 best_num[2];
+ opus_val32 best_den[2];
+#ifdef FIXED_POINT
+ int xshift;
+
+ xshift = celt_ilog2(maxcorr)-14;
+#endif
+
+ best_num[0] = -1;
+ best_num[1] = -1;
+ best_den[0] = 0;
+ best_den[1] = 0;
+ best_pitch[0] = 0;
+ best_pitch[1] = 1;
+ for (j=0;j<len;j++)
+ Syy = ADD32(Syy, SHR32(MULT16_16(y[j],y[j]), yshift));
+ for (i=0;i<max_pitch;i++)
+ {
+ if (xcorr[i]>0)
+ {
+ opus_val16 num;
+ opus_val32 xcorr16;
+ xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift));
+#ifndef FIXED_POINT
+ /* Considering the range of xcorr16, this should avoid both underflows
+ and overflows (inf) when squaring xcorr16 */
+ xcorr16 *= 1e-12f;
+#endif
+ num = MULT16_16_Q15(xcorr16,xcorr16);
+ if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy))
+ {
+ if (MULT16_32_Q15(num,best_den[0]) > MULT16_32_Q15(best_num[0],Syy))
+ {
+ best_num[1] = best_num[0];
+ best_den[1] = best_den[0];
+ best_pitch[1] = best_pitch[0];
+ best_num[0] = num;
+ best_den[0] = Syy;
+ best_pitch[0] = i;
+ } else {
+ best_num[1] = num;
+ best_den[1] = Syy;
+ best_pitch[1] = i;
+ }
+ }
+ }
+ Syy += SHR32(MULT16_16(y[i+len],y[i+len]),yshift) - SHR32(MULT16_16(y[i],y[i]),yshift);
+ Syy = MAX32(1, Syy);
+ }
+}
+
+static void celt_fir5(opus_val16 *x,
+ const opus_val16 *num,
+ int N)
+{
+ int i;
+ opus_val16 num0, num1, num2, num3, num4;
+ opus_val32 mem0, mem1, mem2, mem3, mem4;
+ num0=num[0];
+ num1=num[1];
+ num2=num[2];
+ num3=num[3];
+ num4=num[4];
+ mem0=0;
+ mem1=0;
+ mem2=0;
+ mem3=0;
+ mem4=0;
+ for (i=0;i<N;i++)
+ {
+ opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
+ sum = MAC16_16(sum,num0,mem0);
+ sum = MAC16_16(sum,num1,mem1);
+ sum = MAC16_16(sum,num2,mem2);
+ sum = MAC16_16(sum,num3,mem3);
+ sum = MAC16_16(sum,num4,mem4);
+ mem4 = mem3;
+ mem3 = mem2;
+ mem2 = mem1;
+ mem1 = mem0;
+ mem0 = x[i];
+ x[i] = ROUND16(sum, SIG_SHIFT);
+ }
+}
+
+
+void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
+ int len, int C, int factor, int arch)
+{
+ int i;
+ opus_val32 ac[5];
+ opus_val16 tmp=Q15ONE;
+ opus_val16 lpc[4];
+ opus_val16 lpc2[5];
+ opus_val16 c1 = QCONST16(.8f,15);
+ int offset;
+#ifdef FIXED_POINT
+ int shift;
+ opus_val32 maxabs;
+#endif
+ offset = factor/2;
+#ifdef FIXED_POINT
+ maxabs = celt_maxabs32(x[0], len*factor);
+ if (C==2)
+ {
+ opus_val32 maxabs_1 = celt_maxabs32(x[1], len*factor);
+ maxabs = MAX32(maxabs, maxabs_1);
+ }
+ if (maxabs<1)
+ maxabs=1;
+ shift = celt_ilog2(maxabs)-10;
+ if (shift<0)
+ shift=0;
+ if (C==2)
+ shift++;
+ for (i=1;i<len;i++)
+ x_lp[i] = SHR32(x[0][(factor*i-offset)], shift+2) + SHR32(x[0][(factor*i+offset)], shift+2) + SHR32(x[0][factor*i], shift+1);
+ x_lp[0] = SHR32(x[0][offset], shift+2) + SHR32(x[0][0], shift+1);
+ if (C==2)
+ {
+ for (i=1;i<len;i++)
+ x_lp[i] += SHR32(x[1][(factor*i-offset)], shift+2) + SHR32(x[1][(factor*i+offset)], shift+2) + SHR32(x[1][factor*i], shift+1);
+ x_lp[0] += SHR32(x[1][offset], shift+2) + SHR32(x[1][0], shift+1);
+ }
+#else
+ for (i=1;i<len;i++)
+ x_lp[i] = .25f*x[0][(factor*i-offset)] + .25f*x[0][(factor*i+offset)] + .5f*x[0][factor*i];
+ x_lp[0] = .25f*x[0][offset] + .5f*x[0][0];
+ if (C==2)
+ {
+ for (i=1;i<len;i++)
+ x_lp[i] += .25f*x[1][(factor*i-offset)] + .25f*x[1][(factor*i+offset)] + .5f*x[1][factor*i];
+ x_lp[0] += .25f*x[1][offset] + .5f*x[1][0];
+ }
+#endif
+ _celt_autocorr(x_lp, ac, NULL, 0,
+ 4, len, arch);
+
+ /* Noise floor -40 dB */
+#ifdef FIXED_POINT
+ ac[0] += SHR32(ac[0],13);
+#else
+ ac[0] *= 1.0001f;
+#endif
+ /* Lag windowing */
+ for (i=1;i<=4;i++)
+ {
+ /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
+#ifdef FIXED_POINT
+ ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
+#else
+ ac[i] -= ac[i]*(.008f*i)*(.008f*i);
+#endif
+ }
+
+ _celt_lpc(lpc, ac, 4);
+ for (i=0;i<4;i++)
+ {
+ tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp);
+ lpc[i] = MULT16_16_Q15(lpc[i], tmp);
+ }
+ /* Add a zero */
+ lpc2[0] = lpc[0] + QCONST16(.8f,SIG_SHIFT);
+ lpc2[1] = lpc[1] + MULT16_16_Q15(c1,lpc[0]);
+ lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]);
+ lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]);
+ lpc2[4] = MULT16_16_Q15(c1,lpc[3]);
+ celt_fir5(x_lp, lpc2, len);
+}
+
+/* Pure C implementation. */
+#ifdef FIXED_POINT
+opus_val32
+#else
+void
+#endif
+celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
+ opus_val32 *xcorr, int len, int max_pitch, int arch)
+{
+
+#if 0 /* This is a simple version of the pitch correlation that should work
+ well on DSPs like Blackfin and TI C5x/C6x */
+ int i, j;
+#ifdef FIXED_POINT
+ opus_val32 maxcorr=1;
+#endif
+#if !defined(OVERRIDE_PITCH_XCORR)
+ (void)arch;
+#endif
+ for (i=0;i<max_pitch;i++)
+ {
+ opus_val32 sum = 0;
+ for (j=0;j<len;j++)
+ sum = MAC16_16(sum, _x[j], _y[i+j]);
+ xcorr[i] = sum;
+#ifdef FIXED_POINT
+ maxcorr = MAX32(maxcorr, sum);
+#endif
+ }
+#ifdef FIXED_POINT
+ return maxcorr;
+#endif
+
+#else /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */
+ int i;
+ /*The EDSP version requires that max_pitch is at least 1, and that _x is
+ 32-bit aligned.
+ Since it's hard to put asserts in assembly, put them here.*/
+#ifdef FIXED_POINT
+ opus_val32 maxcorr=1;
+#endif
+ celt_assert(max_pitch>0);
+ celt_sig_assert(((size_t)_x&3)==0);
+ for (i=0;i<max_pitch-3;i+=4)
+ {
+ opus_val32 sum[4]={0,0,0,0};
+#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
+ {
+ opus_val32 sum_c[4]={0,0,0,0};
+ xcorr_kernel_c(_x, _y+i, sum_c, len);
+#endif
+ xcorr_kernel(_x, _y+i, sum, len, arch);
+#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
+ celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0);
+ }
+#endif
+ xcorr[i]=sum[0];
+ xcorr[i+1]=sum[1];
+ xcorr[i+2]=sum[2];
+ xcorr[i+3]=sum[3];
+#ifdef FIXED_POINT
+ sum[0] = MAX32(sum[0], sum[1]);
+ sum[2] = MAX32(sum[2], sum[3]);
+ sum[0] = MAX32(sum[0], sum[2]);
+ maxcorr = MAX32(maxcorr, sum[0]);
+#endif
+ }
+ /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
+ for (;i<max_pitch;i++)
+ {
+ opus_val32 sum;
+ sum = celt_inner_prod(_x, _y+i, len, arch);
+ xcorr[i] = sum;
+#ifdef FIXED_POINT
+ maxcorr = MAX32(maxcorr, sum);
+#endif
+ }
+#ifdef FIXED_POINT
+ return maxcorr;
+#endif
+#endif
+}
+
+void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
+ int len, int max_pitch, int *pitch, int arch)
+{
+ int i, j;
+ int lag;
+ int best_pitch[2]={0,0};
+ VARDECL(opus_val16, x_lp4);
+ VARDECL(opus_val16, y_lp4);
+ VARDECL(opus_val32, xcorr);
+#ifdef FIXED_POINT
+ opus_val32 maxcorr;
+ opus_val32 xmax, ymax;
+ int shift=0;
+#endif
+ int offset;
+
+ SAVE_STACK;
+
+ celt_assert(len>0);
+ celt_assert(max_pitch>0);
+ lag = len+max_pitch;
+
+ ALLOC(x_lp4, len>>2, opus_val16);
+ ALLOC(y_lp4, lag>>2, opus_val16);
+ ALLOC(xcorr, max_pitch>>1, opus_val32);
+
+ /* Downsample by 2 again */
+ for (j=0;j<len>>2;j++)
+ x_lp4[j] = x_lp[2*j];
+ for (j=0;j<lag>>2;j++)
+ y_lp4[j] = y[2*j];
+
+#ifdef FIXED_POINT
+ xmax = celt_maxabs16(x_lp4, len>>2);
+ ymax = celt_maxabs16(y_lp4, lag>>2);
+ shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax))) - 14 + celt_ilog2(len)/2;
+ if (shift>0)
+ {
+ for (j=0;j<len>>2;j++)
+ x_lp4[j] = SHR16(x_lp4[j], shift);
+ for (j=0;j<lag>>2;j++)
+ y_lp4[j] = SHR16(y_lp4[j], shift);
+ /* Use double the shift for a MAC */
+ shift *= 2;
+ } else {
+ shift = 0;
+ }
+#endif
+
+ /* Coarse search with 4x decimation */
+
+#ifdef FIXED_POINT
+ maxcorr =
+#endif
+ celt_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2, arch);
+
+ find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
+#ifdef FIXED_POINT
+ , 0, maxcorr
+#endif
+ );
+
+ /* Finer search with 2x decimation */
+#ifdef FIXED_POINT
+ maxcorr=1;
+#endif
+ for (i=0;i<max_pitch>>1;i++)
+ {
+ opus_val32 sum;
+ xcorr[i] = 0;
+ if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
+ continue;
+#ifdef FIXED_POINT
+ sum = 0;
+ for (j=0;j<len>>1;j++)
+ sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
+#else
+ sum = celt_inner_prod(x_lp, y+i, len>>1, arch);
+#endif
+ xcorr[i] = MAX32(-1, sum);
+#ifdef FIXED_POINT
+ maxcorr = MAX32(maxcorr, sum);
+#endif
+ }
+ find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
+#ifdef FIXED_POINT
+ , shift+1, maxcorr
+#endif
+ );
+
+ /* Refine by pseudo-interpolation */
+ if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
+ {
+ opus_val32 a, b, c;
+ a = xcorr[best_pitch[0]-1];
+ b = xcorr[best_pitch[0]];
+ c = xcorr[best_pitch[0]+1];
+ if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
+ offset = 1;
+ else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
+ offset = -1;
+ else
+ offset = 0;
+ } else {
+ offset = 0;
+ }
+ *pitch = 2*best_pitch[0]-offset;
+
+ RESTORE_STACK;
+}
+
+#ifdef FIXED_POINT
+static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
+{
+ opus_val32 x2y2;
+ int sx, sy, shift;
+ opus_val32 g;
+ opus_val16 den;
+ if (xy == 0 || xx == 0 || yy == 0)
+ return 0;
+ sx = celt_ilog2(xx)-14;
+ sy = celt_ilog2(yy)-14;
+ shift = sx + sy;
+ x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14);
+ if (shift & 1) {
+ if (x2y2 < 32768)
+ {
+ x2y2 <<= 1;
+ shift--;
+ } else {
+ x2y2 >>= 1;
+ shift++;
+ }
+ }
+ den = celt_rsqrt_norm(x2y2);
+ g = MULT16_32_Q15(den, xy);
+ g = VSHR32(g, (shift>>1)-1);
+ return EXTRACT16(MAX32(-Q15ONE, MIN32(g, Q15ONE)));
+}
+#else
+static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
+{
+ return xy/celt_sqrt(1+xx*yy);
+}
+#endif
+
+static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
+opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
+ int N, int *T0_, int prev_period, opus_val16 prev_gain, int arch)
+{
+ int k, i, T, T0;
+ opus_val16 g, g0;
+ opus_val16 pg;
+ opus_val32 xy,xx,yy,xy2;
+ opus_val32 xcorr[3];
+ opus_val32 best_xy, best_yy;
+ int offset;
+ int minperiod0;
+ VARDECL(opus_val32, yy_lookup);
+ SAVE_STACK;
+
+ minperiod0 = minperiod;
+ maxperiod /= 2;
+ minperiod /= 2;
+ *T0_ /= 2;
+ prev_period /= 2;
+ N /= 2;
+ x += maxperiod;
+ if (*T0_>=maxperiod)
+ *T0_=maxperiod-1;
+
+ T = T0 = *T0_;
+ ALLOC(yy_lookup, maxperiod+1, opus_val32);
+ dual_inner_prod(x, x, x-T0, N, &xx, &xy, arch);
+ yy_lookup[0] = xx;
+ yy=xx;
+ for (i=1;i<=maxperiod;i++)
+ {
+ yy = yy+MULT16_16(x[-i],x[-i])-MULT16_16(x[N-i],x[N-i]);
+ yy_lookup[i] = MAX32(0, yy);
+ }
+ yy = yy_lookup[T0];
+ best_xy = xy;
+ best_yy = yy;
+ g = g0 = compute_pitch_gain(xy, xx, yy);
+ /* Look for any pitch at T/k */
+ for (k=2;k<=15;k++)
+ {
+ int T1, T1b;
+ opus_val16 g1;
+ opus_val16 cont=0;
+ opus_val16 thresh;
+ T1 = celt_udiv(2*T0+k, 2*k);
+ if (T1 < minperiod)
+ break;
+ /* Look for another strong correlation at T1b */
+ if (k==2)
+ {
+ if (T1+T0>maxperiod)
+ T1b = T0;
+ else
+ T1b = T0+T1;
+ } else
+ {
+ T1b = celt_udiv(2*second_check[k]*T0+k, 2*k);
+ }
+ dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2, arch);
+ xy = HALF32(xy + xy2);
+ yy = HALF32(yy_lookup[T1] + yy_lookup[T1b]);
+ g1 = compute_pitch_gain(xy, xx, yy);
+ if (abs(T1-prev_period)<=1)
+ cont = prev_gain;
+ else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
+ cont = HALF16(prev_gain);
+ else
+ cont = 0;
+ thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont);
+ /* Bias against very high pitch (very short period) to avoid false-positives
+ due to short-term correlation */
+ if (T1<3*minperiod)
+ thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont);
+ else if (T1<2*minperiod)
+ thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont);
+ if (g1 > thresh)
+ {
+ best_xy = xy;
+ best_yy = yy;
+ T = T1;
+ g = g1;
+ }
+ }
+ best_xy = MAX32(0, best_xy);
+ if (best_yy <= best_xy)
+ pg = Q15ONE;
+ else
+ pg = SHR32(frac_div32(best_xy,best_yy+1),16);
+
+ for (k=0;k<3;k++)
+ xcorr[k] = celt_inner_prod(x, x-(T+k-1), N, arch);
+ if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
+ offset = 1;
+ else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
+ offset = -1;
+ else
+ offset = 0;
+ if (pg > g)
+ pg = g;
+ *T0_ = 2*T+offset;
+
+ if (*T0_<minperiod0)
+ *T0_=minperiod0;
+ RESTORE_STACK;
+ return pg;
+}
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/**
+ @file pitch.h
+ @brief Pitch analysis
+ */
+
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 PITCH_H
+#define PITCH_H
+
+#include "modes.h"
+#include "cpu_support.h"
+
+#if (defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)) \
+ || ((defined(OPUS_X86_MAY_HAVE_SSE4_1) || defined(OPUS_X86_MAY_HAVE_SSE2)) && defined(FIXED_POINT))
+#include "x86/pitch_sse.h"
+#endif
+
+#if defined(FIXED_POINT) && defined(__mips)
+#include "mips/pitch_mipsr1.h"
+#endif
+
+#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+# include "arm/pitch_arm.h"
+#endif
+
+void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
+ int len, int C, int factor, int arch);
+
+void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
+ int len, int max_pitch, int *pitch, int arch);
+
+opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
+ int N, int *T0, int prev_period, opus_val16 prev_gain, int arch);
+
+
+/* OPT: This is the kernel you really want to optimize. It gets used a lot
+ by the prefilter and by the PLC. */
+static OPUS_INLINE void xcorr_kernel_c(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[4], int len)
+{
+ int j;
+ opus_val16 y_0, y_1, y_2, y_3;
+ celt_assert(len>=3);
+ y_3=0; /* gcc doesn't realize that y_3 can't be used uninitialized */
+ y_0=*y++;
+ y_1=*y++;
+ y_2=*y++;
+ for (j=0;j<len-3;j+=4)
+ {
+ opus_val16 tmp;
+ tmp = *x++;
+ y_3=*y++;
+ sum[0] = MAC16_16(sum[0],tmp,y_0);
+ sum[1] = MAC16_16(sum[1],tmp,y_1);
+ sum[2] = MAC16_16(sum[2],tmp,y_2);
+ sum[3] = MAC16_16(sum[3],tmp,y_3);
+ tmp=*x++;
+ y_0=*y++;
+ sum[0] = MAC16_16(sum[0],tmp,y_1);
+ sum[1] = MAC16_16(sum[1],tmp,y_2);
+ sum[2] = MAC16_16(sum[2],tmp,y_3);
+ sum[3] = MAC16_16(sum[3],tmp,y_0);
+ tmp=*x++;
+ y_1=*y++;
+ sum[0] = MAC16_16(sum[0],tmp,y_2);
+ sum[1] = MAC16_16(sum[1],tmp,y_3);
+ sum[2] = MAC16_16(sum[2],tmp,y_0);
+ sum[3] = MAC16_16(sum[3],tmp,y_1);
+ tmp=*x++;
+ y_2=*y++;
+ sum[0] = MAC16_16(sum[0],tmp,y_3);
+ sum[1] = MAC16_16(sum[1],tmp,y_0);
+ sum[2] = MAC16_16(sum[2],tmp,y_1);
+ sum[3] = MAC16_16(sum[3],tmp,y_2);
+ }
+ if (j++<len)
+ {
+ opus_val16 tmp = *x++;
+ y_3=*y++;
+ sum[0] = MAC16_16(sum[0],tmp,y_0);
+ sum[1] = MAC16_16(sum[1],tmp,y_1);
+ sum[2] = MAC16_16(sum[2],tmp,y_2);
+ sum[3] = MAC16_16(sum[3],tmp,y_3);
+ }
+ if (j++<len)
+ {
+ opus_val16 tmp=*x++;
+ y_0=*y++;
+ sum[0] = MAC16_16(sum[0],tmp,y_1);
+ sum[1] = MAC16_16(sum[1],tmp,y_2);
+ sum[2] = MAC16_16(sum[2],tmp,y_3);
+ sum[3] = MAC16_16(sum[3],tmp,y_0);
+ }
+ if (j<len)
+ {
+ opus_val16 tmp=*x++;
+ y_1=*y++;
+ sum[0] = MAC16_16(sum[0],tmp,y_2);
+ sum[1] = MAC16_16(sum[1],tmp,y_3);
+ sum[2] = MAC16_16(sum[2],tmp,y_0);
+ sum[3] = MAC16_16(sum[3],tmp,y_1);
+ }
+}
+
+#ifndef OVERRIDE_XCORR_KERNEL
+#define xcorr_kernel(x, y, sum, len, arch) \
+ ((void)(arch),xcorr_kernel_c(x, y, sum, len))
+#endif /* OVERRIDE_XCORR_KERNEL */
+
+
+static OPUS_INLINE void dual_inner_prod_c(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
+ int N, opus_val32 *xy1, opus_val32 *xy2)
+{
+ int i;
+ opus_val32 xy01=0;
+ opus_val32 xy02=0;
+ for (i=0;i<N;i++)
+ {
+ xy01 = MAC16_16(xy01, x[i], y01[i]);
+ xy02 = MAC16_16(xy02, x[i], y02[i]);
+ }
+ *xy1 = xy01;
+ *xy2 = xy02;
+}
+
+#ifndef OVERRIDE_DUAL_INNER_PROD
+# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) \
+ ((void)(arch),dual_inner_prod_c(x, y01, y02, N, xy1, xy2))
+#endif
+
+/*We make sure a C version is always available for cases where the overhead of
+ vectorization and passing around an arch flag aren't worth it.*/
+static OPUS_INLINE opus_val32 celt_inner_prod_c(const opus_val16 *x,
+ const opus_val16 *y, int N)
+{
+ int i;
+ opus_val32 xy=0;
+ for (i=0;i<N;i++)
+ xy = MAC16_16(xy, x[i], y[i]);
+ return xy;
+}
+
+#if !defined(OVERRIDE_CELT_INNER_PROD)
+# define celt_inner_prod(x, y, N, arch) \
+ ((void)(arch),celt_inner_prod_c(x, y, N))
+#endif
+
+#ifdef NON_STATIC_COMB_FILTER_CONST_C
+void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
+ opus_val16 g10, opus_val16 g11, opus_val16 g12);
+#endif
+
+
+#ifdef FIXED_POINT
+opus_val32
+#else
+void
+#endif
+celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
+ opus_val32 *xcorr, int len, int max_pitch, int arch);
+
+#ifndef OVERRIDE_PITCH_XCORR
+# define celt_pitch_xcorr celt_pitch_xcorr_c
+#endif
+
+#ifdef NON_STATIC_COMB_FILTER_CONST_C
+void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
+ opus_val16 g10, opus_val16 g11, opus_val16 g12);
+#endif
+
+#ifndef OVERRIDE_COMB_FILTER_CONST
+# define comb_filter_const(y, x, T, N, g10, g11, g12, arch) \
+ ((void)(arch),comb_filter_const_c(y, x, T, N, g10, g11, g12))
+#endif
+
+
+#endif
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "quant_bands.h"
+#include "laplace.h"
+#include <math.h>
+#include "os_support.h"
+#include "arch.h"
+#include "mathops.h"
+#include "stack_alloc.h"
+#include "rate.h"
+
+#ifdef FIXED_POINT
+/* Mean energy in each band quantized in Q4 */
+const signed char eMeans[25] = {
+ 103,100, 92, 85, 81,
+ 77, 72, 70, 78, 75,
+ 73, 71, 78, 74, 69,
+ 72, 70, 74, 76, 71,
+ 60, 60, 60, 60, 60
+};
+#else
+/* Mean energy in each band quantized in Q4 and converted back to float */
+const opus_val16 eMeans[25] = {
+ 6.437500f, 6.250000f, 5.750000f, 5.312500f, 5.062500f,
+ 4.812500f, 4.500000f, 4.375000f, 4.875000f, 4.687500f,
+ 4.562500f, 4.437500f, 4.875000f, 4.625000f, 4.312500f,
+ 4.500000f, 4.375000f, 4.625000f, 4.750000f, 4.437500f,
+ 3.750000f, 3.750000f, 3.750000f, 3.750000f, 3.750000f
+};
+#endif
+/* prediction coefficients: 0.9, 0.8, 0.65, 0.5 */
+#ifdef FIXED_POINT
+static const opus_val16 pred_coef[4] = {29440, 26112, 21248, 16384};
+static const opus_val16 beta_coef[4] = {30147, 22282, 12124, 6554};
+static const opus_val16 beta_intra = 4915;
+#else
+static const opus_val16 pred_coef[4] = {29440/32768., 26112/32768., 21248/32768., 16384/32768.};
+static const opus_val16 beta_coef[4] = {30147/32768., 22282/32768., 12124/32768., 6554/32768.};
+static const opus_val16 beta_intra = 4915/32768.;
+#endif
+
+/*Parameters of the Laplace-like probability models used for the coarse energy.
+ There is one pair of parameters for each frame size, prediction type
+ (inter/intra), and band number.
+ The first number of each pair is the probability of 0, and the second is the
+ decay rate, both in Q8 precision.*/
+static const unsigned char e_prob_model[4][2][42] = {
+ /*120 sample frames.*/
+ {
+ /*Inter*/
+ {
+ 72, 127, 65, 129, 66, 128, 65, 128, 64, 128, 62, 128, 64, 128,
+ 64, 128, 92, 78, 92, 79, 92, 78, 90, 79, 116, 41, 115, 40,
+ 114, 40, 132, 26, 132, 26, 145, 17, 161, 12, 176, 10, 177, 11
+ },
+ /*Intra*/
+ {
+ 24, 179, 48, 138, 54, 135, 54, 132, 53, 134, 56, 133, 55, 132,
+ 55, 132, 61, 114, 70, 96, 74, 88, 75, 88, 87, 74, 89, 66,
+ 91, 67, 100, 59, 108, 50, 120, 40, 122, 37, 97, 43, 78, 50
+ }
+ },
+ /*240 sample frames.*/
+ {
+ /*Inter*/
+ {
+ 83, 78, 84, 81, 88, 75, 86, 74, 87, 71, 90, 73, 93, 74,
+ 93, 74, 109, 40, 114, 36, 117, 34, 117, 34, 143, 17, 145, 18,
+ 146, 19, 162, 12, 165, 10, 178, 7, 189, 6, 190, 8, 177, 9
+ },
+ /*Intra*/
+ {
+ 23, 178, 54, 115, 63, 102, 66, 98, 69, 99, 74, 89, 71, 91,
+ 73, 91, 78, 89, 86, 80, 92, 66, 93, 64, 102, 59, 103, 60,
+ 104, 60, 117, 52, 123, 44, 138, 35, 133, 31, 97, 38, 77, 45
+ }
+ },
+ /*480 sample frames.*/
+ {
+ /*Inter*/
+ {
+ 61, 90, 93, 60, 105, 42, 107, 41, 110, 45, 116, 38, 113, 38,
+ 112, 38, 124, 26, 132, 27, 136, 19, 140, 20, 155, 14, 159, 16,
+ 158, 18, 170, 13, 177, 10, 187, 8, 192, 6, 175, 9, 159, 10
+ },
+ /*Intra*/
+ {
+ 21, 178, 59, 110, 71, 86, 75, 85, 84, 83, 91, 66, 88, 73,
+ 87, 72, 92, 75, 98, 72, 105, 58, 107, 54, 115, 52, 114, 55,
+ 112, 56, 129, 51, 132, 40, 150, 33, 140, 29, 98, 35, 77, 42
+ }
+ },
+ /*960 sample frames.*/
+ {
+ /*Inter*/
+ {
+ 42, 121, 96, 66, 108, 43, 111, 40, 117, 44, 123, 32, 120, 36,
+ 119, 33, 127, 33, 134, 34, 139, 21, 147, 23, 152, 20, 158, 25,
+ 154, 26, 166, 21, 173, 16, 184, 13, 184, 10, 150, 13, 139, 15
+ },
+ /*Intra*/
+ {
+ 22, 178, 63, 114, 74, 82, 84, 83, 92, 82, 103, 62, 96, 72,
+ 96, 67, 101, 73, 107, 72, 113, 55, 118, 52, 125, 52, 118, 52,
+ 117, 55, 135, 49, 137, 39, 157, 32, 145, 29, 97, 33, 77, 40
+ }
+ }
+};
+
+static const unsigned char small_energy_icdf[3]={2,1,0};
+
+static opus_val32 loss_distortion(const celt_glog *eBands, celt_glog *oldEBands, int start, int end, int len, int C)
+{
+ int c, i;
+ opus_val32 dist = 0;
+ c=0; do {
+ for (i=start;i<end;i++)
+ {
+ celt_glog d = PSHR32(SUB32(eBands[i+c*len], oldEBands[i+c*len]), DB_SHIFT-7);
+ dist = MAC16_16(dist, d,d);
+ }
+ } while (++c<C);
+ return MIN32(200,SHR32(dist,14));
+}
+
+static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,
+ const celt_glog *eBands, celt_glog *oldEBands,
+ opus_int32 budget, opus_int32 tell,
+ const unsigned char *prob_model, celt_glog *error, ec_enc *enc,
+ int C, int LM, int intra, celt_glog max_decay, int lfe)
+{
+ int i, c;
+ int badness = 0;
+ opus_val32 prev[2] = {0,0};
+ opus_val16 coef;
+ opus_val16 beta;
+
+ if (tell+3 <= budget)
+ ec_enc_bit_logp(enc, intra, 3);
+ if (intra)
+ {
+ coef = 0;
+ beta = beta_intra;
+ } else {
+ beta = beta_coef[LM];
+ coef = pred_coef[LM];
+ }
+
+ /* Encode at a fixed coarse resolution */
+ for (i=start;i<end;i++)
+ {
+ c=0;
+ do {
+ int bits_left;
+ int qi, qi0;
+ opus_val32 q;
+ celt_glog x;
+ opus_val32 f, tmp;
+ celt_glog oldE;
+ celt_glog decay_bound;
+ x = eBands[i+c*m->nbEBands];
+ oldE = MAXG(-GCONST(9.f), oldEBands[i+c*m->nbEBands]);
+#ifdef FIXED_POINT
+ f = x - MULT16_32_Q15(coef,oldE) - prev[c];
+ /* Rounding to nearest integer here is really important! */
+ qi = (f+QCONST32(.5f,DB_SHIFT))>>DB_SHIFT;
+ decay_bound = MAXG(-GCONST(28.f), SUB32((opus_val32)oldEBands[i+c*m->nbEBands],max_decay));
+#else
+ f = x-coef*oldE-prev[c];
+ /* Rounding to nearest integer here is really important! */
+ qi = (int)floor(.5f+f);
+ decay_bound = MAXG(-GCONST(28.f), oldEBands[i+c*m->nbEBands]) - max_decay;
+#endif
+ /* Prevent the energy from going down too quickly (e.g. for bands
+ that have just one bin) */
+ if (qi < 0 && x < decay_bound)
+ {
+ qi += (int)SHR32(SUB32(decay_bound,x), DB_SHIFT);
+ if (qi > 0)
+ qi = 0;
+ }
+ qi0 = qi;
+ /* If we don't have enough bits to encode all the energy, just assume
+ something safe. */
+ tell = ec_tell(enc);
+ bits_left = budget-tell-3*C*(end-i);
+ if (i!=start && bits_left < 30)
+ {
+ if (bits_left < 24)
+ qi = IMIN(1, qi);
+ if (bits_left < 16)
+ qi = IMAX(-1, qi);
+ }
+ if (lfe && i>=2)
+ qi = IMIN(qi, 0);
+ if (budget-tell >= 15)
+ {
+ int pi;
+ pi = 2*IMIN(i,20);
+ ec_laplace_encode(enc, &qi,
+ prob_model[pi]<<7, prob_model[pi+1]<<6);
+ }
+ else if(budget-tell >= 2)
+ {
+ qi = IMAX(-1, IMIN(qi, 1));
+ ec_enc_icdf(enc, 2*qi^-(qi<0), small_energy_icdf, 2);
+ }
+ else if(budget-tell >= 1)
+ {
+ qi = IMIN(0, qi);
+ ec_enc_bit_logp(enc, -qi, 1);
+ }
+ else
+ qi = -1;
+ error[i+c*m->nbEBands] = f - SHL32(qi,DB_SHIFT);
+ badness += abs(qi0-qi);
+ q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT);
+
+ tmp = MULT16_32_Q15(coef,oldE) + prev[c] + q;
+#ifdef FIXED_POINT
+ tmp = MAX32(-GCONST(28.f), tmp);
+#endif
+ oldEBands[i+c*m->nbEBands] = tmp;
+ prev[c] = prev[c] + q - MULT16_32_Q15(beta,q);
+ } while (++c < C);
+ }
+ return lfe ? 0 : badness;
+}
+
+void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
+ const celt_glog *eBands, celt_glog *oldEBands, opus_uint32 budget,
+ celt_glog *error, ec_enc *enc, int C, int LM, int nbAvailableBytes,
+ int force_intra, opus_val32 *delayedIntra, int two_pass, int loss_rate, int lfe)
+{
+ int intra;
+ celt_glog max_decay;
+ VARDECL(celt_glog, oldEBands_intra);
+ VARDECL(celt_glog, error_intra);
+ ec_enc enc_start_state;
+ opus_uint32 tell;
+ int badness1=0;
+ opus_int32 intra_bias;
+ opus_val32 new_distortion;
+ SAVE_STACK;
+
+ intra = force_intra || (!two_pass && *delayedIntra>2*C*(end-start) && nbAvailableBytes > (end-start)*C);
+ intra_bias = (opus_int32)((budget**delayedIntra*loss_rate)/(C*512));
+ new_distortion = loss_distortion(eBands, oldEBands, start, effEnd, m->nbEBands, C);
+
+ tell = ec_tell(enc);
+ if (tell+3 > budget)
+ two_pass = intra = 0;
+
+ max_decay = GCONST(16.f);
+ if (end-start>10)
+ {
+#ifdef FIXED_POINT
+ max_decay = SHL32(MIN32(SHR32(max_decay,DB_SHIFT-3), EXTEND32(nbAvailableBytes)),DB_SHIFT-3);
+#else
+ max_decay = MIN32(max_decay, .125f*nbAvailableBytes);
+#endif
+ }
+ if (lfe)
+ max_decay = GCONST(3.f);
+ enc_start_state = *enc;
+
+ ALLOC(oldEBands_intra, C*m->nbEBands, celt_glog);
+ ALLOC(error_intra, C*m->nbEBands, celt_glog);
+ OPUS_COPY(oldEBands_intra, oldEBands, C*m->nbEBands);
+
+ if (two_pass || intra)
+ {
+ badness1 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands_intra, budget,
+ tell, e_prob_model[LM][1], error_intra, enc, C, LM, 1, max_decay, lfe);
+ }
+
+ if (!intra)
+ {
+ unsigned char *intra_buf;
+ ec_enc enc_intra_state;
+ opus_int32 tell_intra;
+ opus_uint32 nstart_bytes;
+ opus_uint32 nintra_bytes;
+ opus_uint32 save_bytes;
+ int badness2;
+ VARDECL(unsigned char, intra_bits);
+
+ tell_intra = ec_tell_frac(enc);
+
+ enc_intra_state = *enc;
+
+ nstart_bytes = ec_range_bytes(&enc_start_state);
+ nintra_bytes = ec_range_bytes(&enc_intra_state);
+ intra_buf = ec_get_buffer(&enc_intra_state) + nstart_bytes;
+ save_bytes = nintra_bytes-nstart_bytes;
+ if (save_bytes == 0)
+ save_bytes = ALLOC_NONE;
+ ALLOC(intra_bits, save_bytes, unsigned char);
+ /* Copy bits from intra bit-stream */
+ OPUS_COPY(intra_bits, intra_buf, nintra_bytes - nstart_bytes);
+
+ *enc = enc_start_state;
+
+ badness2 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands, budget,
+ tell, e_prob_model[LM][intra], error, enc, C, LM, 0, max_decay, lfe);
+
+ if (two_pass && (badness1 < badness2 || (badness1 == badness2 && ((opus_int32)ec_tell_frac(enc))+intra_bias > tell_intra)))
+ {
+ *enc = enc_intra_state;
+ /* Copy intra bits to bit-stream */
+ OPUS_COPY(intra_buf, intra_bits, nintra_bytes - nstart_bytes);
+ OPUS_COPY(oldEBands, oldEBands_intra, C*m->nbEBands);
+ OPUS_COPY(error, error_intra, C*m->nbEBands);
+ intra = 1;
+ }
+ } else {
+ OPUS_COPY(oldEBands, oldEBands_intra, C*m->nbEBands);
+ OPUS_COPY(error, error_intra, C*m->nbEBands);
+ }
+
+ if (intra)
+ *delayedIntra = new_distortion;
+ else
+ *delayedIntra = ADD32(MULT16_32_Q15(MULT16_16_Q15(pred_coef[LM], pred_coef[LM]),*delayedIntra),
+ new_distortion);
+
+ RESTORE_STACK;
+}
+
+void quant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *prev_quant, int *extra_quant, ec_enc *enc, int C)
+{
+ int i, c;
+ /* Encode finer resolution */
+ for (i=start;i<end;i++)
+ {
+ opus_int16 extra, prev;
+ extra = 1<<extra_quant[i];
+ if (extra_quant[i] <= 0)
+ continue;
+ if (ec_tell(enc)+C*extra_quant[i] > (opus_int32)enc->storage*8) continue;
+ prev = (prev_quant!=NULL) ? prev_quant[i] : 0;
+ c=0;
+ do {
+ int q2;
+ celt_glog offset;
+#ifdef FIXED_POINT
+ /* Has to be without rounding */
+ q2 = VSHR32(ADD32(error[i+c*m->nbEBands], SHR32(GCONST(.5f), prev)), DB_SHIFT-extra_quant[i]-prev);
+#else
+ q2 = (int)floor((error[i+c*m->nbEBands]*(1<<prev)+.5f)*extra);
+#endif
+ if (q2 > extra-1)
+ q2 = extra-1;
+ if (q2<0)
+ q2 = 0;
+ ec_enc_bits(enc, q2, extra_quant[i]);
+#ifdef FIXED_POINT
+ offset = SUB32(VSHR32(2*q2+1, extra_quant[i]-DB_SHIFT+1), GCONST(.5f));
+ offset = SHR32(offset, prev);
+#else
+ offset = (q2+.5f)*(1<<(14-extra_quant[i]))*(1.f/16384) - .5f;
+ offset *= (1<<(14-prev))*(1.f/16384);
+#endif
+ oldEBands[i+c*m->nbEBands] += offset;
+ error[i+c*m->nbEBands] -= offset;
+ /*printf ("%f ", error[i] - offset);*/
+ } while (++c < C);
+ }
+}
+
+void quant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C)
+{
+ int i, prio, c;
+
+ /* Use up the remaining bits */
+ for (prio=0;prio<2;prio++)
+ {
+ for (i=start;i<end && bits_left>=C ;i++)
+ {
+ if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio)
+ continue;
+ c=0;
+ do {
+ int q2;
+ celt_glog offset;
+ q2 = error[i+c*m->nbEBands]<0 ? 0 : 1;
+ ec_enc_bits(enc, q2, 1);
+#ifdef FIXED_POINT
+ offset = SHR32(SHL32(q2,DB_SHIFT)-GCONST(.5f),fine_quant[i]+1);
+#else
+ offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
+#endif
+ if (oldEBands != NULL) oldEBands[i+c*m->nbEBands] += offset;
+ error[i+c*m->nbEBands] -= offset;
+ bits_left--;
+ } while (++c < C);
+ }
+ }
+}
+
+void unquant_coarse_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int intra, ec_dec *dec, int C, int LM)
+{
+ const unsigned char *prob_model = e_prob_model[LM][intra];
+ int i, c;
+ opus_val64 prev[2] = {0, 0};
+ opus_val16 coef;
+ opus_val16 beta;
+ opus_int32 budget;
+ opus_int32 tell;
+
+ if (intra)
+ {
+ coef = 0;
+ beta = beta_intra;
+ } else {
+ beta = beta_coef[LM];
+ coef = pred_coef[LM];
+ }
+
+ budget = dec->storage*8;
+
+ /* Decode at a fixed coarse resolution */
+ for (i=start;i<end;i++)
+ {
+ c=0;
+ do {
+ int qi;
+ opus_val32 q;
+ opus_val32 tmp;
+ /* It would be better to express this invariant as a
+ test on C at function entry, but that isn't enough
+ to make the static analyzer happy. */
+ celt_sig_assert(c<2);
+ tell = ec_tell(dec);
+ if(budget-tell>=15)
+ {
+ int pi;
+ pi = 2*IMIN(i,20);
+ qi = ec_laplace_decode(dec,
+ prob_model[pi]<<7, prob_model[pi+1]<<6);
+ }
+ else if(budget-tell>=2)
+ {
+ qi = ec_dec_icdf(dec, small_energy_icdf, 2);
+ qi = (qi>>1)^-(qi&1);
+ }
+ else if(budget-tell>=1)
+ {
+ qi = -ec_dec_bit_logp(dec, 1);
+ }
+ else
+ qi = -1;
+ q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT);
+
+ oldEBands[i+c*m->nbEBands] = MAXG(-GCONST(9.f), oldEBands[i+c*m->nbEBands]);
+ tmp = MULT16_32_Q15(coef,oldEBands[i+c*m->nbEBands]) + prev[c] + q;
+#ifdef FIXED_POINT
+ tmp = MIN32(GCONST(28.f), MAX32(-GCONST(28.f), tmp));
+#endif
+ oldEBands[i+c*m->nbEBands] = tmp;
+ prev[c] = prev[c] + q - MULT16_32_Q15(beta,q);
+ } while (++c < C);
+ }
+}
+
+void unquant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *prev_quant, int *extra_quant, ec_dec *dec, int C)
+{
+ int i, c;
+ /* Decode finer resolution */
+ for (i=start;i<end;i++)
+ {
+ opus_int16 extra, prev;
+ extra = extra_quant[i];
+ if (extra_quant[i] <= 0)
+ continue;
+ if (ec_tell(dec)+C*extra_quant[i] > (opus_int32)dec->storage*8) continue;
+ prev = (prev_quant!=NULL) ? prev_quant[i] : 0;
+ c=0;
+ do {
+ int q2;
+ celt_glog offset;
+ q2 = ec_dec_bits(dec, extra);
+#ifdef FIXED_POINT
+ offset = SUB32(VSHR32(2*q2+1, extra-DB_SHIFT+1), GCONST(.5f));
+ offset = SHR32(offset, prev);
+#else
+ offset = (q2+.5f)*(1<<(14-extra))*(1.f/16384) - .5f;
+ offset *= (1<<(14-prev))*(1.f/16384);
+#endif
+ oldEBands[i+c*m->nbEBands] += offset;
+ } while (++c < C);
+ }
+}
+
+void unquant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C)
+{
+ int i, prio, c;
+
+ /* Use up the remaining bits */
+ for (prio=0;prio<2;prio++)
+ {
+ for (i=start;i<end && bits_left>=C ;i++)
+ {
+ if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio)
+ continue;
+ c=0;
+ do {
+ int q2;
+ celt_glog offset;
+ q2 = ec_dec_bits(dec, 1);
+#ifdef FIXED_POINT
+ offset = SHR32(SHL32(q2,DB_SHIFT)-GCONST(.5f),fine_quant[i]+1);
+#else
+ offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
+#endif
+ if (oldEBands != NULL) oldEBands[i+c*m->nbEBands] += offset;
+ bits_left--;
+ } while (++c < C);
+ }
+ }
+}
+
+void amp2Log2(const CELTMode *m, int effEnd, int end,
+ celt_ener *bandE, celt_glog *bandLogE, int C)
+{
+ int c, i;
+ c=0;
+ do {
+ for (i=0;i<effEnd;i++)
+ {
+ bandLogE[i+c*m->nbEBands] =
+ celt_log2_db(bandE[i+c*m->nbEBands])
+ - SHL32((celt_glog)eMeans[i],DB_SHIFT-4);
+#ifdef FIXED_POINT
+ /* Compensate for bandE[] being Q12 but celt_log2() taking a Q14 input. */
+ bandLogE[i+c*m->nbEBands] += GCONST(2.f);
+#endif
+ }
+ for (i=effEnd;i<end;i++)
+ bandLogE[c*m->nbEBands+i] = -GCONST(14.f);
+ } while (++c < C);
+}
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 QUANT_BANDS
+#define QUANT_BANDS
+
+#include "arch.h"
+#include "modes.h"
+#include "entenc.h"
+#include "entdec.h"
+#include "mathops.h"
+
+#ifdef FIXED_POINT
+extern const signed char eMeans[25];
+#else
+extern const opus_val16 eMeans[25];
+#endif
+
+void amp2Log2(const CELTMode *m, int effEnd, int end,
+ celt_ener *bandE, celt_glog *bandLogE, int C);
+
+void log2Amp(const CELTMode *m, int start, int end,
+ celt_ener *eBands, const celt_glog *oldEBands, int C);
+
+void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
+ const celt_glog *eBands, celt_glog *oldEBands, opus_uint32 budget,
+ celt_glog *error, ec_enc *enc, int C, int LM,
+ int nbAvailableBytes, int force_intra, opus_val32 *delayedIntra,
+ int two_pass, int loss_rate, int lfe);
+
+void quant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *fine_quant, int *extra_quant, ec_enc *enc, int C);
+
+void quant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C);
+
+void unquant_coarse_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int intra, ec_dec *dec, int C, int LM);
+
+void unquant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *fine_quant, int *extra_quant, ec_dec *dec, int C);
+
+void unquant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C);
+
+#endif /* QUANT_BANDS */
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include "modes.h"
+#include "cwrs.h"
+#include "arch.h"
+#include "os_support.h"
+
+#include "entcode.h"
+#include "rate.h"
+#include "quant_bands.h"
+
+static const unsigned char LOG2_FRAC_TABLE[24]={
+ 0,
+ 8,13,
+ 16,19,21,23,
+ 24,26,27,28,29,30,31,32,
+ 32,33,34,34,35,36,36,37,37
+};
+
+#if defined(CUSTOM_MODES)
+
+/*Determines if V(N,K) fits in a 32-bit unsigned integer.
+ N and K are themselves limited to 15 bits.*/
+static int fits_in32(int _n, int _k)
+{
+ static const opus_int16 maxN[15] = {
+ 32767, 32767, 32767, 1476, 283, 109, 60, 40,
+ 29, 24, 20, 18, 16, 14, 13};
+ static const opus_int16 maxK[15] = {
+ 32767, 32767, 32767, 32767, 1172, 238, 95, 53,
+ 36, 27, 22, 18, 16, 15, 13};
+ if (_n>=14)
+ {
+ if (_k>=14)
+ return 0;
+ else
+ return _n <= maxN[_k];
+ } else {
+ return _k <= maxK[_n];
+ }
+}
+
+void compute_pulse_cache(CELTMode *m, int LM)
+{
+ int C;
+ int i;
+ int j;
+ int curr=0;
+ int nbEntries=0;
+ int entryN[100], entryK[100], entryI[100];
+ const opus_int16 *eBands = m->eBands;
+ PulseCache *cache = &m->cache;
+ opus_int16 *cindex;
+ unsigned char *bits;
+ unsigned char *cap;
+
+ cindex = (opus_int16 *)opus_alloc(sizeof(cache->index[0])*m->nbEBands*(LM+2));
+ cache->index = cindex;
+
+ /* Scan for all unique band sizes */
+ for (i=0;i<=LM+1;i++)
+ {
+ for (j=0;j<m->nbEBands;j++)
+ {
+ int k;
+ int N = (eBands[j+1]-eBands[j])<<i>>1;
+ cindex[i*m->nbEBands+j] = -1;
+ /* Find other bands that have the same size */
+ for (k=0;k<=i;k++)
+ {
+ int n;
+ for (n=0;n<m->nbEBands && (k!=i || n<j);n++)
+ {
+ if (N == (eBands[n+1]-eBands[n])<<k>>1)
+ {
+ cindex[i*m->nbEBands+j] = cindex[k*m->nbEBands+n];
+ break;
+ }
+ }
+ }
+ if (cache->index[i*m->nbEBands+j] == -1 && N!=0)
+ {
+ int K;
+ entryN[nbEntries] = N;
+ K = 0;
+ while (fits_in32(N,get_pulses(K+1)) && K<MAX_PSEUDO)
+ K++;
+ entryK[nbEntries] = K;
+ cindex[i*m->nbEBands+j] = curr;
+ entryI[nbEntries] = curr;
+
+ curr += K+1;
+ nbEntries++;
+ }
+ }
+ }
+ bits = (unsigned char *)opus_alloc(sizeof(unsigned char)*curr);
+ cache->bits = bits;
+ cache->size = curr;
+ /* Compute the cache for all unique sizes */
+ for (i=0;i<nbEntries;i++)
+ {
+ unsigned char *ptr = bits+entryI[i];
+ opus_int16 tmp[CELT_MAX_PULSES+1];
+ get_required_bits(tmp, entryN[i], get_pulses(entryK[i]), BITRES);
+ for (j=1;j<=entryK[i];j++)
+ ptr[j] = tmp[get_pulses(j)]-1;
+ ptr[0] = entryK[i];
+ }
+
+ /* Compute the maximum rate for each band at which we'll reliably use as
+ many bits as we ask for. */
+ cache->caps = cap = (unsigned char *)opus_alloc(sizeof(cache->caps[0])*(LM+1)*2*m->nbEBands);
+ for (i=0;i<=LM;i++)
+ {
+ for (C=1;C<=2;C++)
+ {
+ for (j=0;j<m->nbEBands;j++)
+ {
+ int N0;
+ int max_bits;
+ N0 = m->eBands[j+1]-m->eBands[j];
+ /* N=1 bands only have a sign bit and fine bits. */
+ if (N0<<i == 1)
+ max_bits = C*(1+MAX_FINE_BITS)<<BITRES;
+ else
+ {
+ const unsigned char *pcache;
+ opus_int32 num;
+ opus_int32 den;
+ int LM0;
+ int N;
+ int offset;
+ int ndof;
+ int qb;
+ int k;
+ LM0 = 0;
+ /* Even-sized bands bigger than N=2 can be split one more time.
+ As of commit 44203907 all bands >1 are even, including custom modes.*/
+ if (N0 > 2)
+ {
+ N0>>=1;
+ LM0--;
+ }
+ /* N0=1 bands can't be split down to N<2. */
+ else if (N0 <= 1)
+ {
+ LM0=IMIN(i,1);
+ N0<<=LM0;
+ }
+ /* Compute the cost for the lowest-level PVQ of a fully split
+ band. */
+ pcache = bits + cindex[(LM0+1)*m->nbEBands+j];
+ max_bits = pcache[pcache[0]]+1;
+ /* Add in the cost of coding regular splits. */
+ N = N0;
+ for(k=0;k<i-LM0;k++){
+ max_bits <<= 1;
+ /* Offset the number of qtheta bits by log2(N)/2
+ + QTHETA_OFFSET compared to their "fair share" of
+ total/N */
+ offset = ((m->logN[j]+(opus_int32)((opus_uint32)(LM0+k)<<BITRES))>>1)-QTHETA_OFFSET;
+ /* The number of qtheta bits we'll allocate if the remainder
+ is to be max_bits.
+ The average measured cost for theta is 0.89701 times qb,
+ approximated here as 459/512. */
+ num=459*(opus_int32)((2*N-1)*offset+max_bits);
+ den=((opus_int32)(2*N-1)<<9)-459;
+ qb = IMIN((num+(den>>1))/den, 57);
+ celt_assert(qb >= 0);
+ max_bits += qb;
+ N <<= 1;
+ }
+ /* Add in the cost of a stereo split, if necessary. */
+ if (C==2)
+ {
+ max_bits <<= 1;
+ offset = ((m->logN[j]+(i<<BITRES))>>1)-(N==2?QTHETA_OFFSET_TWOPHASE:QTHETA_OFFSET);
+ ndof = 2*N-1-(N==2);
+ /* The average measured cost for theta with the step PDF is
+ 0.95164 times qb, approximated here as 487/512. */
+ num = (N==2?512:487)*(opus_int32)(max_bits+ndof*offset);
+ den = ((opus_int32)ndof<<9)-(N==2?512:487);
+ qb = IMIN((num+(den>>1))/den, (N==2?64:61));
+ celt_assert(qb >= 0);
+ max_bits += qb;
+ }
+ /* Add the fine bits we'll use. */
+ /* Compensate for the extra DoF in stereo */
+ ndof = C*N + ((C==2 && N>2) ? 1 : 0);
+ /* Offset the number of fine bits by log2(N)/2 + FINE_OFFSET
+ compared to their "fair share" of total/N */
+ offset = ((m->logN[j] + (i<<BITRES))>>1)-FINE_OFFSET;
+ /* N=2 is the only point that doesn't match the curve */
+ if (N==2)
+ offset += 1<<BITRES>>2;
+ /* The number of fine bits we'll allocate if the remainder is
+ to be max_bits. */
+ num = max_bits+ndof*offset;
+ den = (ndof-1)<<BITRES;
+ qb = IMIN((num+(den>>1))/den, MAX_FINE_BITS);
+ celt_assert(qb >= 0);
+ max_bits += C*qb<<BITRES;
+ }
+ max_bits = (4*max_bits/(C*((m->eBands[j+1]-m->eBands[j])<<i)))-64;
+ celt_assert(max_bits >= 0);
+ celt_assert(max_bits < 256);
+ *cap++ = (unsigned char)max_bits;
+ }
+ }
+ }
+}
+
+#endif /* CUSTOM_MODES */
+
+#define ALLOC_STEPS 6
+
+static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end, int skip_start,
+ const int *bits1, const int *bits2, const int *thresh, const int *cap, opus_int32 total, opus_int32 *_balance,
+ int skip_rsv, int *intensity, int intensity_rsv, int *dual_stereo, int dual_stereo_rsv, int *bits,
+ int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth)
+{
+ opus_int32 psum;
+ int lo, hi;
+ int i, j;
+ int logM;
+ int stereo;
+ int codedBands=-1;
+ int alloc_floor;
+ opus_int32 left, percoeff;
+ int done;
+ opus_int32 balance;
+ SAVE_STACK;
+
+ alloc_floor = C<<BITRES;
+ stereo = C>1;
+
+ logM = LM<<BITRES;
+ lo = 0;
+ hi = 1<<ALLOC_STEPS;
+ for (i=0;i<ALLOC_STEPS;i++)
+ {
+ int mid = (lo+hi)>>1;
+ psum = 0;
+ done = 0;
+ for (j=end;j-->start;)
+ {
+ int tmp = bits1[j] + (mid*(opus_int32)bits2[j]>>ALLOC_STEPS);
+ if (tmp >= thresh[j] || done)
+ {
+ done = 1;
+ /* Don't allocate more than we can actually use */
+ psum += IMIN(tmp, cap[j]);
+ } else {
+ if (tmp >= alloc_floor)
+ psum += alloc_floor;
+ }
+ }
+ if (psum > total)
+ hi = mid;
+ else
+ lo = mid;
+ }
+ psum = 0;
+ /*printf ("interp bisection gave %d\n", lo);*/
+ done = 0;
+ for (j=end;j-->start;)
+ {
+ int tmp = bits1[j] + ((opus_int32)lo*bits2[j]>>ALLOC_STEPS);
+ if (tmp < thresh[j] && !done)
+ {
+ if (tmp >= alloc_floor)
+ tmp = alloc_floor;
+ else
+ tmp = 0;
+ } else
+ done = 1;
+ /* Don't allocate more than we can actually use */
+ tmp = IMIN(tmp, cap[j]);
+ bits[j] = tmp;
+ psum += tmp;
+ }
+
+ /* Decide which bands to skip, working backwards from the end. */
+ for (codedBands=end;;codedBands--)
+ {
+ int band_width;
+ int band_bits;
+ int rem;
+ j = codedBands-1;
+ /* Never skip the first band, nor a band that has been boosted by
+ dynalloc.
+ In the first case, we'd be coding a bit to signal we're going to waste
+ all the other bits.
+ In the second case, we'd be coding a bit to redistribute all the bits
+ we just signaled should be concentrated in this band. */
+ if (j<=skip_start)
+ {
+ /* Give the bit we reserved to end skipping back. */
+ total += skip_rsv;
+ break;
+ }
+ /*Figure out how many left-over bits we would be adding to this band.
+ This can include bits we've stolen back from higher, skipped bands.*/
+ left = total-psum;
+ percoeff = celt_udiv(left, m->eBands[codedBands]-m->eBands[start]);
+ left -= (m->eBands[codedBands]-m->eBands[start])*percoeff;
+ rem = IMAX(left-(m->eBands[j]-m->eBands[start]),0);
+ band_width = m->eBands[codedBands]-m->eBands[j];
+ band_bits = (int)(bits[j] + percoeff*band_width + rem);
+ /*Only code a skip decision if we're above the threshold for this band.
+ Otherwise it is force-skipped.
+ This ensures that we have enough bits to code the skip flag.*/
+ if (band_bits >= IMAX(thresh[j], alloc_floor+(1<<BITRES)))
+ {
+ if (encode)
+ {
+ /*This if() block is the only part of the allocation function that
+ is not a mandatory part of the bitstream: any bands we choose to
+ skip here must be explicitly signaled.*/
+ int depth_threshold;
+ /*We choose a threshold with some hysteresis to keep bands from
+ fluctuating in and out, but we try not to fold below a certain point. */
+ if (codedBands > 17)
+ depth_threshold = j<prev ? 7 : 9;
+ else
+ depth_threshold = 0;
+#ifdef FUZZING
+ (void)signalBandwidth;
+ (void)depth_threshold;
+ if ((rand()&0x1) == 0)
+#else
+ if (codedBands<=start+2 || (band_bits > (depth_threshold*band_width<<LM<<BITRES)>>4 && j<=signalBandwidth))
+#endif
+ {
+ ec_enc_bit_logp(ec, 1, 1);
+ break;
+ }
+ ec_enc_bit_logp(ec, 0, 1);
+ } else if (ec_dec_bit_logp(ec, 1)) {
+ break;
+ }
+ /*We used a bit to skip this band.*/
+ psum += 1<<BITRES;
+ band_bits -= 1<<BITRES;
+ }
+ /*Reclaim the bits originally allocated to this band.*/
+ psum -= bits[j]+intensity_rsv;
+ if (intensity_rsv > 0)
+ intensity_rsv = LOG2_FRAC_TABLE[j-start];
+ psum += intensity_rsv;
+ if (band_bits >= alloc_floor)
+ {
+ /*If we have enough for a fine energy bit per channel, use it.*/
+ psum += alloc_floor;
+ bits[j] = alloc_floor;
+ } else {
+ /*Otherwise this band gets nothing at all.*/
+ bits[j] = 0;
+ }
+ }
+
+ celt_assert(codedBands > start);
+ /* Code the intensity and dual stereo parameters. */
+ if (intensity_rsv > 0)
+ {
+ if (encode)
+ {
+ *intensity = IMIN(*intensity, codedBands);
+ ec_enc_uint(ec, *intensity-start, codedBands+1-start);
+ }
+ else
+ *intensity = start+ec_dec_uint(ec, codedBands+1-start);
+ }
+ else
+ *intensity = 0;
+ if (*intensity <= start)
+ {
+ total += dual_stereo_rsv;
+ dual_stereo_rsv = 0;
+ }
+ if (dual_stereo_rsv > 0)
+ {
+ if (encode)
+ ec_enc_bit_logp(ec, *dual_stereo, 1);
+ else
+ *dual_stereo = ec_dec_bit_logp(ec, 1);
+ }
+ else
+ *dual_stereo = 0;
+
+ /* Allocate the remaining bits */
+ left = total-psum;
+ percoeff = celt_udiv(left, m->eBands[codedBands]-m->eBands[start]);
+ left -= (m->eBands[codedBands]-m->eBands[start])*percoeff;
+ for (j=start;j<codedBands;j++)
+ bits[j] += ((int)percoeff*(m->eBands[j+1]-m->eBands[j]));
+ for (j=start;j<codedBands;j++)
+ {
+ int tmp = (int)IMIN(left, m->eBands[j+1]-m->eBands[j]);
+ bits[j] += tmp;
+ left -= tmp;
+ }
+ /*for (j=0;j<end;j++)printf("%d ", bits[j]);printf("\n");*/
+
+ balance = 0;
+ for (j=start;j<codedBands;j++)
+ {
+ int N0, N, den;
+ int offset;
+ int NClogN;
+ opus_int32 excess, bit;
+
+ celt_assert(bits[j] >= 0);
+ N0 = m->eBands[j+1]-m->eBands[j];
+ N=N0<<LM;
+ bit = (opus_int32)bits[j]+balance;
+
+ if (N>1)
+ {
+ excess = MAX32(bit-cap[j],0);
+ bits[j] = bit-excess;
+
+ /* Compensate for the extra DoF in stereo */
+ den=(C*N+ ((C==2 && N>2 && !*dual_stereo && j<*intensity) ? 1 : 0));
+
+ NClogN = den*(m->logN[j] + logM);
+
+ /* Offset for the number of fine bits by log2(N)/2 + FINE_OFFSET
+ compared to their "fair share" of total/N */
+ offset = (NClogN>>1)-den*FINE_OFFSET;
+
+ /* N=2 is the only point that doesn't match the curve */
+ if (N==2)
+ offset += den<<BITRES>>2;
+
+ /* Changing the offset for allocating the second and third
+ fine energy bit */
+ if (bits[j] + offset < den*2<<BITRES)
+ offset += NClogN>>2;
+ else if (bits[j] + offset < den*3<<BITRES)
+ offset += NClogN>>3;
+
+ /* Divide with rounding */
+ ebits[j] = IMAX(0, (bits[j] + offset + (den<<(BITRES-1))));
+ ebits[j] = celt_udiv(ebits[j], den)>>BITRES;
+
+ /* Make sure not to bust */
+ if (C*ebits[j] > (bits[j]>>BITRES))
+ ebits[j] = bits[j] >> stereo >> BITRES;
+
+ /* More than that is useless because that's about as far as PVQ can go */
+ ebits[j] = IMIN(ebits[j], MAX_FINE_BITS);
+
+ /* If we rounded down or capped this band, make it a candidate for the
+ final fine energy pass */
+ fine_priority[j] = ebits[j]*(den<<BITRES) >= bits[j]+offset;
+
+ /* Remove the allocated fine bits; the rest are assigned to PVQ */
+ bits[j] -= C*ebits[j]<<BITRES;
+
+ } else {
+ /* For N=1, all bits go to fine energy except for a single sign bit */
+ excess = MAX32(0,bit-(C<<BITRES));
+ bits[j] = bit-excess;
+ ebits[j] = 0;
+ fine_priority[j] = 1;
+ }
+
+ /* Fine energy can't take advantage of the re-balancing in
+ quant_all_bands().
+ Instead, do the re-balancing here.*/
+ if(excess > 0)
+ {
+ int extra_fine;
+ int extra_bits;
+ extra_fine = IMIN(excess>>(stereo+BITRES),MAX_FINE_BITS-ebits[j]);
+ ebits[j] += extra_fine;
+ extra_bits = extra_fine*C<<BITRES;
+ fine_priority[j] = extra_bits >= excess-balance;
+ excess -= extra_bits;
+ }
+ balance = excess;
+
+ celt_assert(bits[j] >= 0);
+ celt_assert(ebits[j] >= 0);
+ }
+ /* Save any remaining bits over the cap for the rebalancing in
+ quant_all_bands(). */
+ *_balance = balance;
+
+ /* The skipped bands use all their bits for fine energy. */
+ for (;j<end;j++)
+ {
+ ebits[j] = bits[j] >> stereo >> BITRES;
+ celt_assert(C*ebits[j]<<BITRES == bits[j]);
+ bits[j] = 0;
+ fine_priority[j] = ebits[j]<1;
+ }
+ RESTORE_STACK;
+ return codedBands;
+}
+
+int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
+ opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth)
+{
+ int lo, hi, len, j;
+ int codedBands;
+ int skip_start;
+ int skip_rsv;
+ int intensity_rsv;
+ int dual_stereo_rsv;
+ VARDECL(int, bits1);
+ VARDECL(int, bits2);
+ VARDECL(int, thresh);
+ VARDECL(int, trim_offset);
+ SAVE_STACK;
+
+ total = IMAX(total, 0);
+ len = m->nbEBands;
+ skip_start = start;
+ /* Reserve a bit to signal the end of manually skipped bands. */
+ skip_rsv = total >= 1<<BITRES ? 1<<BITRES : 0;
+ total -= skip_rsv;
+ /* Reserve bits for the intensity and dual stereo parameters. */
+ intensity_rsv = dual_stereo_rsv = 0;
+ if (C==2)
+ {
+ intensity_rsv = LOG2_FRAC_TABLE[end-start];
+ if (intensity_rsv>total)
+ intensity_rsv = 0;
+ else
+ {
+ total -= intensity_rsv;
+ dual_stereo_rsv = total>=1<<BITRES ? 1<<BITRES : 0;
+ total -= dual_stereo_rsv;
+ }
+ }
+ ALLOC(bits1, len, int);
+ ALLOC(bits2, len, int);
+ ALLOC(thresh, len, int);
+ ALLOC(trim_offset, len, int);
+
+ for (j=start;j<end;j++)
+ {
+ /* Below this threshold, we're sure not to allocate any PVQ bits */
+ thresh[j] = IMAX((C)<<BITRES, (3*(m->eBands[j+1]-m->eBands[j])<<LM<<BITRES)>>4);
+ /* Tilt of the allocation curve */
+ trim_offset[j] = C*(m->eBands[j+1]-m->eBands[j])*(alloc_trim-5-LM)*(end-j-1)
+ *(1<<(LM+BITRES))>>6;
+ /* Giving less resolution to single-coefficient bands because they get
+ more benefit from having one coarse value per coefficient*/
+ if ((m->eBands[j+1]-m->eBands[j])<<LM==1)
+ trim_offset[j] -= C<<BITRES;
+ }
+ lo = 1;
+ hi = m->nbAllocVectors - 1;
+ do
+ {
+ int done = 0;
+ int psum = 0;
+ int mid = (lo+hi) >> 1;
+ for (j=end;j-->start;)
+ {
+ int bitsj;
+ int N = m->eBands[j+1]-m->eBands[j];
+ bitsj = C*N*m->allocVectors[mid*len+j]<<LM>>2;
+ if (bitsj > 0)
+ bitsj = IMAX(0, bitsj + trim_offset[j]);
+ bitsj += offsets[j];
+ if (bitsj >= thresh[j] || done)
+ {
+ done = 1;
+ /* Don't allocate more than we can actually use */
+ psum += IMIN(bitsj, cap[j]);
+ } else {
+ if (bitsj >= C<<BITRES)
+ psum += C<<BITRES;
+ }
+ }
+ if (psum > total)
+ hi = mid - 1;
+ else
+ lo = mid + 1;
+ /*printf ("lo = %d, hi = %d\n", lo, hi);*/
+ }
+ while (lo <= hi);
+ hi = lo--;
+ /*printf ("interp between %d and %d\n", lo, hi);*/
+ for (j=start;j<end;j++)
+ {
+ int bits1j, bits2j;
+ int N = m->eBands[j+1]-m->eBands[j];
+ bits1j = C*N*m->allocVectors[lo*len+j]<<LM>>2;
+ bits2j = hi>=m->nbAllocVectors ?
+ cap[j] : C*N*m->allocVectors[hi*len+j]<<LM>>2;
+ if (bits1j > 0)
+ bits1j = IMAX(0, bits1j + trim_offset[j]);
+ if (bits2j > 0)
+ bits2j = IMAX(0, bits2j + trim_offset[j]);
+ if (lo > 0)
+ bits1j += offsets[j];
+ bits2j += offsets[j];
+ if (offsets[j]>0)
+ skip_start = j;
+ bits2j = IMAX(0,bits2j-bits1j);
+ bits1[j] = bits1j;
+ bits2[j] = bits2j;
+ }
+ codedBands = interp_bits2pulses(m, start, end, skip_start, bits1, bits2, thresh, cap,
+ total, balance, skip_rsv, intensity, intensity_rsv, dual_stereo, dual_stereo_rsv,
+ pulses, ebits, fine_priority, C, LM, ec, encode, prev, signalBandwidth);
+ RESTORE_STACK;
+ return codedBands;
+}
+#ifdef ENABLE_QEXT
+
+static const unsigned char last_zero[3] = {64, 50, 0};
+static const unsigned char last_cap[3] = {110, 60, 0};
+static const unsigned char last_other[4] = {120, 112, 70, 0};
+
+static void ec_enc_depth(ec_enc *enc, opus_int32 depth, opus_int32 cap, opus_int32 *last) {
+ int sym = 3;
+ if (depth==*last) sym = 2;
+ if (depth==cap) sym = 1;
+ if (depth==0) sym = 0;
+ if (*last == 0) {
+ ec_enc_icdf(enc, IMIN(sym, 2), last_zero, 7);
+ } else if (*last == cap) {
+ ec_enc_icdf(enc, IMIN(sym, 2), last_cap, 7);
+ } else {
+ ec_enc_icdf(enc, sym, last_other, 7);
+ }
+ /* We accept some redundancy if depth==last (for last different from 0 and cap). */
+ if (sym == 3) ec_enc_uint(enc, depth-1, cap);
+ *last = depth;
+}
+
+static int ec_dec_depth(ec_dec *dec, opus_int32 cap, opus_int32 *last) {
+ int depth, sym;
+ if (*last == 0) {
+ sym = ec_dec_icdf(dec, last_zero, 7);
+ if (sym==2) sym=3;
+ } else if (*last == cap) {
+ sym = ec_dec_icdf(dec, last_cap, 7);
+ if (sym==2) sym=3;
+ } else {
+ sym = ec_dec_icdf(dec, last_other, 7);
+ }
+ if (sym==0) depth=0;
+ else if (sym==1) depth=cap;
+ else if (sym==2) depth=*last;
+ else depth = 1 + ec_dec_uint(dec, cap);
+ *last = depth;
+ return depth;
+}
+
+#define MSWAP16(a,b) do {opus_val16 tmp = a;a=b;b=tmp;} while(0)
+static opus_val16 median_of_5_val16(const opus_val16 *x)
+{
+ opus_val16 t0, t1, t2, t3, t4;
+ t2 = x[2];
+ if (x[0] > x[1])
+ {
+ t0 = x[1];
+ t1 = x[0];
+ } else {
+ t0 = x[0];
+ t1 = x[1];
+ }
+ if (x[3] > x[4])
+ {
+ t3 = x[4];
+ t4 = x[3];
+ } else {
+ t3 = x[3];
+ t4 = x[4];
+ }
+ if (t0 > t3)
+ {
+ MSWAP16(t0, t3);
+ MSWAP16(t1, t4);
+ }
+ if (t2 > t1)
+ {
+ if (t1 < t3)
+ return MIN16(t2, t3);
+ else
+ return MIN16(t4, t1);
+ } else {
+ if (t2 < t3)
+ return MIN16(t1, t3);
+ else
+ return MIN16(t2, t4);
+ }
+}
+
+void clt_compute_extra_allocation(const CELTMode *m, const CELTMode *qext_mode, int start, int end, int qext_end, const celt_glog *bandLogE, const celt_glog *qext_bandLogE,
+ opus_int32 total, int *extra_pulses, int *extra_equant, int C, int LM, ec_ctx *ec, int encode, opus_val16 tone_freq, opus_val32 toneishness)
+{
+ int i;
+ opus_int32 last=0;
+ opus_val32 sum;
+ opus_val32 fill;
+ int iter;
+ int tot_bands;
+ int tot_samples;
+ VARDECL(int, depth);
+ VARDECL(opus_int32, cap);
+#ifdef FUZZING
+ float depth_std;
+#endif
+ SAVE_STACK;
+#ifdef FUZZING
+ depth_std = -10.f*log(1e-8+(float)rand()/(float)RAND_MAX);
+ depth_std = FMAX(0, FMIN(48, depth_std));
+#endif
+ if (qext_mode != NULL) {
+ celt_assert(end==m->nbEBands);
+ tot_bands = end + qext_end;
+ tot_samples = qext_mode->eBands[qext_end]*C<<LM;
+ } else {
+ tot_bands = end;
+ tot_samples = (m->eBands[end]-m->eBands[start])*C<<LM;
+ }
+ ALLOC(cap, tot_bands, opus_int32);
+ for (i=start;i<end;i++) cap[i] = 12;
+ if (qext_mode != NULL) {
+ for (i=0;i<qext_end;i++) cap[end+i] = 14;
+ }
+ if (total <= 0) {
+ for (i=start;i<m->nbEBands+qext_end;i++) {
+ extra_pulses[i] = extra_equant[i] = 0;
+ }
+ RESTORE_STACK;
+ return;
+ }
+ ALLOC(depth, tot_bands, int);
+ if (encode) {
+ VARDECL(opus_val16, flatE);
+ VARDECL(int, Ncoef);
+ VARDECL(opus_val16, min);
+ VARDECL(opus_val16, follower);
+
+ ALLOC(flatE, tot_bands, opus_val16);
+ ALLOC(min, tot_bands, opus_val16);
+ ALLOC(Ncoef, tot_bands, int);
+ for (i=start;i<end;i++) {
+ Ncoef[i] = (m->eBands[i+1]-m->eBands[i])*C<<LM;
+ }
+ /* Remove the effect of band width, eMeans and pre-emphasis to compute the real (flat) spectrum. */
+ for (i=start;i<end;i++) {
+ flatE[i] = PSHR32(bandLogE[i] - GCONST(0.0625f)*m->logN[i] + SHL32(eMeans[i],DB_SHIFT-4) - GCONST(.0062f)*(i+5)*(i+5), DB_SHIFT-10);
+ min[i] = 0;
+ }
+ if (C==2) {
+ for (i=start;i<end;i++) {
+ flatE[i] = MAXG(flatE[i], PSHR32(bandLogE[m->nbEBands+i] - GCONST(0.0625f)*m->logN[i] + SHL32(eMeans[i],DB_SHIFT-4) - GCONST(.0062f)*(i+5)*(i+5), DB_SHIFT-10));
+ }
+ }
+ flatE[end-1] += QCONST16(2.f, 10);
+ if (qext_mode != NULL) {
+ opus_val16 min_depth = 0;
+ /* If we have enough bits, give at least 1 bit of depth to all higher bands. */
+ if (total >= 3*C*(qext_mode->eBands[qext_end]-qext_mode->eBands[start])<<LM<<BITRES && (toneishness < QCONST32(.98f, 29) || tone_freq > 1.33f))
+ min_depth = QCONST16(1.f, 10);
+ for (i=0;i<qext_end;i++) {
+ Ncoef[end+i] = (qext_mode->eBands[i+1]-qext_mode->eBands[i])*C<<LM;
+ min[end+i] = min_depth;
+ }
+ for (i=0;i<qext_end;i++) {
+ flatE[end+i] = PSHR32(qext_bandLogE[i] - GCONST(0.0625f)*qext_mode->logN[i] + SHL32(eMeans[i],DB_SHIFT-4) - GCONST(.0062f)*(end+i+5)*(end+i+5), DB_SHIFT-10);
+ }
+ if (C==2) {
+ for (i=0;i<qext_end;i++) {
+ flatE[end+i] = MAXG(flatE[end+i], PSHR32(qext_bandLogE[NB_QEXT_BANDS+i] - GCONST(0.0625f)*qext_mode->logN[i] + SHL32(eMeans[i],DB_SHIFT-4) - GCONST(.0062f)*(end+i+5)*(end+i+5), DB_SHIFT-10));
+ }
+ }
+ }
+ ALLOC(follower, tot_bands, opus_val16);
+ for (i=start+2;i<tot_bands-2;i++) {
+ follower[i] = median_of_5_val16(&flatE[i-2]);
+ }
+ follower[start] = follower[start+1] = follower[start+2];
+ follower[tot_bands-1] = follower[tot_bands-2] = follower[tot_bands-3];
+ for (i=start+1;i<tot_bands;i++) {
+ follower[i] = MAX16(follower[i], follower[i-1]-QCONST16(1.f, 10));
+ }
+ for (i=tot_bands-2;i>=start;i--) {
+ follower[i] = MAX16(follower[i], follower[i+1]-QCONST16(1.f, 10));
+ }
+ for (i=start;i<tot_bands;i++) flatE[i] -= MULT16_16_Q15(Q15ONE-PSHR32(toneishness, 14), follower[i]);
+ if (qext_mode != NULL) {
+ for (i=0;i<qext_end;i++) flatE[end+i] = flatE[end+i] + QCONST16(3.f, 10) + QCONST16(.2f, 10)*i;
+ }
+ /* Approximate fill level assuming all bands contribute fully. */
+ sum = 0;
+ for (i=start;i<tot_bands;i++) {
+ sum += MULT16_16(Ncoef[i], flatE[i]);
+ }
+ total >>= BITRES;
+ fill = (SHL32(total, 10) + sum)/tot_samples;
+ /* Iteratively refine the fill level considering the depth min and cap. */
+ for (iter=0;iter<10;iter++) {
+ sum = 0;
+ for (i=start;i<tot_bands;i++)
+ sum += Ncoef[i] * MIN32(SHL32(cap[i], 10), MAX32(min[i], flatE[i]-fill));
+ fill -= (SHL32(total, 10) - sum)/tot_samples;
+ }
+ for (i=start;i<tot_bands;i++) {
+#ifdef FIXED_POINT
+ depth[i] = PSHR32(MIN32(SHL32(cap[i], 10), MAX32(min[i], flatE[i]-fill)), 10-2);
+#else
+ depth[i] = (int)floor(.5+4*MIN32(SHL32(cap[i], 10), MAX32(min[i], flatE[i]-fill)));
+#endif
+#ifdef FUZZING
+ depth[i] = (int)-depth_std*log(1e-8+(float)rand()/(float)RAND_MAX);
+ depth[i] = IMAX(0, IMIN(cap[i]<<2, depth[i]));
+#endif
+ if (ec_tell_frac(ec) + 80 < ec->storage*8<<BITRES)
+ ec_enc_depth(ec, depth[i], 4*cap[i], &last);
+ else
+ depth[i] = 0;
+ }
+ } else {
+ for (i=start;i<tot_bands;i++) {
+ if (ec_tell_frac(ec) + 80 < ec->storage*8<<BITRES)
+ depth[i] = ec_dec_depth(ec, 4*cap[i], &last);
+ else
+ depth[i] = 0;
+ }
+ }
+ for (i=start;i<end;i++) {
+ extra_equant[i] = (depth[i]+3)>>2;
+ extra_pulses[i] = ((((m->eBands[i+1]-m->eBands[i])<<LM)-1)*C * depth[i] * (1<<BITRES) + 2)>>2;
+ }
+ if (qext_mode) {
+ for (i=0;i<qext_end;i++) {
+ extra_equant[end+i] = (depth[end+i]+3)>>2;
+ extra_pulses[end+i] = ((((qext_mode->eBands[i+1]-qext_mode->eBands[i])<<LM)-1)*C * depth[end+i] * (1<<BITRES) + 2)>>2;
+ }
+ }
+ RESTORE_STACK;
+}
+#endif
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 RATE_H
+#define RATE_H
+
+#define MAX_PSEUDO 40
+#define LOG_MAX_PSEUDO 6
+
+#define CELT_MAX_PULSES 128
+
+#define MAX_FINE_BITS 8
+
+#define FINE_OFFSET 21
+#define QTHETA_OFFSET 4
+#define QTHETA_OFFSET_TWOPHASE 16
+
+#include "cwrs.h"
+#include "modes.h"
+
+void compute_pulse_cache(CELTMode *m, int LM);
+
+static OPUS_INLINE int get_pulses(int i)
+{
+ return i<8 ? i : (8 + (i&7)) << ((i>>3)-1);
+}
+
+static OPUS_INLINE int bits2pulses(const CELTMode *m, int band, int LM, int bits)
+{
+ int i;
+ int lo, hi;
+ const unsigned char *cache;
+
+ LM++;
+ cache = m->cache.bits + m->cache.index[LM*m->nbEBands+band];
+
+ lo = 0;
+ hi = cache[0];
+ bits--;
+ for (i=0;i<LOG_MAX_PSEUDO;i++)
+ {
+ int mid = (lo+hi+1)>>1;
+ /* OPT: Make sure this is implemented with a conditional move */
+ if ((int)cache[mid] >= bits)
+ hi = mid;
+ else
+ lo = mid;
+ }
+ if (bits- (lo == 0 ? -1 : (int)cache[lo]) <= (int)cache[hi]-bits)
+ return lo;
+ else
+ return hi;
+}
+
+static OPUS_INLINE int pulses2bits(const CELTMode *m, int band, int LM, int pulses)
+{
+ const unsigned char *cache;
+
+ LM++;
+ cache = m->cache.bits + m->cache.index[LM*m->nbEBands+band];
+ return pulses == 0 ? 0 : cache[pulses]+1;
+}
+
+/** Compute the pulse allocation, i.e. how many pulses will go in each
+ * band.
+ @param m mode
+ @param offsets Requested increase or decrease in the number of bits for
+ each band
+ @param total Number of bands
+ @param pulses Number of pulses per band (returned)
+ @return Total number of bits allocated
+*/
+int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
+ opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth);
+
+void clt_compute_extra_allocation(const CELTMode *m, const CELTMode *qext_mode, int start, int end, int qext_end, const celt_glog *bandLogE, const celt_glog *qext_bandLogE,
+ opus_int32 total, int *extra_pulses, int *extra_equant, int C, int LM, ec_ctx *ec, int encode, opus_val16 tone_freq, opus_val32 toneishness);
+
+#endif
--- /dev/null
+/* Copyright (C) 2002-2003 Jean-Marc Valin
+ Copyright (C) 2007-2009 Xiph.Org Foundation */
+/**
+ @file stack_alloc.h
+ @brief Temporary memory allocation on stack
+*/
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 STACK_ALLOC_H
+#define STACK_ALLOC_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#if (!defined (VAR_ARRAYS) && !defined (USE_ALLOCA) && !defined (NONTHREADSAFE_PSEUDOSTACK))
+#error "Opus requires one of VAR_ARRAYS, USE_ALLOCA, or NONTHREADSAFE_PSEUDOSTACK be defined to select the temporary allocation mode."
+#endif
+
+#ifdef USE_ALLOCA
+# ifdef _WIN32
+# include <malloc.h>
+# else
+# ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# include <stdlib.h>
+# endif
+# endif
+#endif
+
+/**
+ * @def ALIGN(stack, size)
+ *
+ * Aligns the stack to a 'size' boundary
+ *
+ * @param stack Stack
+ * @param size New size boundary
+ */
+
+/**
+ * @def PUSH(stack, size, type)
+ *
+ * Allocates 'size' elements of type 'type' on the stack
+ *
+ * @param stack Stack
+ * @param size Number of elements
+ * @param type Type of element
+ */
+
+/**
+ * @def VARDECL(var)
+ *
+ * Declare variable on stack
+ *
+ * @param var Variable to declare
+ */
+
+/**
+ * @def ALLOC(var, size, type)
+ *
+ * Allocate 'size' elements of 'type' on stack
+ *
+ * @param var Name of variable to allocate
+ * @param size Number of elements
+ * @param type Type of element
+ */
+
+#if defined(VAR_ARRAYS)
+
+#define VARDECL(type, var)
+#define ALLOC(var, size, type) type var[size]
+#define SAVE_STACK
+#define RESTORE_STACK
+#define ALLOC_STACK
+/* C99 does not allow VLAs of size zero */
+#define ALLOC_NONE 1
+
+#elif defined(USE_ALLOCA)
+
+#define VARDECL(type, var) type *var
+
+# ifdef _WIN32
+# define ALLOC(var, size, type) var = ((type*)_alloca(sizeof(type)*(size)))
+# else
+# define ALLOC(var, size, type) var = ((type*)alloca(sizeof(type)*(size)))
+# endif
+
+#define SAVE_STACK
+#define RESTORE_STACK
+#define ALLOC_STACK
+#define ALLOC_NONE 0
+
+#else
+
+#ifdef CELT_C
+char *scratch_ptr=0;
+char *global_stack=0;
+#else
+extern char *global_stack;
+extern char *scratch_ptr;
+#endif /* CELT_C */
+
+#if __STDC_VERSION__ >= 201112L
+# include <stdalign.h>
+# define ALIGNOF(T) alignof(T)
+#elif defined(__GNUC__) || defined(__clang__)
+# define ALIGNOF(T) __alignof__(T)
+#else
+# include <stddef.h>
+# ifdef __cplusplus
+template <typename T>
+struct alignment_helper {
+ char c;
+ T member;
+};
+# define ALIGNOF(T) (offsetof(alignment_helper<T>, member))
+# else
+# define ALIGNOF(T) (offsetof(struct { char c; T member; }, member))
+# endif
+#endif
+
+#ifdef ENABLE_VALGRIND
+
+#include <valgrind/memcheck.h>
+
+#ifdef CELT_C
+char *global_stack_top=0;
+#else
+extern char *global_stack_top;
+#endif /* CELT_C */
+
+#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
+#define PUSH(stack, size, type) (VALGRIND_MAKE_MEM_NOACCESS(stack, global_stack_top-stack),ALIGN((stack),ALIGNOF(type)),VALGRIND_MAKE_MEM_UNDEFINED(stack, ((size)*sizeof(type)/sizeof(char))),(stack)+=(2*(size)*sizeof(type)/sizeof(char)),(type*)((stack)-(2*(size)*sizeof(type)/sizeof(char))))
+#define RESTORE_STACK ((global_stack = _saved_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack))
+#define ALLOC_STACK char *_saved_stack; ((global_stack = (global_stack==0) ? ((global_stack_top=(char*)opus_alloc_scratch(GLOBAL_STACK_SIZE*2)+(GLOBAL_STACK_SIZE*2))-(GLOBAL_STACK_SIZE*2)) : global_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack)); _saved_stack = global_stack;
+
+#else
+
+#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
+#ifdef ENABLE_HARDENING
+#include "arch.h"
+#define PUSH(stack, size, type) (ALIGN((stack),ALIGNOF(type)),(void)(((int)((size)*(sizeof(type)/(sizeof(char)))) <= (scratch_ptr)+GLOBAL_STACK_SIZE-(stack))?0:CELT_FATAL("pseudostack overflow")),(stack)+=(size)*(sizeof(type)/(sizeof(char))),(type*)(void*)((stack)-(size)*(sizeof(type)/(sizeof(char)))))
+#else
+#define PUSH(stack, size, type) (ALIGN((stack),ALIGNOF(type)),(stack)+=(size)*(sizeof(type)/(sizeof(char))),(type*)(void*)((stack)-(size)*(sizeof(type)/(sizeof(char)))))
+#endif
+
+#if 0 /* Set this to 1 to instrument pseudostack usage */
+#define RESTORE_STACK (printf("%ld %s:%d\n", global_stack-scratch_ptr, __FILE__, __LINE__),global_stack = _saved_stack)
+#else
+#define RESTORE_STACK (global_stack = _saved_stack)
+#endif
+#define ALLOC_STACK char *_saved_stack; (global_stack = (global_stack==0) ? (scratch_ptr=(char*)opus_alloc_scratch(GLOBAL_STACK_SIZE)) : global_stack); _saved_stack = global_stack;
+
+#endif /* ENABLE_VALGRIND */
+
+#include "os_support.h"
+#define VARDECL(type, var) type *var
+#define ALLOC(var, size, type) var = PUSH(global_stack, size, type)
+#define SAVE_STACK char *_saved_stack = global_stack;
+#define ALLOC_NONE 0
+
+#endif /* VAR_ARRAYS */
+
+
+#ifdef ENABLE_VALGRIND
+
+#include <valgrind/memcheck.h>
+#define OPUS_CHECK_ARRAY(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr))
+#define OPUS_CHECK_VALUE(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value)
+#define OPUS_CHECK_ARRAY_COND(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr))
+#define OPUS_CHECK_VALUE_COND(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value)
+#define OPUS_PRINT_INT(value) do {fprintf(stderr, #value " = %d at %s:%d\n", value, __FILE__, __LINE__);}while(0)
+#define OPUS_FPRINTF fprintf
+
+#else
+
+static OPUS_INLINE int _opus_false(void) {return 0;}
+#define OPUS_CHECK_ARRAY(ptr, len) _opus_false()
+#define OPUS_CHECK_VALUE(value) _opus_false()
+#define OPUS_PRINT_INT(value) do{}while(0)
+#define OPUS_FPRINTF (void)
+
+#endif
+
+
+#endif /* STACK_ALLOC_H */
--- /dev/null
+/* The contents of this file was automatically generated by dump_modes.c
+ with arguments: 48000 960 96000 1920
+ It contains static definitions for some pre-defined modes. */
+#include "modes.h"
+#include "rate.h"
+
+#ifdef HAVE_ARM_NE10
+#define OVERRIDE_FFT 1
+#include "static_modes_fixed_arm_ne10.h"
+#endif
+
+#ifndef DEF_WINDOW120
+#define DEF_WINDOW120
+static const celt_coef window120[120] = {
+#ifdef ENABLE_QEXT
+144497, 1300330, 3611201, 7075520, 11690888,
+17454086, 24361057, 32406886, 41585775, 51891010,
+63314937, 75848919, 89483305, 104207389, 120009370,
+136876310, 154794092, 173747379, 193719571, 214692768,
+236647730, 259563841, 283419077, 308189974, 333851611,
+360377579, 387739975, 415909390, 444854905, 474544098,
+504943052, 536016380, 567727246, 600037405, 632907246,
+666295842, 700161014, 734459402, 769146541, 804176950,
+839504226, 875081152, 910859802, 946791664, 982827767,
+1018918807, 1055015290, 1091067670, 1127026498, 1162842573,
+1198467087, 1233851789, 1268949131, 1303712428, 1338096006,
+1372055358, 1405547288, 1438530058, 1470963524, 1502809271,
+1534030739, 1564593342, 1594464577, 1623614128, 1652013956,
+1679638382, 1706464158, 1732470524, 1757639263, 1781954729,
+1805403879, 1827976282, 1849664120, 1870462177, 1890367816,
+1909380946, 1927503971, 1944741741, 1961101475, 1976592692,
+1991227121, 2005018607, 2017983004, 2030138067, 2041503335,
+2052100006, 2061950806, 2071079861, 2079512553, 2087275384,
+2094395835, 2100902218, 2106823532, 2112189321, 2117029527,
+2121374347, 2125254092, 2128699049, 2131739343, 2134404804,
+2136724838, 2138728301, 2140443380, 2141897478, 2143117097,
+2144127740, 2144953807, 2145618502, 2146143741, 2146550077,
+2146856618, 2147080958, 2147239113, 2147345467, 2147412716,
+2147451825, 2147471991, 2147480611, 2147483254, 2147483643,
+#else
+2, 20, 55, 108, 178,
+266, 372, 494, 635, 792,
+966, 1157, 1365, 1590, 1831,
+2089, 2362, 2651, 2956, 3276,
+3611, 3961, 4325, 4703, 5094,
+5499, 5916, 6346, 6788, 7241,
+7705, 8179, 8663, 9156, 9657,
+10167, 10684, 11207, 11736, 12271,
+12810, 13353, 13899, 14447, 14997,
+15547, 16098, 16648, 17197, 17744,
+18287, 18827, 19363, 19893, 20418,
+20936, 21447, 21950, 22445, 22931,
+23407, 23874, 24330, 24774, 25208,
+25629, 26039, 26435, 26819, 27190,
+27548, 27893, 28224, 28541, 28845,
+29135, 29411, 29674, 29924, 30160,
+30384, 30594, 30792, 30977, 31151,
+31313, 31463, 31602, 31731, 31849,
+31958, 32057, 32148, 32229, 32303,
+32370, 32429, 32481, 32528, 32568,
+32604, 32634, 32661, 32683, 32701,
+32717, 32729, 32740, 32748, 32754,
+32758, 32762, 32764, 32766, 32767,
+32767, 32767, 32767, 32767, 32767,
+#endif
+};
+#endif
+
+#ifndef DEF_LOGN400
+#define DEF_LOGN400
+static const opus_int16 logN400[21] = {
+0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
+#endif
+
+#ifndef DEF_PULSE_CACHE50
+#define DEF_PULSE_CACHE50
+static const opus_int16 cache_index50[105] = {
+-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
+82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
+41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
+318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
+305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
+240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
+};
+static const unsigned char cache_bits50[392] = {
+40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
+31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
+51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
+66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
+64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
+94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
+124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
+97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
+142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
+28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
+153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
+229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
+166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
+86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
+25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
+185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
+110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
+74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
+163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
+228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
+90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
+87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
+106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
+224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
+182, 234, };
+static const unsigned char cache_caps50[168] = {
+224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
+178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
+240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
+160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
+138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
+204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
+185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
+207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
+188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
+193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
+204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
+140, 66, 40, };
+#endif
+
+#ifdef ENABLE_QEXT
+# ifndef DEF_QEXT_PULSE_CACHE50
+# define DEF_QEXT_PULSE_CACHE50
+static const opus_int16 qext_cache_index50[70] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 61, 61,
+61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 72, 72, 72,
+72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 80, 80, 80, 80,
+80, 80, 80, 80, 80, 80, 80, 80, 80, 80, };
+static const unsigned char qext_cache_bits50[86] = {
+40, 26, 45, 59, 70, 79, 87, 94, 100, 105, 110, 114, 118, 122, 125,
+128, 131, 136, 141, 146, 150, 153, 157, 160, 163, 168, 173, 178, 182, 185,
+189, 192, 195, 200, 205, 210, 214, 217, 221, 224, 227, 19, 34, 61, 83,
+101, 118, 132, 145, 157, 167, 177, 186, 194, 202, 209, 216, 222, 234, 245,
+254, 10, 42, 77, 107, 133, 157, 179, 200, 219, 236, 253, 7, 50, 93,
+131, 165, 197, 227, 255, 5, 58, 109, 155, 197, 237, };
+static const unsigned char qext_cache_caps50[112] = {
+159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 171,
+171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 167, 167, 167,
+167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 166, 166, 166, 166, 166,
+166, 166, 166, 166, 166, 166, 166, 166, 166, 163, 163, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 165, 165, 165, 165, 165, 165, 165,
+165, 165, 165, 165, 165, 165, 165, };
+# endif
+#endif
+
+#ifndef FFT_TWIDDLES48000_960
+#define FFT_TWIDDLES48000_960
+static const kiss_twiddle_cpx fft_twiddles48000_960[480] = {
+#ifdef ENABLE_QEXT
+{2147483647, 0}, {2147299668, -28109692},
+{2146747759, -56214568}, {2145828016, -84309812},
+{2144540596, -112390610}, {2142885721, -140452151},
+{2140863673, -168489625}, {2138474799, -196498230},
+{2135719508, -224473166}, {2132598273, -252409639},
+{2129111628, -280302863}, {2125260170, -308148059},
+{2121044561, -335940456}, {2116465521, -363675290},
+{2111523836, -391347811}, {2106220352, -418953276},
+{2100555978, -446486956}, {2094531684, -473944133},
+{2088148504, -501320102}, {2081407530, -528610172},
+{2074309917, -555809667}, {2066856882, -582913927},
+{2059049702, -609918309}, {2050889714, -636818183},
+{2042378317, -663608942}, {2033516969, -690285996},
+{2024307188, -716844772}, {2014750553, -743280720},
+{2004848700, -769589312}, {1994603327, -795766038},
+{1984016189, -821806413}, {1973089100, -847705977},
+{1961823932, -873460290}, {1950222616, -899064940},
+{1938287139, -924515541}, {1926019547, -949807730},
+{1913421941, -974937175}, {1900496480, -999899569},
+{1887245379, -1024690635}, {1873670908, -1049306126},
+{1859775393, -1073741824}, {1845561216, -1097993542},
+{1831030811, -1122057124}, {1816186668, -1145928447},
+{1801031331, -1169603422}, {1785567396, -1193077991},
+{1769797514, -1216348132}, {1753724386, -1239409858},
+{1737350766, -1262259218}, {1720679461, -1284892296},
+{1703713325, -1307305214}, {1686455268, -1329494133},
+{1668908244, -1351455249}, {1651075262, -1373184801},
+{1632959377, -1394679064}, {1614563692, -1415934356},
+{1595891361, -1436947036}, {1576945581, -1457713501},
+{1557729600, -1478230195}, {1538246711, -1498493602},
+{1518500250, -1518500250}, {1498493602, -1538246711},
+{1478230195, -1557729600}, {1457713501, -1576945581},
+{1436947036, -1595891361}, {1415934356, -1614563692},
+{1394679064, -1632959377}, {1373184801, -1651075262},
+{1351455249, -1668908244}, {1329494133, -1686455268},
+{1307305214, -1703713325}, {1284892296, -1720679461},
+{1262259218, -1737350766}, {1239409858, -1753724386},
+{1216348132, -1769797514}, {1193077991, -1785567396},
+{1169603422, -1801031331}, {1145928447, -1816186668},
+{1122057124, -1831030811}, {1097993542, -1845561216},
+{1073741824, -1859775393}, {1049306126, -1873670908},
+{1024690635, -1887245379}, {999899569, -1900496480},
+{974937175, -1913421941}, {949807730, -1926019547},
+{924515541, -1938287139}, {899064940, -1950222616},
+{873460290, -1961823932}, {847705977, -1973089100},
+{821806413, -1984016189}, {795766038, -1994603327},
+{769589312, -2004848700}, {743280720, -2014750553},
+{716844772, -2024307188}, {690285996, -2033516969},
+{663608942, -2042378317}, {636818183, -2050889714},
+{609918309, -2059049702}, {582913927, -2066856882},
+{555809667, -2074309917}, {528610172, -2081407530},
+{501320102, -2088148504}, {473944133, -2094531684},
+{446486956, -2100555978}, {418953276, -2106220352},
+{391347811, -2111523836}, {363675290, -2116465521},
+{335940456, -2121044561}, {308148059, -2125260170},
+{280302863, -2129111628}, {252409639, -2132598273},
+{224473166, -2135719508}, {196498230, -2138474799},
+{168489625, -2140863673}, {140452151, -2142885721},
+{112390610, -2144540596}, {84309812, -2145828016},
+{56214568, -2146747759}, {28109692, -2147299668},
+{0, -2147483648}, {-28109692, -2147299668},
+{-56214568, -2146747759}, {-84309812, -2145828016},
+{-112390610, -2144540596}, {-140452151, -2142885721},
+{-168489625, -2140863673}, {-196498230, -2138474799},
+{-224473166, -2135719508}, {-252409639, -2132598273},
+{-280302863, -2129111628}, {-308148059, -2125260170},
+{-335940456, -2121044561}, {-363675290, -2116465521},
+{-391347811, -2111523836}, {-418953276, -2106220352},
+{-446486956, -2100555978}, {-473944133, -2094531684},
+{-501320102, -2088148504}, {-528610172, -2081407530},
+{-555809667, -2074309917}, {-582913927, -2066856882},
+{-609918309, -2059049702}, {-636818183, -2050889714},
+{-663608942, -2042378317}, {-690285996, -2033516969},
+{-716844772, -2024307188}, {-743280720, -2014750553},
+{-769589312, -2004848700}, {-795766038, -1994603327},
+{-821806413, -1984016189}, {-847705977, -1973089100},
+{-873460290, -1961823932}, {-899064940, -1950222616},
+{-924515541, -1938287139}, {-949807730, -1926019547},
+{-974937175, -1913421941}, {-999899569, -1900496480},
+{-1024690635, -1887245379}, {-1049306126, -1873670908},
+{-1073741824, -1859775393}, {-1097993542, -1845561216},
+{-1122057124, -1831030811}, {-1145928447, -1816186668},
+{-1169603422, -1801031331}, {-1193077991, -1785567396},
+{-1216348132, -1769797514}, {-1239409858, -1753724386},
+{-1262259218, -1737350766}, {-1284892296, -1720679461},
+{-1307305214, -1703713325}, {-1329494133, -1686455268},
+{-1351455249, -1668908244}, {-1373184801, -1651075262},
+{-1394679064, -1632959377}, {-1415934356, -1614563692},
+{-1436947036, -1595891361}, {-1457713501, -1576945581},
+{-1478230195, -1557729600}, {-1498493602, -1538246711},
+{-1518500250, -1518500250}, {-1538246711, -1498493602},
+{-1557729600, -1478230195}, {-1576945581, -1457713501},
+{-1595891361, -1436947036}, {-1614563692, -1415934356},
+{-1632959377, -1394679064}, {-1651075262, -1373184801},
+{-1668908244, -1351455249}, {-1686455268, -1329494133},
+{-1703713325, -1307305214}, {-1720679461, -1284892296},
+{-1737350766, -1262259218}, {-1753724386, -1239409858},
+{-1769797514, -1216348132}, {-1785567396, -1193077991},
+{-1801031331, -1169603422}, {-1816186668, -1145928447},
+{-1831030811, -1122057124}, {-1845561216, -1097993542},
+{-1859775393, -1073741824}, {-1873670908, -1049306126},
+{-1887245379, -1024690635}, {-1900496480, -999899569},
+{-1913421941, -974937175}, {-1926019547, -949807730},
+{-1938287139, -924515541}, {-1950222616, -899064940},
+{-1961823932, -873460290}, {-1973089100, -847705977},
+{-1984016189, -821806413}, {-1994603327, -795766038},
+{-2004848700, -769589312}, {-2014750553, -743280720},
+{-2024307188, -716844772}, {-2033516969, -690285996},
+{-2042378317, -663608942}, {-2050889714, -636818183},
+{-2059049702, -609918309}, {-2066856882, -582913927},
+{-2074309917, -555809667}, {-2081407530, -528610172},
+{-2088148504, -501320102}, {-2094531684, -473944133},
+{-2100555978, -446486956}, {-2106220352, -418953276},
+{-2111523836, -391347811}, {-2116465521, -363675290},
+{-2121044561, -335940456}, {-2125260170, -308148059},
+{-2129111628, -280302863}, {-2132598273, -252409639},
+{-2135719508, -224473166}, {-2138474799, -196498230},
+{-2140863673, -168489625}, {-2142885721, -140452151},
+{-2144540596, -112390610}, {-2145828016, -84309812},
+{-2146747759, -56214568}, {-2147299668, -28109692},
+{-2147483648, 0}, {-2147299668, 28109692},
+{-2146747759, 56214568}, {-2145828016, 84309812},
+{-2144540596, 112390610}, {-2142885721, 140452151},
+{-2140863673, 168489625}, {-2138474799, 196498230},
+{-2135719508, 224473166}, {-2132598273, 252409639},
+{-2129111628, 280302863}, {-2125260170, 308148059},
+{-2121044561, 335940456}, {-2116465521, 363675290},
+{-2111523836, 391347811}, {-2106220352, 418953276},
+{-2100555978, 446486956}, {-2094531684, 473944133},
+{-2088148504, 501320102}, {-2081407530, 528610172},
+{-2074309917, 555809667}, {-2066856882, 582913927},
+{-2059049702, 609918309}, {-2050889714, 636818183},
+{-2042378317, 663608942}, {-2033516969, 690285996},
+{-2024307188, 716844772}, {-2014750553, 743280720},
+{-2004848700, 769589312}, {-1994603327, 795766038},
+{-1984016189, 821806413}, {-1973089100, 847705977},
+{-1961823932, 873460290}, {-1950222616, 899064940},
+{-1938287139, 924515541}, {-1926019547, 949807730},
+{-1913421941, 974937175}, {-1900496480, 999899569},
+{-1887245379, 1024690635}, {-1873670908, 1049306126},
+{-1859775393, 1073741824}, {-1845561216, 1097993542},
+{-1831030811, 1122057124}, {-1816186668, 1145928447},
+{-1801031331, 1169603422}, {-1785567396, 1193077991},
+{-1769797514, 1216348132}, {-1753724386, 1239409858},
+{-1737350766, 1262259218}, {-1720679461, 1284892296},
+{-1703713325, 1307305214}, {-1686455268, 1329494133},
+{-1668908244, 1351455249}, {-1651075262, 1373184801},
+{-1632959377, 1394679064}, {-1614563692, 1415934356},
+{-1595891361, 1436947036}, {-1576945581, 1457713501},
+{-1557729600, 1478230195}, {-1538246711, 1498493602},
+{-1518500250, 1518500250}, {-1498493602, 1538246711},
+{-1478230195, 1557729600}, {-1457713501, 1576945581},
+{-1436947036, 1595891361}, {-1415934356, 1614563692},
+{-1394679064, 1632959377}, {-1373184801, 1651075262},
+{-1351455249, 1668908244}, {-1329494133, 1686455268},
+{-1307305214, 1703713325}, {-1284892296, 1720679461},
+{-1262259218, 1737350766}, {-1239409858, 1753724386},
+{-1216348132, 1769797514}, {-1193077991, 1785567396},
+{-1169603422, 1801031331}, {-1145928447, 1816186668},
+{-1122057124, 1831030811}, {-1097993542, 1845561216},
+{-1073741824, 1859775393}, {-1049306126, 1873670908},
+{-1024690635, 1887245379}, {-999899569, 1900496480},
+{-974937175, 1913421941}, {-949807730, 1926019547},
+{-924515541, 1938287139}, {-899064940, 1950222616},
+{-873460290, 1961823932}, {-847705977, 1973089100},
+{-821806413, 1984016189}, {-795766038, 1994603327},
+{-769589312, 2004848700}, {-743280720, 2014750553},
+{-716844772, 2024307188}, {-690285996, 2033516969},
+{-663608942, 2042378317}, {-636818183, 2050889714},
+{-609918309, 2059049702}, {-582913927, 2066856882},
+{-555809667, 2074309917}, {-528610172, 2081407530},
+{-501320102, 2088148504}, {-473944133, 2094531684},
+{-446486956, 2100555978}, {-418953276, 2106220352},
+{-391347811, 2111523836}, {-363675290, 2116465521},
+{-335940456, 2121044561}, {-308148059, 2125260170},
+{-280302863, 2129111628}, {-252409639, 2132598273},
+{-224473166, 2135719508}, {-196498230, 2138474799},
+{-168489625, 2140863673}, {-140452151, 2142885721},
+{-112390610, 2144540596}, {-84309812, 2145828016},
+{-56214568, 2146747759}, {-28109692, 2147299668},
+{0, 2147483647}, {28109692, 2147299668},
+{56214568, 2146747759}, {84309812, 2145828016},
+{112390610, 2144540596}, {140452151, 2142885721},
+{168489625, 2140863673}, {196498230, 2138474799},
+{224473166, 2135719508}, {252409639, 2132598273},
+{280302863, 2129111628}, {308148059, 2125260170},
+{335940456, 2121044561}, {363675290, 2116465521},
+{391347811, 2111523836}, {418953276, 2106220352},
+{446486956, 2100555978}, {473944133, 2094531684},
+{501320102, 2088148504}, {528610172, 2081407530},
+{555809667, 2074309917}, {582913927, 2066856882},
+{609918309, 2059049702}, {636818183, 2050889714},
+{663608942, 2042378317}, {690285996, 2033516969},
+{716844772, 2024307188}, {743280720, 2014750553},
+{769589312, 2004848700}, {795766038, 1994603327},
+{821806413, 1984016189}, {847705977, 1973089100},
+{873460290, 1961823932}, {899064940, 1950222616},
+{924515541, 1938287139}, {949807730, 1926019547},
+{974937175, 1913421941}, {999899569, 1900496480},
+{1024690635, 1887245379}, {1049306126, 1873670908},
+{1073741824, 1859775393}, {1097993542, 1845561216},
+{1122057124, 1831030811}, {1145928447, 1816186668},
+{1169603422, 1801031331}, {1193077991, 1785567396},
+{1216348132, 1769797514}, {1239409858, 1753724386},
+{1262259218, 1737350766}, {1284892296, 1720679461},
+{1307305214, 1703713325}, {1329494133, 1686455268},
+{1351455249, 1668908244}, {1373184801, 1651075262},
+{1394679064, 1632959377}, {1415934356, 1614563692},
+{1436947036, 1595891361}, {1457713501, 1576945581},
+{1478230195, 1557729600}, {1498493602, 1538246711},
+{1518500250, 1518500250}, {1538246711, 1498493602},
+{1557729600, 1478230195}, {1576945581, 1457713501},
+{1595891361, 1436947036}, {1614563692, 1415934356},
+{1632959377, 1394679064}, {1651075262, 1373184801},
+{1668908244, 1351455249}, {1686455268, 1329494133},
+{1703713325, 1307305214}, {1720679461, 1284892296},
+{1737350766, 1262259218}, {1753724386, 1239409858},
+{1769797514, 1216348132}, {1785567396, 1193077991},
+{1801031331, 1169603422}, {1816186668, 1145928447},
+{1831030811, 1122057124}, {1845561216, 1097993542},
+{1859775393, 1073741824}, {1873670908, 1049306126},
+{1887245379, 1024690635}, {1900496480, 999899569},
+{1913421941, 974937175}, {1926019547, 949807730},
+{1938287139, 924515541}, {1950222616, 899064940},
+{1961823932, 873460290}, {1973089100, 847705977},
+{1984016189, 821806413}, {1994603327, 795766038},
+{2004848700, 769589312}, {2014750553, 743280720},
+{2024307188, 716844772}, {2033516969, 690285996},
+{2042378317, 663608942}, {2050889714, 636818183},
+{2059049702, 609918309}, {2066856882, 582913927},
+{2074309917, 555809667}, {2081407530, 528610172},
+{2088148504, 501320102}, {2094531684, 473944133},
+{2100555978, 446486956}, {2106220352, 418953276},
+{2111523836, 391347811}, {2116465521, 363675290},
+{2121044561, 335940456}, {2125260170, 308148059},
+{2129111628, 280302863}, {2132598273, 252409639},
+{2135719508, 224473166}, {2138474799, 196498230},
+{2140863673, 168489625}, {2142885721, 140452151},
+{2144540596, 112390610}, {2145828016, 84309812},
+{2146747759, 56214568}, {2147299668, 28109692},
+#else
+{32767, 0}, {32765, -429},
+{32757, -858}, {32743, -1286},
+{32723, -1715}, {32698, -2143},
+{32667, -2571}, {32631, -2998},
+{32588, -3425}, {32541, -3851},
+{32488, -4277}, {32429, -4702},
+{32365, -5126}, {32295, -5549},
+{32219, -5971}, {32138, -6393},
+{32052, -6813}, {31960, -7232},
+{31863, -7650}, {31760, -8066},
+{31651, -8481}, {31538, -8895},
+{31419, -9307}, {31294, -9717},
+{31164, -10126}, {31029, -10533},
+{30888, -10938}, {30743, -11342},
+{30592, -11743}, {30435, -12142},
+{30274, -12540}, {30107, -12935},
+{29935, -13328}, {29758, -13719},
+{29576, -14107}, {29389, -14493},
+{29197, -14876}, {28999, -15257},
+{28797, -15636}, {28590, -16011},
+{28378, -16384}, {28161, -16754},
+{27939, -17121}, {27713, -17485},
+{27482, -17847}, {27246, -18205},
+{27005, -18560}, {26760, -18912},
+{26510, -19261}, {26255, -19606},
+{25997, -19948}, {25733, -20286},
+{25466, -20622}, {25193, -20953},
+{24917, -21281}, {24636, -21605},
+{24351, -21926}, {24062, -22243},
+{23769, -22556}, {23472, -22865},
+{23170, -23170}, {22865, -23472},
+{22556, -23769}, {22243, -24062},
+{21926, -24351}, {21605, -24636},
+{21281, -24917}, {20953, -25193},
+{20622, -25466}, {20286, -25733},
+{19948, -25997}, {19606, -26255},
+{19261, -26510}, {18912, -26760},
+{18560, -27005}, {18205, -27246},
+{17847, -27482}, {17485, -27713},
+{17121, -27939}, {16754, -28161},
+{16384, -28378}, {16011, -28590},
+{15636, -28797}, {15257, -28999},
+{14876, -29197}, {14493, -29389},
+{14107, -29576}, {13719, -29758},
+{13328, -29935}, {12935, -30107},
+{12540, -30274}, {12142, -30435},
+{11743, -30592}, {11342, -30743},
+{10938, -30888}, {10533, -31029},
+{10126, -31164}, {9717, -31294},
+{9307, -31419}, {8895, -31538},
+{8481, -31651}, {8066, -31760},
+{7650, -31863}, {7232, -31960},
+{6813, -32052}, {6393, -32138},
+{5971, -32219}, {5549, -32295},
+{5126, -32365}, {4702, -32429},
+{4277, -32488}, {3851, -32541},
+{3425, -32588}, {2998, -32631},
+{2571, -32667}, {2143, -32698},
+{1715, -32723}, {1286, -32743},
+{858, -32757}, {429, -32765},
+{0, -32767}, {-429, -32765},
+{-858, -32757}, {-1286, -32743},
+{-1715, -32723}, {-2143, -32698},
+{-2571, -32667}, {-2998, -32631},
+{-3425, -32588}, {-3851, -32541},
+{-4277, -32488}, {-4702, -32429},
+{-5126, -32365}, {-5549, -32295},
+{-5971, -32219}, {-6393, -32138},
+{-6813, -32052}, {-7232, -31960},
+{-7650, -31863}, {-8066, -31760},
+{-8481, -31651}, {-8895, -31538},
+{-9307, -31419}, {-9717, -31294},
+{-10126, -31164}, {-10533, -31029},
+{-10938, -30888}, {-11342, -30743},
+{-11743, -30592}, {-12142, -30435},
+{-12540, -30274}, {-12935, -30107},
+{-13328, -29935}, {-13719, -29758},
+{-14107, -29576}, {-14493, -29389},
+{-14876, -29197}, {-15257, -28999},
+{-15636, -28797}, {-16011, -28590},
+{-16384, -28378}, {-16754, -28161},
+{-17121, -27939}, {-17485, -27713},
+{-17847, -27482}, {-18205, -27246},
+{-18560, -27005}, {-18912, -26760},
+{-19261, -26510}, {-19606, -26255},
+{-19948, -25997}, {-20286, -25733},
+{-20622, -25466}, {-20953, -25193},
+{-21281, -24917}, {-21605, -24636},
+{-21926, -24351}, {-22243, -24062},
+{-22556, -23769}, {-22865, -23472},
+{-23170, -23170}, {-23472, -22865},
+{-23769, -22556}, {-24062, -22243},
+{-24351, -21926}, {-24636, -21605},
+{-24917, -21281}, {-25193, -20953},
+{-25466, -20622}, {-25733, -20286},
+{-25997, -19948}, {-26255, -19606},
+{-26510, -19261}, {-26760, -18912},
+{-27005, -18560}, {-27246, -18205},
+{-27482, -17847}, {-27713, -17485},
+{-27939, -17121}, {-28161, -16754},
+{-28378, -16384}, {-28590, -16011},
+{-28797, -15636}, {-28999, -15257},
+{-29197, -14876}, {-29389, -14493},
+{-29576, -14107}, {-29758, -13719},
+{-29935, -13328}, {-30107, -12935},
+{-30274, -12540}, {-30435, -12142},
+{-30592, -11743}, {-30743, -11342},
+{-30888, -10938}, {-31029, -10533},
+{-31164, -10126}, {-31294, -9717},
+{-31419, -9307}, {-31538, -8895},
+{-31651, -8481}, {-31760, -8066},
+{-31863, -7650}, {-31960, -7232},
+{-32052, -6813}, {-32138, -6393},
+{-32219, -5971}, {-32295, -5549},
+{-32365, -5126}, {-32429, -4702},
+{-32488, -4277}, {-32541, -3851},
+{-32588, -3425}, {-32631, -2998},
+{-32667, -2571}, {-32698, -2143},
+{-32723, -1715}, {-32743, -1286},
+{-32757, -858}, {-32765, -429},
+{-32767, 0}, {-32765, 429},
+{-32757, 858}, {-32743, 1286},
+{-32723, 1715}, {-32698, 2143},
+{-32667, 2571}, {-32631, 2998},
+{-32588, 3425}, {-32541, 3851},
+{-32488, 4277}, {-32429, 4702},
+{-32365, 5126}, {-32295, 5549},
+{-32219, 5971}, {-32138, 6393},
+{-32052, 6813}, {-31960, 7232},
+{-31863, 7650}, {-31760, 8066},
+{-31651, 8481}, {-31538, 8895},
+{-31419, 9307}, {-31294, 9717},
+{-31164, 10126}, {-31029, 10533},
+{-30888, 10938}, {-30743, 11342},
+{-30592, 11743}, {-30435, 12142},
+{-30274, 12540}, {-30107, 12935},
+{-29935, 13328}, {-29758, 13719},
+{-29576, 14107}, {-29389, 14493},
+{-29197, 14876}, {-28999, 15257},
+{-28797, 15636}, {-28590, 16011},
+{-28378, 16384}, {-28161, 16754},
+{-27939, 17121}, {-27713, 17485},
+{-27482, 17847}, {-27246, 18205},
+{-27005, 18560}, {-26760, 18912},
+{-26510, 19261}, {-26255, 19606},
+{-25997, 19948}, {-25733, 20286},
+{-25466, 20622}, {-25193, 20953},
+{-24917, 21281}, {-24636, 21605},
+{-24351, 21926}, {-24062, 22243},
+{-23769, 22556}, {-23472, 22865},
+{-23170, 23170}, {-22865, 23472},
+{-22556, 23769}, {-22243, 24062},
+{-21926, 24351}, {-21605, 24636},
+{-21281, 24917}, {-20953, 25193},
+{-20622, 25466}, {-20286, 25733},
+{-19948, 25997}, {-19606, 26255},
+{-19261, 26510}, {-18912, 26760},
+{-18560, 27005}, {-18205, 27246},
+{-17847, 27482}, {-17485, 27713},
+{-17121, 27939}, {-16754, 28161},
+{-16384, 28378}, {-16011, 28590},
+{-15636, 28797}, {-15257, 28999},
+{-14876, 29197}, {-14493, 29389},
+{-14107, 29576}, {-13719, 29758},
+{-13328, 29935}, {-12935, 30107},
+{-12540, 30274}, {-12142, 30435},
+{-11743, 30592}, {-11342, 30743},
+{-10938, 30888}, {-10533, 31029},
+{-10126, 31164}, {-9717, 31294},
+{-9307, 31419}, {-8895, 31538},
+{-8481, 31651}, {-8066, 31760},
+{-7650, 31863}, {-7232, 31960},
+{-6813, 32052}, {-6393, 32138},
+{-5971, 32219}, {-5549, 32295},
+{-5126, 32365}, {-4702, 32429},
+{-4277, 32488}, {-3851, 32541},
+{-3425, 32588}, {-2998, 32631},
+{-2571, 32667}, {-2143, 32698},
+{-1715, 32723}, {-1286, 32743},
+{-858, 32757}, {-429, 32765},
+{0, 32767}, {429, 32765},
+{858, 32757}, {1286, 32743},
+{1715, 32723}, {2143, 32698},
+{2571, 32667}, {2998, 32631},
+{3425, 32588}, {3851, 32541},
+{4277, 32488}, {4702, 32429},
+{5126, 32365}, {5549, 32295},
+{5971, 32219}, {6393, 32138},
+{6813, 32052}, {7232, 31960},
+{7650, 31863}, {8066, 31760},
+{8481, 31651}, {8895, 31538},
+{9307, 31419}, {9717, 31294},
+{10126, 31164}, {10533, 31029},
+{10938, 30888}, {11342, 30743},
+{11743, 30592}, {12142, 30435},
+{12540, 30274}, {12935, 30107},
+{13328, 29935}, {13719, 29758},
+{14107, 29576}, {14493, 29389},
+{14876, 29197}, {15257, 28999},
+{15636, 28797}, {16011, 28590},
+{16384, 28378}, {16754, 28161},
+{17121, 27939}, {17485, 27713},
+{17847, 27482}, {18205, 27246},
+{18560, 27005}, {18912, 26760},
+{19261, 26510}, {19606, 26255},
+{19948, 25997}, {20286, 25733},
+{20622, 25466}, {20953, 25193},
+{21281, 24917}, {21605, 24636},
+{21926, 24351}, {22243, 24062},
+{22556, 23769}, {22865, 23472},
+{23170, 23170}, {23472, 22865},
+{23769, 22556}, {24062, 22243},
+{24351, 21926}, {24636, 21605},
+{24917, 21281}, {25193, 20953},
+{25466, 20622}, {25733, 20286},
+{25997, 19948}, {26255, 19606},
+{26510, 19261}, {26760, 18912},
+{27005, 18560}, {27246, 18205},
+{27482, 17847}, {27713, 17485},
+{27939, 17121}, {28161, 16754},
+{28378, 16384}, {28590, 16011},
+{28797, 15636}, {28999, 15257},
+{29197, 14876}, {29389, 14493},
+{29576, 14107}, {29758, 13719},
+{29935, 13328}, {30107, 12935},
+{30274, 12540}, {30435, 12142},
+{30592, 11743}, {30743, 11342},
+{30888, 10938}, {31029, 10533},
+{31164, 10126}, {31294, 9717},
+{31419, 9307}, {31538, 8895},
+{31651, 8481}, {31760, 8066},
+{31863, 7650}, {31960, 7232},
+{32052, 6813}, {32138, 6393},
+{32219, 5971}, {32295, 5549},
+{32365, 5126}, {32429, 4702},
+{32488, 4277}, {32541, 3851},
+{32588, 3425}, {32631, 2998},
+{32667, 2571}, {32698, 2143},
+{32723, 1715}, {32743, 1286},
+{32757, 858}, {32765, 429},
+#endif
+};
+#ifndef FFT_BITREV480
+#define FFT_BITREV480
+static const opus_int16 fft_bitrev480[480] = {
+0, 96, 192, 288, 384, 32, 128, 224, 320, 416, 64, 160, 256, 352, 448,
+8, 104, 200, 296, 392, 40, 136, 232, 328, 424, 72, 168, 264, 360, 456,
+16, 112, 208, 304, 400, 48, 144, 240, 336, 432, 80, 176, 272, 368, 464,
+24, 120, 216, 312, 408, 56, 152, 248, 344, 440, 88, 184, 280, 376, 472,
+4, 100, 196, 292, 388, 36, 132, 228, 324, 420, 68, 164, 260, 356, 452,
+12, 108, 204, 300, 396, 44, 140, 236, 332, 428, 76, 172, 268, 364, 460,
+20, 116, 212, 308, 404, 52, 148, 244, 340, 436, 84, 180, 276, 372, 468,
+28, 124, 220, 316, 412, 60, 156, 252, 348, 444, 92, 188, 284, 380, 476,
+1, 97, 193, 289, 385, 33, 129, 225, 321, 417, 65, 161, 257, 353, 449,
+9, 105, 201, 297, 393, 41, 137, 233, 329, 425, 73, 169, 265, 361, 457,
+17, 113, 209, 305, 401, 49, 145, 241, 337, 433, 81, 177, 273, 369, 465,
+25, 121, 217, 313, 409, 57, 153, 249, 345, 441, 89, 185, 281, 377, 473,
+5, 101, 197, 293, 389, 37, 133, 229, 325, 421, 69, 165, 261, 357, 453,
+13, 109, 205, 301, 397, 45, 141, 237, 333, 429, 77, 173, 269, 365, 461,
+21, 117, 213, 309, 405, 53, 149, 245, 341, 437, 85, 181, 277, 373, 469,
+29, 125, 221, 317, 413, 61, 157, 253, 349, 445, 93, 189, 285, 381, 477,
+2, 98, 194, 290, 386, 34, 130, 226, 322, 418, 66, 162, 258, 354, 450,
+10, 106, 202, 298, 394, 42, 138, 234, 330, 426, 74, 170, 266, 362, 458,
+18, 114, 210, 306, 402, 50, 146, 242, 338, 434, 82, 178, 274, 370, 466,
+26, 122, 218, 314, 410, 58, 154, 250, 346, 442, 90, 186, 282, 378, 474,
+6, 102, 198, 294, 390, 38, 134, 230, 326, 422, 70, 166, 262, 358, 454,
+14, 110, 206, 302, 398, 46, 142, 238, 334, 430, 78, 174, 270, 366, 462,
+22, 118, 214, 310, 406, 54, 150, 246, 342, 438, 86, 182, 278, 374, 470,
+30, 126, 222, 318, 414, 62, 158, 254, 350, 446, 94, 190, 286, 382, 478,
+3, 99, 195, 291, 387, 35, 131, 227, 323, 419, 67, 163, 259, 355, 451,
+11, 107, 203, 299, 395, 43, 139, 235, 331, 427, 75, 171, 267, 363, 459,
+19, 115, 211, 307, 403, 51, 147, 243, 339, 435, 83, 179, 275, 371, 467,
+27, 123, 219, 315, 411, 59, 155, 251, 347, 443, 91, 187, 283, 379, 475,
+7, 103, 199, 295, 391, 39, 135, 231, 327, 423, 71, 167, 263, 359, 455,
+15, 111, 207, 303, 399, 47, 143, 239, 335, 431, 79, 175, 271, 367, 463,
+23, 119, 215, 311, 407, 55, 151, 247, 343, 439, 87, 183, 279, 375, 471,
+31, 127, 223, 319, 415, 63, 159, 255, 351, 447, 95, 191, 287, 383, 479,
+};
+#endif
+
+#ifndef FFT_BITREV240
+#define FFT_BITREV240
+static const opus_int16 fft_bitrev240[240] = {
+0, 48, 96, 144, 192, 16, 64, 112, 160, 208, 32, 80, 128, 176, 224,
+4, 52, 100, 148, 196, 20, 68, 116, 164, 212, 36, 84, 132, 180, 228,
+8, 56, 104, 152, 200, 24, 72, 120, 168, 216, 40, 88, 136, 184, 232,
+12, 60, 108, 156, 204, 28, 76, 124, 172, 220, 44, 92, 140, 188, 236,
+1, 49, 97, 145, 193, 17, 65, 113, 161, 209, 33, 81, 129, 177, 225,
+5, 53, 101, 149, 197, 21, 69, 117, 165, 213, 37, 85, 133, 181, 229,
+9, 57, 105, 153, 201, 25, 73, 121, 169, 217, 41, 89, 137, 185, 233,
+13, 61, 109, 157, 205, 29, 77, 125, 173, 221, 45, 93, 141, 189, 237,
+2, 50, 98, 146, 194, 18, 66, 114, 162, 210, 34, 82, 130, 178, 226,
+6, 54, 102, 150, 198, 22, 70, 118, 166, 214, 38, 86, 134, 182, 230,
+10, 58, 106, 154, 202, 26, 74, 122, 170, 218, 42, 90, 138, 186, 234,
+14, 62, 110, 158, 206, 30, 78, 126, 174, 222, 46, 94, 142, 190, 238,
+3, 51, 99, 147, 195, 19, 67, 115, 163, 211, 35, 83, 131, 179, 227,
+7, 55, 103, 151, 199, 23, 71, 119, 167, 215, 39, 87, 135, 183, 231,
+11, 59, 107, 155, 203, 27, 75, 123, 171, 219, 43, 91, 139, 187, 235,
+15, 63, 111, 159, 207, 31, 79, 127, 175, 223, 47, 95, 143, 191, 239,
+};
+#endif
+
+#ifndef FFT_BITREV120
+#define FFT_BITREV120
+static const opus_int16 fft_bitrev120[120] = {
+0, 24, 48, 72, 96, 8, 32, 56, 80, 104, 16, 40, 64, 88, 112,
+4, 28, 52, 76, 100, 12, 36, 60, 84, 108, 20, 44, 68, 92, 116,
+1, 25, 49, 73, 97, 9, 33, 57, 81, 105, 17, 41, 65, 89, 113,
+5, 29, 53, 77, 101, 13, 37, 61, 85, 109, 21, 45, 69, 93, 117,
+2, 26, 50, 74, 98, 10, 34, 58, 82, 106, 18, 42, 66, 90, 114,
+6, 30, 54, 78, 102, 14, 38, 62, 86, 110, 22, 46, 70, 94, 118,
+3, 27, 51, 75, 99, 11, 35, 59, 83, 107, 19, 43, 67, 91, 115,
+7, 31, 55, 79, 103, 15, 39, 63, 87, 111, 23, 47, 71, 95, 119,
+};
+#endif
+
+#ifndef FFT_BITREV60
+#define FFT_BITREV60
+static const opus_int16 fft_bitrev60[60] = {
+0, 12, 24, 36, 48, 4, 16, 28, 40, 52, 8, 20, 32, 44, 56,
+1, 13, 25, 37, 49, 5, 17, 29, 41, 53, 9, 21, 33, 45, 57,
+2, 14, 26, 38, 50, 6, 18, 30, 42, 54, 10, 22, 34, 46, 58,
+3, 15, 27, 39, 51, 7, 19, 31, 43, 55, 11, 23, 35, 47, 59,
+};
+#endif
+
+#ifndef FFT_STATE48000_960_0
+#define FFT_STATE48000_960_0
+static const kiss_fft_state fft_state48000_960_0 = {
+480, /* nfft */
+#ifdef ENABLE_QEXT
+572662306, /* scale */
+#else
+17476, /* scale */
+#endif
+8, /* scale_shift */
+-1, /* shift */
+{5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev480, /* bitrev */
+fft_twiddles48000_960, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_480,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE48000_960_1
+#define FFT_STATE48000_960_1
+static const kiss_fft_state fft_state48000_960_1 = {
+240, /* nfft */
+#ifdef ENABLE_QEXT
+572662306, /* scale */
+#else
+17476, /* scale */
+#endif
+7, /* scale_shift */
+1, /* shift */
+{5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev240, /* bitrev */
+fft_twiddles48000_960, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_240,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE48000_960_2
+#define FFT_STATE48000_960_2
+static const kiss_fft_state fft_state48000_960_2 = {
+120, /* nfft */
+#ifdef ENABLE_QEXT
+572662306, /* scale */
+#else
+17476, /* scale */
+#endif
+6, /* scale_shift */
+2, /* shift */
+{5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev120, /* bitrev */
+fft_twiddles48000_960, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_120,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE48000_960_3
+#define FFT_STATE48000_960_3
+static const kiss_fft_state fft_state48000_960_3 = {
+60, /* nfft */
+#ifdef ENABLE_QEXT
+572662306, /* scale */
+#else
+17476, /* scale */
+#endif
+5, /* scale_shift */
+3, /* shift */
+{5, 12, 3, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev60, /* bitrev */
+fft_twiddles48000_960, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_60,
+#else
+NULL,
+#endif
+};
+#endif
+
+#endif
+
+#ifndef MDCT_TWIDDLES960
+#define MDCT_TWIDDLES960
+static const celt_coef mdct_twiddles960[1800] = {
+#ifdef ENABLE_QEXT
+2147483468, 2147469095, 2147431723, 2147371355, 2147287990,
+2147181629, 2147052273, 2146899924, 2146724584, 2146526254,
+2146304937, 2146060634, 2145793349, 2145503083, 2145189842,
+2144853627, 2144494442, 2144112292, 2143707180, 2143279110,
+2142828088, 2142354118, 2141857204, 2141337354, 2140794571,
+2140228862, 2139640233, 2139028690, 2138394240, 2137736889,
+2137056645, 2136353515, 2135627506, 2134878626, 2134106884,
+2133312286, 2132494843, 2131654563, 2130791454, 2129905526,
+2128996788, 2128065251, 2127110924, 2126133817, 2125133941,
+2124111307, 2123065925, 2121997806, 2120906963, 2119793407,
+2118657149, 2117498202, 2116316578, 2115112291, 2113885352,
+2112635775, 2111363574, 2110068761, 2108751352, 2107411359,
+2106048798, 2104663683, 2103256028, 2101825849, 2100373162,
+2098897981, 2097400322, 2095880202, 2094337637, 2092772643,
+2091185237, 2089575437, 2087943258, 2086288720, 2084611839,
+2082912633, 2081191122, 2079447322, 2077681253, 2075892934,
+2074082383, 2072249621, 2070394667, 2068517540, 2066618262,
+2064696851, 2062753329, 2060787717, 2058800036, 2056790306,
+2054758550, 2052704789, 2050629045, 2048531340, 2046411698,
+2044270140, 2042106689, 2039921369, 2037714204, 2035485216,
+2033234429, 2030961869, 2028667558, 2026351522, 2024013785,
+2021654373, 2019273310, 2016870623, 2014446336, 2012000477,
+2009533071, 2007044144, 2004533723, 2002001835, 1999448508,
+1996873768, 1994277643, 1991660161, 1989021350, 1986361238,
+1983679853, 1980977226, 1978253383, 1975508355, 1972742171,
+1969954860, 1967146453, 1964316979, 1961466469, 1958594953,
+1955702462, 1952789027, 1949854680, 1946899451, 1943923372,
+1940926475, 1937908793, 1934870357, 1931811201, 1928731356,
+1925630856, 1922509734, 1919368023, 1916205758, 1913022972,
+1909819698, 1906595972, 1903351828, 1900087301, 1896802425,
+1893497236, 1890171769, 1886826060, 1883460144, 1880074058,
+1876667838, 1873241521, 1869795142, 1866328740, 1862842350,
+1859336011, 1855809760, 1852263635, 1848697674, 1845111914,
+1841506395, 1837881155, 1834236233, 1830571667, 1826887497,
+1823183763, 1819460504, 1815717761, 1811955572, 1808173978,
+1804373021, 1800552740, 1796713177, 1792854372, 1788976368,
+1785079205, 1781162925, 1777227570, 1773273182, 1769299805,
+1765307479, 1761296249, 1757266156, 1753217244, 1749149557,
+1745063138, 1740958031, 1736834279, 1732691928, 1728531020,
+1724351602, 1720153717, 1715937410, 1711702727, 1707449714,
+1703178415, 1698888876, 1694581143, 1690255263, 1685911282,
+1681549245, 1677169201, 1672771196, 1668355276, 1663921490,
+1659469885, 1655000508, 1650513407, 1646008631, 1641486227,
+1636946244, 1632388731, 1627813736, 1623221309, 1618611498,
+1613984353, 1609339924, 1604678260, 1599999411, 1595303428,
+1590590360, 1585860258, 1581113173, 1576349155, 1571568256,
+1566770527, 1561956018, 1557124783, 1552276872, 1547412337,
+1542531231, 1537633606, 1532719513, 1527789007, 1522842139,
+1517878963, 1512899531, 1507903898, 1502892116, 1497864239,
+1492820322, 1487760417, 1482684580, 1477592864, 1472485325,
+1467362016, 1462222994, 1457068312, 1451898025, 1446712191,
+1441510863, 1436294098, 1431061951, 1425814478, 1420551737,
+1415273782, 1409980671, 1404672460, 1399349206, 1394010966,
+1388657798, 1383289758, 1377906904, 1372509294, 1367096986,
+1361670037, 1356228505, 1350772450, 1345301929, 1339817000,
+1334317724, 1328804158, 1323276361, 1317734393, 1312178313,
+1306608181, 1301024057, 1295425999, 1289814068, 1284188325,
+1278548828, 1272895640, 1267228820, 1261548429, 1255854528,
+1250147177, 1244426439, 1238692373, 1232945043, 1227184508,
+1221410831, 1215624074, 1209824299, 1204011567, 1198185941,
+1192347484, 1186496258, 1180632325, 1174755748, 1168866591,
+1162964917, 1157050787, 1151124267, 1145185419, 1139234307,
+1133270995, 1127295547, 1121308026, 1115308496, 1109297023,
+1103273670, 1097238502, 1091191583, 1085132978, 1079062753,
+1072980972, 1066887699, 1060783002, 1054666944, 1048539592,
+1042401010, 1036251266, 1030090423, 1023918550, 1017735711,
+1011541973, 1005337402, 999122065, 992896028, 986659358,
+980412122, 974154386, 967886217, 961607684, 955318852,
+949019790, 942710564, 936391243, 930061894, 923722585,
+917373383, 911014357, 904645574, 898267104, 891879014,
+885481373, 879074249, 872657710, 866231826, 859796666,
+853352298, 846898791, 840436214, 833964638, 827484130,
+820994760, 814496598, 807989714, 801474176, 794950056,
+788417422, 781876345, 775326894, 768769141, 762203154,
+755629005, 749046764, 742456501, 735858287, 729252193,
+722638289, 716016646, 709387335, 702750427, 696105993,
+689454104, 682794832, 676128248, 669454423, 662773428,
+656085336, 649390218, 642688145, 635979190, 629263424,
+622540918, 615811746, 609075979, 602333690, 595584950,
+588829831, 582068407, 575300749, 568526931, 561747023,
+554961100, 548169234, 541371497, 534567963, 527758704,
+520943793, 514123303, 507297307, 500465878, 493629090,
+486787016, 479939728, 473087301, 466229807, 459367320,
+452499914, 445627662, 438750638, 431868915, 424982567,
+418091668, 411196291, 404296511, 397392401, 390484035,
+383571488, 376654833, 369734144, 362809495, 355880961,
+348948616, 342012534, 335072790, 328129457, 321182610,
+314232323, 307278671, 300321729, 293361570, 286398270,
+279431902, 272462542, 265490265, 258515144, 251537254,
+244556671, 237573469, 230587722, 223599506, 216608896,
+209615966, 202620791, 195623446, 188624006, 181622546,
+174619141, 167613866, 160606796, 153598006, 146587571,
+139575567, 132562067, 125547148, 118530885, 111513352,
+104494625, 97474778, 90453888, 83432030, 76409277,
+69385707, 62361393, 55336412, 48310838, 41284746,
+34258213, 27231312, 20204120, 13176712, 6149162,
+-878453, -7906059, -14933580, -21960942, -28988068,
+-36014884, -43041314, -50067283, -57092716, -64117537,
+-71141672, -78165045, -85187581, -92209205, -99229841,
+-106249414, -113267850, -120285073, -127301007, -134315578,
+-141328711, -148340330, -155350361, -162358728, -169365356,
+-176370170, -183373096, -190374058, -197372981, -204369791,
+-211364411, -218356769, -225346788, -232334393, -239319511,
+-246302065, -253281982, -260259186, -267233603, -274205159,
+-281173778, -288139385, -295101907, -302061269, -309017396,
+-315970213, -322919647, -329865622, -336808065, -343746901,
+-350682056, -357613455, -364541025, -371464690, -378384377,
+-385300013, -392211522, -399118830, -406021865, -412920551,
+-419814815, -426704583, -433589782, -440470337, -447346176,
+-454217223, -461083406, -467944652, -474800886, -481652035,
+-488498026, -495338786, -502174241, -509004318, -515828944,
+-522648046, -529461551, -536269386, -543071478, -549867754,
+-556658141, -563442567, -570220959, -576993244, -583759350,
+-590519205, -597272736, -604019870, -610760536, -617494660,
+-624222173, -630943000, -637657070, -644364312, -651064652,
+-657758021, -664444345, -671123554, -677795576, -684460338,
+-691117771, -697767803, -704410362, -711045377, -717672778,
+-724292493, -730904451, -737508582, -744104815, -750693079,
+-757273304, -763845419, -770409354, -776965038, -783512402,
+-790051375, -796581887, -803103868, -809617249, -816121959,
+-822617929, -829105090, -835583372, -842052705, -848513021,
+-854964249, -861406322, -867839170, -874262724, -880676915,
+-887081675, -893476935, -899862626, -906238681, -912605031,
+-918961607, -925308342, -931645168, -937972016, -944288820,
+-950595511, -956892022, -963178285, -969454234, -975719800,
+-981974918, -988219519, -994453537, -1000676905, -1006889557,
+-1013091426, -1019282445, -1025462549, -1031631671, -1037789745,
+-1043936705, -1050072485, -1056197020, -1062310244, -1068412091,
+-1074502497, -1080581395, -1086648722, -1092704411, -1098748398,
+-1104780618, -1110801008, -1116809501, -1122806034, -1128790543,
+-1134762964, -1140723232, -1146671283, -1152607055, -1158530484,
+-1164441505, -1170340057, -1176226074, -1182099496, -1187960258,
+-1193808298, -1199643553, -1205465961, -1211275460, -1217071986,
+-1222855479, -1228625876, -1234383115, -1240127136, -1245857875,
+-1251575272, -1257279266, -1262969796, -1268646800, -1274310217,
+-1279959989, -1285596052, -1291218348, -1296826816, -1302421396,
+-1308002029, -1313568653, -1319121210, -1324659641, -1330183885,
+-1335693885, -1341189580, -1346670912, -1352137822, -1357590252,
+-1363028143, -1368451438, -1373860077, -1379254004, -1384633159,
+-1389997487, -1395346928, -1400681427, -1406000925, -1411305366,
+-1416594694, -1421868850, -1427127780, -1432371426, -1437599733,
+-1442812644, -1448010104, -1453192057, -1458358447, -1463509220,
+-1468644319, -1473763690, -1478867279, -1483955030, -1489026889,
+-1494082802, -1499122714, -1504146572, -1509154322, -1514145910,
+-1519121283, -1524080387, -1529023170, -1533949577, -1538859558,
+-1543753058, -1548630027, -1553490410, -1558334157, -1563161216,
+-1567971534, -1572765060, -1577541744, -1582301533, -1587044377,
+-1591770225, -1596479027, -1601170732, -1605845289, -1610502649,
+-1615142762, -1619765578, -1624371047, -1628959121, -1633529750,
+-1638082885, -1642618478, -1647136479, -1651636841, -1656119516,
+-1660584454, -1665031609, -1669460933, -1673872378, -1678265898,
+-1682641444, -1686998971, -1691338432, -1695659779, -1699962968,
+-1704247951, -1708514683, -1712763118, -1716993211, -1721204917,
+-1725398189, -1729572984, -1733729257, -1737866963, -1741986057,
+-1746086497, -1750168237, -1754231234, -1758275445, -1762300826,
+-1766307335, -1770294927, -1774263561, -1778213194, -1782143784,
+-1786055289, -1789947667, -1793820875, -1797674873, -1801509620,
+-1805325074, -1809121194, -1812897940, -1816655271, -1820393147,
+-1824111529, -1827810376, -1831489648, -1835149306, -1838789312,
+-1842409625, -1846010208, -1849591022, -1853152028, -1856693188,
+-1860214464, -1863715819, -1867197215, -1870658615, -1874099982,
+-1877521279, -1880922469, -1884303515, -1887664383, -1891005035,
+-1894325435, -1897625550, -1900905342, -1904164776, -1907403819,
+-1910622435, -1913820590, -1916998250, -1920155379, -1923291946,
+-1926407915, -1929503255, -1932577931, -1935631910, -1938665161,
+-1941677650, -1944669345, -1947640214, -1950590226, -1953519348,
+-1956427550, -1959314800, -1962181067, -1965026321, -1967850531,
+-1970653667, -1973435699, -1976196596, -1978936331, -1981654873,
+-1984352192, -1987028261, -1989683050, -1992316532, -1994928677,
+-1997519459, -2000088848, -2002636818, -2005163342, -2007668391,
+-2010151941, -2012613963, -2015054432, -2017473321, -2019870604,
+-2022246257, -2024600252, -2026932566, -2029243173, -2031532049,
+-2033799168, -2036044507, -2038268042, -2040469748, -2042649603,
+-2044807583, -2046943664, -2049057824, -2051150040, -2053220291,
+-2055268553, -2057294804, -2059299024, -2061281190, -2063241282,
+-2065179277, -2067095157, -2068988899, -2070860485, -2072709893,
+-2074537104, -2076342098, -2078124857, -2079885360, -2081623590,
+-2083339527, -2085033153, -2086704450, -2088353400, -2089979985,
+-2091584189, -2093165993, -2094725382, -2096262337, -2097776843,
+-2099268884, -2100738443, -2102185505, -2103610054, -2105012075,
+-2106391553, -2107748474, -2109082822, -2110394584, -2111683744,
+-2112950291, -2114194210, -2115415487, -2116614110, -2117790065,
+-2118943341, -2120073924, -2121181804, -2122266967, -2123329402,
+-2124369098, -2125386044, -2126380229, -2127351642, -2128300272,
+-2129226111, -2130129147, -2131009371, -2131866773, -2132701345,
+-2133513078, -2134301962, -2135067990, -2135811153, -2136531442,
+-2137228852, -2137903373, -2138555000, -2139183723, -2139789539,
+-2140372438, -2140932416, -2141469466, -2141983583, -2142474761,
+-2142942995, -2143388280, -2143810610, -2144209982, -2144586392,
+-2144939834, -2145270306, -2145577804, -2145862324, -2146123864,
+-2146362421, -2146577992, -2146770575, -2146940167, -2147086768,
+-2147210375, -2147310987, -2147388603, -2147443222, -2147474844,
+2147482929, 2147425435, 2147275952, 2147034487, 2146701050,
+2146275656, 2145758322, 2145149071, 2144447929, 2143654926,
+2142770096, 2141793477, 2140725111, 2139565043, 2138313323,
+2136970005, 2135535146, 2134008809, 2132391057, 2130681961,
+2128881593, 2126990031, 2125007356, 2122933653, 2120769010,
+2118513521, 2116167282, 2113730393, 2111202959, 2108585087,
+2105876892, 2103078487, 2100189994, 2097211535, 2094143239,
+2090985237, 2087737664, 2084400659, 2080974365, 2077458929,
+2073854502, 2070161238, 2066379295, 2062508835, 2058550025,
+2054503033, 2050368032, 2046145201, 2041834720, 2037436773,
+2032951550, 2028379241, 2023720043, 2018974156, 2014141783,
+2009223131, 2004218410, 1999127836, 1993951625, 1988690000,
+1983343186, 1977911412, 1972394912, 1966793920, 1961108677,
+1955339428, 1949486417, 1943549898, 1937530123, 1931427351,
+1925241843, 1918973864, 1912623682, 1906191570, 1899677803,
+1893082661, 1886406424, 1879649381, 1872811820, 1865894033,
+1858896318, 1851818974, 1844662304, 1837426615, 1830112217,
+1822719423, 1815248550, 1807699917, 1800073849, 1792370671,
+1784590714, 1776734311, 1768801799, 1760793518, 1752709809,
+1744551021, 1736317502, 1728009604, 1719627685, 1711172102,
+1702643219, 1694041400, 1685367013, 1676620432, 1667802029,
+1658912184, 1649951276, 1640919689, 1631817811, 1622646032,
+1613404744, 1604094343, 1594715227, 1585267800, 1575752465,
+1566169630, 1556519705, 1546803104, 1537020244, 1527171542,
+1517257422, 1507278307, 1497234626, 1487126808, 1476955286,
+1466720497, 1456422878, 1446062871, 1435640919, 1425157469,
+1414612971, 1404007875, 1393342636, 1382617710, 1371833558,
+1360990642, 1350089425, 1339130374, 1328113960, 1317040654,
+1305910930, 1294725265, 1283484138, 1272188032, 1260837429,
+1249432816, 1237974681, 1226463516, 1214899813, 1203284068,
+1191616778, 1179898443, 1168129565, 1156310649, 1144442200,
+1132524727, 1120558740, 1108544752, 1096483278, 1084374834,
+1072219940, 1060019115, 1047772882, 1035481766, 1023146293,
+1010766993, 998344394, 985879030, 973371434, 960822142,
+948231691, 935600622, 922929474, 910218791, 897469118,
+884680999, 871854984, 858991622, 846091463, 833155061,
+820182969, 807175743, 794133941, 781058120, 767948841,
+754806666, 741632158, 728425880, 715188400, 701920283,
+688622098, 675294414, 661937804, 648552838, 635140090,
+621700135, 608233549, 594740907, 581222789, 567679774,
+554112440, 540521371, 526907147, 513270353, 499611571,
+485931388, 472230390, 458509162, 444768294, 431008373,
+417229989, 403433732, 389620194, 375789965, 361943639,
+348081809, 334205068, 320314011, 306409232, 292491328,
+278560894, 264618528, 250664827, 236700388, 222725809,
+208741690, 194748629, 180747225, 166738079, 152721790,
+138698959, 124670187, 110636075, 96597223, 82554233,
+68507707, 54458246, 40406452, 26352928, 12298274,
+-1756906, -15812011, -29866438, -43919586, -57970853,
+-72019637, -86065335, -100107347, -114145071, -128177904,
+-142205248, -156226499, -170241059, -184248325, -198247699,
+-212238581, -226220372, -240192472, -254154282, -268105206,
+-282044645, -295972002, -309886680, -323788084, -337675619,
+-351548688, -365406698, -379249055, -393075166, -406884440,
+-420676284, -434450107, -448205320, -461941333, -475657559,
+-489353409, -503028296, -516681636, -530312842, -543921332,
+-557506522, -571067830, -584604676, -598116479, -611602660,
+-625062643, -638495850, -651901706, -665279637, -678629069,
+-691949432, -705240153, -718500664, -731730397, -744928785,
+-758095263, -771229267, -784330234, -797397602, -810430813,
+-823429308, -836392529, -849319923, -862210934, -875065011,
+-887881603, -900660162, -913400139, -926100989, -938762167,
+-951383133, -963963344, -976502263, -988999351, -1001454074,
+-1013865898, -1026234291, -1038558724, -1050838668, -1063073598,
+-1075262990, -1087406320, -1099503070, -1111552721, -1123554757,
+-1135508663, -1147413928, -1159270041, -1171076495, -1182832785,
+-1194538405, -1206192856, -1217795637, -1229346252, -1240844206,
+-1252289006, -1263680162, -1275017186, -1286299593, -1297526899,
+-1308698624, -1319814288, -1330873416, -1341875533, -1352820169,
+-1363706855, -1374535124, -1385304512, -1396014559, -1406664805,
+-1417254794, -1427784073, -1438252190, -1448658697, -1459003149,
+-1469285102, -1479504115, -1489659751, -1499751576, -1509779156,
+-1519742062, -1529639867, -1539472148, -1549238483, -1558938453,
+-1568571644, -1578137643, -1587636039, -1597066426, -1606428400,
+-1615721561, -1624945509, -1634099849, -1643184191, -1652198144,
+-1661141322, -1670013342, -1678813825, -1687542393, -1696198672,
+-1704782292, -1713292884, -1721730085, -1730093532, -1738382868,
+-1746597738, -1754737789, -1762802673, -1770792044, -1778705561,
+-1786542883, -1794303676, -1801987607, -1809594347, -1817123570,
+-1824574954, -1831948179, -1839242929, -1846458892, -1853595759,
+-1860653224, -1867630985, -1874528743, -1881346202, -1888083070,
+-1894739060, -1901313885, -1907807264, -1914218919, -1920548575,
+-1926795962, -1932960811, -1939042858, -1945041843, -1950957509,
+-1956789602, -1962537873, -1968202076, -1973781967, -1979277308,
+-1984687864, -1990013401, -1995253694, -2000408516, -2005477648,
+-2010460871, -2015357973, -2020168744, -2024892978, -2029530472,
+-2034081027, -2038544449, -2042920547, -2047209133, -2051410023,
+-2055523038, -2059548001, -2063484740, -2067333086, -2071092874,
+-2074763944, -2078346137, -2081839301, -2085243286, -2088557947,
+-2091783140, -2094918728, -2097964577, -2100920556, -2103786539,
+-2106562402, -2109248028, -2111843300, -2114348108, -2116762344,
+-2119085905, -2121318692, -2123460608, -2125511562, -2127471467,
+-2129340237, -2131117794, -2132804061, -2134398966, -2135902440,
+-2137314419, -2138634843, -2139863654, -2141000801, -2142046235,
+-2142999911, -2143861787, -2144631828, -2145310000, -2145896274,
+-2146390624, -2146793031, -2147103476, -2147321946, -2147448433,
+2147480773, 2147250799, 2146652904, 2145687192, 2144353827,
+2142653038, 2140585116, 2138150417, 2135349356, 2132182414,
+2128650133, 2124753120, 2120492040, 2115867626, 2110880668,
+2105532022, 2099822604, 2093753392, 2087325426, 2080539807,
+2073397699, 2065900325, 2058048970, 2049844978, 2041289756,
+2032384769, 2023131544, 2013531666, 2003586779, 1993298588,
+1982668856, 1971699403, 1960392110, 1948748914, 1936771810,
+1924462850, 1911824143, 1898857855, 1885566207, 1871951478,
+1858015999, 1843762158, 1829192399, 1814309216, 1799115162,
+1783612838, 1767804901, 1751694060, 1735283075, 1718574758,
+1701571972, 1684277631, 1666694698, 1648826185, 1630675154,
+1612244715, 1593538026, 1574558293, 1555308768, 1535792748,
+1516013578, 1495974647, 1475679389, 1455131280, 1434333842,
+1413290638, 1392005275, 1370481398, 1348722696, 1326732898,
+1304515771, 1282075122, 1259414796, 1236538675, 1213450681,
+1190154767, 1166654927, 1142955186, 1119059606, 1094972281,
+1070697338, 1046238936, 1021601267, 996788551, 971805042,
+946655018, 921342790, 895872694, 870249095, 844476384,
+818558976, 792501312, 766307857, 739983099, 713531549,
+686957739, 660266222, 633461572, 606548381, 579531262,
+552414843, 525203770, 497902707, 470516330, 443049333,
+415506422, 387892316, 360211746, 332469456, 304670200,
+276818739, 248919847, 220978304, 192998897, 164986421,
+136945676, 108881465, 80798598, 52701887, 24596146,
+-3513810, -31623164, -59727099, -87820801, -115899455,
+-143958250, -171992378, -199997036, -227967426, -255898755,
+-283786237, -311625094, -339410555, -367137861, -394802258,
+-422399009, -449923384, -477370666, -504736154, -532015158,
+-559203003, -586295032, -613286603, -640173090, -666949886,
+-693612404, -720156076, -746576352, -772868706, -799028633,
+-825051651, -850933300, -876669146, -902254780, -927685817,
+-952957899, -978066697, -1003007909, -1027777260, -1052370507,
+-1076783436, -1101011863, -1125051638, -1148898640, -1172548785,
+-1195998020, -1219242327, -1242277723, -1265100260, -1287706030,
+-1310091157, -1332251808, -1354184184, -1375884527, -1397349119,
+-1418574283, -1439556382, -1460291820, -1480777044, -1501008545,
+-1520982856, -1540696555, -1560146263, -1579328647, -1598240423,
+-1616878347, -1635239228, -1653319919, -1671117323, -1688628389,
+-1705850117, -1722779556, -1739413807, -1755750017, -1771785389,
+-1787517174, -1802942678, -1818059257, -1832864320, -1847355332,
+-1861529809, -1875385322, -1888919498, -1902130017, -1915014616,
+-1927571087, -1939797279, -1951691096, -1963250501, -1974473513,
+-1985358210, -1995902725, -2006105253, -2015964045, -2025477412,
+-2034643724, -2043461410, -2051928960, -2060044922, -2067807906,
+-2075216581, -2082269679, -2088965991, -2095304370, -2101283728,
+-2106903043, -2112161350, -2117057750, -2121591402, -2125761531,
+-2129567422, -2133008422, -2136083942, -2138793455, -2141136497,
+-2143112666, -2144721624, -2145963095, -2146836866, -2147342788,
+2147472149, 2146552303, 2144161316, 2140300829, 2134973487,
+2128182940, 2119933843, 2110231849, 2099083608, 2086496759,
+2072479930, 2057042727, 2040195730, 2021950484, 2002319494,
+1981316215, 1958955040, 1935251296, 1910221227, 1883881987,
+1856251629, 1827349089, 1797194176, 1765807555, 1733210737,
+1699426064, 1664476689, 1628386565, 1591180426, 1552883771,
+1513522847, 1473124631, 1431716808, 1389327759, 1345986533,
+1301722835, 1256567002, 1210549980, 1163703308, 1116059092,
+1067649985, 1018509163, 968670307, 918167572, 867035571,
+815309347, 763024350, 710216415, 656921734, 603176830,
+549018540, 494483979, 439610524, 384435782, 328997567,
+273333873, 217482850, 161482775, 105372028, 49189064,
+-7027611, -63239471, -119407989, -175494670, -231461077,
+-287268852, -342879747, -398255649, -453358607, -508150855,
+-562594842, -616653255, -670289044, -723465451, -776146031,
+-828294679, -879875655, -930853609, -981193602, -1030861133,
+-1079822164, -1128043139, -1175491010, -1222133257, -1267937916,
+-1312873593, -1356909492, -1400015434, -1442161874, -1483319929,
+-1523461391, -1562558748, -1600585205, -1637514702, -1673321927,
+-1707982341, -1741472190, -1773768520, -1804849198, -1834692923,
+-1863279241, -1890588560, -1916602164, -1941302225, -1964671814,
+-1986694916, -2007356435, -2026642214, -2044539032, -2061034626,
+-2076117690, -2089777886, -2102005853, -2112793210, -2122132564,
+-2130017514, -2136442657, -2141403589, -2144896910, -2146920225,
+#else
+32767, 32767, 32767, 32766, 32765,
+32763, 32761, 32759, 32756, 32753,
+32750, 32746, 32742, 32738, 32733,
+32728, 32722, 32717, 32710, 32704,
+32697, 32690, 32682, 32674, 32666,
+32657, 32648, 32639, 32629, 32619,
+32609, 32598, 32587, 32576, 32564,
+32552, 32539, 32526, 32513, 32500,
+32486, 32472, 32457, 32442, 32427,
+32411, 32395, 32379, 32362, 32345,
+32328, 32310, 32292, 32274, 32255,
+32236, 32217, 32197, 32177, 32157,
+32136, 32115, 32093, 32071, 32049,
+32027, 32004, 31981, 31957, 31933,
+31909, 31884, 31859, 31834, 31809,
+31783, 31756, 31730, 31703, 31676,
+31648, 31620, 31592, 31563, 31534,
+31505, 31475, 31445, 31415, 31384,
+31353, 31322, 31290, 31258, 31226,
+31193, 31160, 31127, 31093, 31059,
+31025, 30990, 30955, 30920, 30884,
+30848, 30812, 30775, 30738, 30701,
+30663, 30625, 30587, 30548, 30509,
+30470, 30430, 30390, 30350, 30309,
+30269, 30227, 30186, 30144, 30102,
+30059, 30016, 29973, 29930, 29886,
+29842, 29797, 29752, 29707, 29662,
+29616, 29570, 29524, 29477, 29430,
+29383, 29335, 29287, 29239, 29190,
+29142, 29092, 29043, 28993, 28943,
+28892, 28842, 28791, 28739, 28688,
+28636, 28583, 28531, 28478, 28425,
+28371, 28317, 28263, 28209, 28154,
+28099, 28044, 27988, 27932, 27876,
+27820, 27763, 27706, 27648, 27591,
+27533, 27474, 27416, 27357, 27298,
+27238, 27178, 27118, 27058, 26997,
+26936, 26875, 26814, 26752, 26690,
+26628, 26565, 26502, 26439, 26375,
+26312, 26247, 26183, 26119, 26054,
+25988, 25923, 25857, 25791, 25725,
+25658, 25592, 25524, 25457, 25389,
+25322, 25253, 25185, 25116, 25047,
+24978, 24908, 24838, 24768, 24698,
+24627, 24557, 24485, 24414, 24342,
+24270, 24198, 24126, 24053, 23980,
+23907, 23834, 23760, 23686, 23612,
+23537, 23462, 23387, 23312, 23237,
+23161, 23085, 23009, 22932, 22856,
+22779, 22701, 22624, 22546, 22468,
+22390, 22312, 22233, 22154, 22075,
+21996, 21916, 21836, 21756, 21676,
+21595, 21515, 21434, 21352, 21271,
+21189, 21107, 21025, 20943, 20860,
+20777, 20694, 20611, 20528, 20444,
+20360, 20276, 20192, 20107, 20022,
+19937, 19852, 19767, 19681, 19595,
+19509, 19423, 19336, 19250, 19163,
+19076, 18988, 18901, 18813, 18725,
+18637, 18549, 18460, 18372, 18283,
+18194, 18104, 18015, 17925, 17835,
+17745, 17655, 17565, 17474, 17383,
+17292, 17201, 17110, 17018, 16927,
+16835, 16743, 16650, 16558, 16465,
+16372, 16279, 16186, 16093, 15999,
+15906, 15812, 15718, 15624, 15529,
+15435, 15340, 15245, 15150, 15055,
+14960, 14864, 14769, 14673, 14577,
+14481, 14385, 14288, 14192, 14095,
+13998, 13901, 13804, 13706, 13609,
+13511, 13414, 13316, 13218, 13119,
+13021, 12923, 12824, 12725, 12626,
+12527, 12428, 12329, 12230, 12130,
+12030, 11930, 11831, 11730, 11630,
+11530, 11430, 11329, 11228, 11128,
+11027, 10926, 10824, 10723, 10622,
+10520, 10419, 10317, 10215, 10113,
+10011, 9909, 9807, 9704, 9602,
+9499, 9397, 9294, 9191, 9088,
+8985, 8882, 8778, 8675, 8572,
+8468, 8364, 8261, 8157, 8053,
+7949, 7845, 7741, 7637, 7532,
+7428, 7323, 7219, 7114, 7009,
+6905, 6800, 6695, 6590, 6485,
+6380, 6274, 6169, 6064, 5958,
+5853, 5747, 5642, 5536, 5430,
+5325, 5219, 5113, 5007, 4901,
+4795, 4689, 4583, 4476, 4370,
+4264, 4157, 4051, 3945, 3838,
+3732, 3625, 3518, 3412, 3305,
+3198, 3092, 2985, 2878, 2771,
+2664, 2558, 2451, 2344, 2237,
+2130, 2023, 1916, 1809, 1702,
+1594, 1487, 1380, 1273, 1166,
+1059, 952, 844, 737, 630,
+523, 416, 308, 201, 94,
+-13, -121, -228, -335, -442,
+-550, -657, -764, -871, -978,
+-1086, -1193, -1300, -1407, -1514,
+-1621, -1728, -1835, -1942, -2049,
+-2157, -2263, -2370, -2477, -2584,
+-2691, -2798, -2905, -3012, -3118,
+-3225, -3332, -3439, -3545, -3652,
+-3758, -3865, -3971, -4078, -4184,
+-4290, -4397, -4503, -4609, -4715,
+-4821, -4927, -5033, -5139, -5245,
+-5351, -5457, -5562, -5668, -5774,
+-5879, -5985, -6090, -6195, -6301,
+-6406, -6511, -6616, -6721, -6826,
+-6931, -7036, -7140, -7245, -7349,
+-7454, -7558, -7663, -7767, -7871,
+-7975, -8079, -8183, -8287, -8390,
+-8494, -8597, -8701, -8804, -8907,
+-9011, -9114, -9217, -9319, -9422,
+-9525, -9627, -9730, -9832, -9934,
+-10037, -10139, -10241, -10342, -10444,
+-10546, -10647, -10748, -10850, -10951,
+-11052, -11153, -11253, -11354, -11455,
+-11555, -11655, -11756, -11856, -11955,
+-12055, -12155, -12254, -12354, -12453,
+-12552, -12651, -12750, -12849, -12947,
+-13046, -13144, -13242, -13340, -13438,
+-13536, -13633, -13731, -13828, -13925,
+-14022, -14119, -14216, -14312, -14409,
+-14505, -14601, -14697, -14793, -14888,
+-14984, -15079, -15174, -15269, -15364,
+-15459, -15553, -15647, -15741, -15835,
+-15929, -16023, -16116, -16210, -16303,
+-16396, -16488, -16581, -16673, -16766,
+-16858, -16949, -17041, -17133, -17224,
+-17315, -17406, -17497, -17587, -17678,
+-17768, -17858, -17948, -18037, -18127,
+-18216, -18305, -18394, -18483, -18571,
+-18659, -18747, -18835, -18923, -19010,
+-19098, -19185, -19271, -19358, -19444,
+-19531, -19617, -19702, -19788, -19873,
+-19959, -20043, -20128, -20213, -20297,
+-20381, -20465, -20549, -20632, -20715,
+-20798, -20881, -20963, -21046, -21128,
+-21210, -21291, -21373, -21454, -21535,
+-21616, -21696, -21776, -21856, -21936,
+-22016, -22095, -22174, -22253, -22331,
+-22410, -22488, -22566, -22643, -22721,
+-22798, -22875, -22951, -23028, -23104,
+-23180, -23256, -23331, -23406, -23481,
+-23556, -23630, -23704, -23778, -23852,
+-23925, -23998, -24071, -24144, -24216,
+-24288, -24360, -24432, -24503, -24574,
+-24645, -24716, -24786, -24856, -24926,
+-24995, -25064, -25133, -25202, -25270,
+-25339, -25406, -25474, -25541, -25608,
+-25675, -25742, -25808, -25874, -25939,
+-26005, -26070, -26135, -26199, -26264,
+-26327, -26391, -26455, -26518, -26581,
+-26643, -26705, -26767, -26829, -26891,
+-26952, -27013, -27073, -27133, -27193,
+-27253, -27312, -27372, -27430, -27489,
+-27547, -27605, -27663, -27720, -27777,
+-27834, -27890, -27946, -28002, -28058,
+-28113, -28168, -28223, -28277, -28331,
+-28385, -28438, -28491, -28544, -28596,
+-28649, -28701, -28752, -28803, -28854,
+-28905, -28955, -29006, -29055, -29105,
+-29154, -29203, -29251, -29299, -29347,
+-29395, -29442, -29489, -29535, -29582,
+-29628, -29673, -29719, -29764, -29808,
+-29853, -29897, -29941, -29984, -30027,
+-30070, -30112, -30154, -30196, -30238,
+-30279, -30320, -30360, -30400, -30440,
+-30480, -30519, -30558, -30596, -30635,
+-30672, -30710, -30747, -30784, -30821,
+-30857, -30893, -30929, -30964, -30999,
+-31033, -31068, -31102, -31135, -31168,
+-31201, -31234, -31266, -31298, -31330,
+-31361, -31392, -31422, -31453, -31483,
+-31512, -31541, -31570, -31599, -31627,
+-31655, -31682, -31710, -31737, -31763,
+-31789, -31815, -31841, -31866, -31891,
+-31915, -31939, -31963, -31986, -32010,
+-32032, -32055, -32077, -32099, -32120,
+-32141, -32162, -32182, -32202, -32222,
+-32241, -32260, -32279, -32297, -32315,
+-32333, -32350, -32367, -32383, -32399,
+-32415, -32431, -32446, -32461, -32475,
+-32489, -32503, -32517, -32530, -32542,
+-32555, -32567, -32579, -32590, -32601,
+-32612, -32622, -32632, -32641, -32651,
+-32659, -32668, -32676, -32684, -32692,
+-32699, -32706, -32712, -32718, -32724,
+-32729, -32734, -32739, -32743, -32747,
+-32751, -32754, -32757, -32760, -32762,
+-32764, -32765, -32767, -32767, -32767,
+32767, 32767, 32765, 32761, 32756,
+32750, 32742, 32732, 32722, 32710,
+32696, 32681, 32665, 32647, 32628,
+32608, 32586, 32562, 32538, 32512,
+32484, 32455, 32425, 32393, 32360,
+32326, 32290, 32253, 32214, 32174,
+32133, 32090, 32046, 32001, 31954,
+31906, 31856, 31805, 31753, 31700,
+31645, 31588, 31530, 31471, 31411,
+31349, 31286, 31222, 31156, 31089,
+31020, 30951, 30880, 30807, 30733,
+30658, 30582, 30504, 30425, 30345,
+30263, 30181, 30096, 30011, 29924,
+29836, 29747, 29656, 29564, 29471,
+29377, 29281, 29184, 29086, 28987,
+28886, 28784, 28681, 28577, 28471,
+28365, 28257, 28147, 28037, 27925,
+27812, 27698, 27583, 27467, 27349,
+27231, 27111, 26990, 26868, 26744,
+26620, 26494, 26367, 26239, 26110,
+25980, 25849, 25717, 25583, 25449,
+25313, 25176, 25038, 24900, 24760,
+24619, 24477, 24333, 24189, 24044,
+23898, 23751, 23602, 23453, 23303,
+23152, 22999, 22846, 22692, 22537,
+22380, 22223, 22065, 21906, 21746,
+21585, 21423, 21261, 21097, 20933,
+20767, 20601, 20434, 20265, 20096,
+19927, 19756, 19584, 19412, 19239,
+19065, 18890, 18714, 18538, 18361,
+18183, 18004, 17824, 17644, 17463,
+17281, 17098, 16915, 16731, 16546,
+16361, 16175, 15988, 15800, 15612,
+15423, 15234, 15043, 14852, 14661,
+14469, 14276, 14083, 13889, 13694,
+13499, 13303, 13107, 12910, 12713,
+12515, 12317, 12118, 11918, 11718,
+11517, 11316, 11115, 10913, 10710,
+10508, 10304, 10100, 9896, 9691,
+9486, 9281, 9075, 8869, 8662,
+8455, 8248, 8040, 7832, 7623,
+7415, 7206, 6996, 6787, 6577,
+6366, 6156, 5945, 5734, 5523,
+5311, 5100, 4888, 4675, 4463,
+4251, 4038, 3825, 3612, 3399,
+3185, 2972, 2758, 2544, 2330,
+2116, 1902, 1688, 1474, 1260,
+1045, 831, 617, 402, 188,
+-27, -241, -456, -670, -885,
+-1099, -1313, -1528, -1742, -1956,
+-2170, -2384, -2598, -2811, -3025,
+-3239, -3452, -3665, -3878, -4091,
+-4304, -4516, -4728, -4941, -5153,
+-5364, -5576, -5787, -5998, -6209,
+-6419, -6629, -6839, -7049, -7258,
+-7467, -7676, -7884, -8092, -8300,
+-8507, -8714, -8920, -9127, -9332,
+-9538, -9743, -9947, -10151, -10355,
+-10558, -10761, -10963, -11165, -11367,
+-11568, -11768, -11968, -12167, -12366,
+-12565, -12762, -12960, -13156, -13352,
+-13548, -13743, -13937, -14131, -14324,
+-14517, -14709, -14900, -15091, -15281,
+-15470, -15659, -15847, -16035, -16221,
+-16407, -16593, -16777, -16961, -17144,
+-17326, -17508, -17689, -17869, -18049,
+-18227, -18405, -18582, -18758, -18934,
+-19108, -19282, -19455, -19627, -19799,
+-19969, -20139, -20308, -20475, -20642,
+-20809, -20974, -21138, -21301, -21464,
+-21626, -21786, -21946, -22105, -22263,
+-22420, -22575, -22730, -22884, -23037,
+-23189, -23340, -23490, -23640, -23788,
+-23935, -24080, -24225, -24369, -24512,
+-24654, -24795, -24934, -25073, -25211,
+-25347, -25482, -25617, -25750, -25882,
+-26013, -26143, -26272, -26399, -26526,
+-26651, -26775, -26898, -27020, -27141,
+-27260, -27379, -27496, -27612, -27727,
+-27841, -27953, -28065, -28175, -28284,
+-28391, -28498, -28603, -28707, -28810,
+-28911, -29012, -29111, -29209, -29305,
+-29401, -29495, -29587, -29679, -29769,
+-29858, -29946, -30032, -30118, -30201,
+-30284, -30365, -30445, -30524, -30601,
+-30677, -30752, -30825, -30897, -30968,
+-31038, -31106, -31172, -31238, -31302,
+-31365, -31426, -31486, -31545, -31602,
+-31658, -31713, -31766, -31818, -31869,
+-31918, -31966, -32012, -32058, -32101,
+-32144, -32185, -32224, -32262, -32299,
+-32335, -32369, -32401, -32433, -32463,
+-32491, -32518, -32544, -32568, -32591,
+-32613, -32633, -32652, -32669, -32685,
+-32700, -32713, -32724, -32735, -32744,
+-32751, -32757, -32762, -32766, -32767,
+32767, 32764, 32755, 32741, 32720,
+32694, 32663, 32626, 32583, 32535,
+32481, 32421, 32356, 32286, 32209,
+32128, 32041, 31948, 31850, 31747,
+31638, 31523, 31403, 31278, 31148,
+31012, 30871, 30724, 30572, 30415,
+30253, 30086, 29913, 29736, 29553,
+29365, 29172, 28974, 28771, 28564,
+28351, 28134, 27911, 27684, 27452,
+27216, 26975, 26729, 26478, 26223,
+25964, 25700, 25432, 25159, 24882,
+24601, 24315, 24026, 23732, 23434,
+23133, 22827, 22517, 22204, 21886,
+21565, 21240, 20912, 20580, 20244,
+19905, 19563, 19217, 18868, 18516,
+18160, 17802, 17440, 17075, 16708,
+16338, 15964, 15588, 15210, 14829,
+14445, 14059, 13670, 13279, 12886,
+12490, 12093, 11693, 11291, 10888,
+10482, 10075, 9666, 9255, 8843,
+8429, 8014, 7597, 7180, 6760,
+6340, 5919, 5496, 5073, 4649,
+4224, 3798, 3372, 2945, 2517,
+2090, 1661, 1233, 804, 375,
+-54, -483, -911, -1340, -1768,
+-2197, -2624, -3052, -3479, -3905,
+-4330, -4755, -5179, -5602, -6024,
+-6445, -6865, -7284, -7702, -8118,
+-8533, -8946, -9358, -9768, -10177,
+-10584, -10989, -11392, -11793, -12192,
+-12589, -12984, -13377, -13767, -14155,
+-14541, -14924, -15305, -15683, -16058,
+-16430, -16800, -17167, -17531, -17892,
+-18249, -18604, -18956, -19304, -19649,
+-19990, -20329, -20663, -20994, -21322,
+-21646, -21966, -22282, -22595, -22904,
+-23208, -23509, -23806, -24099, -24387,
+-24672, -24952, -25228, -25499, -25766,
+-26029, -26288, -26541, -26791, -27035,
+-27275, -27511, -27741, -27967, -28188,
+-28405, -28616, -28823, -29024, -29221,
+-29412, -29599, -29780, -29957, -30128,
+-30294, -30455, -30611, -30761, -30906,
+-31046, -31181, -31310, -31434, -31552,
+-31665, -31773, -31875, -31972, -32063,
+-32149, -32229, -32304, -32373, -32437,
+-32495, -32547, -32594, -32635, -32671,
+-32701, -32726, -32745, -32758, -32766,
+32767, 32754, 32717, 32658, 32577,
+32473, 32348, 32200, 32029, 31837,
+31624, 31388, 31131, 30853, 30553,
+30232, 29891, 29530, 29148, 28746,
+28324, 27883, 27423, 26944, 26447,
+25931, 25398, 24847, 24279, 23695,
+23095, 22478, 21846, 21199, 20538,
+19863, 19174, 18472, 17757, 17030,
+16291, 15541, 14781, 14010, 13230,
+12441, 11643, 10837, 10024, 9204,
+8377, 7545, 6708, 5866, 5020,
+4171, 3319, 2464, 1608, 751,
+-107, -965, -1822, -2678, -3532,
+-4383, -5232, -6077, -6918, -7754,
+-8585, -9409, -10228, -11039, -11843,
+-12639, -13426, -14204, -14972, -15730,
+-16477, -17213, -17937, -18648, -19347,
+-20033, -20705, -21363, -22006, -22634,
+-23246, -23843, -24423, -24986, -25533,
+-26062, -26573, -27066, -27540, -27995,
+-28431, -28848, -29245, -29622, -29979,
+-30315, -30630, -30924, -31197, -31449,
+-31679, -31887, -32074, -32239, -32381,
+-32501, -32600, -32675, -32729, -32759,
+#endif
+};
+#endif
+
+static const CELTMode mode48000_960_120 = {
+48000, /* Fs */
+120, /* overlap */
+21, /* nbEBands */
+21, /* effEBands */
+{27853, 0, 4096, 8192, }, /* preemph */
+eband5ms, /* eBands */
+3, /* maxLM */
+8, /* nbShortMdcts */
+120, /* shortMdctSize */
+11, /* nbAllocVectors */
+band_allocation, /* allocVectors */
+logN400, /* logN */
+window120, /* window */
+{1920, 3, {&fft_state48000_960_0, &fft_state48000_960_1, &fft_state48000_960_2, &fft_state48000_960_3, }, mdct_twiddles960}, /* mdct */
+{392, cache_index50, cache_bits50, cache_caps50}, /* cache */
+#ifdef ENABLE_QEXT
+{86, qext_cache_index50, qext_cache_bits50, qext_cache_caps50}, /* qext_cache */
+#endif
+};
+
+#ifdef ENABLE_QEXT
+#ifndef DEF_WINDOW240
+#define DEF_WINDOW240
+static const celt_coef window240[240] = {
+#ifdef ENABLE_QEXT
+36124, 325113, 903042, 1769811, 2925272,
+4369225, 6101422, 8121563, 10429297, 13024223,
+15905885, 19073777, 22527339, 26265958, 30288963,
+34595631, 39185180, 44056771, 49209509, 54642435,
+60354533, 66344724, 72611866, 79154752, 85972112,
+93062609, 100424835, 108057317, 115958510, 124126796,
+132560487, 141257817, 150216948, 159435962, 168912864,
+178645581, 188631957, 198869754, 209356654, 220090250,
+231068053, 242287487, 253745886, 265440499, 277368483,
+289526906, 301912744, 314522883, 327354113, 340403136,
+353666556, 367140886, 380822544, 394707853, 408793044,
+423074251, 437547515, 452208783, 467053909, 482078654,
+497278684, 512649576, 528186815, 543885797, 559741828,
+575750127, 591905825, 608203972, 624639532, 641207388,
+657902345, 674719130, 691652394, 708696716, 725846605,
+743096501, 760440782, 777873759, 795389689, 812982769,
+830647145, 848376914, 866166126, 884008788, 901898872,
+919830310, 937797006, 955792839, 973811661, 991847308,
+1009893601, 1027944353, 1045993369, 1064034454, 1082061416,
+1100068075, 1118048258, 1135995815, 1153904614, 1171768555,
+1189581567, 1207337616, 1225030710, 1242654904, 1260204305,
+1277673075, 1295055437, 1312345681, 1329538165, 1346627326,
+1363607677, 1380473817, 1397220435, 1413842311, 1430334323,
+1446691453, 1462908786, 1478981520, 1494904965, 1510674550,
+1526285825, 1541734465, 1557016274, 1572127189, 1587063280,
+1601820758, 1616395971, 1630785416, 1644985731, 1658993707,
+1672806283, 1686420553, 1699833765, 1713043324, 1726046792,
+1738841892, 1751426506, 1763798678, 1775956615, 1787898686,
+1799623424, 1811129525, 1822415848, 1833481417, 1844325418,
+1854947198, 1865346267, 1875522297, 1885475119, 1895204720,
+1904711247, 1913995001, 1923056438, 1931896164, 1940514936,
+1948913657, 1957093375, 1965055281, 1972800706, 1980331118,
+1987648116, 1994753433, 2001648928, 2008336584, 2014818504,
+2021096911, 2027174137, 2033052626, 2038734929, 2044223696,
+2049521676, 2054631712, 2059556735, 2064299763, 2068863893,
+2073252301, 2077468232, 2081515002, 2085395988, 2089114627,
+2092674410, 2096078878, 2099331616, 2102436251, 2105396446,
+2108215896, 2110898322, 2113447469, 2115867100, 2118160991,
+2120332927, 2122386699, 2124326098, 2126154912, 2127876920,
+2129495889, 2131015570, 2132439692, 2133771963, 2135016059,
+2136175624, 2137254268, 2138255559, 2139183022, 2140040133,
+2140830320, 2141556955, 2142223351, 2142832762, 2143388377,
+2143893317, 2144350634, 2144763305, 2145134231, 2145466235,
+2145762059, 2146024357, 2146255701, 2146458570, 2146635355,
+2146788350, 2146919756, 2147031676, 2147126111, 2147204964,
+2147270033, 2147323012, 2147365487, 2147398940, 2147424741,
+2147444152, 2147458322, 2147468290, 2147474980, 2147479203,
+2147481655, 2147482918, 2147483458, 2147483623, 2147483647,
+#else
+1, 5, 14, 27, 45,
+67, 93, 124, 159, 199,
+243, 291, 344, 401, 462,
+528, 598, 672, 751, 834,
+921, 1012, 1108, 1208, 1312,
+1420, 1532, 1649, 1769, 1894,
+2023, 2155, 2292, 2433, 2577,
+2726, 2878, 3035, 3195, 3358,
+3526, 3697, 3872, 4050, 4232,
+4418, 4607, 4799, 4995, 5194,
+5397, 5602, 5811, 6023, 6238,
+6456, 6676, 6900, 7127, 7356,
+7588, 7822, 8059, 8299, 8541,
+8785, 9032, 9280, 9531, 9784,
+10039, 10295, 10554, 10814, 11076,
+11339, 11603, 11869, 12137, 12405,
+12675, 12945, 13217, 13489, 13762,
+14035, 14310, 14584, 14859, 15134,
+15410, 15685, 15961, 16236, 16511,
+16786, 17060, 17334, 17607, 17880,
+18152, 18423, 18692, 18961, 19229,
+19496, 19761, 20025, 20287, 20548,
+20807, 21064, 21320, 21574, 21825,
+22075, 22322, 22567, 22810, 23051,
+23289, 23525, 23758, 23989, 24217,
+24442, 24664, 24884, 25100, 25314,
+25525, 25733, 25937, 26139, 26337,
+26533, 26725, 26913, 27099, 27281,
+27460, 27636, 27808, 27977, 28142,
+28304, 28463, 28618, 28770, 28919,
+29064, 29205, 29344, 29478, 29610,
+29738, 29863, 29984, 30103, 30217,
+30329, 30438, 30543, 30645, 30744,
+30839, 30932, 31022, 31109, 31192,
+31273, 31351, 31426, 31499, 31568,
+31635, 31700, 31761, 31821, 31877,
+31932, 31984, 32033, 32081, 32126,
+32169, 32210, 32249, 32286, 32321,
+32354, 32385, 32415, 32443, 32469,
+32494, 32517, 32538, 32559, 32578,
+32595, 32612, 32627, 32641, 32654,
+32666, 32678, 32688, 32697, 32706,
+32713, 32720, 32726, 32732, 32737,
+32742, 32746, 32749, 32752, 32755,
+32757, 32759, 32761, 32763, 32764,
+32765, 32766, 32766, 32767, 32767,
+32767, 32767, 32767, 32767, 32767,
+32767, 32767, 32767, 32767, 32767,
+#endif
+};
+#endif
+
+#ifndef DEF_LOGN400
+#define DEF_LOGN400
+static const opus_int16 logN400[21] = {
+0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
+#endif
+
+#ifndef DEF_PULSE_CACHE50
+#define DEF_PULSE_CACHE50
+static const opus_int16 cache_index50[105] = {
+-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
+82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
+41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
+318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
+305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
+240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
+};
+static const unsigned char cache_bits50[392] = {
+40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
+31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
+51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
+66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
+64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
+94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
+124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
+97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
+142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
+28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
+153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
+229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
+166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
+86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
+25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
+185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
+110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
+74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
+163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
+228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
+90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
+87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
+106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
+224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
+182, 234, };
+static const unsigned char cache_caps50[168] = {
+224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
+178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
+240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
+160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
+138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
+204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
+185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
+207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
+188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
+193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
+204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
+140, 66, 40, };
+#endif
+
+#ifdef ENABLE_QEXT
+# ifndef DEF_QEXT_PULSE_CACHE50
+# define DEF_QEXT_PULSE_CACHE50
+static const opus_int16 qext_cache_index50[70] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 61, 61,
+61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 72, 72, 72,
+72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 80, 80, 80, 80,
+80, 80, 80, 80, 80, 80, 80, 80, 80, 80, };
+static const unsigned char qext_cache_bits50[86] = {
+40, 26, 45, 59, 70, 79, 87, 94, 100, 105, 110, 114, 118, 122, 125,
+128, 131, 136, 141, 146, 150, 153, 157, 160, 163, 168, 173, 178, 182, 185,
+189, 192, 195, 200, 205, 210, 214, 217, 221, 224, 227, 19, 34, 61, 83,
+101, 118, 132, 145, 157, 167, 177, 186, 194, 202, 209, 216, 222, 234, 245,
+254, 10, 42, 77, 107, 133, 157, 179, 200, 219, 236, 253, 7, 50, 93,
+131, 165, 197, 227, 255, 5, 58, 109, 155, 197, 237, };
+static const unsigned char qext_cache_caps50[112] = {
+159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 171,
+171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 167, 167, 167,
+167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 166, 166, 166, 166, 166,
+166, 166, 166, 166, 166, 166, 166, 166, 166, 163, 163, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 165, 165, 165, 165, 165, 165, 165,
+165, 165, 165, 165, 165, 165, 165, };
+# endif
+#endif
+
+#ifndef FFT_TWIDDLES96000_1920
+#define FFT_TWIDDLES96000_1920
+static const kiss_twiddle_cpx fft_twiddles96000_1920[960] = {
+#ifdef ENABLE_QEXT
+{2147483647, 0}, {2147437652, -14055147},
+{2147299668, -28109692}, {2147069700, -42163034},
+{2146747759, -56214568}, {2146333858, -70263695},
+{2145828016, -84309812}, {2145230253, -98352318},
+{2144540596, -112390610}, {2143759074, -126424088},
+{2142885721, -140452151}, {2141920573, -154474196},
+{2140863673, -168489625}, {2139715065, -182497836},
+{2138474799, -196498230}, {2137142927, -210490206},
+{2135719508, -224473166}, {2134204601, -238446509},
+{2132598273, -252409639}, {2130900591, -266361956},
+{2129111628, -280302863}, {2127231461, -294231763},
+{2125260170, -308148059}, {2123197841, -322051155},
+{2121044561, -335940456}, {2118800422, -349815365},
+{2116465521, -363675290}, {2114039958, -377519637},
+{2111523836, -391347811}, {2108917263, -405159222},
+{2106220352, -418953276}, {2103433217, -432729385},
+{2100555978, -446486956}, {2097588758, -460225402},
+{2094531684, -473944133}, {2091384888, -487642562},
+{2088148504, -501320102}, {2084822670, -514976167},
+{2081407530, -528610172}, {2077903229, -542221533},
+{2074309917, -555809667}, {2070627749, -569373992},
+{2066856882, -582913927}, {2062997478, -596428893},
+{2059049702, -609918309}, {2055013723, -623381598},
+{2050889714, -636818183}, {2046677852, -650227490},
+{2042378317, -663608942}, {2037991293, -676961968},
+{2033516969, -690285996}, {2028955535, -703580453},
+{2024307188, -716844772}, {2019572126, -730078383},
+{2014750553, -743280720}, {2009842674, -756451218},
+{2004848700, -769589312}, {1999768845, -782694439},
+{1994603327, -795766038}, {1989352366, -808803549},
+{1984016189, -821806413}, {1978595022, -834774075},
+{1973089100, -847705977}, {1967498656, -860601566},
+{1961823932, -873460290}, {1956065170, -886281598},
+{1950222616, -899064940}, {1944296521, -911809770},
+{1938287139, -924515541}, {1932194727, -937181708},
+{1926019547, -949807730}, {1919761862, -962393065},
+{1913421941, -974937175}, {1907000055, -987439521},
+{1900496480, -999899569}, {1893911494, -1012316784},
+{1887245379, -1024690635}, {1880498421, -1037020592},
+{1873670908, -1049306126}, {1866763134, -1061546712},
+{1859775393, -1073741824}, {1852707986, -1085890941},
+{1845561216, -1097993542}, {1838335387, -1110049108},
+{1831030811, -1122057124}, {1823647799, -1134017074},
+{1816186668, -1145928447}, {1808647737, -1157790732},
+{1801031331, -1169603422}, {1793337774, -1181366009},
+{1785567396, -1193077991}, {1777720531, -1204738865},
+{1769797514, -1216348132}, {1761798685, -1227905295},
+{1753724386, -1239409858}, {1745574963, -1250861329},
+{1737350766, -1262259218}, {1729052147, -1273603035},
+{1720679461, -1284892296}, {1712233066, -1296126516},
+{1703713325, -1307305214}, {1695120603, -1318427912},
+{1686455268, -1329494133}, {1677717690, -1340503402},
+{1668908244, -1351455249}, {1660027308, -1362349204},
+{1651075262, -1373184801}, {1642052490, -1383961574},
+{1632959377, -1394679064}, {1623796314, -1405336810},
+{1614563692, -1415934356}, {1605261909, -1426471249},
+{1595891361, -1436947036}, {1586452450, -1447361268},
+{1576945581, -1457713501}, {1567371161, -1468003290},
+{1557729600, -1478230195}, {1548021312, -1488393778},
+{1538246711, -1498493602}, {1528406216, -1508529236},
+{1518500250, -1518500250}, {1508529236, -1528406216},
+{1498493602, -1538246711}, {1488393778, -1548021312},
+{1478230195, -1557729600}, {1468003290, -1567371161},
+{1457713501, -1576945581}, {1447361268, -1586452450},
+{1436947036, -1595891361}, {1426471249, -1605261909},
+{1415934356, -1614563692}, {1405336810, -1623796314},
+{1394679064, -1632959377}, {1383961574, -1642052490},
+{1373184801, -1651075262}, {1362349204, -1660027308},
+{1351455249, -1668908244}, {1340503402, -1677717690},
+{1329494133, -1686455268}, {1318427912, -1695120603},
+{1307305214, -1703713325}, {1296126516, -1712233066},
+{1284892296, -1720679461}, {1273603035, -1729052147},
+{1262259218, -1737350766}, {1250861329, -1745574963},
+{1239409858, -1753724386}, {1227905295, -1761798685},
+{1216348132, -1769797514}, {1204738865, -1777720531},
+{1193077991, -1785567396}, {1181366009, -1793337774},
+{1169603422, -1801031331}, {1157790732, -1808647737},
+{1145928447, -1816186668}, {1134017074, -1823647799},
+{1122057124, -1831030811}, {1110049108, -1838335387},
+{1097993542, -1845561216}, {1085890941, -1852707986},
+{1073741824, -1859775393}, {1061546712, -1866763134},
+{1049306126, -1873670908}, {1037020592, -1880498421},
+{1024690635, -1887245379}, {1012316784, -1893911494},
+{999899569, -1900496480}, {987439521, -1907000055},
+{974937175, -1913421941}, {962393065, -1919761862},
+{949807730, -1926019547}, {937181708, -1932194727},
+{924515541, -1938287139}, {911809770, -1944296521},
+{899064940, -1950222616}, {886281598, -1956065170},
+{873460290, -1961823932}, {860601566, -1967498656},
+{847705977, -1973089100}, {834774075, -1978595022},
+{821806413, -1984016189}, {808803549, -1989352366},
+{795766038, -1994603327}, {782694439, -1999768845},
+{769589312, -2004848700}, {756451218, -2009842674},
+{743280720, -2014750553}, {730078383, -2019572126},
+{716844772, -2024307188}, {703580453, -2028955535},
+{690285996, -2033516969}, {676961968, -2037991293},
+{663608942, -2042378317}, {650227490, -2046677852},
+{636818183, -2050889714}, {623381598, -2055013723},
+{609918309, -2059049702}, {596428893, -2062997478},
+{582913927, -2066856882}, {569373992, -2070627749},
+{555809667, -2074309917}, {542221533, -2077903229},
+{528610172, -2081407530}, {514976167, -2084822670},
+{501320102, -2088148504}, {487642562, -2091384888},
+{473944133, -2094531684}, {460225402, -2097588758},
+{446486956, -2100555978}, {432729385, -2103433217},
+{418953276, -2106220352}, {405159222, -2108917263},
+{391347811, -2111523836}, {377519637, -2114039958},
+{363675290, -2116465521}, {349815365, -2118800422},
+{335940456, -2121044561}, {322051155, -2123197841},
+{308148059, -2125260170}, {294231763, -2127231461},
+{280302863, -2129111628}, {266361956, -2130900591},
+{252409639, -2132598273}, {238446509, -2134204601},
+{224473166, -2135719508}, {210490206, -2137142927},
+{196498230, -2138474799}, {182497836, -2139715065},
+{168489625, -2140863673}, {154474196, -2141920573},
+{140452151, -2142885721}, {126424088, -2143759074},
+{112390610, -2144540596}, {98352318, -2145230253},
+{84309812, -2145828016}, {70263695, -2146333858},
+{56214568, -2146747759}, {42163034, -2147069700},
+{28109692, -2147299668}, {14055147, -2147437652},
+{0, -2147483648}, {-14055147, -2147437652},
+{-28109692, -2147299668}, {-42163034, -2147069700},
+{-56214568, -2146747759}, {-70263695, -2146333858},
+{-84309812, -2145828016}, {-98352318, -2145230253},
+{-112390610, -2144540596}, {-126424088, -2143759074},
+{-140452151, -2142885721}, {-154474196, -2141920573},
+{-168489625, -2140863673}, {-182497836, -2139715065},
+{-196498230, -2138474799}, {-210490206, -2137142927},
+{-224473166, -2135719508}, {-238446509, -2134204601},
+{-252409639, -2132598273}, {-266361956, -2130900591},
+{-280302863, -2129111628}, {-294231763, -2127231461},
+{-308148059, -2125260170}, {-322051155, -2123197841},
+{-335940456, -2121044561}, {-349815365, -2118800422},
+{-363675290, -2116465521}, {-377519637, -2114039958},
+{-391347811, -2111523836}, {-405159222, -2108917263},
+{-418953276, -2106220352}, {-432729385, -2103433217},
+{-446486956, -2100555978}, {-460225402, -2097588758},
+{-473944133, -2094531684}, {-487642562, -2091384888},
+{-501320102, -2088148504}, {-514976167, -2084822670},
+{-528610172, -2081407530}, {-542221533, -2077903229},
+{-555809667, -2074309917}, {-569373992, -2070627749},
+{-582913927, -2066856882}, {-596428893, -2062997478},
+{-609918309, -2059049702}, {-623381598, -2055013723},
+{-636818183, -2050889714}, {-650227490, -2046677852},
+{-663608942, -2042378317}, {-676961968, -2037991293},
+{-690285996, -2033516969}, {-703580453, -2028955535},
+{-716844772, -2024307188}, {-730078383, -2019572126},
+{-743280720, -2014750553}, {-756451218, -2009842674},
+{-769589312, -2004848700}, {-782694439, -1999768845},
+{-795766038, -1994603327}, {-808803549, -1989352366},
+{-821806413, -1984016189}, {-834774075, -1978595022},
+{-847705977, -1973089100}, {-860601566, -1967498656},
+{-873460290, -1961823932}, {-886281598, -1956065170},
+{-899064940, -1950222616}, {-911809770, -1944296521},
+{-924515541, -1938287139}, {-937181708, -1932194727},
+{-949807730, -1926019547}, {-962393065, -1919761862},
+{-974937175, -1913421941}, {-987439521, -1907000055},
+{-999899569, -1900496480}, {-1012316784, -1893911494},
+{-1024690635, -1887245379}, {-1037020592, -1880498421},
+{-1049306126, -1873670908}, {-1061546712, -1866763134},
+{-1073741824, -1859775393}, {-1085890941, -1852707986},
+{-1097993542, -1845561216}, {-1110049108, -1838335387},
+{-1122057124, -1831030811}, {-1134017074, -1823647799},
+{-1145928447, -1816186668}, {-1157790732, -1808647737},
+{-1169603422, -1801031331}, {-1181366009, -1793337774},
+{-1193077991, -1785567396}, {-1204738865, -1777720531},
+{-1216348132, -1769797514}, {-1227905295, -1761798685},
+{-1239409858, -1753724386}, {-1250861329, -1745574963},
+{-1262259218, -1737350766}, {-1273603035, -1729052147},
+{-1284892296, -1720679461}, {-1296126516, -1712233066},
+{-1307305214, -1703713325}, {-1318427912, -1695120603},
+{-1329494133, -1686455268}, {-1340503402, -1677717690},
+{-1351455249, -1668908244}, {-1362349204, -1660027308},
+{-1373184801, -1651075262}, {-1383961574, -1642052490},
+{-1394679064, -1632959377}, {-1405336810, -1623796314},
+{-1415934356, -1614563692}, {-1426471249, -1605261909},
+{-1436947036, -1595891361}, {-1447361268, -1586452450},
+{-1457713501, -1576945581}, {-1468003290, -1567371161},
+{-1478230195, -1557729600}, {-1488393778, -1548021312},
+{-1498493602, -1538246711}, {-1508529236, -1528406216},
+{-1518500250, -1518500250}, {-1528406216, -1508529236},
+{-1538246711, -1498493602}, {-1548021312, -1488393778},
+{-1557729600, -1478230195}, {-1567371161, -1468003290},
+{-1576945581, -1457713501}, {-1586452450, -1447361268},
+{-1595891361, -1436947036}, {-1605261909, -1426471249},
+{-1614563692, -1415934356}, {-1623796314, -1405336810},
+{-1632959377, -1394679064}, {-1642052490, -1383961574},
+{-1651075262, -1373184801}, {-1660027308, -1362349204},
+{-1668908244, -1351455249}, {-1677717690, -1340503402},
+{-1686455268, -1329494133}, {-1695120603, -1318427912},
+{-1703713325, -1307305214}, {-1712233066, -1296126516},
+{-1720679461, -1284892296}, {-1729052147, -1273603035},
+{-1737350766, -1262259218}, {-1745574963, -1250861329},
+{-1753724386, -1239409858}, {-1761798685, -1227905295},
+{-1769797514, -1216348132}, {-1777720531, -1204738865},
+{-1785567396, -1193077991}, {-1793337774, -1181366009},
+{-1801031331, -1169603422}, {-1808647737, -1157790732},
+{-1816186668, -1145928447}, {-1823647799, -1134017074},
+{-1831030811, -1122057124}, {-1838335387, -1110049108},
+{-1845561216, -1097993542}, {-1852707986, -1085890941},
+{-1859775393, -1073741824}, {-1866763134, -1061546712},
+{-1873670908, -1049306126}, {-1880498421, -1037020592},
+{-1887245379, -1024690635}, {-1893911494, -1012316784},
+{-1900496480, -999899569}, {-1907000055, -987439521},
+{-1913421941, -974937175}, {-1919761862, -962393065},
+{-1926019547, -949807730}, {-1932194727, -937181708},
+{-1938287139, -924515541}, {-1944296521, -911809770},
+{-1950222616, -899064940}, {-1956065170, -886281598},
+{-1961823932, -873460290}, {-1967498656, -860601566},
+{-1973089100, -847705977}, {-1978595022, -834774075},
+{-1984016189, -821806413}, {-1989352366, -808803549},
+{-1994603327, -795766038}, {-1999768845, -782694439},
+{-2004848700, -769589312}, {-2009842674, -756451218},
+{-2014750553, -743280720}, {-2019572126, -730078383},
+{-2024307188, -716844772}, {-2028955535, -703580453},
+{-2033516969, -690285996}, {-2037991293, -676961968},
+{-2042378317, -663608942}, {-2046677852, -650227490},
+{-2050889714, -636818183}, {-2055013723, -623381598},
+{-2059049702, -609918309}, {-2062997478, -596428893},
+{-2066856882, -582913927}, {-2070627749, -569373992},
+{-2074309917, -555809667}, {-2077903229, -542221533},
+{-2081407530, -528610172}, {-2084822670, -514976167},
+{-2088148504, -501320102}, {-2091384888, -487642562},
+{-2094531684, -473944133}, {-2097588758, -460225402},
+{-2100555978, -446486956}, {-2103433217, -432729385},
+{-2106220352, -418953276}, {-2108917263, -405159222},
+{-2111523836, -391347811}, {-2114039958, -377519637},
+{-2116465521, -363675290}, {-2118800422, -349815365},
+{-2121044561, -335940456}, {-2123197841, -322051155},
+{-2125260170, -308148059}, {-2127231461, -294231763},
+{-2129111628, -280302863}, {-2130900591, -266361956},
+{-2132598273, -252409639}, {-2134204601, -238446509},
+{-2135719508, -224473166}, {-2137142927, -210490206},
+{-2138474799, -196498230}, {-2139715065, -182497836},
+{-2140863673, -168489625}, {-2141920573, -154474196},
+{-2142885721, -140452151}, {-2143759074, -126424088},
+{-2144540596, -112390610}, {-2145230253, -98352318},
+{-2145828016, -84309812}, {-2146333858, -70263695},
+{-2146747759, -56214568}, {-2147069700, -42163034},
+{-2147299668, -28109692}, {-2147437652, -14055147},
+{-2147483648, 0}, {-2147437652, 14055147},
+{-2147299668, 28109692}, {-2147069700, 42163034},
+{-2146747759, 56214568}, {-2146333858, 70263695},
+{-2145828016, 84309812}, {-2145230253, 98352318},
+{-2144540596, 112390610}, {-2143759074, 126424088},
+{-2142885721, 140452151}, {-2141920573, 154474196},
+{-2140863673, 168489625}, {-2139715065, 182497836},
+{-2138474799, 196498230}, {-2137142927, 210490206},
+{-2135719508, 224473166}, {-2134204601, 238446509},
+{-2132598273, 252409639}, {-2130900591, 266361956},
+{-2129111628, 280302863}, {-2127231461, 294231763},
+{-2125260170, 308148059}, {-2123197841, 322051155},
+{-2121044561, 335940456}, {-2118800422, 349815365},
+{-2116465521, 363675290}, {-2114039958, 377519637},
+{-2111523836, 391347811}, {-2108917263, 405159222},
+{-2106220352, 418953276}, {-2103433217, 432729385},
+{-2100555978, 446486956}, {-2097588758, 460225402},
+{-2094531684, 473944133}, {-2091384888, 487642562},
+{-2088148504, 501320102}, {-2084822670, 514976167},
+{-2081407530, 528610172}, {-2077903229, 542221533},
+{-2074309917, 555809667}, {-2070627749, 569373992},
+{-2066856882, 582913927}, {-2062997478, 596428893},
+{-2059049702, 609918309}, {-2055013723, 623381598},
+{-2050889714, 636818183}, {-2046677852, 650227490},
+{-2042378317, 663608942}, {-2037991293, 676961968},
+{-2033516969, 690285996}, {-2028955535, 703580453},
+{-2024307188, 716844772}, {-2019572126, 730078383},
+{-2014750553, 743280720}, {-2009842674, 756451218},
+{-2004848700, 769589312}, {-1999768845, 782694439},
+{-1994603327, 795766038}, {-1989352366, 808803549},
+{-1984016189, 821806413}, {-1978595022, 834774075},
+{-1973089100, 847705977}, {-1967498656, 860601566},
+{-1961823932, 873460290}, {-1956065170, 886281598},
+{-1950222616, 899064940}, {-1944296521, 911809770},
+{-1938287139, 924515541}, {-1932194727, 937181708},
+{-1926019547, 949807730}, {-1919761862, 962393065},
+{-1913421941, 974937175}, {-1907000055, 987439521},
+{-1900496480, 999899569}, {-1893911494, 1012316784},
+{-1887245379, 1024690635}, {-1880498421, 1037020592},
+{-1873670908, 1049306126}, {-1866763134, 1061546712},
+{-1859775393, 1073741824}, {-1852707986, 1085890941},
+{-1845561216, 1097993542}, {-1838335387, 1110049108},
+{-1831030811, 1122057124}, {-1823647799, 1134017074},
+{-1816186668, 1145928447}, {-1808647737, 1157790732},
+{-1801031331, 1169603422}, {-1793337774, 1181366009},
+{-1785567396, 1193077991}, {-1777720531, 1204738865},
+{-1769797514, 1216348132}, {-1761798685, 1227905295},
+{-1753724386, 1239409858}, {-1745574963, 1250861329},
+{-1737350766, 1262259218}, {-1729052147, 1273603035},
+{-1720679461, 1284892296}, {-1712233066, 1296126516},
+{-1703713325, 1307305214}, {-1695120603, 1318427912},
+{-1686455268, 1329494133}, {-1677717690, 1340503402},
+{-1668908244, 1351455249}, {-1660027308, 1362349204},
+{-1651075262, 1373184801}, {-1642052490, 1383961574},
+{-1632959377, 1394679064}, {-1623796314, 1405336810},
+{-1614563692, 1415934356}, {-1605261909, 1426471249},
+{-1595891361, 1436947036}, {-1586452450, 1447361268},
+{-1576945581, 1457713501}, {-1567371161, 1468003290},
+{-1557729600, 1478230195}, {-1548021312, 1488393778},
+{-1538246711, 1498493602}, {-1528406216, 1508529236},
+{-1518500250, 1518500250}, {-1508529236, 1528406216},
+{-1498493602, 1538246711}, {-1488393778, 1548021312},
+{-1478230195, 1557729600}, {-1468003290, 1567371161},
+{-1457713501, 1576945581}, {-1447361268, 1586452450},
+{-1436947036, 1595891361}, {-1426471249, 1605261909},
+{-1415934356, 1614563692}, {-1405336810, 1623796314},
+{-1394679064, 1632959377}, {-1383961574, 1642052490},
+{-1373184801, 1651075262}, {-1362349204, 1660027308},
+{-1351455249, 1668908244}, {-1340503402, 1677717690},
+{-1329494133, 1686455268}, {-1318427912, 1695120603},
+{-1307305214, 1703713325}, {-1296126516, 1712233066},
+{-1284892296, 1720679461}, {-1273603035, 1729052147},
+{-1262259218, 1737350766}, {-1250861329, 1745574963},
+{-1239409858, 1753724386}, {-1227905295, 1761798685},
+{-1216348132, 1769797514}, {-1204738865, 1777720531},
+{-1193077991, 1785567396}, {-1181366009, 1793337774},
+{-1169603422, 1801031331}, {-1157790732, 1808647737},
+{-1145928447, 1816186668}, {-1134017074, 1823647799},
+{-1122057124, 1831030811}, {-1110049108, 1838335387},
+{-1097993542, 1845561216}, {-1085890941, 1852707986},
+{-1073741824, 1859775393}, {-1061546712, 1866763134},
+{-1049306126, 1873670908}, {-1037020592, 1880498421},
+{-1024690635, 1887245379}, {-1012316784, 1893911494},
+{-999899569, 1900496480}, {-987439521, 1907000055},
+{-974937175, 1913421941}, {-962393065, 1919761862},
+{-949807730, 1926019547}, {-937181708, 1932194727},
+{-924515541, 1938287139}, {-911809770, 1944296521},
+{-899064940, 1950222616}, {-886281598, 1956065170},
+{-873460290, 1961823932}, {-860601566, 1967498656},
+{-847705977, 1973089100}, {-834774075, 1978595022},
+{-821806413, 1984016189}, {-808803549, 1989352366},
+{-795766038, 1994603327}, {-782694439, 1999768845},
+{-769589312, 2004848700}, {-756451218, 2009842674},
+{-743280720, 2014750553}, {-730078383, 2019572126},
+{-716844772, 2024307188}, {-703580453, 2028955535},
+{-690285996, 2033516969}, {-676961968, 2037991293},
+{-663608942, 2042378317}, {-650227490, 2046677852},
+{-636818183, 2050889714}, {-623381598, 2055013723},
+{-609918309, 2059049702}, {-596428893, 2062997478},
+{-582913927, 2066856882}, {-569373992, 2070627749},
+{-555809667, 2074309917}, {-542221533, 2077903229},
+{-528610172, 2081407530}, {-514976167, 2084822670},
+{-501320102, 2088148504}, {-487642562, 2091384888},
+{-473944133, 2094531684}, {-460225402, 2097588758},
+{-446486956, 2100555978}, {-432729385, 2103433217},
+{-418953276, 2106220352}, {-405159222, 2108917263},
+{-391347811, 2111523836}, {-377519637, 2114039958},
+{-363675290, 2116465521}, {-349815365, 2118800422},
+{-335940456, 2121044561}, {-322051155, 2123197841},
+{-308148059, 2125260170}, {-294231763, 2127231461},
+{-280302863, 2129111628}, {-266361956, 2130900591},
+{-252409639, 2132598273}, {-238446509, 2134204601},
+{-224473166, 2135719508}, {-210490206, 2137142927},
+{-196498230, 2138474799}, {-182497836, 2139715065},
+{-168489625, 2140863673}, {-154474196, 2141920573},
+{-140452151, 2142885721}, {-126424088, 2143759074},
+{-112390610, 2144540596}, {-98352318, 2145230253},
+{-84309812, 2145828016}, {-70263695, 2146333858},
+{-56214568, 2146747759}, {-42163034, 2147069700},
+{-28109692, 2147299668}, {-14055147, 2147437652},
+{0, 2147483647}, {14055147, 2147437652},
+{28109692, 2147299668}, {42163034, 2147069700},
+{56214568, 2146747759}, {70263695, 2146333858},
+{84309812, 2145828016}, {98352318, 2145230253},
+{112390610, 2144540596}, {126424088, 2143759074},
+{140452151, 2142885721}, {154474196, 2141920573},
+{168489625, 2140863673}, {182497836, 2139715065},
+{196498230, 2138474799}, {210490206, 2137142927},
+{224473166, 2135719508}, {238446509, 2134204601},
+{252409639, 2132598273}, {266361956, 2130900591},
+{280302863, 2129111628}, {294231763, 2127231461},
+{308148059, 2125260170}, {322051155, 2123197841},
+{335940456, 2121044561}, {349815365, 2118800422},
+{363675290, 2116465521}, {377519637, 2114039958},
+{391347811, 2111523836}, {405159222, 2108917263},
+{418953276, 2106220352}, {432729385, 2103433217},
+{446486956, 2100555978}, {460225402, 2097588758},
+{473944133, 2094531684}, {487642562, 2091384888},
+{501320102, 2088148504}, {514976167, 2084822670},
+{528610172, 2081407530}, {542221533, 2077903229},
+{555809667, 2074309917}, {569373992, 2070627749},
+{582913927, 2066856882}, {596428893, 2062997478},
+{609918309, 2059049702}, {623381598, 2055013723},
+{636818183, 2050889714}, {650227490, 2046677852},
+{663608942, 2042378317}, {676961968, 2037991293},
+{690285996, 2033516969}, {703580453, 2028955535},
+{716844772, 2024307188}, {730078383, 2019572126},
+{743280720, 2014750553}, {756451218, 2009842674},
+{769589312, 2004848700}, {782694439, 1999768845},
+{795766038, 1994603327}, {808803549, 1989352366},
+{821806413, 1984016189}, {834774075, 1978595022},
+{847705977, 1973089100}, {860601566, 1967498656},
+{873460290, 1961823932}, {886281598, 1956065170},
+{899064940, 1950222616}, {911809770, 1944296521},
+{924515541, 1938287139}, {937181708, 1932194727},
+{949807730, 1926019547}, {962393065, 1919761862},
+{974937175, 1913421941}, {987439521, 1907000055},
+{999899569, 1900496480}, {1012316784, 1893911494},
+{1024690635, 1887245379}, {1037020592, 1880498421},
+{1049306126, 1873670908}, {1061546712, 1866763134},
+{1073741824, 1859775393}, {1085890941, 1852707986},
+{1097993542, 1845561216}, {1110049108, 1838335387},
+{1122057124, 1831030811}, {1134017074, 1823647799},
+{1145928447, 1816186668}, {1157790732, 1808647737},
+{1169603422, 1801031331}, {1181366009, 1793337774},
+{1193077991, 1785567396}, {1204738865, 1777720531},
+{1216348132, 1769797514}, {1227905295, 1761798685},
+{1239409858, 1753724386}, {1250861329, 1745574963},
+{1262259218, 1737350766}, {1273603035, 1729052147},
+{1284892296, 1720679461}, {1296126516, 1712233066},
+{1307305214, 1703713325}, {1318427912, 1695120603},
+{1329494133, 1686455268}, {1340503402, 1677717690},
+{1351455249, 1668908244}, {1362349204, 1660027308},
+{1373184801, 1651075262}, {1383961574, 1642052490},
+{1394679064, 1632959377}, {1405336810, 1623796314},
+{1415934356, 1614563692}, {1426471249, 1605261909},
+{1436947036, 1595891361}, {1447361268, 1586452450},
+{1457713501, 1576945581}, {1468003290, 1567371161},
+{1478230195, 1557729600}, {1488393778, 1548021312},
+{1498493602, 1538246711}, {1508529236, 1528406216},
+{1518500250, 1518500250}, {1528406216, 1508529236},
+{1538246711, 1498493602}, {1548021312, 1488393778},
+{1557729600, 1478230195}, {1567371161, 1468003290},
+{1576945581, 1457713501}, {1586452450, 1447361268},
+{1595891361, 1436947036}, {1605261909, 1426471249},
+{1614563692, 1415934356}, {1623796314, 1405336810},
+{1632959377, 1394679064}, {1642052490, 1383961574},
+{1651075262, 1373184801}, {1660027308, 1362349204},
+{1668908244, 1351455249}, {1677717690, 1340503402},
+{1686455268, 1329494133}, {1695120603, 1318427912},
+{1703713325, 1307305214}, {1712233066, 1296126516},
+{1720679461, 1284892296}, {1729052147, 1273603035},
+{1737350766, 1262259218}, {1745574963, 1250861329},
+{1753724386, 1239409858}, {1761798685, 1227905295},
+{1769797514, 1216348132}, {1777720531, 1204738865},
+{1785567396, 1193077991}, {1793337774, 1181366009},
+{1801031331, 1169603422}, {1808647737, 1157790732},
+{1816186668, 1145928447}, {1823647799, 1134017074},
+{1831030811, 1122057124}, {1838335387, 1110049108},
+{1845561216, 1097993542}, {1852707986, 1085890941},
+{1859775393, 1073741824}, {1866763134, 1061546712},
+{1873670908, 1049306126}, {1880498421, 1037020592},
+{1887245379, 1024690635}, {1893911494, 1012316784},
+{1900496480, 999899569}, {1907000055, 987439521},
+{1913421941, 974937175}, {1919761862, 962393065},
+{1926019547, 949807730}, {1932194727, 937181708},
+{1938287139, 924515541}, {1944296521, 911809770},
+{1950222616, 899064940}, {1956065170, 886281598},
+{1961823932, 873460290}, {1967498656, 860601566},
+{1973089100, 847705977}, {1978595022, 834774075},
+{1984016189, 821806413}, {1989352366, 808803549},
+{1994603327, 795766038}, {1999768845, 782694439},
+{2004848700, 769589312}, {2009842674, 756451218},
+{2014750553, 743280720}, {2019572126, 730078383},
+{2024307188, 716844772}, {2028955535, 703580453},
+{2033516969, 690285996}, {2037991293, 676961968},
+{2042378317, 663608942}, {2046677852, 650227490},
+{2050889714, 636818183}, {2055013723, 623381598},
+{2059049702, 609918309}, {2062997478, 596428893},
+{2066856882, 582913927}, {2070627749, 569373992},
+{2074309917, 555809667}, {2077903229, 542221533},
+{2081407530, 528610172}, {2084822670, 514976167},
+{2088148504, 501320102}, {2091384888, 487642562},
+{2094531684, 473944133}, {2097588758, 460225402},
+{2100555978, 446486956}, {2103433217, 432729385},
+{2106220352, 418953276}, {2108917263, 405159222},
+{2111523836, 391347811}, {2114039958, 377519637},
+{2116465521, 363675290}, {2118800422, 349815365},
+{2121044561, 335940456}, {2123197841, 322051155},
+{2125260170, 308148059}, {2127231461, 294231763},
+{2129111628, 280302863}, {2130900591, 266361956},
+{2132598273, 252409639}, {2134204601, 238446509},
+{2135719508, 224473166}, {2137142927, 210490206},
+{2138474799, 196498230}, {2139715065, 182497836},
+{2140863673, 168489625}, {2141920573, 154474196},
+{2142885721, 140452151}, {2143759074, 126424088},
+{2144540596, 112390610}, {2145230253, 98352318},
+{2145828016, 84309812}, {2146333858, 70263695},
+{2146747759, 56214568}, {2147069700, 42163034},
+{2147299668, 28109692}, {2147437652, 14055147},
+#else
+{32767, 0}, {32767, -214},
+{32765, -429}, {32762, -643},
+{32757, -858}, {32750, -1072},
+{32743, -1286}, {32734, -1501},
+{32723, -1715}, {32711, -1929},
+{32698, -2143}, {32683, -2357},
+{32667, -2571}, {32649, -2785},
+{32631, -2998}, {32610, -3212},
+{32588, -3425}, {32565, -3638},
+{32541, -3851}, {32515, -4064},
+{32488, -4277}, {32459, -4490},
+{32429, -4702}, {32397, -4914},
+{32365, -5126}, {32330, -5338},
+{32295, -5549}, {32258, -5760},
+{32219, -5971}, {32180, -6182},
+{32138, -6393}, {32096, -6603},
+{32052, -6813}, {32007, -7022},
+{31960, -7232}, {31912, -7441},
+{31863, -7650}, {31812, -7858},
+{31760, -8066}, {31706, -8274},
+{31651, -8481}, {31595, -8688},
+{31538, -8895}, {31479, -9101},
+{31419, -9307}, {31357, -9512},
+{31294, -9717}, {31230, -9922},
+{31164, -10126}, {31097, -10330},
+{31029, -10533}, {30959, -10736},
+{30888, -10938}, {30816, -11140},
+{30743, -11342}, {30668, -11543},
+{30592, -11743}, {30514, -11943},
+{30435, -12142}, {30355, -12341},
+{30274, -12540}, {30191, -12738},
+{30107, -12935}, {30022, -13132},
+{29935, -13328}, {29847, -13524},
+{29758, -13719}, {29668, -13913},
+{29576, -14107}, {29483, -14300},
+{29389, -14493}, {29293, -14685},
+{29197, -14876}, {29099, -15067},
+{28999, -15257}, {28899, -15447},
+{28797, -15636}, {28694, -15824},
+{28590, -16011}, {28485, -16198},
+{28378, -16384}, {28270, -16569},
+{28161, -16754}, {28051, -16938},
+{27939, -17121}, {27827, -17304},
+{27713, -17485}, {27598, -17666},
+{27482, -17847}, {27364, -18026},
+{27246, -18205}, {27126, -18383},
+{27005, -18560}, {26883, -18736},
+{26760, -18912}, {26635, -19087},
+{26510, -19261}, {26383, -19434},
+{26255, -19606}, {26127, -19777},
+{25997, -19948}, {25865, -20118},
+{25733, -20286}, {25600, -20454},
+{25466, -20622}, {25330, -20788},
+{25193, -20953}, {25056, -21118},
+{24917, -21281}, {24777, -21444},
+{24636, -21605}, {24494, -21766},
+{24351, -21926}, {24207, -22085},
+{24062, -22243}, {23916, -22400},
+{23769, -22556}, {23621, -22711},
+{23472, -22865}, {23322, -23018},
+{23170, -23170}, {23018, -23322},
+{22865, -23472}, {22711, -23621},
+{22556, -23769}, {22400, -23916},
+{22243, -24062}, {22085, -24207},
+{21926, -24351}, {21766, -24494},
+{21605, -24636}, {21444, -24777},
+{21281, -24917}, {21118, -25056},
+{20953, -25193}, {20788, -25330},
+{20622, -25466}, {20454, -25600},
+{20286, -25733}, {20118, -25865},
+{19948, -25997}, {19777, -26127},
+{19606, -26255}, {19434, -26383},
+{19261, -26510}, {19087, -26635},
+{18912, -26760}, {18736, -26883},
+{18560, -27005}, {18383, -27126},
+{18205, -27246}, {18026, -27364},
+{17847, -27482}, {17666, -27598},
+{17485, -27713}, {17304, -27827},
+{17121, -27939}, {16938, -28051},
+{16754, -28161}, {16569, -28270},
+{16384, -28378}, {16198, -28485},
+{16011, -28590}, {15824, -28694},
+{15636, -28797}, {15447, -28899},
+{15257, -28999}, {15067, -29099},
+{14876, -29197}, {14685, -29293},
+{14493, -29389}, {14300, -29483},
+{14107, -29576}, {13913, -29668},
+{13719, -29758}, {13524, -29847},
+{13328, -29935}, {13132, -30022},
+{12935, -30107}, {12738, -30191},
+{12540, -30274}, {12341, -30355},
+{12142, -30435}, {11943, -30514},
+{11743, -30592}, {11543, -30668},
+{11342, -30743}, {11140, -30816},
+{10938, -30888}, {10736, -30959},
+{10533, -31029}, {10330, -31097},
+{10126, -31164}, {9922, -31230},
+{9717, -31294}, {9512, -31357},
+{9307, -31419}, {9101, -31479},
+{8895, -31538}, {8688, -31595},
+{8481, -31651}, {8274, -31706},
+{8066, -31760}, {7858, -31812},
+{7650, -31863}, {7441, -31912},
+{7232, -31960}, {7022, -32007},
+{6813, -32052}, {6603, -32096},
+{6393, -32138}, {6182, -32180},
+{5971, -32219}, {5760, -32258},
+{5549, -32295}, {5338, -32330},
+{5126, -32365}, {4914, -32397},
+{4702, -32429}, {4490, -32459},
+{4277, -32488}, {4064, -32515},
+{3851, -32541}, {3638, -32565},
+{3425, -32588}, {3212, -32610},
+{2998, -32631}, {2785, -32649},
+{2571, -32667}, {2357, -32683},
+{2143, -32698}, {1929, -32711},
+{1715, -32723}, {1501, -32734},
+{1286, -32743}, {1072, -32750},
+{858, -32757}, {643, -32762},
+{429, -32765}, {214, -32767},
+{0, -32767}, {-214, -32767},
+{-429, -32765}, {-643, -32762},
+{-858, -32757}, {-1072, -32750},
+{-1286, -32743}, {-1501, -32734},
+{-1715, -32723}, {-1929, -32711},
+{-2143, -32698}, {-2357, -32683},
+{-2571, -32667}, {-2785, -32649},
+{-2998, -32631}, {-3212, -32610},
+{-3425, -32588}, {-3638, -32565},
+{-3851, -32541}, {-4064, -32515},
+{-4277, -32488}, {-4490, -32459},
+{-4702, -32429}, {-4914, -32397},
+{-5126, -32365}, {-5338, -32330},
+{-5549, -32295}, {-5760, -32258},
+{-5971, -32219}, {-6182, -32180},
+{-6393, -32138}, {-6603, -32096},
+{-6813, -32052}, {-7022, -32007},
+{-7232, -31960}, {-7441, -31912},
+{-7650, -31863}, {-7858, -31812},
+{-8066, -31760}, {-8274, -31706},
+{-8481, -31651}, {-8688, -31595},
+{-8895, -31538}, {-9101, -31479},
+{-9307, -31419}, {-9512, -31357},
+{-9717, -31294}, {-9922, -31230},
+{-10126, -31164}, {-10330, -31097},
+{-10533, -31029}, {-10736, -30959},
+{-10938, -30888}, {-11140, -30816},
+{-11342, -30743}, {-11543, -30668},
+{-11743, -30592}, {-11943, -30514},
+{-12142, -30435}, {-12341, -30355},
+{-12540, -30274}, {-12738, -30191},
+{-12935, -30107}, {-13132, -30022},
+{-13328, -29935}, {-13524, -29847},
+{-13719, -29758}, {-13913, -29668},
+{-14107, -29576}, {-14300, -29483},
+{-14493, -29389}, {-14685, -29293},
+{-14876, -29197}, {-15067, -29099},
+{-15257, -28999}, {-15447, -28899},
+{-15636, -28797}, {-15824, -28694},
+{-16011, -28590}, {-16198, -28485},
+{-16384, -28378}, {-16569, -28270},
+{-16754, -28161}, {-16938, -28051},
+{-17121, -27939}, {-17304, -27827},
+{-17485, -27713}, {-17666, -27598},
+{-17847, -27482}, {-18026, -27364},
+{-18205, -27246}, {-18383, -27126},
+{-18560, -27005}, {-18736, -26883},
+{-18912, -26760}, {-19087, -26635},
+{-19261, -26510}, {-19434, -26383},
+{-19606, -26255}, {-19777, -26127},
+{-19948, -25997}, {-20118, -25865},
+{-20286, -25733}, {-20454, -25600},
+{-20622, -25466}, {-20788, -25330},
+{-20953, -25193}, {-21118, -25056},
+{-21281, -24917}, {-21444, -24777},
+{-21605, -24636}, {-21766, -24494},
+{-21926, -24351}, {-22085, -24207},
+{-22243, -24062}, {-22400, -23916},
+{-22556, -23769}, {-22711, -23621},
+{-22865, -23472}, {-23018, -23322},
+{-23170, -23170}, {-23322, -23018},
+{-23472, -22865}, {-23621, -22711},
+{-23769, -22556}, {-23916, -22400},
+{-24062, -22243}, {-24207, -22085},
+{-24351, -21926}, {-24494, -21766},
+{-24636, -21605}, {-24777, -21444},
+{-24917, -21281}, {-25056, -21118},
+{-25193, -20953}, {-25330, -20788},
+{-25466, -20622}, {-25600, -20454},
+{-25733, -20286}, {-25865, -20118},
+{-25997, -19948}, {-26127, -19777},
+{-26255, -19606}, {-26383, -19434},
+{-26510, -19261}, {-26635, -19087},
+{-26760, -18912}, {-26883, -18736},
+{-27005, -18560}, {-27126, -18383},
+{-27246, -18205}, {-27364, -18026},
+{-27482, -17847}, {-27598, -17666},
+{-27713, -17485}, {-27827, -17304},
+{-27939, -17121}, {-28051, -16938},
+{-28161, -16754}, {-28270, -16569},
+{-28378, -16384}, {-28485, -16198},
+{-28590, -16011}, {-28694, -15824},
+{-28797, -15636}, {-28899, -15447},
+{-28999, -15257}, {-29099, -15067},
+{-29197, -14876}, {-29293, -14685},
+{-29389, -14493}, {-29483, -14300},
+{-29576, -14107}, {-29668, -13913},
+{-29758, -13719}, {-29847, -13524},
+{-29935, -13328}, {-30022, -13132},
+{-30107, -12935}, {-30191, -12738},
+{-30274, -12540}, {-30355, -12341},
+{-30435, -12142}, {-30514, -11943},
+{-30592, -11743}, {-30668, -11543},
+{-30743, -11342}, {-30816, -11140},
+{-30888, -10938}, {-30959, -10736},
+{-31029, -10533}, {-31097, -10330},
+{-31164, -10126}, {-31230, -9922},
+{-31294, -9717}, {-31357, -9512},
+{-31419, -9307}, {-31479, -9101},
+{-31538, -8895}, {-31595, -8688},
+{-31651, -8481}, {-31706, -8274},
+{-31760, -8066}, {-31812, -7858},
+{-31863, -7650}, {-31912, -7441},
+{-31960, -7232}, {-32007, -7022},
+{-32052, -6813}, {-32096, -6603},
+{-32138, -6393}, {-32180, -6182},
+{-32219, -5971}, {-32258, -5760},
+{-32295, -5549}, {-32330, -5338},
+{-32365, -5126}, {-32397, -4914},
+{-32429, -4702}, {-32459, -4490},
+{-32488, -4277}, {-32515, -4064},
+{-32541, -3851}, {-32565, -3638},
+{-32588, -3425}, {-32610, -3212},
+{-32631, -2998}, {-32649, -2785},
+{-32667, -2571}, {-32683, -2357},
+{-32698, -2143}, {-32711, -1929},
+{-32723, -1715}, {-32734, -1501},
+{-32743, -1286}, {-32750, -1072},
+{-32757, -858}, {-32762, -643},
+{-32765, -429}, {-32767, -214},
+{-32767, 0}, {-32767, 214},
+{-32765, 429}, {-32762, 643},
+{-32757, 858}, {-32750, 1072},
+{-32743, 1286}, {-32734, 1501},
+{-32723, 1715}, {-32711, 1929},
+{-32698, 2143}, {-32683, 2357},
+{-32667, 2571}, {-32649, 2785},
+{-32631, 2998}, {-32610, 3212},
+{-32588, 3425}, {-32565, 3638},
+{-32541, 3851}, {-32515, 4064},
+{-32488, 4277}, {-32459, 4490},
+{-32429, 4702}, {-32397, 4914},
+{-32365, 5126}, {-32330, 5338},
+{-32295, 5549}, {-32258, 5760},
+{-32219, 5971}, {-32180, 6182},
+{-32138, 6393}, {-32096, 6603},
+{-32052, 6813}, {-32007, 7022},
+{-31960, 7232}, {-31912, 7441},
+{-31863, 7650}, {-31812, 7858},
+{-31760, 8066}, {-31706, 8274},
+{-31651, 8481}, {-31595, 8688},
+{-31538, 8895}, {-31479, 9101},
+{-31419, 9307}, {-31357, 9512},
+{-31294, 9717}, {-31230, 9922},
+{-31164, 10126}, {-31097, 10330},
+{-31029, 10533}, {-30959, 10736},
+{-30888, 10938}, {-30816, 11140},
+{-30743, 11342}, {-30668, 11543},
+{-30592, 11743}, {-30514, 11943},
+{-30435, 12142}, {-30355, 12341},
+{-30274, 12540}, {-30191, 12738},
+{-30107, 12935}, {-30022, 13132},
+{-29935, 13328}, {-29847, 13524},
+{-29758, 13719}, {-29668, 13913},
+{-29576, 14107}, {-29483, 14300},
+{-29389, 14493}, {-29293, 14685},
+{-29197, 14876}, {-29099, 15067},
+{-28999, 15257}, {-28899, 15447},
+{-28797, 15636}, {-28694, 15824},
+{-28590, 16011}, {-28485, 16198},
+{-28378, 16384}, {-28270, 16569},
+{-28161, 16754}, {-28051, 16938},
+{-27939, 17121}, {-27827, 17304},
+{-27713, 17485}, {-27598, 17666},
+{-27482, 17847}, {-27364, 18026},
+{-27246, 18205}, {-27126, 18383},
+{-27005, 18560}, {-26883, 18736},
+{-26760, 18912}, {-26635, 19087},
+{-26510, 19261}, {-26383, 19434},
+{-26255, 19606}, {-26127, 19777},
+{-25997, 19948}, {-25865, 20118},
+{-25733, 20286}, {-25600, 20454},
+{-25466, 20622}, {-25330, 20788},
+{-25193, 20953}, {-25056, 21118},
+{-24917, 21281}, {-24777, 21444},
+{-24636, 21605}, {-24494, 21766},
+{-24351, 21926}, {-24207, 22085},
+{-24062, 22243}, {-23916, 22400},
+{-23769, 22556}, {-23621, 22711},
+{-23472, 22865}, {-23322, 23018},
+{-23170, 23170}, {-23018, 23322},
+{-22865, 23472}, {-22711, 23621},
+{-22556, 23769}, {-22400, 23916},
+{-22243, 24062}, {-22085, 24207},
+{-21926, 24351}, {-21766, 24494},
+{-21605, 24636}, {-21444, 24777},
+{-21281, 24917}, {-21118, 25056},
+{-20953, 25193}, {-20788, 25330},
+{-20622, 25466}, {-20454, 25600},
+{-20286, 25733}, {-20118, 25865},
+{-19948, 25997}, {-19777, 26127},
+{-19606, 26255}, {-19434, 26383},
+{-19261, 26510}, {-19087, 26635},
+{-18912, 26760}, {-18736, 26883},
+{-18560, 27005}, {-18383, 27126},
+{-18205, 27246}, {-18026, 27364},
+{-17847, 27482}, {-17666, 27598},
+{-17485, 27713}, {-17304, 27827},
+{-17121, 27939}, {-16938, 28051},
+{-16754, 28161}, {-16569, 28270},
+{-16384, 28378}, {-16198, 28485},
+{-16011, 28590}, {-15824, 28694},
+{-15636, 28797}, {-15447, 28899},
+{-15257, 28999}, {-15067, 29099},
+{-14876, 29197}, {-14685, 29293},
+{-14493, 29389}, {-14300, 29483},
+{-14107, 29576}, {-13913, 29668},
+{-13719, 29758}, {-13524, 29847},
+{-13328, 29935}, {-13132, 30022},
+{-12935, 30107}, {-12738, 30191},
+{-12540, 30274}, {-12341, 30355},
+{-12142, 30435}, {-11943, 30514},
+{-11743, 30592}, {-11543, 30668},
+{-11342, 30743}, {-11140, 30816},
+{-10938, 30888}, {-10736, 30959},
+{-10533, 31029}, {-10330, 31097},
+{-10126, 31164}, {-9922, 31230},
+{-9717, 31294}, {-9512, 31357},
+{-9307, 31419}, {-9101, 31479},
+{-8895, 31538}, {-8688, 31595},
+{-8481, 31651}, {-8274, 31706},
+{-8066, 31760}, {-7858, 31812},
+{-7650, 31863}, {-7441, 31912},
+{-7232, 31960}, {-7022, 32007},
+{-6813, 32052}, {-6603, 32096},
+{-6393, 32138}, {-6182, 32180},
+{-5971, 32219}, {-5760, 32258},
+{-5549, 32295}, {-5338, 32330},
+{-5126, 32365}, {-4914, 32397},
+{-4702, 32429}, {-4490, 32459},
+{-4277, 32488}, {-4064, 32515},
+{-3851, 32541}, {-3638, 32565},
+{-3425, 32588}, {-3212, 32610},
+{-2998, 32631}, {-2785, 32649},
+{-2571, 32667}, {-2357, 32683},
+{-2143, 32698}, {-1929, 32711},
+{-1715, 32723}, {-1501, 32734},
+{-1286, 32743}, {-1072, 32750},
+{-858, 32757}, {-643, 32762},
+{-429, 32765}, {-214, 32767},
+{0, 32767}, {214, 32767},
+{429, 32765}, {643, 32762},
+{858, 32757}, {1072, 32750},
+{1286, 32743}, {1501, 32734},
+{1715, 32723}, {1929, 32711},
+{2143, 32698}, {2357, 32683},
+{2571, 32667}, {2785, 32649},
+{2998, 32631}, {3212, 32610},
+{3425, 32588}, {3638, 32565},
+{3851, 32541}, {4064, 32515},
+{4277, 32488}, {4490, 32459},
+{4702, 32429}, {4914, 32397},
+{5126, 32365}, {5338, 32330},
+{5549, 32295}, {5760, 32258},
+{5971, 32219}, {6182, 32180},
+{6393, 32138}, {6603, 32096},
+{6813, 32052}, {7022, 32007},
+{7232, 31960}, {7441, 31912},
+{7650, 31863}, {7858, 31812},
+{8066, 31760}, {8274, 31706},
+{8481, 31651}, {8688, 31595},
+{8895, 31538}, {9101, 31479},
+{9307, 31419}, {9512, 31357},
+{9717, 31294}, {9922, 31230},
+{10126, 31164}, {10330, 31097},
+{10533, 31029}, {10736, 30959},
+{10938, 30888}, {11140, 30816},
+{11342, 30743}, {11543, 30668},
+{11743, 30592}, {11943, 30514},
+{12142, 30435}, {12341, 30355},
+{12540, 30274}, {12738, 30191},
+{12935, 30107}, {13132, 30022},
+{13328, 29935}, {13524, 29847},
+{13719, 29758}, {13913, 29668},
+{14107, 29576}, {14300, 29483},
+{14493, 29389}, {14685, 29293},
+{14876, 29197}, {15067, 29099},
+{15257, 28999}, {15447, 28899},
+{15636, 28797}, {15824, 28694},
+{16011, 28590}, {16198, 28485},
+{16384, 28378}, {16569, 28270},
+{16754, 28161}, {16938, 28051},
+{17121, 27939}, {17304, 27827},
+{17485, 27713}, {17666, 27598},
+{17847, 27482}, {18026, 27364},
+{18205, 27246}, {18383, 27126},
+{18560, 27005}, {18736, 26883},
+{18912, 26760}, {19087, 26635},
+{19261, 26510}, {19434, 26383},
+{19606, 26255}, {19777, 26127},
+{19948, 25997}, {20118, 25865},
+{20286, 25733}, {20454, 25600},
+{20622, 25466}, {20788, 25330},
+{20953, 25193}, {21118, 25056},
+{21281, 24917}, {21444, 24777},
+{21605, 24636}, {21766, 24494},
+{21926, 24351}, {22085, 24207},
+{22243, 24062}, {22400, 23916},
+{22556, 23769}, {22711, 23621},
+{22865, 23472}, {23018, 23322},
+{23170, 23170}, {23322, 23018},
+{23472, 22865}, {23621, 22711},
+{23769, 22556}, {23916, 22400},
+{24062, 22243}, {24207, 22085},
+{24351, 21926}, {24494, 21766},
+{24636, 21605}, {24777, 21444},
+{24917, 21281}, {25056, 21118},
+{25193, 20953}, {25330, 20788},
+{25466, 20622}, {25600, 20454},
+{25733, 20286}, {25865, 20118},
+{25997, 19948}, {26127, 19777},
+{26255, 19606}, {26383, 19434},
+{26510, 19261}, {26635, 19087},
+{26760, 18912}, {26883, 18736},
+{27005, 18560}, {27126, 18383},
+{27246, 18205}, {27364, 18026},
+{27482, 17847}, {27598, 17666},
+{27713, 17485}, {27827, 17304},
+{27939, 17121}, {28051, 16938},
+{28161, 16754}, {28270, 16569},
+{28378, 16384}, {28485, 16198},
+{28590, 16011}, {28694, 15824},
+{28797, 15636}, {28899, 15447},
+{28999, 15257}, {29099, 15067},
+{29197, 14876}, {29293, 14685},
+{29389, 14493}, {29483, 14300},
+{29576, 14107}, {29668, 13913},
+{29758, 13719}, {29847, 13524},
+{29935, 13328}, {30022, 13132},
+{30107, 12935}, {30191, 12738},
+{30274, 12540}, {30355, 12341},
+{30435, 12142}, {30514, 11943},
+{30592, 11743}, {30668, 11543},
+{30743, 11342}, {30816, 11140},
+{30888, 10938}, {30959, 10736},
+{31029, 10533}, {31097, 10330},
+{31164, 10126}, {31230, 9922},
+{31294, 9717}, {31357, 9512},
+{31419, 9307}, {31479, 9101},
+{31538, 8895}, {31595, 8688},
+{31651, 8481}, {31706, 8274},
+{31760, 8066}, {31812, 7858},
+{31863, 7650}, {31912, 7441},
+{31960, 7232}, {32007, 7022},
+{32052, 6813}, {32096, 6603},
+{32138, 6393}, {32180, 6182},
+{32219, 5971}, {32258, 5760},
+{32295, 5549}, {32330, 5338},
+{32365, 5126}, {32397, 4914},
+{32429, 4702}, {32459, 4490},
+{32488, 4277}, {32515, 4064},
+{32541, 3851}, {32565, 3638},
+{32588, 3425}, {32610, 3212},
+{32631, 2998}, {32649, 2785},
+{32667, 2571}, {32683, 2357},
+{32698, 2143}, {32711, 1929},
+{32723, 1715}, {32734, 1501},
+{32743, 1286}, {32750, 1072},
+{32757, 858}, {32762, 643},
+{32765, 429}, {32767, 214},
+#endif
+};
+#ifndef FFT_BITREV960
+#define FFT_BITREV960
+static const opus_int16 fft_bitrev960[960] = {
+0, 192, 384, 576, 768, 64, 256, 448, 640, 832, 128, 320, 512, 704, 896,
+16, 208, 400, 592, 784, 80, 272, 464, 656, 848, 144, 336, 528, 720, 912,
+32, 224, 416, 608, 800, 96, 288, 480, 672, 864, 160, 352, 544, 736, 928,
+48, 240, 432, 624, 816, 112, 304, 496, 688, 880, 176, 368, 560, 752, 944,
+4, 196, 388, 580, 772, 68, 260, 452, 644, 836, 132, 324, 516, 708, 900,
+20, 212, 404, 596, 788, 84, 276, 468, 660, 852, 148, 340, 532, 724, 916,
+36, 228, 420, 612, 804, 100, 292, 484, 676, 868, 164, 356, 548, 740, 932,
+52, 244, 436, 628, 820, 116, 308, 500, 692, 884, 180, 372, 564, 756, 948,
+8, 200, 392, 584, 776, 72, 264, 456, 648, 840, 136, 328, 520, 712, 904,
+24, 216, 408, 600, 792, 88, 280, 472, 664, 856, 152, 344, 536, 728, 920,
+40, 232, 424, 616, 808, 104, 296, 488, 680, 872, 168, 360, 552, 744, 936,
+56, 248, 440, 632, 824, 120, 312, 504, 696, 888, 184, 376, 568, 760, 952,
+12, 204, 396, 588, 780, 76, 268, 460, 652, 844, 140, 332, 524, 716, 908,
+28, 220, 412, 604, 796, 92, 284, 476, 668, 860, 156, 348, 540, 732, 924,
+44, 236, 428, 620, 812, 108, 300, 492, 684, 876, 172, 364, 556, 748, 940,
+60, 252, 444, 636, 828, 124, 316, 508, 700, 892, 188, 380, 572, 764, 956,
+1, 193, 385, 577, 769, 65, 257, 449, 641, 833, 129, 321, 513, 705, 897,
+17, 209, 401, 593, 785, 81, 273, 465, 657, 849, 145, 337, 529, 721, 913,
+33, 225, 417, 609, 801, 97, 289, 481, 673, 865, 161, 353, 545, 737, 929,
+49, 241, 433, 625, 817, 113, 305, 497, 689, 881, 177, 369, 561, 753, 945,
+5, 197, 389, 581, 773, 69, 261, 453, 645, 837, 133, 325, 517, 709, 901,
+21, 213, 405, 597, 789, 85, 277, 469, 661, 853, 149, 341, 533, 725, 917,
+37, 229, 421, 613, 805, 101, 293, 485, 677, 869, 165, 357, 549, 741, 933,
+53, 245, 437, 629, 821, 117, 309, 501, 693, 885, 181, 373, 565, 757, 949,
+9, 201, 393, 585, 777, 73, 265, 457, 649, 841, 137, 329, 521, 713, 905,
+25, 217, 409, 601, 793, 89, 281, 473, 665, 857, 153, 345, 537, 729, 921,
+41, 233, 425, 617, 809, 105, 297, 489, 681, 873, 169, 361, 553, 745, 937,
+57, 249, 441, 633, 825, 121, 313, 505, 697, 889, 185, 377, 569, 761, 953,
+13, 205, 397, 589, 781, 77, 269, 461, 653, 845, 141, 333, 525, 717, 909,
+29, 221, 413, 605, 797, 93, 285, 477, 669, 861, 157, 349, 541, 733, 925,
+45, 237, 429, 621, 813, 109, 301, 493, 685, 877, 173, 365, 557, 749, 941,
+61, 253, 445, 637, 829, 125, 317, 509, 701, 893, 189, 381, 573, 765, 957,
+2, 194, 386, 578, 770, 66, 258, 450, 642, 834, 130, 322, 514, 706, 898,
+18, 210, 402, 594, 786, 82, 274, 466, 658, 850, 146, 338, 530, 722, 914,
+34, 226, 418, 610, 802, 98, 290, 482, 674, 866, 162, 354, 546, 738, 930,
+50, 242, 434, 626, 818, 114, 306, 498, 690, 882, 178, 370, 562, 754, 946,
+6, 198, 390, 582, 774, 70, 262, 454, 646, 838, 134, 326, 518, 710, 902,
+22, 214, 406, 598, 790, 86, 278, 470, 662, 854, 150, 342, 534, 726, 918,
+38, 230, 422, 614, 806, 102, 294, 486, 678, 870, 166, 358, 550, 742, 934,
+54, 246, 438, 630, 822, 118, 310, 502, 694, 886, 182, 374, 566, 758, 950,
+10, 202, 394, 586, 778, 74, 266, 458, 650, 842, 138, 330, 522, 714, 906,
+26, 218, 410, 602, 794, 90, 282, 474, 666, 858, 154, 346, 538, 730, 922,
+42, 234, 426, 618, 810, 106, 298, 490, 682, 874, 170, 362, 554, 746, 938,
+58, 250, 442, 634, 826, 122, 314, 506, 698, 890, 186, 378, 570, 762, 954,
+14, 206, 398, 590, 782, 78, 270, 462, 654, 846, 142, 334, 526, 718, 910,
+30, 222, 414, 606, 798, 94, 286, 478, 670, 862, 158, 350, 542, 734, 926,
+46, 238, 430, 622, 814, 110, 302, 494, 686, 878, 174, 366, 558, 750, 942,
+62, 254, 446, 638, 830, 126, 318, 510, 702, 894, 190, 382, 574, 766, 958,
+3, 195, 387, 579, 771, 67, 259, 451, 643, 835, 131, 323, 515, 707, 899,
+19, 211, 403, 595, 787, 83, 275, 467, 659, 851, 147, 339, 531, 723, 915,
+35, 227, 419, 611, 803, 99, 291, 483, 675, 867, 163, 355, 547, 739, 931,
+51, 243, 435, 627, 819, 115, 307, 499, 691, 883, 179, 371, 563, 755, 947,
+7, 199, 391, 583, 775, 71, 263, 455, 647, 839, 135, 327, 519, 711, 903,
+23, 215, 407, 599, 791, 87, 279, 471, 663, 855, 151, 343, 535, 727, 919,
+39, 231, 423, 615, 807, 103, 295, 487, 679, 871, 167, 359, 551, 743, 935,
+55, 247, 439, 631, 823, 119, 311, 503, 695, 887, 183, 375, 567, 759, 951,
+11, 203, 395, 587, 779, 75, 267, 459, 651, 843, 139, 331, 523, 715, 907,
+27, 219, 411, 603, 795, 91, 283, 475, 667, 859, 155, 347, 539, 731, 923,
+43, 235, 427, 619, 811, 107, 299, 491, 683, 875, 171, 363, 555, 747, 939,
+59, 251, 443, 635, 827, 123, 315, 507, 699, 891, 187, 379, 571, 763, 955,
+15, 207, 399, 591, 783, 79, 271, 463, 655, 847, 143, 335, 527, 719, 911,
+31, 223, 415, 607, 799, 95, 287, 479, 671, 863, 159, 351, 543, 735, 927,
+47, 239, 431, 623, 815, 111, 303, 495, 687, 879, 175, 367, 559, 751, 943,
+63, 255, 447, 639, 831, 127, 319, 511, 703, 895, 191, 383, 575, 767, 959,
+};
+#endif
+
+#ifndef FFT_BITREV480
+#define FFT_BITREV480
+static const opus_int16 fft_bitrev480[480] = {
+0, 96, 192, 288, 384, 32, 128, 224, 320, 416, 64, 160, 256, 352, 448,
+8, 104, 200, 296, 392, 40, 136, 232, 328, 424, 72, 168, 264, 360, 456,
+16, 112, 208, 304, 400, 48, 144, 240, 336, 432, 80, 176, 272, 368, 464,
+24, 120, 216, 312, 408, 56, 152, 248, 344, 440, 88, 184, 280, 376, 472,
+4, 100, 196, 292, 388, 36, 132, 228, 324, 420, 68, 164, 260, 356, 452,
+12, 108, 204, 300, 396, 44, 140, 236, 332, 428, 76, 172, 268, 364, 460,
+20, 116, 212, 308, 404, 52, 148, 244, 340, 436, 84, 180, 276, 372, 468,
+28, 124, 220, 316, 412, 60, 156, 252, 348, 444, 92, 188, 284, 380, 476,
+1, 97, 193, 289, 385, 33, 129, 225, 321, 417, 65, 161, 257, 353, 449,
+9, 105, 201, 297, 393, 41, 137, 233, 329, 425, 73, 169, 265, 361, 457,
+17, 113, 209, 305, 401, 49, 145, 241, 337, 433, 81, 177, 273, 369, 465,
+25, 121, 217, 313, 409, 57, 153, 249, 345, 441, 89, 185, 281, 377, 473,
+5, 101, 197, 293, 389, 37, 133, 229, 325, 421, 69, 165, 261, 357, 453,
+13, 109, 205, 301, 397, 45, 141, 237, 333, 429, 77, 173, 269, 365, 461,
+21, 117, 213, 309, 405, 53, 149, 245, 341, 437, 85, 181, 277, 373, 469,
+29, 125, 221, 317, 413, 61, 157, 253, 349, 445, 93, 189, 285, 381, 477,
+2, 98, 194, 290, 386, 34, 130, 226, 322, 418, 66, 162, 258, 354, 450,
+10, 106, 202, 298, 394, 42, 138, 234, 330, 426, 74, 170, 266, 362, 458,
+18, 114, 210, 306, 402, 50, 146, 242, 338, 434, 82, 178, 274, 370, 466,
+26, 122, 218, 314, 410, 58, 154, 250, 346, 442, 90, 186, 282, 378, 474,
+6, 102, 198, 294, 390, 38, 134, 230, 326, 422, 70, 166, 262, 358, 454,
+14, 110, 206, 302, 398, 46, 142, 238, 334, 430, 78, 174, 270, 366, 462,
+22, 118, 214, 310, 406, 54, 150, 246, 342, 438, 86, 182, 278, 374, 470,
+30, 126, 222, 318, 414, 62, 158, 254, 350, 446, 94, 190, 286, 382, 478,
+3, 99, 195, 291, 387, 35, 131, 227, 323, 419, 67, 163, 259, 355, 451,
+11, 107, 203, 299, 395, 43, 139, 235, 331, 427, 75, 171, 267, 363, 459,
+19, 115, 211, 307, 403, 51, 147, 243, 339, 435, 83, 179, 275, 371, 467,
+27, 123, 219, 315, 411, 59, 155, 251, 347, 443, 91, 187, 283, 379, 475,
+7, 103, 199, 295, 391, 39, 135, 231, 327, 423, 71, 167, 263, 359, 455,
+15, 111, 207, 303, 399, 47, 143, 239, 335, 431, 79, 175, 271, 367, 463,
+23, 119, 215, 311, 407, 55, 151, 247, 343, 439, 87, 183, 279, 375, 471,
+31, 127, 223, 319, 415, 63, 159, 255, 351, 447, 95, 191, 287, 383, 479,
+};
+#endif
+
+#ifndef FFT_BITREV240
+#define FFT_BITREV240
+static const opus_int16 fft_bitrev240[240] = {
+0, 48, 96, 144, 192, 16, 64, 112, 160, 208, 32, 80, 128, 176, 224,
+4, 52, 100, 148, 196, 20, 68, 116, 164, 212, 36, 84, 132, 180, 228,
+8, 56, 104, 152, 200, 24, 72, 120, 168, 216, 40, 88, 136, 184, 232,
+12, 60, 108, 156, 204, 28, 76, 124, 172, 220, 44, 92, 140, 188, 236,
+1, 49, 97, 145, 193, 17, 65, 113, 161, 209, 33, 81, 129, 177, 225,
+5, 53, 101, 149, 197, 21, 69, 117, 165, 213, 37, 85, 133, 181, 229,
+9, 57, 105, 153, 201, 25, 73, 121, 169, 217, 41, 89, 137, 185, 233,
+13, 61, 109, 157, 205, 29, 77, 125, 173, 221, 45, 93, 141, 189, 237,
+2, 50, 98, 146, 194, 18, 66, 114, 162, 210, 34, 82, 130, 178, 226,
+6, 54, 102, 150, 198, 22, 70, 118, 166, 214, 38, 86, 134, 182, 230,
+10, 58, 106, 154, 202, 26, 74, 122, 170, 218, 42, 90, 138, 186, 234,
+14, 62, 110, 158, 206, 30, 78, 126, 174, 222, 46, 94, 142, 190, 238,
+3, 51, 99, 147, 195, 19, 67, 115, 163, 211, 35, 83, 131, 179, 227,
+7, 55, 103, 151, 199, 23, 71, 119, 167, 215, 39, 87, 135, 183, 231,
+11, 59, 107, 155, 203, 27, 75, 123, 171, 219, 43, 91, 139, 187, 235,
+15, 63, 111, 159, 207, 31, 79, 127, 175, 223, 47, 95, 143, 191, 239,
+};
+#endif
+
+#ifndef FFT_BITREV120
+#define FFT_BITREV120
+static const opus_int16 fft_bitrev120[120] = {
+0, 24, 48, 72, 96, 8, 32, 56, 80, 104, 16, 40, 64, 88, 112,
+4, 28, 52, 76, 100, 12, 36, 60, 84, 108, 20, 44, 68, 92, 116,
+1, 25, 49, 73, 97, 9, 33, 57, 81, 105, 17, 41, 65, 89, 113,
+5, 29, 53, 77, 101, 13, 37, 61, 85, 109, 21, 45, 69, 93, 117,
+2, 26, 50, 74, 98, 10, 34, 58, 82, 106, 18, 42, 66, 90, 114,
+6, 30, 54, 78, 102, 14, 38, 62, 86, 110, 22, 46, 70, 94, 118,
+3, 27, 51, 75, 99, 11, 35, 59, 83, 107, 19, 43, 67, 91, 115,
+7, 31, 55, 79, 103, 15, 39, 63, 87, 111, 23, 47, 71, 95, 119,
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_0
+#define FFT_STATE96000_1920_0
+static const kiss_fft_state fft_state96000_1920_0 = {
+960, /* nfft */
+#ifdef ENABLE_QEXT
+572662306, /* scale */
+#else
+17476, /* scale */
+#endif
+9, /* scale_shift */
+-1, /* shift */
+{5, 192, 3, 64, 4, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev960, /* bitrev */
+fft_twiddles96000_1920, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_960,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_1
+#define FFT_STATE96000_1920_1
+static const kiss_fft_state fft_state96000_1920_1 = {
+480, /* nfft */
+#ifdef ENABLE_QEXT
+572662306, /* scale */
+#else
+17476, /* scale */
+#endif
+8, /* scale_shift */
+1, /* shift */
+{5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev480, /* bitrev */
+fft_twiddles96000_1920, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_480,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_2
+#define FFT_STATE96000_1920_2
+static const kiss_fft_state fft_state96000_1920_2 = {
+240, /* nfft */
+#ifdef ENABLE_QEXT
+572662306, /* scale */
+#else
+17476, /* scale */
+#endif
+7, /* scale_shift */
+2, /* shift */
+{5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev240, /* bitrev */
+fft_twiddles96000_1920, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_240,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_3
+#define FFT_STATE96000_1920_3
+static const kiss_fft_state fft_state96000_1920_3 = {
+120, /* nfft */
+#ifdef ENABLE_QEXT
+572662306, /* scale */
+#else
+17476, /* scale */
+#endif
+6, /* scale_shift */
+3, /* shift */
+{5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev120, /* bitrev */
+fft_twiddles96000_1920, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_120,
+#else
+NULL,
+#endif
+};
+#endif
+
+#endif
+
+#ifndef MDCT_TWIDDLES1920
+#define MDCT_TWIDDLES1920
+static const celt_coef mdct_twiddles1920[3600] = {
+#ifdef ENABLE_QEXT
+2147483603, 2147480010, 2147470667, 2147455575, 2147434733,
+2147408142, 2147375802, 2147337712, 2147293874, 2147244286,
+2147188950, 2147127865, 2147061032, 2146988450, 2146910120,
+2146826042, 2146736216, 2146640643, 2146539323, 2146432256,
+2146319442, 2146200882, 2146076576, 2145946524, 2145810727,
+2145669185, 2145521898, 2145368867, 2145210092, 2145045574,
+2144875313, 2144699310, 2144517564, 2144330077, 2144136849,
+2143937880, 2143733172, 2143522724, 2143306537, 2143084612,
+2142856949, 2142623549, 2142384413, 2142139541, 2141888933,
+2141632592, 2141370516, 2141102708, 2140829167, 2140549894,
+2140264890, 2139974157, 2139677694, 2139375502, 2139067583,
+2138753936, 2138434564, 2138109466, 2137778644, 2137442099,
+2137099831, 2136751841, 2136398131, 2136038701, 2135673552,
+2135302685, 2134926101, 2134543801, 2134155787, 2133762059,
+2133362618, 2132957466, 2132546603, 2132130030, 2131707749,
+2131279761, 2130846067, 2130406668, 2129961565, 2129510759,
+2129054253, 2128592046, 2128124140, 2127650537, 2127171237,
+2126686242, 2126195553, 2125699172, 2125197100, 2124689338,
+2124175888, 2123656750, 2123131927, 2122601420, 2122065230,
+2121523358, 2120975806, 2120422576, 2119863669, 2119299086,
+2118728830, 2118152901, 2117571301, 2116984031, 2116391094,
+2115792491, 2115188222, 2114578291, 2113962699, 2113341447,
+2112714537, 2112081970, 2111443749, 2110799875, 2110150349,
+2109495174, 2108834352, 2108167883, 2107495770, 2106818015,
+2106134619, 2105445584, 2104750913, 2104050606, 2103344666,
+2102633095, 2101915895, 2101193067, 2100464614, 2099730537,
+2098990838, 2098245520, 2097494584, 2096738032, 2095975867,
+2095208091, 2094434705, 2093655711, 2092871112, 2092080910,
+2091285107, 2090483704, 2089676705, 2088864111, 2088045925,
+2087222148, 2086392783, 2085557833, 2084717298, 2083871182,
+2083019487, 2082162216, 2081299369, 2080430950, 2079556962,
+2078677406, 2077792284, 2076901600, 2076005355, 2075103552,
+2074196194, 2073283282, 2072364819, 2071440808, 2070511251,
+2069576151, 2068635510, 2067689330, 2066737615, 2065780367,
+2064817587, 2063849280, 2062875447, 2061896091, 2060911215,
+2059920821, 2058924912, 2057923491, 2056916560, 2055904122,
+2054886179, 2053862736, 2052833793, 2051799354, 2050759422,
+2049714000, 2048663090, 2047606695, 2046544818, 2045477461,
+2044404629, 2043326323, 2042242546, 2041153301, 2040058592,
+2038958421, 2037852791, 2036741705, 2035625166, 2034503177,
+2033375742, 2032242862, 2031104541, 2029960782, 2028811589,
+2027656964, 2026496910, 2025331431, 2024160529, 2022984208,
+2021802471, 2020615320, 2019422760, 2018224794, 2017021424,
+2015812654, 2014598487, 2013378926, 2012153975, 2010923636,
+2009687914, 2008446811, 2007200332, 2005948478, 2004691253,
+2003428662, 2002160707, 2000887391, 1999608718, 1998324692,
+1997035316, 1995740593, 1994440527, 1993135121, 1991824379,
+1990508304, 1989186900, 1987860170, 1986528118, 1985190748,
+1983848063, 1982500066, 1981146762, 1979788153, 1978424244,
+1977055038, 1975680539, 1974300751, 1972915676, 1971525320,
+1970129685, 1968728776, 1967322596, 1965911148, 1964494438,
+1963072467, 1961645241, 1960212764, 1958775038, 1957332067,
+1955883857, 1954430410, 1952971730, 1951507822, 1950038689,
+1948564335, 1947084764, 1945599980, 1944109987, 1942614790,
+1941114391, 1939608795, 1938098007, 1936582029, 1935060867,
+1933534524, 1932003004, 1930466312, 1928924452, 1927377427,
+1925825242, 1924267900, 1922705408, 1921137767, 1919564983,
+1917987059, 1916404001, 1914815812, 1913222496, 1911624058,
+1910020502, 1908411833, 1906798054, 1905179170, 1903555185,
+1901926103, 1900291930, 1898652669, 1897008325, 1895358902,
+1893704404, 1892044837, 1890380204, 1888710510, 1887035759,
+1885355956, 1883671105, 1881981211, 1880286279, 1878586312,
+1876881316, 1875171295, 1873456254, 1871736196, 1870011128,
+1868281053, 1866545976, 1864805901, 1863060834, 1861310779,
+1859555741, 1857795724, 1856030734, 1854260774, 1852485850,
+1850705966, 1848921127, 1847131338, 1845336604, 1843536929,
+1841732318, 1839922777, 1838108310, 1836288921, 1834464616,
+1832635400, 1830801277, 1828962253, 1827118332, 1825269519,
+1823415819, 1821557238, 1819693779, 1817825449, 1815952252,
+1814074193, 1812191278, 1810303510, 1808410896, 1806513440,
+1804611147, 1802704023, 1800792073, 1798875302, 1796953714,
+1795027315, 1793096111, 1791160105, 1789219305, 1787273714,
+1785323338, 1783368182, 1781408251, 1779443552, 1777474088,
+1775499865, 1773520888, 1771537164, 1769548696, 1767555491,
+1765557554, 1763554889, 1761547504, 1759535401, 1757518588,
+1755497070, 1753470852, 1751439939, 1749404337, 1747364051,
+1745319087, 1743269451, 1741215147, 1739156181, 1737092559,
+1735024287, 1732951369, 1730873811, 1728791620, 1726704800,
+1724613357, 1722517297, 1720416625, 1718311347, 1716201468,
+1714086995, 1711967933, 1709844287, 1707716063, 1705583268,
+1703445906, 1701303983, 1699157505, 1697006479, 1694850909,
+1692690801, 1690526161, 1688356996, 1686183310, 1684005110,
+1681822401, 1679635189, 1677443481, 1675247281, 1673046596,
+1670841433, 1668631795, 1666417691, 1664199124, 1661976103,
+1659748631, 1657516716, 1655280364, 1653039579, 1650794369,
+1648544739, 1646290696, 1644032245, 1641769393, 1639502145,
+1637230507, 1634954486, 1632674088, 1630389319, 1628100184,
+1625806691, 1623508845, 1621206653, 1618900119, 1616589252,
+1614274057, 1611954539, 1609630706, 1607302564, 1604970118,
+1602633375, 1600292342, 1597947024, 1595597428, 1593243560,
+1590885426, 1588523033, 1586156387, 1583785495, 1581410362,
+1579030995, 1576647401, 1574259586, 1571867556, 1569471317,
+1567070877, 1564666241, 1562257416, 1559844408, 1557427224,
+1555005871, 1552580354, 1550150681, 1547716857, 1545278889,
+1542836785, 1540390550, 1537940190, 1535485713, 1533027126,
+1530564434, 1528097644, 1525626762, 1523151797, 1520672753,
+1518189638, 1515702459, 1513211221, 1510715932, 1508216599,
+1505713227, 1503205824, 1500694397, 1498178952, 1495659496,
+1493136035, 1490608577, 1488077129, 1485541696, 1483002286,
+1480458905, 1477911561, 1475360260, 1472805009, 1470245815,
+1467682684, 1465115624, 1462544642, 1459969744, 1457390937,
+1454808228, 1452221624, 1449631133, 1447036760, 1444438513,
+1441836399, 1439230424, 1436620597, 1434006923, 1431389409,
+1428768064, 1426142893, 1423513904, 1420881104, 1418244500,
+1415604099, 1412959907, 1410311933, 1407660183, 1405004664,
+1402345384, 1399682349, 1397015567, 1394345044, 1391670789,
+1388992807, 1386311107, 1383625695, 1380936579, 1378243766,
+1375547262, 1372847076, 1370143215, 1367435685, 1364724494,
+1362009649, 1359291158, 1356569027, 1353843265, 1351113878,
+1348380873, 1345644259, 1342904042, 1340160229, 1337412829,
+1334661848, 1331907293, 1329149173, 1326387494, 1323622264,
+1320853490, 1318081180, 1315305341, 1312525981, 1309743106,
+1306956725, 1304166845, 1301373473, 1298576617, 1295776285,
+1292972483, 1290165219, 1287354501, 1284540337, 1281722734,
+1278901699, 1276077240, 1273249364, 1270418080, 1267583394,
+1264745315, 1261903850, 1259059006, 1256210791, 1253359213,
+1250504279, 1247645998, 1244784376, 1241919421, 1239051142,
+1236179545, 1233304638, 1230426430, 1227544927, 1224660138,
+1221772070, 1218880731, 1215986128, 1213088271, 1210187165,
+1207282819, 1204375241, 1201464439, 1198550419, 1195633191,
+1192712762, 1189789140, 1186862332, 1183932347, 1180999192,
+1178062875, 1175123404, 1172180786, 1169235031, 1166286145,
+1163334137, 1160379014, 1157420784, 1154459456, 1151495036,
+1148527534, 1145556957, 1142583313, 1139606610, 1136626856,
+1133644058, 1130658226, 1127669367, 1124677488, 1121682598,
+1118684705, 1115683818, 1112679943, 1109673089, 1106663264,
+1103650476, 1100634734, 1097616045, 1094594417, 1091569858,
+1088542378, 1085511982, 1082478681, 1079442481, 1076403392,
+1073361420, 1070316575, 1067268864, 1064218296, 1061164879,
+1058108621, 1055049529, 1051987613, 1048922881, 1045855340,
+1042784999, 1039711867, 1036635950, 1033557259, 1030475800,
+1027391582, 1024304614, 1021214903, 1018122458, 1015027288,
+1011929400, 1008828802, 1005725504, 1002619513, 999510838,
+996399486, 993285468, 990168789, 987049460, 983927488,
+980802882, 977675650, 974545800, 971413342, 968278282,
+965140630, 962000395, 958857583, 955712205, 952564267,
+949413780, 946260750, 943105188, 939947100, 936786495,
+933623383, 930457771, 927289668, 924119082, 920946022,
+917770497, 914592514, 911412082, 908229211, 905043908,
+901856182, 898666041, 895473494, 892278550, 889081217,
+885881504, 882679419, 879474970, 876268167, 873059018,
+869847532, 866633717, 863417581, 860199134, 856978384,
+853755339, 850530009, 847302402, 844072526, 840840390,
+837606003, 834369373, 831130510, 827889422, 824646117,
+821400604, 818152892, 814902989, 811650905, 808396648,
+805140227, 801881649, 798620925, 795358063, 792093072,
+788825960, 785556735, 782285408, 779011986, 775736479,
+772458895, 769179242, 765897531, 762613768, 759327964,
+756040127, 752750266, 749458390, 746164507, 742868626,
+739570757, 736270907, 732969086, 729665303, 726359567,
+723051885, 719742268, 716430724, 713117261, 709801890,
+706484618, 703165455, 699844409, 696521489, 693196705,
+689870064, 686541577, 683211252, 679879097, 676545122,
+673209336, 669871748, 666532366, 663191199, 659848257,
+656503549, 653157082, 649808867, 646458913, 643107227,
+639753820, 636398700, 633041876, 629683357, 626323153,
+622961271, 619597722, 616232514, 612865656, 609497157,
+606127026, 602755273, 599381905, 596006934, 592630366,
+589252212, 585872480, 582491179, 579108320, 575723909,
+572337957, 568950473, 565561466, 562170945, 558778918,
+555385395, 551990386, 548593898, 545195942, 541796526,
+538395660, 534993352, 531589612, 528184449, 524777871,
+521369889, 517960510, 514549745, 511137603, 507724092,
+504309221, 500893000, 497475439, 494056545, 490636329,
+487214799, 483791965, 480367835, 476942419, 473515727,
+470087766, 466658548, 463228079, 459796371, 456363431,
+452929270, 449493896, 446057319, 442619547, 439180590,
+435740458, 432299159, 428856702, 425413098, 421968354,
+418522481, 415075487, 411627382, 408178175, 404727875,
+401276491, 397824033, 394370510, 390915931, 387460306,
+384003643, 380545952, 377087242, 373627523, 370166803,
+366705093, 363242400, 359778735, 356314107, 352848525,
+349381998, 345914536, 342446148, 338976842, 335506630,
+332035519, 328563519, 325090639, 321616889, 318142278,
+314666815, 311190510, 307713372, 304235410, 300756633,
+297277051, 293796673, 290315508, 286833567, 283350857,
+279867389, 276383171, 272898214, 269412525, 265926116,
+262438995, 258951170, 255462653, 251973452, 248483576,
+244993035, 241501838, 238009994, 234517513, 231024404,
+227530677, 224036341, 220541404, 217045878, 213549770,
+210053090, 206555848, 203058053, 199559715, 196060842,
+192561444, 189061531, 185561111, 182060195, 178558791,
+175056909, 171554559, 168051749, 164548489, 161044789,
+157540658, 154036105, 150531139, 147025770, 143520008,
+140013862, 136507340, 133000453, 129493210, 125985621,
+122477694, 118969439, 115460866, 111951983, 108442801,
+104933329, 101423575, 97913550, 94403263, 90892723,
+87381940, 83870923, 80359681, 76848224, 73336562,
+69824703, 66312657, 62800433, 59288042, 55775491,
+52262792, 48749952, 45236982, 41723891, 38210688,
+34697383, 31183985, 27670503, 24156947, 20643327,
+17129651, 13615930, 10102172, 6588387, 3074584,
+-439226, -3953036, -7466835, -10980614, -14494364,
+-18008075, -21521738, -25035343, -28548881, -32062342,
+-35575718, -39088999, -42602174, -46115236, -49628175,
+-53140980, -56653643, -60166155, -63678505, -67190685,
+-70702685, -74214496, -77726108, -81237512, -84748698,
+-88259658, -91770381, -95280859, -98791081, -102301039,
+-105810723, -109320124, -112829232, -116338038, -119846533,
+-123354707, -126862550, -130370054, -133877209, -137384005,
+-140890434, -144396485, -147902150, -151407418, -154912282,
+-158416730, -161920755, -165424346, -168927494, -172430190,
+-175932424, -179434187, -182935470, -186436263, -189936557,
+-193436342, -196935610, -200434350, -203932553, -207430211,
+-210927313, -214423851, -217919814, -221415194, -224909981,
+-228404166, -231897740, -235390693, -238883015, -242374698,
+-245865732, -249356108, -252845816, -256334847, -259823192,
+-263310841, -266797785, -270284015, -273769522, -277254295,
+-280738326, -284221606, -287704124, -291185873, -294666841,
+-298147021, -301626403, -305104977, -308582734, -312059665,
+-315535760, -319011011, -322485408, -325958941, -329431602,
+-332903380, -336374268, -339844254, -343313331, -346781489,
+-350248718, -353715010, -357180354, -360644742, -364108165,
+-367570613, -371032077, -374492547, -377952015, -381410471,
+-384867905, -388324310, -391779674, -395233990, -398687248,
+-402139438, -405590552, -409040579, -412489512, -415937340,
+-419384055, -422829646, -426274106, -429717424, -433159592,
+-436600601, -440040440, -443479101, -446916575, -450352853,
+-453787924, -457221781, -460654414, -464085813, -467515970,
+-470944875, -474372519, -477798893, -481223988, -484647795,
+-488070304, -491491506, -494911393, -498329954, -501747182,
+-505163066, -508577597, -511990767, -515402566, -518812985,
+-522222016, -525629648, -529035873, -532440681, -535844064,
+-539246012, -542646517, -546045568, -549443158, -552839277,
+-556233916, -559627065, -563018716, -566408860, -569797488,
+-573184589, -576570157, -579954180, -583336651, -586717560,
+-590096899, -593474657, -596850827, -600225398, -603598363,
+-606969711, -610339435, -613707524, -617073971, -620438765,
+-623801898, -627163361, -630523145, -633881241, -637237640,
+-640592333, -643945310, -647296564, -650646085, -653993863,
+-657339891, -660684159, -664026658, -667367379, -670706313,
+-674043452, -677378786, -680712307, -684044005, -687373872,
+-690701898, -694028075, -697352394, -700674846, -703995422,
+-707314114, -710630911, -713945806, -717258790, -720569853,
+-723878987, -727186183, -730491433, -733794726, -737096055,
+-740395410, -743692783, -746988165, -750281547, -753572921,
+-756862277, -760149606, -763434901, -766718151, -769999349,
+-773278485, -776555551, -779830538, -783103437, -786374239,
+-789642936, -792909519, -796173979, -799436307, -802696495,
+-805954534, -809210416, -812464130, -815715670, -818965026,
+-822212189, -825457150, -828699902, -831940435, -835178741,
+-838414810, -841648635, -844880207, -848109516, -851336555,
+-854561315, -857783787, -861003962, -864221832, -867437388,
+-870650622, -873861525, -877070088, -880276304, -883480162,
+-886681655, -889880774, -893077511, -896271856, -899463802,
+-902653340, -905840461, -909025157, -912207419, -915387239,
+-918564609, -921739519, -924911961, -928081927, -931249408,
+-934414396, -937576882, -940736858, -943894315, -947049246,
+-950201640, -953351491, -956498790, -959643527, -962785695,
+-965925286, -969062291, -972196701, -975328508, -978457704,
+-981584280, -984708228, -987829540, -990948208, -994064222,
+-997177575, -1000288258, -1003396263, -1006501581, -1009604205,
+-1012704126, -1015801336, -1018895826, -1021987588, -1025076613,
+-1028162895, -1031246424, -1034327191, -1037405190, -1040480411,
+-1043552847, -1046622488, -1049689328, -1052753357, -1055814567,
+-1058872951, -1061928500, -1064981206, -1068031060, -1071078055,
+-1074122183, -1077163435, -1080201802, -1083237278, -1086269854,
+-1089299521, -1092326272, -1095350099, -1098370993, -1101388946,
+-1104403951, -1107415998, -1110425081, -1113431191, -1116434320,
+-1119434460, -1122431603, -1125425740, -1128416865, -1131404968,
+-1134390043, -1137372080, -1140351072, -1143327011, -1146299889,
+-1149269698, -1152236431, -1155200078, -1158160632, -1161118086,
+-1164072431, -1167023660, -1169971764, -1172916735, -1175858567,
+-1178797250, -1181732777, -1184665141, -1187594332, -1190520344,
+-1193443169, -1196362799, -1199279225, -1202192441, -1205102438,
+-1208009209, -1210912745, -1213813040, -1216710085, -1219603872,
+-1222494394, -1225381643, -1228265611, -1231146291, -1234023675,
+-1236897754, -1239768523, -1242635972, -1245500094, -1248360882,
+-1251218327, -1254072422, -1256923160, -1259770533, -1262614533,
+-1265455153, -1268292384, -1271126220, -1273956653, -1276783675,
+-1279607279, -1282427457, -1285244201, -1288057504, -1290867359,
+-1293673758, -1296476693, -1299276157, -1302072143, -1304864643,
+-1307653649, -1310439154, -1313221151, -1315999631, -1318774589,
+-1321546016, -1324313904, -1327078247, -1329839037, -1332596266,
+-1335349928, -1338100015, -1340846519, -1343589433, -1346328751,
+-1349064463, -1351796564, -1354525046, -1357249901, -1359971122,
+-1362688702, -1365402634, -1368112911, -1370819524, -1373522468,
+-1376221734, -1378917315, -1381609205, -1384297396, -1386981880,
+-1389662652, -1392339702, -1395013025, -1397682613, -1400348459,
+-1403010556, -1405668897, -1408323474, -1410974281, -1413621310,
+-1416264555, -1418904007, -1421539661, -1424171509, -1426799544,
+-1429423759, -1432044147, -1434660701, -1437273414, -1439882279,
+-1442487289, -1445088437, -1447685717, -1450279120, -1452868640,
+-1455454271, -1458036005, -1460613835, -1463187755, -1465757757,
+-1468323835, -1470885982, -1473444191, -1475998456, -1478548768,
+-1481095122, -1483637511, -1486175927, -1488710365, -1491240816,
+-1493767276, -1496289736, -1498808190, -1501322631, -1503833053,
+-1506339448, -1508841811, -1511340134, -1513834411, -1516324634,
+-1518810798, -1521292896, -1523770921, -1526244866, -1528714725,
+-1531180491, -1533642158, -1536099718, -1538553166, -1541002495,
+-1543447698, -1545888769, -1548325701, -1550758488, -1553187123,
+-1555611600, -1558031911, -1560448052, -1562860014, -1565267793,
+-1567671380, -1570070771, -1572465958, -1574856935, -1577243696,
+-1579626234, -1582004542, -1584378616, -1586748447, -1589114030,
+-1591475359, -1593832427, -1596185227, -1598533754, -1600878002,
+-1603217963, -1605553632, -1607885003, -1610212069, -1612534823,
+-1614853261, -1617167375, -1619477159, -1621782608, -1624083714,
+-1626380473, -1628672877, -1630960921, -1633244598, -1635523902,
+-1637798828, -1640069368, -1642335518, -1644597271, -1646854620,
+-1649107561, -1651356086, -1653600190, -1655839867, -1658075111,
+-1660305916, -1662532275, -1664754184, -1666971635, -1669184624,
+-1671393143, -1673597188, -1675796752, -1677991829, -1680182414,
+-1682368500, -1684550083, -1686727155, -1688899711, -1691067746,
+-1693231253, -1695390227, -1697544662, -1699694551, -1701839891,
+-1703980674, -1706116895, -1708248548, -1710375628, -1712498128,
+-1714616044, -1716729369, -1718838098, -1720942225, -1723041744,
+-1725136651, -1727226938, -1729312602, -1731393635, -1733470033,
+-1735541790, -1737608901, -1739671359, -1741729160, -1743782298,
+-1745830767, -1747874561, -1749913677, -1751948107, -1753977847,
+-1756002891, -1758023233, -1760038869, -1762049792, -1764055998,
+-1766057481, -1768054236, -1770046258, -1772033540, -1774016078,
+-1775993866, -1777966900, -1779935173, -1781898681, -1783857419,
+-1785811380, -1787760560, -1789704954, -1791644556, -1793579362,
+-1795509366, -1797434562, -1799354946, -1801270513, -1803181257,
+-1805087174, -1806988258, -1808884503, -1810775906, -1812662462,
+-1814544164, -1816421007, -1818292988, -1820160101, -1822022340,
+-1823879702, -1825732180, -1827579771, -1829422468, -1831260267,
+-1833093164, -1834921153, -1836744229, -1838562388, -1840375624,
+-1842183933, -1843987310, -1845785751, -1847579249, -1849367801,
+-1851151401, -1852930046, -1854703729, -1856472447, -1858236195,
+-1859994968, -1861748761, -1863497569, -1865241388, -1866980214,
+-1868714041, -1870442864, -1872166681, -1873885484, -1875599271,
+-1877308036, -1879011776, -1880710484, -1882404157, -1884092791,
+-1885776380, -1887454920, -1889128407, -1890796837, -1892460204,
+-1894118504, -1895771734, -1897419887, -1899062961, -1900700951,
+-1902333851, -1903961659, -1905584369, -1907201977, -1908814479,
+-1910421871, -1912024148, -1913621306, -1915213340, -1916800247,
+-1918382022, -1919958661, -1921530159, -1923096514, -1924657719,
+-1926213771, -1927764667, -1929310401, -1930850970, -1932386369,
+-1933916595, -1935441643, -1936961510, -1938476190, -1939985681,
+-1941489978, -1942989077, -1944482974, -1945971664, -1947455145,
+-1948933412, -1950406461, -1951874289, -1953336890, -1954794262,
+-1956246401, -1957693301, -1959134961, -1960571375, -1962002540,
+-1963428453, -1964849109, -1966264504, -1967674635, -1969079498,
+-1970479089, -1971873404, -1973262440, -1974646194, -1976024660,
+-1977397836, -1978765718, -1980128302, -1981485585, -1982837563,
+-1984184232, -1985525589, -1986861630, -1988192351, -1989517750,
+-1990837822, -1992152564, -1993461973, -1994766044, -1996064775,
+-1997358161, -1998646200, -1999928888, -2001206222, -2002478198,
+-2003744813, -2005006063, -2006261945, -2007512455, -2008757591,
+-2009997349, -2011231726, -2012460718, -2013684322, -2014902534,
+-2016115352, -2017322773, -2018524792, -2019721407, -2020912615,
+-2022098413, -2023278796, -2024453763, -2025623309, -2026787432,
+-2027946129, -2029099397, -2030247232, -2031389631, -2032526592,
+-2033658111, -2034784185, -2035904812, -2037019988, -2038129710,
+-2039233976, -2040332782, -2041426125, -2042514003, -2043596412,
+-2044673350, -2045744814, -2046810801, -2047871308, -2048926332,
+-2049975870, -2051019920, -2052058479, -2053091544, -2054119112,
+-2055141181, -2056157747, -2057168809, -2058174363, -2059174406,
+-2060168936, -2061157951, -2062141448, -2063119423, -2064091875,
+-2065058800, -2066020197, -2066976063, -2067926394, -2068871190,
+-2069810446, -2070744160, -2071672331, -2072594955, -2073512030,
+-2074423554, -2075329524, -2076229937, -2077124792, -2078014086,
+-2078897817, -2079775981, -2080648577, -2081515603, -2082377056,
+-2083232934, -2084083234, -2084927955, -2085767094, -2086600648,
+-2087428616, -2088250996, -2089067784, -2089878979, -2090684580,
+-2091484582, -2092278986, -2093067787, -2093850985, -2094628577,
+-2095400561, -2096166935, -2096927697, -2097682844, -2098432376,
+-2099176290, -2099914583, -2100647254, -2101374302, -2102095723,
+-2102811516, -2103521679, -2104226211, -2104925109, -2105618372,
+-2106305997, -2106987983, -2107664327, -2108335029, -2109000087,
+-2109659498, -2110313260, -2110961373, -2111603834, -2112240642,
+-2112871795, -2113497290, -2114117128, -2114731305, -2115339820,
+-2115942673, -2116539860, -2117131380, -2117717232, -2118297415,
+-2118871926, -2119440764, -2120003928, -2120561416, -2121113227,
+-2121659358, -2122199810, -2122734579, -2123263666, -2123787068,
+-2124304784, -2124816812, -2125323152, -2125823801, -2126318759,
+-2126808025, -2127291596, -2127769472, -2128241651, -2128708132,
+-2129168914, -2129623995, -2130073375, -2130517052, -2130955025,
+-2131387293, -2131813854, -2132234708, -2132649854, -2133059289,
+-2133463014, -2133861027, -2134253326, -2134639912, -2135020783,
+-2135395937, -2135765375, -2136129094, -2136487095, -2136839375,
+-2137185934, -2137526772, -2137861886, -2138191277, -2138514944,
+-2138832885, -2139145099, -2139451587, -2139752346, -2140047377,
+-2140336678, -2140620249, -2140898089, -2141170197, -2141436573,
+-2141697215, -2141952123, -2142201296, -2142444735, -2142682437,
+-2142914403, -2143140631, -2143361122, -2143575874, -2143784887,
+-2143988161, -2144185694, -2144377487, -2144563539, -2144743849,
+-2144918417, -2145087242, -2145250325, -2145407663, -2145559258,
+-2145705109, -2145845215, -2145979576, -2146108191, -2146231061,
+-2146348185, -2146459562, -2146565192, -2146665076, -2146759212,
+-2146847600, -2146930241, -2147007134, -2147078279, -2147143675,
+-2147203323, -2147257222, -2147305372, -2147347773, -2147384426,
+-2147415329, -2147440482, -2147459887, -2147473542, -2147481447,
+2147483468, 2147469095, 2147431723, 2147371355, 2147287990,
+2147181629, 2147052273, 2146899924, 2146724584, 2146526254,
+2146304937, 2146060634, 2145793349, 2145503083, 2145189842,
+2144853627, 2144494442, 2144112292, 2143707180, 2143279110,
+2142828088, 2142354118, 2141857204, 2141337354, 2140794571,
+2140228862, 2139640233, 2139028690, 2138394240, 2137736889,
+2137056645, 2136353515, 2135627506, 2134878626, 2134106884,
+2133312286, 2132494843, 2131654563, 2130791454, 2129905526,
+2128996788, 2128065251, 2127110924, 2126133817, 2125133941,
+2124111307, 2123065925, 2121997806, 2120906963, 2119793407,
+2118657149, 2117498202, 2116316578, 2115112291, 2113885352,
+2112635775, 2111363574, 2110068761, 2108751352, 2107411359,
+2106048798, 2104663683, 2103256028, 2101825849, 2100373162,
+2098897981, 2097400322, 2095880202, 2094337637, 2092772643,
+2091185237, 2089575437, 2087943258, 2086288720, 2084611839,
+2082912633, 2081191122, 2079447322, 2077681253, 2075892934,
+2074082383, 2072249621, 2070394667, 2068517540, 2066618262,
+2064696851, 2062753329, 2060787717, 2058800036, 2056790306,
+2054758550, 2052704789, 2050629045, 2048531340, 2046411698,
+2044270140, 2042106689, 2039921369, 2037714204, 2035485216,
+2033234429, 2030961869, 2028667558, 2026351522, 2024013785,
+2021654373, 2019273310, 2016870623, 2014446336, 2012000477,
+2009533071, 2007044144, 2004533723, 2002001835, 1999448508,
+1996873768, 1994277643, 1991660161, 1989021350, 1986361238,
+1983679853, 1980977226, 1978253383, 1975508355, 1972742171,
+1969954860, 1967146453, 1964316979, 1961466469, 1958594953,
+1955702462, 1952789027, 1949854680, 1946899451, 1943923372,
+1940926475, 1937908793, 1934870357, 1931811201, 1928731356,
+1925630856, 1922509734, 1919368023, 1916205758, 1913022972,
+1909819698, 1906595972, 1903351828, 1900087301, 1896802425,
+1893497236, 1890171769, 1886826060, 1883460144, 1880074058,
+1876667838, 1873241521, 1869795142, 1866328740, 1862842350,
+1859336011, 1855809760, 1852263635, 1848697674, 1845111914,
+1841506395, 1837881155, 1834236233, 1830571667, 1826887497,
+1823183763, 1819460504, 1815717761, 1811955572, 1808173978,
+1804373021, 1800552740, 1796713177, 1792854372, 1788976368,
+1785079205, 1781162925, 1777227570, 1773273182, 1769299805,
+1765307479, 1761296249, 1757266156, 1753217244, 1749149557,
+1745063138, 1740958031, 1736834279, 1732691928, 1728531020,
+1724351602, 1720153717, 1715937410, 1711702727, 1707449714,
+1703178415, 1698888876, 1694581143, 1690255263, 1685911282,
+1681549245, 1677169201, 1672771196, 1668355276, 1663921490,
+1659469885, 1655000508, 1650513407, 1646008631, 1641486227,
+1636946244, 1632388731, 1627813736, 1623221309, 1618611498,
+1613984353, 1609339924, 1604678260, 1599999411, 1595303428,
+1590590360, 1585860258, 1581113173, 1576349155, 1571568256,
+1566770527, 1561956018, 1557124783, 1552276872, 1547412337,
+1542531231, 1537633606, 1532719513, 1527789007, 1522842139,
+1517878963, 1512899531, 1507903898, 1502892116, 1497864239,
+1492820322, 1487760417, 1482684580, 1477592864, 1472485325,
+1467362016, 1462222994, 1457068312, 1451898025, 1446712191,
+1441510863, 1436294098, 1431061951, 1425814478, 1420551737,
+1415273782, 1409980671, 1404672460, 1399349206, 1394010966,
+1388657798, 1383289758, 1377906904, 1372509294, 1367096986,
+1361670037, 1356228505, 1350772450, 1345301929, 1339817000,
+1334317724, 1328804158, 1323276361, 1317734393, 1312178313,
+1306608181, 1301024057, 1295425999, 1289814068, 1284188325,
+1278548828, 1272895640, 1267228820, 1261548429, 1255854528,
+1250147177, 1244426439, 1238692373, 1232945043, 1227184508,
+1221410831, 1215624074, 1209824299, 1204011567, 1198185941,
+1192347484, 1186496258, 1180632325, 1174755748, 1168866591,
+1162964917, 1157050787, 1151124267, 1145185419, 1139234307,
+1133270995, 1127295547, 1121308026, 1115308496, 1109297023,
+1103273670, 1097238502, 1091191583, 1085132978, 1079062753,
+1072980972, 1066887699, 1060783002, 1054666944, 1048539592,
+1042401010, 1036251266, 1030090423, 1023918550, 1017735711,
+1011541973, 1005337402, 999122065, 992896028, 986659358,
+980412122, 974154386, 967886217, 961607684, 955318852,
+949019790, 942710564, 936391243, 930061894, 923722585,
+917373383, 911014357, 904645574, 898267104, 891879014,
+885481373, 879074249, 872657710, 866231826, 859796666,
+853352298, 846898791, 840436214, 833964638, 827484130,
+820994760, 814496598, 807989714, 801474176, 794950056,
+788417422, 781876345, 775326894, 768769141, 762203154,
+755629005, 749046764, 742456501, 735858287, 729252193,
+722638289, 716016646, 709387335, 702750427, 696105993,
+689454104, 682794832, 676128248, 669454423, 662773428,
+656085336, 649390218, 642688145, 635979190, 629263424,
+622540918, 615811746, 609075979, 602333690, 595584950,
+588829831, 582068407, 575300749, 568526931, 561747023,
+554961100, 548169234, 541371497, 534567963, 527758704,
+520943793, 514123303, 507297307, 500465878, 493629090,
+486787016, 479939728, 473087301, 466229807, 459367320,
+452499914, 445627662, 438750638, 431868915, 424982567,
+418091668, 411196291, 404296511, 397392401, 390484035,
+383571488, 376654833, 369734144, 362809495, 355880961,
+348948616, 342012534, 335072790, 328129457, 321182610,
+314232323, 307278671, 300321729, 293361570, 286398270,
+279431902, 272462542, 265490265, 258515144, 251537254,
+244556671, 237573469, 230587722, 223599506, 216608896,
+209615966, 202620791, 195623446, 188624006, 181622546,
+174619141, 167613866, 160606796, 153598006, 146587571,
+139575567, 132562067, 125547148, 118530885, 111513352,
+104494625, 97474778, 90453888, 83432030, 76409277,
+69385707, 62361393, 55336412, 48310838, 41284746,
+34258213, 27231312, 20204120, 13176712, 6149162,
+-878453, -7906059, -14933580, -21960942, -28988068,
+-36014884, -43041314, -50067283, -57092716, -64117537,
+-71141672, -78165045, -85187581, -92209205, -99229841,
+-106249414, -113267850, -120285073, -127301007, -134315578,
+-141328711, -148340330, -155350361, -162358728, -169365356,
+-176370170, -183373096, -190374058, -197372981, -204369791,
+-211364411, -218356769, -225346788, -232334393, -239319511,
+-246302065, -253281982, -260259186, -267233603, -274205159,
+-281173778, -288139385, -295101907, -302061269, -309017396,
+-315970213, -322919647, -329865622, -336808065, -343746901,
+-350682056, -357613455, -364541025, -371464690, -378384377,
+-385300013, -392211522, -399118830, -406021865, -412920551,
+-419814815, -426704583, -433589782, -440470337, -447346176,
+-454217223, -461083406, -467944652, -474800886, -481652035,
+-488498026, -495338786, -502174241, -509004318, -515828944,
+-522648046, -529461551, -536269386, -543071478, -549867754,
+-556658141, -563442567, -570220959, -576993244, -583759350,
+-590519205, -597272736, -604019870, -610760536, -617494660,
+-624222173, -630943000, -637657070, -644364312, -651064652,
+-657758021, -664444345, -671123554, -677795576, -684460338,
+-691117771, -697767803, -704410362, -711045377, -717672778,
+-724292493, -730904451, -737508582, -744104815, -750693079,
+-757273304, -763845419, -770409354, -776965038, -783512402,
+-790051375, -796581887, -803103868, -809617249, -816121959,
+-822617929, -829105090, -835583372, -842052705, -848513021,
+-854964249, -861406322, -867839170, -874262724, -880676915,
+-887081675, -893476935, -899862626, -906238681, -912605031,
+-918961607, -925308342, -931645168, -937972016, -944288820,
+-950595511, -956892022, -963178285, -969454234, -975719800,
+-981974918, -988219519, -994453537, -1000676905, -1006889557,
+-1013091426, -1019282445, -1025462549, -1031631671, -1037789745,
+-1043936705, -1050072485, -1056197020, -1062310244, -1068412091,
+-1074502497, -1080581395, -1086648722, -1092704411, -1098748398,
+-1104780618, -1110801008, -1116809501, -1122806034, -1128790543,
+-1134762964, -1140723232, -1146671283, -1152607055, -1158530484,
+-1164441505, -1170340057, -1176226074, -1182099496, -1187960258,
+-1193808298, -1199643553, -1205465961, -1211275460, -1217071986,
+-1222855479, -1228625876, -1234383115, -1240127136, -1245857875,
+-1251575272, -1257279266, -1262969796, -1268646800, -1274310217,
+-1279959989, -1285596052, -1291218348, -1296826816, -1302421396,
+-1308002029, -1313568653, -1319121210, -1324659641, -1330183885,
+-1335693885, -1341189580, -1346670912, -1352137822, -1357590252,
+-1363028143, -1368451438, -1373860077, -1379254004, -1384633159,
+-1389997487, -1395346928, -1400681427, -1406000925, -1411305366,
+-1416594694, -1421868850, -1427127780, -1432371426, -1437599733,
+-1442812644, -1448010104, -1453192057, -1458358447, -1463509220,
+-1468644319, -1473763690, -1478867279, -1483955030, -1489026889,
+-1494082802, -1499122714, -1504146572, -1509154322, -1514145910,
+-1519121283, -1524080387, -1529023170, -1533949577, -1538859558,
+-1543753058, -1548630027, -1553490410, -1558334157, -1563161216,
+-1567971534, -1572765060, -1577541744, -1582301533, -1587044377,
+-1591770225, -1596479027, -1601170732, -1605845289, -1610502649,
+-1615142762, -1619765578, -1624371047, -1628959121, -1633529750,
+-1638082885, -1642618478, -1647136479, -1651636841, -1656119516,
+-1660584454, -1665031609, -1669460933, -1673872378, -1678265898,
+-1682641444, -1686998971, -1691338432, -1695659779, -1699962968,
+-1704247951, -1708514683, -1712763118, -1716993211, -1721204917,
+-1725398189, -1729572984, -1733729257, -1737866963, -1741986057,
+-1746086497, -1750168237, -1754231234, -1758275445, -1762300826,
+-1766307335, -1770294927, -1774263561, -1778213194, -1782143784,
+-1786055289, -1789947667, -1793820875, -1797674873, -1801509620,
+-1805325074, -1809121194, -1812897940, -1816655271, -1820393147,
+-1824111529, -1827810376, -1831489648, -1835149306, -1838789312,
+-1842409625, -1846010208, -1849591022, -1853152028, -1856693188,
+-1860214464, -1863715819, -1867197215, -1870658615, -1874099982,
+-1877521279, -1880922469, -1884303515, -1887664383, -1891005035,
+-1894325435, -1897625550, -1900905342, -1904164776, -1907403819,
+-1910622435, -1913820590, -1916998250, -1920155379, -1923291946,
+-1926407915, -1929503255, -1932577931, -1935631910, -1938665161,
+-1941677650, -1944669345, -1947640214, -1950590226, -1953519348,
+-1956427550, -1959314800, -1962181067, -1965026321, -1967850531,
+-1970653667, -1973435699, -1976196596, -1978936331, -1981654873,
+-1984352192, -1987028261, -1989683050, -1992316532, -1994928677,
+-1997519459, -2000088848, -2002636818, -2005163342, -2007668391,
+-2010151941, -2012613963, -2015054432, -2017473321, -2019870604,
+-2022246257, -2024600252, -2026932566, -2029243173, -2031532049,
+-2033799168, -2036044507, -2038268042, -2040469748, -2042649603,
+-2044807583, -2046943664, -2049057824, -2051150040, -2053220291,
+-2055268553, -2057294804, -2059299024, -2061281190, -2063241282,
+-2065179277, -2067095157, -2068988899, -2070860485, -2072709893,
+-2074537104, -2076342098, -2078124857, -2079885360, -2081623590,
+-2083339527, -2085033153, -2086704450, -2088353400, -2089979985,
+-2091584189, -2093165993, -2094725382, -2096262337, -2097776843,
+-2099268884, -2100738443, -2102185505, -2103610054, -2105012075,
+-2106391553, -2107748474, -2109082822, -2110394584, -2111683744,
+-2112950291, -2114194210, -2115415487, -2116614110, -2117790065,
+-2118943341, -2120073924, -2121181804, -2122266967, -2123329402,
+-2124369098, -2125386044, -2126380229, -2127351642, -2128300272,
+-2129226111, -2130129147, -2131009371, -2131866773, -2132701345,
+-2133513078, -2134301962, -2135067990, -2135811153, -2136531442,
+-2137228852, -2137903373, -2138555000, -2139183723, -2139789539,
+-2140372438, -2140932416, -2141469466, -2141983583, -2142474761,
+-2142942995, -2143388280, -2143810610, -2144209982, -2144586392,
+-2144939834, -2145270306, -2145577804, -2145862324, -2146123864,
+-2146362421, -2146577992, -2146770575, -2146940167, -2147086768,
+-2147210375, -2147310987, -2147388603, -2147443222, -2147474844,
+2147482929, 2147425435, 2147275952, 2147034487, 2146701050,
+2146275656, 2145758322, 2145149071, 2144447929, 2143654926,
+2142770096, 2141793477, 2140725111, 2139565043, 2138313323,
+2136970005, 2135535146, 2134008809, 2132391057, 2130681961,
+2128881593, 2126990031, 2125007356, 2122933653, 2120769010,
+2118513521, 2116167282, 2113730393, 2111202959, 2108585087,
+2105876892, 2103078487, 2100189994, 2097211535, 2094143239,
+2090985237, 2087737664, 2084400659, 2080974365, 2077458929,
+2073854502, 2070161238, 2066379295, 2062508835, 2058550025,
+2054503033, 2050368032, 2046145201, 2041834720, 2037436773,
+2032951550, 2028379241, 2023720043, 2018974156, 2014141783,
+2009223131, 2004218410, 1999127836, 1993951625, 1988690000,
+1983343186, 1977911412, 1972394912, 1966793920, 1961108677,
+1955339428, 1949486417, 1943549898, 1937530123, 1931427351,
+1925241843, 1918973864, 1912623682, 1906191570, 1899677803,
+1893082661, 1886406424, 1879649381, 1872811820, 1865894033,
+1858896318, 1851818974, 1844662304, 1837426615, 1830112217,
+1822719423, 1815248550, 1807699917, 1800073849, 1792370671,
+1784590714, 1776734311, 1768801799, 1760793518, 1752709809,
+1744551021, 1736317502, 1728009604, 1719627685, 1711172102,
+1702643219, 1694041400, 1685367013, 1676620432, 1667802029,
+1658912184, 1649951276, 1640919689, 1631817811, 1622646032,
+1613404744, 1604094343, 1594715227, 1585267800, 1575752465,
+1566169630, 1556519705, 1546803104, 1537020244, 1527171542,
+1517257422, 1507278307, 1497234626, 1487126808, 1476955286,
+1466720497, 1456422878, 1446062871, 1435640919, 1425157469,
+1414612971, 1404007875, 1393342636, 1382617710, 1371833558,
+1360990642, 1350089425, 1339130374, 1328113960, 1317040654,
+1305910930, 1294725265, 1283484138, 1272188032, 1260837429,
+1249432816, 1237974681, 1226463516, 1214899813, 1203284068,
+1191616778, 1179898443, 1168129565, 1156310649, 1144442200,
+1132524727, 1120558740, 1108544752, 1096483278, 1084374834,
+1072219940, 1060019115, 1047772882, 1035481766, 1023146293,
+1010766993, 998344394, 985879030, 973371434, 960822142,
+948231691, 935600622, 922929474, 910218791, 897469118,
+884680999, 871854984, 858991622, 846091463, 833155061,
+820182969, 807175743, 794133941, 781058120, 767948841,
+754806666, 741632158, 728425880, 715188400, 701920283,
+688622098, 675294414, 661937804, 648552838, 635140090,
+621700135, 608233549, 594740907, 581222789, 567679774,
+554112440, 540521371, 526907147, 513270353, 499611571,
+485931388, 472230390, 458509162, 444768294, 431008373,
+417229989, 403433732, 389620194, 375789965, 361943639,
+348081809, 334205068, 320314011, 306409232, 292491328,
+278560894, 264618528, 250664827, 236700388, 222725809,
+208741690, 194748629, 180747225, 166738079, 152721790,
+138698959, 124670187, 110636075, 96597223, 82554233,
+68507707, 54458246, 40406452, 26352928, 12298274,
+-1756906, -15812011, -29866438, -43919586, -57970853,
+-72019637, -86065335, -100107347, -114145071, -128177904,
+-142205248, -156226499, -170241059, -184248325, -198247699,
+-212238581, -226220372, -240192472, -254154282, -268105206,
+-282044645, -295972002, -309886680, -323788084, -337675619,
+-351548688, -365406698, -379249055, -393075166, -406884440,
+-420676284, -434450107, -448205320, -461941333, -475657559,
+-489353409, -503028296, -516681636, -530312842, -543921332,
+-557506522, -571067830, -584604676, -598116479, -611602660,
+-625062643, -638495850, -651901706, -665279637, -678629069,
+-691949432, -705240153, -718500664, -731730397, -744928785,
+-758095263, -771229267, -784330234, -797397602, -810430813,
+-823429308, -836392529, -849319923, -862210934, -875065011,
+-887881603, -900660162, -913400139, -926100989, -938762167,
+-951383133, -963963344, -976502263, -988999351, -1001454074,
+-1013865898, -1026234291, -1038558724, -1050838668, -1063073598,
+-1075262990, -1087406320, -1099503070, -1111552721, -1123554757,
+-1135508663, -1147413928, -1159270041, -1171076495, -1182832785,
+-1194538405, -1206192856, -1217795637, -1229346252, -1240844206,
+-1252289006, -1263680162, -1275017186, -1286299593, -1297526899,
+-1308698624, -1319814288, -1330873416, -1341875533, -1352820169,
+-1363706855, -1374535124, -1385304512, -1396014559, -1406664805,
+-1417254794, -1427784073, -1438252190, -1448658697, -1459003149,
+-1469285102, -1479504115, -1489659751, -1499751576, -1509779156,
+-1519742062, -1529639867, -1539472148, -1549238483, -1558938453,
+-1568571644, -1578137643, -1587636039, -1597066426, -1606428400,
+-1615721561, -1624945509, -1634099849, -1643184191, -1652198144,
+-1661141322, -1670013342, -1678813825, -1687542393, -1696198672,
+-1704782292, -1713292884, -1721730085, -1730093532, -1738382868,
+-1746597738, -1754737789, -1762802673, -1770792044, -1778705561,
+-1786542883, -1794303676, -1801987607, -1809594347, -1817123570,
+-1824574954, -1831948179, -1839242929, -1846458892, -1853595759,
+-1860653224, -1867630985, -1874528743, -1881346202, -1888083070,
+-1894739060, -1901313885, -1907807264, -1914218919, -1920548575,
+-1926795962, -1932960811, -1939042858, -1945041843, -1950957509,
+-1956789602, -1962537873, -1968202076, -1973781967, -1979277308,
+-1984687864, -1990013401, -1995253694, -2000408516, -2005477648,
+-2010460871, -2015357973, -2020168744, -2024892978, -2029530472,
+-2034081027, -2038544449, -2042920547, -2047209133, -2051410023,
+-2055523038, -2059548001, -2063484740, -2067333086, -2071092874,
+-2074763944, -2078346137, -2081839301, -2085243286, -2088557947,
+-2091783140, -2094918728, -2097964577, -2100920556, -2103786539,
+-2106562402, -2109248028, -2111843300, -2114348108, -2116762344,
+-2119085905, -2121318692, -2123460608, -2125511562, -2127471467,
+-2129340237, -2131117794, -2132804061, -2134398966, -2135902440,
+-2137314419, -2138634843, -2139863654, -2141000801, -2142046235,
+-2142999911, -2143861787, -2144631828, -2145310000, -2145896274,
+-2146390624, -2146793031, -2147103476, -2147321946, -2147448433,
+2147480773, 2147250799, 2146652904, 2145687192, 2144353827,
+2142653038, 2140585116, 2138150417, 2135349356, 2132182414,
+2128650133, 2124753120, 2120492040, 2115867626, 2110880668,
+2105532022, 2099822604, 2093753392, 2087325426, 2080539807,
+2073397699, 2065900325, 2058048970, 2049844978, 2041289756,
+2032384769, 2023131544, 2013531666, 2003586779, 1993298588,
+1982668856, 1971699403, 1960392110, 1948748914, 1936771810,
+1924462850, 1911824143, 1898857855, 1885566207, 1871951478,
+1858015999, 1843762158, 1829192399, 1814309216, 1799115162,
+1783612838, 1767804901, 1751694060, 1735283075, 1718574758,
+1701571972, 1684277631, 1666694698, 1648826185, 1630675154,
+1612244715, 1593538026, 1574558293, 1555308768, 1535792748,
+1516013578, 1495974647, 1475679389, 1455131280, 1434333842,
+1413290638, 1392005275, 1370481398, 1348722696, 1326732898,
+1304515771, 1282075122, 1259414796, 1236538675, 1213450681,
+1190154767, 1166654927, 1142955186, 1119059606, 1094972281,
+1070697338, 1046238936, 1021601267, 996788551, 971805042,
+946655018, 921342790, 895872694, 870249095, 844476384,
+818558976, 792501312, 766307857, 739983099, 713531549,
+686957739, 660266222, 633461572, 606548381, 579531262,
+552414843, 525203770, 497902707, 470516330, 443049333,
+415506422, 387892316, 360211746, 332469456, 304670200,
+276818739, 248919847, 220978304, 192998897, 164986421,
+136945676, 108881465, 80798598, 52701887, 24596146,
+-3513810, -31623164, -59727099, -87820801, -115899455,
+-143958250, -171992378, -199997036, -227967426, -255898755,
+-283786237, -311625094, -339410555, -367137861, -394802258,
+-422399009, -449923384, -477370666, -504736154, -532015158,
+-559203003, -586295032, -613286603, -640173090, -666949886,
+-693612404, -720156076, -746576352, -772868706, -799028633,
+-825051651, -850933300, -876669146, -902254780, -927685817,
+-952957899, -978066697, -1003007909, -1027777260, -1052370507,
+-1076783436, -1101011863, -1125051638, -1148898640, -1172548785,
+-1195998020, -1219242327, -1242277723, -1265100260, -1287706030,
+-1310091157, -1332251808, -1354184184, -1375884527, -1397349119,
+-1418574283, -1439556382, -1460291820, -1480777044, -1501008545,
+-1520982856, -1540696555, -1560146263, -1579328647, -1598240423,
+-1616878347, -1635239228, -1653319919, -1671117323, -1688628389,
+-1705850117, -1722779556, -1739413807, -1755750017, -1771785389,
+-1787517174, -1802942678, -1818059257, -1832864320, -1847355332,
+-1861529809, -1875385322, -1888919498, -1902130017, -1915014616,
+-1927571087, -1939797279, -1951691096, -1963250501, -1974473513,
+-1985358210, -1995902725, -2006105253, -2015964045, -2025477412,
+-2034643724, -2043461410, -2051928960, -2060044922, -2067807906,
+-2075216581, -2082269679, -2088965991, -2095304370, -2101283728,
+-2106903043, -2112161350, -2117057750, -2121591402, -2125761531,
+-2129567422, -2133008422, -2136083942, -2138793455, -2141136497,
+-2143112666, -2144721624, -2145963095, -2146836866, -2147342788,
+#else
+32767, 32767, 32767, 32767, 32767,
+32767, 32766, 32766, 32765, 32764,
+32764, 32763, 32762, 32760, 32759,
+32758, 32757, 32755, 32754, 32752,
+32750, 32748, 32747, 32745, 32742,
+32740, 32738, 32736, 32733, 32731,
+32728, 32726, 32723, 32720, 32717,
+32714, 32711, 32708, 32704, 32701,
+32697, 32694, 32690, 32686, 32683,
+32679, 32675, 32671, 32666, 32662,
+32658, 32653, 32649, 32644, 32640,
+32635, 32630, 32625, 32620, 32615,
+32610, 32604, 32599, 32593, 32588,
+32582, 32576, 32571, 32565, 32559,
+32553, 32546, 32540, 32534, 32527,
+32521, 32514, 32507, 32501, 32494,
+32487, 32480, 32473, 32465, 32458,
+32451, 32443, 32436, 32428, 32420,
+32412, 32404, 32396, 32388, 32380,
+32372, 32364, 32355, 32347, 32338,
+32329, 32320, 32312, 32303, 32294,
+32284, 32275, 32266, 32257, 32247,
+32237, 32228, 32218, 32208, 32198,
+32188, 32178, 32168, 32158, 32147,
+32137, 32127, 32116, 32105, 32094,
+32084, 32073, 32062, 32051, 32039,
+32028, 32017, 32005, 31994, 31982,
+31970, 31959, 31947, 31935, 31923,
+31910, 31898, 31886, 31874, 31861,
+31848, 31836, 31823, 31810, 31797,
+31784, 31771, 31758, 31745, 31732,
+31718, 31705, 31691, 31677, 31664,
+31650, 31636, 31622, 31608, 31593,
+31579, 31565, 31550, 31536, 31521,
+31507, 31492, 31477, 31462, 31447,
+31432, 31417, 31401, 31386, 31371,
+31355, 31339, 31324, 31308, 31292,
+31276, 31260, 31244, 31228, 31212,
+31195, 31179, 31162, 31146, 31129,
+31112, 31095, 31078, 31061, 31044,
+31027, 31010, 30992, 30975, 30957,
+30940, 30922, 30904, 30886, 30868,
+30850, 30832, 30814, 30796, 30777,
+30759, 30740, 30722, 30703, 30684,
+30665, 30646, 30627, 30608, 30589,
+30570, 30551, 30531, 30512, 30492,
+30472, 30453, 30433, 30413, 30393,
+30373, 30353, 30332, 30312, 30292,
+30271, 30251, 30230, 30209, 30188,
+30167, 30146, 30125, 30104, 30083,
+30062, 30040, 30019, 29997, 29976,
+29954, 29932, 29910, 29889, 29867,
+29844, 29822, 29800, 29778, 29755,
+29733, 29710, 29687, 29665, 29642,
+29619, 29596, 29573, 29550, 29527,
+29503, 29480, 29457, 29433, 29409,
+29386, 29362, 29338, 29314, 29290,
+29266, 29242, 29218, 29193, 29169,
+29145, 29120, 29095, 29071, 29046,
+29021, 28996, 28971, 28946, 28921,
+28896, 28870, 28845, 28819, 28794,
+28768, 28743, 28717, 28691, 28665,
+28639, 28613, 28587, 28560, 28534,
+28508, 28481, 28455, 28428, 28401,
+28375, 28348, 28321, 28294, 28267,
+28240, 28212, 28185, 28158, 28130,
+28103, 28075, 28047, 28020, 27992,
+27964, 27936, 27908, 27880, 27851,
+27823, 27795, 27766, 27738, 27709,
+27681, 27652, 27623, 27594, 27565,
+27536, 27507, 27478, 27449, 27419,
+27390, 27360, 27331, 27301, 27272,
+27242, 27212, 27182, 27152, 27122,
+27092, 27062, 27032, 27001, 26971,
+26940, 26910, 26879, 26848, 26818,
+26787, 26756, 26725, 26694, 26663,
+26631, 26600, 26569, 26537, 26506,
+26474, 26443, 26411, 26379, 26347,
+26316, 26284, 26251, 26219, 26187,
+26155, 26123, 26090, 26058, 26025,
+25993, 25960, 25927, 25894, 25861,
+25828, 25795, 25762, 25729, 25696,
+25663, 25629, 25596, 25562, 25529,
+25495, 25461, 25428, 25394, 25360,
+25326, 25292, 25258, 25223, 25189,
+25155, 25120, 25086, 25051, 25017,
+24982, 24947, 24913, 24878, 24843,
+24808, 24773, 24738, 24702, 24667,
+24632, 24596, 24561, 24525, 24490,
+24454, 24419, 24383, 24347, 24311,
+24275, 24239, 24203, 24167, 24130,
+24094, 24058, 24021, 23985, 23948,
+23912, 23875, 23838, 23801, 23764,
+23728, 23690, 23653, 23616, 23579,
+23542, 23504, 23467, 23430, 23392,
+23355, 23317, 23279, 23241, 23204,
+23166, 23128, 23090, 23052, 23014,
+22975, 22937, 22899, 22860, 22822,
+22783, 22745, 22706, 22668, 22629,
+22590, 22551, 22512, 22473, 22434,
+22395, 22356, 22317, 22277, 22238,
+22199, 22159, 22120, 22080, 22040,
+22001, 21961, 21921, 21881, 21841,
+21801, 21761, 21721, 21681, 21641,
+21600, 21560, 21520, 21479, 21439,
+21398, 21357, 21317, 21276, 21235,
+21194, 21153, 21112, 21071, 21030,
+20989, 20948, 20907, 20865, 20824,
+20783, 20741, 20700, 20658, 20616,
+20575, 20533, 20491, 20449, 20407,
+20365, 20323, 20281, 20239, 20197,
+20155, 20112, 20070, 20028, 19985,
+19943, 19900, 19857, 19815, 19772,
+19729, 19686, 19643, 19601, 19558,
+19514, 19471, 19428, 19385, 19342,
+19298, 19255, 19212, 19168, 19125,
+19081, 19038, 18994, 18950, 18906,
+18863, 18819, 18775, 18731, 18687,
+18643, 18599, 18554, 18510, 18466,
+18422, 18377, 18333, 18288, 18244,
+18199, 18155, 18110, 18065, 18021,
+17976, 17931, 17886, 17841, 17796,
+17751, 17706, 17661, 17616, 17570,
+17525, 17480, 17434, 17389, 17344,
+17298, 17252, 17207, 17161, 17116,
+17070, 17024, 16978, 16932, 16886,
+16840, 16794, 16748, 16702, 16656,
+16610, 16564, 16517, 16471, 16425,
+16378, 16332, 16285, 16239, 16192,
+16145, 16099, 16052, 16005, 15958,
+15912, 15865, 15818, 15771, 15724,
+15677, 15630, 15583, 15535, 15488,
+15441, 15394, 15346, 15299, 15251,
+15204, 15156, 15109, 15061, 15014,
+14966, 14918, 14870, 14823, 14775,
+14727, 14679, 14631, 14583, 14535,
+14487, 14439, 14391, 14342, 14294,
+14246, 14198, 14149, 14101, 14053,
+14004, 13956, 13907, 13858, 13810,
+13761, 13713, 13664, 13615, 13566,
+13517, 13469, 13420, 13371, 13322,
+13273, 13224, 13175, 13126, 13076,
+13027, 12978, 12929, 12880, 12830,
+12781, 12731, 12682, 12633, 12583,
+12534, 12484, 12434, 12385, 12335,
+12285, 12236, 12186, 12136, 12086,
+12037, 11987, 11937, 11887, 11837,
+11787, 11737, 11687, 11637, 11586,
+11536, 11486, 11436, 11386, 11335,
+11285, 11235, 11184, 11134, 11083,
+11033, 10982, 10932, 10881, 10831,
+10780, 10729, 10679, 10628, 10577,
+10527, 10476, 10425, 10374, 10323,
+10272, 10221, 10170, 10119, 10068,
+10017, 9966, 9915, 9864, 9813,
+9762, 9711, 9659, 9608, 9557,
+9506, 9454, 9403, 9352, 9300,
+9249, 9197, 9146, 9094, 9043,
+8991, 8940, 8888, 8836, 8785,
+8733, 8681, 8630, 8578, 8526,
+8475, 8423, 8371, 8319, 8267,
+8215, 8163, 8111, 8059, 8007,
+7955, 7903, 7851, 7799, 7747,
+7695, 7643, 7591, 7539, 7487,
+7434, 7382, 7330, 7278, 7225,
+7173, 7121, 7068, 7016, 6964,
+6911, 6859, 6806, 6754, 6701,
+6649, 6596, 6544, 6491, 6439,
+6386, 6334, 6281, 6228, 6176,
+6123, 6070, 6018, 5965, 5912,
+5859, 5807, 5754, 5701, 5648,
+5595, 5543, 5490, 5437, 5384,
+5331, 5278, 5225, 5172, 5119,
+5066, 5013, 4960, 4907, 4854,
+4801, 4748, 4695, 4642, 4589,
+4536, 4483, 4430, 4377, 4324,
+4270, 4217, 4164, 4111, 4058,
+4005, 3951, 3898, 3845, 3792,
+3738, 3685, 3632, 3578, 3525,
+3472, 3419, 3365, 3312, 3259,
+3205, 3152, 3098, 3045, 2992,
+2938, 2885, 2831, 2778, 2725,
+2671, 2618, 2564, 2511, 2457,
+2404, 2350, 2297, 2243, 2190,
+2136, 2083, 2029, 1976, 1922,
+1869, 1815, 1762, 1708, 1655,
+1601, 1548, 1494, 1440, 1387,
+1333, 1280, 1226, 1173, 1119,
+1065, 1012, 958, 905, 851,
+797, 744, 690, 637, 583,
+529, 476, 422, 369, 315,
+261, 208, 154, 101, 47,
+-7, -60, -114, -168, -221,
+-275, -328, -382, -436, -489,
+-543, -596, -650, -704, -757,
+-811, -864, -918, -972, -1025,
+-1079, -1132, -1186, -1240, -1293,
+-1347, -1400, -1454, -1507, -1561,
+-1615, -1668, -1722, -1775, -1829,
+-1882, -1936, -1989, -2043, -2096,
+-2150, -2203, -2257, -2310, -2364,
+-2417, -2471, -2524, -2578, -2631,
+-2685, -2738, -2791, -2845, -2898,
+-2952, -3005, -3058, -3112, -3165,
+-3218, -3272, -3325, -3379, -3432,
+-3485, -3538, -3592, -3645, -3698,
+-3752, -3805, -3858, -3911, -3965,
+-4018, -4071, -4124, -4177, -4231,
+-4284, -4337, -4390, -4443, -4496,
+-4549, -4602, -4656, -4709, -4762,
+-4815, -4868, -4921, -4974, -5027,
+-5080, -5133, -5186, -5239, -5291,
+-5344, -5397, -5450, -5503, -5556,
+-5609, -5662, -5714, -5767, -5820,
+-5873, -5925, -5978, -6031, -6083,
+-6136, -6189, -6241, -6294, -6347,
+-6399, -6452, -6504, -6557, -6609,
+-6662, -6714, -6767, -6819, -6872,
+-6924, -6977, -7029, -7081, -7134,
+-7186, -7238, -7291, -7343, -7395,
+-7447, -7500, -7552, -7604, -7656,
+-7708, -7760, -7812, -7864, -7916,
+-7968, -8020, -8072, -8124, -8176,
+-8228, -8280, -8332, -8384, -8436,
+-8487, -8539, -8591, -8643, -8694,
+-8746, -8798, -8849, -8901, -8953,
+-9004, -9056, -9107, -9159, -9210,
+-9262, -9313, -9364, -9416, -9467,
+-9518, -9570, -9621, -9672, -9723,
+-9775, -9826, -9877, -9928, -9979,
+-10030, -10081, -10132, -10183, -10234,
+-10285, -10336, -10387, -10438, -10488,
+-10539, -10590, -10641, -10691, -10742,
+-10793, -10843, -10894, -10945, -10995,
+-11046, -11096, -11146, -11197, -11247,
+-11298, -11348, -11398, -11448, -11499,
+-11549, -11599, -11649, -11699, -11749,
+-11799, -11849, -11899, -11949, -11999,
+-12049, -12099, -12149, -12198, -12248,
+-12298, -12348, -12397, -12447, -12496,
+-12546, -12595, -12645, -12694, -12744,
+-12793, -12843, -12892, -12941, -12990,
+-13040, -13089, -13138, -13187, -13236,
+-13285, -13334, -13383, -13432, -13481,
+-13530, -13579, -13627, -13676, -13725,
+-13773, -13822, -13871, -13919, -13968,
+-14016, -14065, -14113, -14161, -14210,
+-14258, -14306, -14355, -14403, -14451,
+-14499, -14547, -14595, -14643, -14691,
+-14739, -14787, -14835, -14882, -14930,
+-14978, -15025, -15073, -15121, -15168,
+-15216, -15263, -15311, -15358, -15405,
+-15453, -15500, -15547, -15594, -15641,
+-15689, -15736, -15783, -15830, -15876,
+-15923, -15970, -16017, -16064, -16110,
+-16157, -16204, -16250, -16297, -16343,
+-16390, -16436, -16483, -16529, -16575,
+-16621, -16668, -16714, -16760, -16806,
+-16852, -16898, -16944, -16990, -17035,
+-17081, -17127, -17173, -17218, -17264,
+-17309, -17355, -17400, -17446, -17491,
+-17536, -17582, -17627, -17672, -17717,
+-17762, -17807, -17852, -17897, -17942,
+-17987, -18032, -18077, -18121, -18166,
+-18210, -18255, -18300, -18344, -18388,
+-18433, -18477, -18521, -18566, -18610,
+-18654, -18698, -18742, -18786, -18830,
+-18874, -18917, -18961, -19005, -19048,
+-19092, -19136, -19179, -19223, -19266,
+-19309, -19353, -19396, -19439, -19482,
+-19525, -19568, -19611, -19654, -19697,
+-19740, -19783, -19825, -19868, -19911,
+-19953, -19996, -20038, -20081, -20123,
+-20165, -20207, -20250, -20292, -20334,
+-20376, -20418, -20460, -20502, -20543,
+-20585, -20627, -20668, -20710, -20752,
+-20793, -20834, -20876, -20917, -20958,
+-20999, -21041, -21082, -21123, -21164,
+-21205, -21245, -21286, -21327, -21368,
+-21408, -21449, -21489, -21530, -21570,
+-21610, -21651, -21691, -21731, -21771,
+-21811, -21851, -21891, -21931, -21971,
+-22011, -22050, -22090, -22130, -22169,
+-22208, -22248, -22287, -22326, -22366,
+-22405, -22444, -22483, -22522, -22561,
+-22600, -22639, -22677, -22716, -22755,
+-22793, -22832, -22870, -22908, -22947,
+-22985, -23023, -23061, -23099, -23137,
+-23175, -23213, -23251, -23289, -23326,
+-23364, -23402, -23439, -23476, -23514,
+-23551, -23588, -23626, -23663, -23700,
+-23737, -23774, -23811, -23847, -23884,
+-23921, -23957, -23994, -24030, -24067,
+-24103, -24139, -24176, -24212, -24248,
+-24284, -24320, -24356, -24392, -24427,
+-24463, -24499, -24534, -24570, -24605,
+-24641, -24676, -24711, -24746, -24782,
+-24817, -24852, -24886, -24921, -24956,
+-24991, -25025, -25060, -25095, -25129,
+-25163, -25198, -25232, -25266, -25300,
+-25334, -25368, -25402, -25436, -25470,
+-25503, -25537, -25571, -25604, -25638,
+-25671, -25704, -25737, -25771, -25804,
+-25837, -25870, -25902, -25935, -25968,
+-26001, -26033, -26066, -26098, -26131,
+-26163, -26195, -26227, -26259, -26292,
+-26323, -26355, -26387, -26419, -26451,
+-26482, -26514, -26545, -26577, -26608,
+-26639, -26670, -26702, -26733, -26764,
+-26794, -26825, -26856, -26887, -26917,
+-26948, -26978, -27009, -27039, -27069,
+-27100, -27130, -27160, -27190, -27220,
+-27249, -27279, -27309, -27338, -27368,
+-27397, -27427, -27456, -27485, -27514,
+-27543, -27572, -27601, -27630, -27659,
+-27688, -27716, -27745, -27773, -27802,
+-27830, -27858, -27887, -27915, -27943,
+-27971, -27999, -28026, -28054, -28082,
+-28109, -28137, -28164, -28192, -28219,
+-28246, -28273, -28301, -28328, -28354,
+-28381, -28408, -28435, -28461, -28488,
+-28514, -28541, -28567, -28593, -28619,
+-28645, -28671, -28697, -28723, -28749,
+-28775, -28800, -28826, -28851, -28877,
+-28902, -28927, -28952, -28977, -29002,
+-29027, -29052, -29077, -29102, -29126,
+-29151, -29175, -29200, -29224, -29248,
+-29272, -29296, -29320, -29344, -29368,
+-29392, -29415, -29439, -29462, -29486,
+-29509, -29532, -29556, -29579, -29602,
+-29625, -29648, -29670, -29693, -29716,
+-29738, -29761, -29783, -29806, -29828,
+-29850, -29872, -29894, -29916, -29938,
+-29960, -29981, -30003, -30024, -30046,
+-30067, -30088, -30110, -30131, -30152,
+-30173, -30194, -30214, -30235, -30256,
+-30276, -30297, -30317, -30337, -30358,
+-30378, -30398, -30418, -30438, -30458,
+-30477, -30497, -30516, -30536, -30555,
+-30575, -30594, -30613, -30632, -30651,
+-30670, -30689, -30708, -30726, -30745,
+-30763, -30782, -30800, -30819, -30837,
+-30855, -30873, -30891, -30909, -30926,
+-30944, -30962, -30979, -30997, -31014,
+-31031, -31048, -31065, -31082, -31099,
+-31116, -31133, -31150, -31166, -31183,
+-31199, -31216, -31232, -31248, -31264,
+-31280, -31296, -31312, -31328, -31343,
+-31359, -31374, -31390, -31405, -31421,
+-31436, -31451, -31466, -31481, -31496,
+-31510, -31525, -31540, -31554, -31568,
+-31583, -31597, -31611, -31625, -31639,
+-31653, -31667, -31681, -31694, -31708,
+-31721, -31735, -31748, -31761, -31775,
+-31788, -31801, -31813, -31826, -31839,
+-31852, -31864, -31877, -31889, -31901,
+-31914, -31926, -31938, -31950, -31961,
+-31973, -31985, -31997, -32008, -32020,
+-32031, -32042, -32053, -32064, -32075,
+-32086, -32097, -32108, -32119, -32129,
+-32140, -32150, -32160, -32171, -32181,
+-32191, -32201, -32211, -32221, -32230,
+-32240, -32249, -32259, -32268, -32278,
+-32287, -32296, -32305, -32314, -32323,
+-32331, -32340, -32349, -32357, -32366,
+-32374, -32382, -32390, -32398, -32406,
+-32414, -32422, -32430, -32437, -32445,
+-32453, -32460, -32467, -32474, -32482,
+-32489, -32495, -32502, -32509, -32516,
+-32522, -32529, -32535, -32542, -32548,
+-32554, -32560, -32566, -32572, -32578,
+-32584, -32589, -32595, -32600, -32606,
+-32611, -32616, -32621, -32626, -32631,
+-32636, -32641, -32645, -32650, -32655,
+-32659, -32663, -32668, -32672, -32676,
+-32680, -32684, -32687, -32691, -32695,
+-32698, -32702, -32705, -32708, -32712,
+-32715, -32718, -32721, -32723, -32726,
+-32729, -32731, -32734, -32736, -32739,
+-32741, -32743, -32745, -32747, -32749,
+-32751, -32752, -32754, -32756, -32757,
+-32758, -32760, -32761, -32762, -32763,
+-32764, -32765, -32765, -32766, -32766,
+-32767, -32767, -32767, -32767, -32767,
+32767, 32767, 32767, 32766, 32765,
+32763, 32761, 32759, 32756, 32753,
+32750, 32746, 32742, 32738, 32733,
+32728, 32722, 32717, 32710, 32704,
+32697, 32690, 32682, 32674, 32666,
+32657, 32648, 32639, 32629, 32619,
+32609, 32598, 32587, 32576, 32564,
+32552, 32539, 32526, 32513, 32500,
+32486, 32472, 32457, 32442, 32427,
+32411, 32395, 32379, 32362, 32345,
+32328, 32310, 32292, 32274, 32255,
+32236, 32217, 32197, 32177, 32157,
+32136, 32115, 32093, 32071, 32049,
+32027, 32004, 31981, 31957, 31933,
+31909, 31884, 31859, 31834, 31809,
+31783, 31756, 31730, 31703, 31676,
+31648, 31620, 31592, 31563, 31534,
+31505, 31475, 31445, 31415, 31384,
+31353, 31322, 31290, 31258, 31226,
+31193, 31160, 31127, 31093, 31059,
+31025, 30990, 30955, 30920, 30884,
+30848, 30812, 30775, 30738, 30701,
+30663, 30625, 30587, 30548, 30509,
+30470, 30430, 30390, 30350, 30309,
+30269, 30227, 30186, 30144, 30102,
+30059, 30016, 29973, 29930, 29886,
+29842, 29797, 29752, 29707, 29662,
+29616, 29570, 29524, 29477, 29430,
+29383, 29335, 29287, 29239, 29190,
+29142, 29092, 29043, 28993, 28943,
+28892, 28842, 28791, 28739, 28688,
+28636, 28583, 28531, 28478, 28425,
+28371, 28317, 28263, 28209, 28154,
+28099, 28044, 27988, 27932, 27876,
+27820, 27763, 27706, 27648, 27591,
+27533, 27474, 27416, 27357, 27298,
+27238, 27178, 27118, 27058, 26997,
+26936, 26875, 26814, 26752, 26690,
+26628, 26565, 26502, 26439, 26375,
+26312, 26247, 26183, 26119, 26054,
+25988, 25923, 25857, 25791, 25725,
+25658, 25592, 25524, 25457, 25389,
+25322, 25253, 25185, 25116, 25047,
+24978, 24908, 24838, 24768, 24698,
+24627, 24557, 24485, 24414, 24342,
+24270, 24198, 24126, 24053, 23980,
+23907, 23834, 23760, 23686, 23612,
+23537, 23462, 23387, 23312, 23237,
+23161, 23085, 23009, 22932, 22856,
+22779, 22701, 22624, 22546, 22468,
+22390, 22312, 22233, 22154, 22075,
+21996, 21916, 21836, 21756, 21676,
+21595, 21515, 21434, 21352, 21271,
+21189, 21107, 21025, 20943, 20860,
+20777, 20694, 20611, 20528, 20444,
+20360, 20276, 20192, 20107, 20022,
+19937, 19852, 19767, 19681, 19595,
+19509, 19423, 19336, 19250, 19163,
+19076, 18988, 18901, 18813, 18725,
+18637, 18549, 18460, 18372, 18283,
+18194, 18104, 18015, 17925, 17835,
+17745, 17655, 17565, 17474, 17383,
+17292, 17201, 17110, 17018, 16927,
+16835, 16743, 16650, 16558, 16465,
+16372, 16279, 16186, 16093, 15999,
+15906, 15812, 15718, 15624, 15529,
+15435, 15340, 15245, 15150, 15055,
+14960, 14864, 14769, 14673, 14577,
+14481, 14385, 14288, 14192, 14095,
+13998, 13901, 13804, 13706, 13609,
+13511, 13414, 13316, 13218, 13119,
+13021, 12923, 12824, 12725, 12626,
+12527, 12428, 12329, 12230, 12130,
+12030, 11930, 11831, 11730, 11630,
+11530, 11430, 11329, 11228, 11128,
+11027, 10926, 10824, 10723, 10622,
+10520, 10419, 10317, 10215, 10113,
+10011, 9909, 9807, 9704, 9602,
+9499, 9397, 9294, 9191, 9088,
+8985, 8882, 8778, 8675, 8572,
+8468, 8364, 8261, 8157, 8053,
+7949, 7845, 7741, 7637, 7532,
+7428, 7323, 7219, 7114, 7009,
+6905, 6800, 6695, 6590, 6485,
+6380, 6274, 6169, 6064, 5958,
+5853, 5747, 5642, 5536, 5430,
+5325, 5219, 5113, 5007, 4901,
+4795, 4689, 4583, 4476, 4370,
+4264, 4157, 4051, 3945, 3838,
+3732, 3625, 3518, 3412, 3305,
+3198, 3092, 2985, 2878, 2771,
+2664, 2558, 2451, 2344, 2237,
+2130, 2023, 1916, 1809, 1702,
+1594, 1487, 1380, 1273, 1166,
+1059, 952, 844, 737, 630,
+523, 416, 308, 201, 94,
+-13, -121, -228, -335, -442,
+-550, -657, -764, -871, -978,
+-1086, -1193, -1300, -1407, -1514,
+-1621, -1728, -1835, -1942, -2049,
+-2157, -2263, -2370, -2477, -2584,
+-2691, -2798, -2905, -3012, -3118,
+-3225, -3332, -3439, -3545, -3652,
+-3758, -3865, -3971, -4078, -4184,
+-4290, -4397, -4503, -4609, -4715,
+-4821, -4927, -5033, -5139, -5245,
+-5351, -5457, -5562, -5668, -5774,
+-5879, -5985, -6090, -6195, -6301,
+-6406, -6511, -6616, -6721, -6826,
+-6931, -7036, -7140, -7245, -7349,
+-7454, -7558, -7663, -7767, -7871,
+-7975, -8079, -8183, -8287, -8390,
+-8494, -8597, -8701, -8804, -8907,
+-9011, -9114, -9217, -9319, -9422,
+-9525, -9627, -9730, -9832, -9934,
+-10037, -10139, -10241, -10342, -10444,
+-10546, -10647, -10748, -10850, -10951,
+-11052, -11153, -11253, -11354, -11455,
+-11555, -11655, -11756, -11856, -11955,
+-12055, -12155, -12254, -12354, -12453,
+-12552, -12651, -12750, -12849, -12947,
+-13046, -13144, -13242, -13340, -13438,
+-13536, -13633, -13731, -13828, -13925,
+-14022, -14119, -14216, -14312, -14409,
+-14505, -14601, -14697, -14793, -14888,
+-14984, -15079, -15174, -15269, -15364,
+-15459, -15553, -15647, -15741, -15835,
+-15929, -16023, -16116, -16210, -16303,
+-16396, -16488, -16581, -16673, -16766,
+-16858, -16949, -17041, -17133, -17224,
+-17315, -17406, -17497, -17587, -17678,
+-17768, -17858, -17948, -18037, -18127,
+-18216, -18305, -18394, -18483, -18571,
+-18659, -18747, -18835, -18923, -19010,
+-19098, -19185, -19271, -19358, -19444,
+-19531, -19617, -19702, -19788, -19873,
+-19959, -20043, -20128, -20213, -20297,
+-20381, -20465, -20549, -20632, -20715,
+-20798, -20881, -20963, -21046, -21128,
+-21210, -21291, -21373, -21454, -21535,
+-21616, -21696, -21776, -21856, -21936,
+-22016, -22095, -22174, -22253, -22331,
+-22410, -22488, -22566, -22643, -22721,
+-22798, -22875, -22951, -23028, -23104,
+-23180, -23256, -23331, -23406, -23481,
+-23556, -23630, -23704, -23778, -23852,
+-23925, -23998, -24071, -24144, -24216,
+-24288, -24360, -24432, -24503, -24574,
+-24645, -24716, -24786, -24856, -24926,
+-24995, -25064, -25133, -25202, -25270,
+-25339, -25406, -25474, -25541, -25608,
+-25675, -25742, -25808, -25874, -25939,
+-26005, -26070, -26135, -26199, -26264,
+-26327, -26391, -26455, -26518, -26581,
+-26643, -26705, -26767, -26829, -26891,
+-26952, -27013, -27073, -27133, -27193,
+-27253, -27312, -27372, -27430, -27489,
+-27547, -27605, -27663, -27720, -27777,
+-27834, -27890, -27946, -28002, -28058,
+-28113, -28168, -28223, -28277, -28331,
+-28385, -28438, -28491, -28544, -28596,
+-28649, -28701, -28752, -28803, -28854,
+-28905, -28955, -29006, -29055, -29105,
+-29154, -29203, -29251, -29299, -29347,
+-29395, -29442, -29489, -29535, -29582,
+-29628, -29673, -29719, -29764, -29808,
+-29853, -29897, -29941, -29984, -30027,
+-30070, -30112, -30154, -30196, -30238,
+-30279, -30320, -30360, -30400, -30440,
+-30480, -30519, -30558, -30596, -30635,
+-30672, -30710, -30747, -30784, -30821,
+-30857, -30893, -30929, -30964, -30999,
+-31033, -31068, -31102, -31135, -31168,
+-31201, -31234, -31266, -31298, -31330,
+-31361, -31392, -31422, -31453, -31483,
+-31512, -31541, -31570, -31599, -31627,
+-31655, -31682, -31710, -31737, -31763,
+-31789, -31815, -31841, -31866, -31891,
+-31915, -31939, -31963, -31986, -32010,
+-32032, -32055, -32077, -32099, -32120,
+-32141, -32162, -32182, -32202, -32222,
+-32241, -32260, -32279, -32297, -32315,
+-32333, -32350, -32367, -32383, -32399,
+-32415, -32431, -32446, -32461, -32475,
+-32489, -32503, -32517, -32530, -32542,
+-32555, -32567, -32579, -32590, -32601,
+-32612, -32622, -32632, -32641, -32651,
+-32659, -32668, -32676, -32684, -32692,
+-32699, -32706, -32712, -32718, -32724,
+-32729, -32734, -32739, -32743, -32747,
+-32751, -32754, -32757, -32760, -32762,
+-32764, -32765, -32767, -32767, -32767,
+32767, 32767, 32765, 32761, 32756,
+32750, 32742, 32732, 32722, 32710,
+32696, 32681, 32665, 32647, 32628,
+32608, 32586, 32562, 32538, 32512,
+32484, 32455, 32425, 32393, 32360,
+32326, 32290, 32253, 32214, 32174,
+32133, 32090, 32046, 32001, 31954,
+31906, 31856, 31805, 31753, 31700,
+31645, 31588, 31530, 31471, 31411,
+31349, 31286, 31222, 31156, 31089,
+31020, 30951, 30880, 30807, 30733,
+30658, 30582, 30504, 30425, 30345,
+30263, 30181, 30096, 30011, 29924,
+29836, 29747, 29656, 29564, 29471,
+29377, 29281, 29184, 29086, 28987,
+28886, 28784, 28681, 28577, 28471,
+28365, 28257, 28147, 28037, 27925,
+27812, 27698, 27583, 27467, 27349,
+27231, 27111, 26990, 26868, 26744,
+26620, 26494, 26367, 26239, 26110,
+25980, 25849, 25717, 25583, 25449,
+25313, 25176, 25038, 24900, 24760,
+24619, 24477, 24333, 24189, 24044,
+23898, 23751, 23602, 23453, 23303,
+23152, 22999, 22846, 22692, 22537,
+22380, 22223, 22065, 21906, 21746,
+21585, 21423, 21261, 21097, 20933,
+20767, 20601, 20434, 20265, 20096,
+19927, 19756, 19584, 19412, 19239,
+19065, 18890, 18714, 18538, 18361,
+18183, 18004, 17824, 17644, 17463,
+17281, 17098, 16915, 16731, 16546,
+16361, 16175, 15988, 15800, 15612,
+15423, 15234, 15043, 14852, 14661,
+14469, 14276, 14083, 13889, 13694,
+13499, 13303, 13107, 12910, 12713,
+12515, 12317, 12118, 11918, 11718,
+11517, 11316, 11115, 10913, 10710,
+10508, 10304, 10100, 9896, 9691,
+9486, 9281, 9075, 8869, 8662,
+8455, 8248, 8040, 7832, 7623,
+7415, 7206, 6996, 6787, 6577,
+6366, 6156, 5945, 5734, 5523,
+5311, 5100, 4888, 4675, 4463,
+4251, 4038, 3825, 3612, 3399,
+3185, 2972, 2758, 2544, 2330,
+2116, 1902, 1688, 1474, 1260,
+1045, 831, 617, 402, 188,
+-27, -241, -456, -670, -885,
+-1099, -1313, -1528, -1742, -1956,
+-2170, -2384, -2598, -2811, -3025,
+-3239, -3452, -3665, -3878, -4091,
+-4304, -4516, -4728, -4941, -5153,
+-5364, -5576, -5787, -5998, -6209,
+-6419, -6629, -6839, -7049, -7258,
+-7467, -7676, -7884, -8092, -8300,
+-8507, -8714, -8920, -9127, -9332,
+-9538, -9743, -9947, -10151, -10355,
+-10558, -10761, -10963, -11165, -11367,
+-11568, -11768, -11968, -12167, -12366,
+-12565, -12762, -12960, -13156, -13352,
+-13548, -13743, -13937, -14131, -14324,
+-14517, -14709, -14900, -15091, -15281,
+-15470, -15659, -15847, -16035, -16221,
+-16407, -16593, -16777, -16961, -17144,
+-17326, -17508, -17689, -17869, -18049,
+-18227, -18405, -18582, -18758, -18934,
+-19108, -19282, -19455, -19627, -19799,
+-19969, -20139, -20308, -20475, -20642,
+-20809, -20974, -21138, -21301, -21464,
+-21626, -21786, -21946, -22105, -22263,
+-22420, -22575, -22730, -22884, -23037,
+-23189, -23340, -23490, -23640, -23788,
+-23935, -24080, -24225, -24369, -24512,
+-24654, -24795, -24934, -25073, -25211,
+-25347, -25482, -25617, -25750, -25882,
+-26013, -26143, -26272, -26399, -26526,
+-26651, -26775, -26898, -27020, -27141,
+-27260, -27379, -27496, -27612, -27727,
+-27841, -27953, -28065, -28175, -28284,
+-28391, -28498, -28603, -28707, -28810,
+-28911, -29012, -29111, -29209, -29305,
+-29401, -29495, -29587, -29679, -29769,
+-29858, -29946, -30032, -30118, -30201,
+-30284, -30365, -30445, -30524, -30601,
+-30677, -30752, -30825, -30897, -30968,
+-31038, -31106, -31172, -31238, -31302,
+-31365, -31426, -31486, -31545, -31602,
+-31658, -31713, -31766, -31818, -31869,
+-31918, -31966, -32012, -32058, -32101,
+-32144, -32185, -32224, -32262, -32299,
+-32335, -32369, -32401, -32433, -32463,
+-32491, -32518, -32544, -32568, -32591,
+-32613, -32633, -32652, -32669, -32685,
+-32700, -32713, -32724, -32735, -32744,
+-32751, -32757, -32762, -32766, -32767,
+32767, 32764, 32755, 32741, 32720,
+32694, 32663, 32626, 32583, 32535,
+32481, 32421, 32356, 32286, 32209,
+32128, 32041, 31948, 31850, 31747,
+31638, 31523, 31403, 31278, 31148,
+31012, 30871, 30724, 30572, 30415,
+30253, 30086, 29913, 29736, 29553,
+29365, 29172, 28974, 28771, 28564,
+28351, 28134, 27911, 27684, 27452,
+27216, 26975, 26729, 26478, 26223,
+25964, 25700, 25432, 25159, 24882,
+24601, 24315, 24026, 23732, 23434,
+23133, 22827, 22517, 22204, 21886,
+21565, 21240, 20912, 20580, 20244,
+19905, 19563, 19217, 18868, 18516,
+18160, 17802, 17440, 17075, 16708,
+16338, 15964, 15588, 15210, 14829,
+14445, 14059, 13670, 13279, 12886,
+12490, 12093, 11693, 11291, 10888,
+10482, 10075, 9666, 9255, 8843,
+8429, 8014, 7597, 7180, 6760,
+6340, 5919, 5496, 5073, 4649,
+4224, 3798, 3372, 2945, 2517,
+2090, 1661, 1233, 804, 375,
+-54, -483, -911, -1340, -1768,
+-2197, -2624, -3052, -3479, -3905,
+-4330, -4755, -5179, -5602, -6024,
+-6445, -6865, -7284, -7702, -8118,
+-8533, -8946, -9358, -9768, -10177,
+-10584, -10989, -11392, -11793, -12192,
+-12589, -12984, -13377, -13767, -14155,
+-14541, -14924, -15305, -15683, -16058,
+-16430, -16800, -17167, -17531, -17892,
+-18249, -18604, -18956, -19304, -19649,
+-19990, -20329, -20663, -20994, -21322,
+-21646, -21966, -22282, -22595, -22904,
+-23208, -23509, -23806, -24099, -24387,
+-24672, -24952, -25228, -25499, -25766,
+-26029, -26288, -26541, -26791, -27035,
+-27275, -27511, -27741, -27967, -28188,
+-28405, -28616, -28823, -29024, -29221,
+-29412, -29599, -29780, -29957, -30128,
+-30294, -30455, -30611, -30761, -30906,
+-31046, -31181, -31310, -31434, -31552,
+-31665, -31773, -31875, -31972, -32063,
+-32149, -32229, -32304, -32373, -32437,
+-32495, -32547, -32594, -32635, -32671,
+-32701, -32726, -32745, -32758, -32766,
+#endif
+};
+#endif
+
+static const CELTMode mode96000_1920_240 = {
+96000, /* Fs */
+240, /* overlap */
+21, /* nbEBands */
+21, /* effEBands */
+{30245, 7209, 6197, 5415, }, /* preemph */
+eband5ms, /* eBands */
+3, /* maxLM */
+8, /* nbShortMdcts */
+240, /* shortMdctSize */
+11, /* nbAllocVectors */
+band_allocation, /* allocVectors */
+logN400, /* logN */
+window240, /* window */
+{3840, 3, {&fft_state96000_1920_0, &fft_state96000_1920_1, &fft_state96000_1920_2, &fft_state96000_1920_3, }, mdct_twiddles1920}, /* mdct */
+{392, cache_index50, cache_bits50, cache_caps50}, /* cache */
+#ifdef ENABLE_QEXT
+{86, qext_cache_index50, qext_cache_bits50, qext_cache_caps50}, /* qext_cache */
+#endif
+};
+#endif /* ENABLE_QEXT */
+
+/* List of all the available modes */
+#ifdef ENABLE_QEXT
+#define TOTAL_MODES 2
+static const CELTMode * const static_mode_list[TOTAL_MODES] = {
+&mode48000_960_120,
+&mode96000_1920_240,
+};
+#else
+#define TOTAL_MODES 1
+static const CELTMode * const static_mode_list[TOTAL_MODES] = {
+&mode48000_960_120,
+};
+#endif
--- /dev/null
+/* The contents of this file was automatically generated by
+ * dump_mode_arm_ne10.c with arguments: 48000 960
+ * It contains static definitions for some pre-defined modes. */
+#include <NE10_types.h>
+
+#ifndef NE10_FFT_PARAMS48000_960
+#define NE10_FFT_PARAMS48000_960
+static const ne10_int32_t ne10_factors_480[64] = {
+4, 40, 4, 30, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, };
+static const ne10_int32_t ne10_factors_240[64] = {
+3, 20, 4, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, };
+static const ne10_int32_t ne10_factors_120[64] = {
+3, 10, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, };
+static const ne10_int32_t ne10_factors_60[64] = {
+2, 5, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, };
+static const ne10_fft_cpx_int32_t ne10_twiddles_480[480] = {
+{0,0}, {2147483647,0}, {2147483647,0},
+{2147483647,0}, {1961823921,-873460313}, {1436946998,-1595891394},
+{2147483647,0}, {1436946998,-1595891394}, {-224473265,-2135719496},
+{2147483647,0}, {663608871,-2042378339}, {-1737350854,-1262259096},
+{2147483647,0}, {-224473265,-2135719496}, {-2100555935,446487152},
+{2147483647,0}, {2100555974,-446486968}, {1961823921,-873460313},
+{1737350743,-1262259248}, {1436946998,-1595891394}, {1073741769,-1859775424},
+{663608871,-2042378339}, {224473078,-2135719516}, {-224473265,-2135719496},
+{-663609049,-2042378281}, {-1073741932,-1859775330}, {-1436947137,-1595891268},
+{-1737350854,-1262259096}, {-1961823997,-873460141}, {-2100556013,-446486785},
+{2147483647,0}, {2144540595,-112390613}, {2135719506,-224473172},
+{2121044558,-335940465}, {2100555974,-446486968}, {2074309912,-555809682},
+{2042378310,-663608960}, {2004848691,-769589332}, {1961823921,-873460313},
+{1913421927,-974937199}, {1859775377,-1073741851}, {1801031311,-1169603450},
+{1737350743,-1262259248}, {1668908218,-1351455280}, {1595891331,-1436947067},
+{1518500216,-1518500282}, {1436946998,-1595891394}, {1351455207,-1668908277},
+{1262259172,-1737350799}, {1169603371,-1801031362}, {1073741769,-1859775424},
+{974937230,-1913421912}, {873460227,-1961823959}, {769589125,-2004848771},
+{663608871,-2042378339}, {555809715,-2074309903}, {446486876,-2100555994},
+{335940246,-2121044593}, {224473078,-2135719516}, {112390647,-2144540593},
+{2147483647,0}, {2135719506,-224473172}, {2100555974,-446486968},
+{2042378310,-663608960}, {1961823921,-873460313}, {1859775377,-1073741851},
+{1737350743,-1262259248}, {1595891331,-1436947067}, {1436946998,-1595891394},
+{1262259172,-1737350799}, {1073741769,-1859775424}, {873460227,-1961823959},
+{663608871,-2042378339}, {446486876,-2100555994}, {224473078,-2135719516},
+{-94,-2147483647}, {-224473265,-2135719496}, {-446487060,-2100555955},
+{-663609049,-2042378281}, {-873460398,-1961823883}, {-1073741932,-1859775330},
+{-1262259116,-1737350839}, {-1436947137,-1595891268}, {-1595891628,-1436946738},
+{-1737350854,-1262259096}, {-1859775343,-1073741910}, {-1961823997,-873460141},
+{-2042378447,-663608538}, {-2100556013,-446486785}, {-2135719499,-224473240},
+{2147483647,0}, {2121044558,-335940465}, {2042378310,-663608960},
+{1913421927,-974937199}, {1737350743,-1262259248}, {1518500216,-1518500282},
+{1262259172,-1737350799}, {974937230,-1913421912}, {663608871,-2042378339},
+{335940246,-2121044593}, {-94,-2147483647}, {-335940431,-2121044564},
+{-663609049,-2042378281}, {-974937397,-1913421827}, {-1262259116,-1737350839},
+{-1518500258,-1518500240}, {-1737350854,-1262259096}, {-1913422071,-974936918},
+{-2042378447,-663608538}, {-2121044568,-335940406}, {-2147483647,188},
+{-2121044509,335940777}, {-2042378331,663608895}, {-1913421900,974937252},
+{-1737350633,1262259400}, {-1518499993,1518500506}, {-1262258813,1737351059},
+{-974936606,1913422229}, {-663609179,2042378239}, {-335940566,2121044542},
+{2147483647,0}, {2147299667,-28109693}, {2146747758,-56214570},
+{2145828015,-84309815}, {2144540595,-112390613}, {2142885719,-140452154},
+{2140863671,-168489630}, {2138474797,-196498235}, {2135719506,-224473172},
+{2132598271,-252409646}, {2129111626,-280302871}, {2125260168,-308148068},
+{2121044558,-335940465}, {2116465518,-363675300}, {2111523833,-391347822},
+{2106220349,-418953288}, {2100555974,-446486968}, {2094531681,-473944146},
+{2088148500,-501320115}, {2081407525,-528610186}, {2074309912,-555809682},
+{2066856885,-582913912}, {2059049696,-609918325}, {2050889698,-636818231},
+{2042378310,-663608960}, {2033516972,-690285983}, {2024307180,-716844791},
+{2014750533,-743280770}, {2004848691,-769589332}, {1994603329,-795766029},
+{1984016179,-821806435}, {1973089077,-847706028}, {1961823921,-873460313},
+{1950222618,-899064934}, {1938287127,-924515564}, {1926019520,-949807783},
+{1913421927,-974937199}, {1900496481,-999899565}, {1887245364,-1024690661},
+{1873670877,-1049306180}, {1859775377,-1073741851}, {1845561215,-1097993541},
+{1831030826,-1122057097}, {1816186632,-1145928502}, {1801031311,-1169603450},
+{1785567394,-1193077993}, {1769797456,-1216348214}, {1753724345,-1239409914},
+{1737350743,-1262259248}, {1720679456,-1284892300}, {1703713340,-1307305194},
+{1686455222,-1329494189}, {1668908218,-1351455280}, {1651075255,-1373184807},
+{1632959307,-1394679144}, {1614563642,-1415934412}, {1595891331,-1436947067},
+{1576945572,-1457713510}, {1557729613,-1478230181}, {1538246655,-1498493658},
+{1518500216,-1518500282}, {1498493590,-1538246721}, {1478230113,-1557729677},
+{1457713441,-1576945636}, {1436946998,-1595891394}, {1415934341,-1614563704},
+{1394679073,-1632959368}, {1373184735,-1651075315}, {1351455207,-1668908277},
+{1329494115,-1686455280}, {1307305120,-1703713397}, {1284892225,-1720679512},
+{1262259172,-1737350799}, {1239409837,-1753724400}, {1216348136,-1769797510},
+{1193077915,-1785567446}, {1169603371,-1801031362}, {1145928423,-1816186682},
+{1122057017,-1831030875}, {1097993571,-1845561197}, {1073741769,-1859775424},
+{1049305987,-1873670985}, {1024690635,-1887245378}, {999899482,-1900496524},
+{974937230,-1913421912}, {949807699,-1926019561}, {924515422,-1938287195},
+{899064965,-1950222603}, {873460227,-1961823959}, {847705824,-1973089164},
+{821806407,-1984016190}, {795765941,-1994603364}, {769589125,-2004848771},
+{743280682,-2014750566}, {716844642,-2024307233}, {690286016,-2033516961},
+{663608871,-2042378339}, {636818019,-2050889764}, {609918296,-2059049705},
+{582913822,-2066856911}, {555809715,-2074309903}, {528610126,-2081407540},
+{501319962,-2088148536}, {473944148,-2094531680}, {446486876,-2100555994},
+{418953102,-2106220386}, {391347792,-2111523838}, {363675176,-2116465540},
+{335940246,-2121044593}, {308148006,-2125260177}, {280302715,-2129111646},
+{252409648,-2132598271}, {224473078,-2135719516}, {196498046,-2138474814},
+{168489600,-2140863674}, {140452029,-2142885728}, {112390647,-2144540593},
+{84309753,-2145828017}, {56214412,-2146747762}, {28109695,-2147299667},
+{2147483647,0}, {2146747758,-56214570}, {2144540595,-112390613},
+{2140863671,-168489630}, {2135719506,-224473172}, {2129111626,-280302871},
+{2121044558,-335940465}, {2111523833,-391347822}, {2100555974,-446486968},
+{2088148500,-501320115}, {2074309912,-555809682}, {2059049696,-609918325},
+{2042378310,-663608960}, {2024307180,-716844791}, {2004848691,-769589332},
+{1984016179,-821806435}, {1961823921,-873460313}, {1938287127,-924515564},
+{1913421927,-974937199}, {1887245364,-1024690661}, {1859775377,-1073741851},
+{1831030826,-1122057097}, {1801031311,-1169603450}, {1769797456,-1216348214},
+{1737350743,-1262259248}, {1703713340,-1307305194}, {1668908218,-1351455280},
+{1632959307,-1394679144}, {1595891331,-1436947067}, {1557729613,-1478230181},
+{1518500216,-1518500282}, {1478230113,-1557729677}, {1436946998,-1595891394},
+{1394679073,-1632959368}, {1351455207,-1668908277}, {1307305120,-1703713397},
+{1262259172,-1737350799}, {1216348136,-1769797510}, {1169603371,-1801031362},
+{1122057017,-1831030875}, {1073741769,-1859775424}, {1024690635,-1887245378},
+{974937230,-1913421912}, {924515422,-1938287195}, {873460227,-1961823959},
+{821806407,-1984016190}, {769589125,-2004848771}, {716844642,-2024307233},
+{663608871,-2042378339}, {609918296,-2059049705}, {555809715,-2074309903},
+{501319962,-2088148536}, {446486876,-2100555994}, {391347792,-2111523838},
+{335940246,-2121044593}, {280302715,-2129111646}, {224473078,-2135719516},
+{168489600,-2140863674}, {112390647,-2144540593}, {56214412,-2146747762},
+{-94,-2147483647}, {-56214600,-2146747757}, {-112390835,-2144540584},
+{-168489787,-2140863659}, {-224473265,-2135719496}, {-280302901,-2129111622},
+{-335940431,-2121044564}, {-391347977,-2111523804}, {-446487060,-2100555955},
+{-501320144,-2088148493}, {-555809896,-2074309855}, {-609918476,-2059049651},
+{-663609049,-2042378281}, {-716844819,-2024307170}, {-769589300,-2004848703},
+{-821806581,-1984016118}, {-873460398,-1961823883}, {-924515591,-1938287114},
+{-974937397,-1913421827}, {-1024690575,-1887245411}, {-1073741932,-1859775330},
+{-1122057395,-1831030643}, {-1169603421,-1801031330}, {-1216348291,-1769797403},
+{-1262259116,-1737350839}, {-1307305268,-1703713283}, {-1351455453,-1668908078},
+{-1394679021,-1632959413}, {-1436947137,-1595891268}, {-1478230435,-1557729372},
+{-1518500258,-1518500240}, {-1557729742,-1478230045}, {-1595891628,-1436946738},
+{-1632959429,-1394679001}, {-1668908417,-1351455035}, {-1703713298,-1307305248},
+{-1737350854,-1262259096}, {-1769797708,-1216347848}, {-1801031344,-1169603400},
+{-1831030924,-1122056937}, {-1859775343,-1073741910}, {-1887245423,-1024690552},
+{-1913422071,-974936918}, {-1938287125,-924515568}, {-1961823997,-873460141},
+{-1984016324,-821806084}, {-2004848713,-769589276}, {-2024307264,-716844553},
+{-2042378447,-663608538}, {-2059049731,-609918206}, {-2074309994,-555809377},
+{-2088148499,-501320119}, {-2100556013,-446486785}, {-2111523902,-391347448},
+{-2121044568,-335940406}, {-2129111659,-280302621}, {-2135719499,-224473240},
+{-2140863681,-168489506}, {-2144540612,-112390298}, {-2146747758,-56214574},
+{2147483647,0}, {2145828015,-84309815}, {2140863671,-168489630},
+{2132598271,-252409646}, {2121044558,-335940465}, {2106220349,-418953288},
+{2088148500,-501320115}, {2066856885,-582913912}, {2042378310,-663608960},
+{2014750533,-743280770}, {1984016179,-821806435}, {1950222618,-899064934},
+{1913421927,-974937199}, {1873670877,-1049306180}, {1831030826,-1122057097},
+{1785567394,-1193077993}, {1737350743,-1262259248}, {1686455222,-1329494189},
+{1632959307,-1394679144}, {1576945572,-1457713510}, {1518500216,-1518500282},
+{1457713441,-1576945636}, {1394679073,-1632959368}, {1329494115,-1686455280},
+{1262259172,-1737350799}, {1193077915,-1785567446}, {1122057017,-1831030875},
+{1049305987,-1873670985}, {974937230,-1913421912}, {899064965,-1950222603},
+{821806407,-1984016190}, {743280682,-2014750566}, {663608871,-2042378339},
+{582913822,-2066856911}, {501319962,-2088148536}, {418953102,-2106220386},
+{335940246,-2121044593}, {252409648,-2132598271}, {168489600,-2140863674},
+{84309753,-2145828017}, {-94,-2147483647}, {-84309940,-2145828010},
+{-168489787,-2140863659}, {-252409834,-2132598249}, {-335940431,-2121044564},
+{-418953286,-2106220349}, {-501320144,-2088148493}, {-582914003,-2066856860},
+{-663609049,-2042378281}, {-743280858,-2014750501}, {-821806581,-1984016118},
+{-899065136,-1950222525}, {-974937397,-1913421827}, {-1049306374,-1873670768},
+{-1122057395,-1831030643}, {-1193078284,-1785567199}, {-1262259116,-1737350839},
+{-1329494061,-1686455323}, {-1394679021,-1632959413}, {-1457713485,-1576945595},
+{-1518500258,-1518500240}, {-1576945613,-1457713466}, {-1632959429,-1394679001},
+{-1686455338,-1329494041}, {-1737350854,-1262259096}, {-1785567498,-1193077837},
+{-1831030924,-1122056937}, {-1873671031,-1049305905}, {-1913422071,-974936918},
+{-1950222750,-899064648}, {-1984016324,-821806084}, {-2014750687,-743280354},
+{-2042378447,-663608538}, {-2066856867,-582913978}, {-2088148499,-501320119},
+{-2106220354,-418953261}, {-2121044568,-335940406}, {-2132598282,-252409555},
+{-2140863681,-168489506}, {-2145828021,-84309659}, {-2147483647,188},
+{-2145828006,84310034}, {-2140863651,168489881}, {-2132598237,252409928},
+{-2121044509,335940777}, {-2106220281,418953629}, {-2088148411,501320484},
+{-2066856765,582914339}, {-2042378331,663608895}, {-2014750557,743280706},
+{-1984016181,821806431}, {-1950222593,899064989}, {-1913421900,974937252},
+{-1873670848,1049306232}, {-1831030728,1122057257}, {-1785567289,1193078149},
+{-1737350633,1262259400}, {-1686455106,1329494336}, {-1632959185,1394679287},
+{-1576945358,1457713742}, {-1518499993,1518500506}, {-1457713209,1576945850},
+{-1394678735,1632959656}, {-1329493766,1686455555}, {-1262258813,1737351059},
+{-1193077546,1785567692}, {-1122056638,1831031107}, {-1049305599,1873671202},
+{-974936606,1913422229}, {-899064330,1950222896}, {-821805761,1984016458},
+{-743280025,2014750808}, {-663609179,2042378239}, {-582914134,2066856823},
+{-501320277,2088148461}, {-418953420,2106220322}, {-335940566,2121044542},
+{-252409716,2132598263}, {-168489668,2140863668}, {-84309821,2145828015},
+};
+static const ne10_fft_cpx_int32_t ne10_twiddles_240[240] = {
+{0,0}, {2147483647,0}, {2147483647,0},
+{2147483647,0}, {1961823921,-873460313}, {1436946998,-1595891394},
+{2147483647,0}, {1436946998,-1595891394}, {-224473265,-2135719496},
+{2147483647,0}, {663608871,-2042378339}, {-1737350854,-1262259096},
+{2147483647,0}, {-224473265,-2135719496}, {-2100555935,446487152},
+{2147483647,0}, {2135719506,-224473172}, {2100555974,-446486968},
+{2042378310,-663608960}, {1961823921,-873460313}, {1859775377,-1073741851},
+{1737350743,-1262259248}, {1595891331,-1436947067}, {1436946998,-1595891394},
+{1262259172,-1737350799}, {1073741769,-1859775424}, {873460227,-1961823959},
+{663608871,-2042378339}, {446486876,-2100555994}, {224473078,-2135719516},
+{2147483647,0}, {2100555974,-446486968}, {1961823921,-873460313},
+{1737350743,-1262259248}, {1436946998,-1595891394}, {1073741769,-1859775424},
+{663608871,-2042378339}, {224473078,-2135719516}, {-224473265,-2135719496},
+{-663609049,-2042378281}, {-1073741932,-1859775330}, {-1436947137,-1595891268},
+{-1737350854,-1262259096}, {-1961823997,-873460141}, {-2100556013,-446486785},
+{2147483647,0}, {2042378310,-663608960}, {1737350743,-1262259248},
+{1262259172,-1737350799}, {663608871,-2042378339}, {-94,-2147483647},
+{-663609049,-2042378281}, {-1262259116,-1737350839}, {-1737350854,-1262259096},
+{-2042378447,-663608538}, {-2147483647,188}, {-2042378331,663608895},
+{-1737350633,1262259400}, {-1262258813,1737351059}, {-663609179,2042378239},
+{2147483647,0}, {2146747758,-56214570}, {2144540595,-112390613},
+{2140863671,-168489630}, {2135719506,-224473172}, {2129111626,-280302871},
+{2121044558,-335940465}, {2111523833,-391347822}, {2100555974,-446486968},
+{2088148500,-501320115}, {2074309912,-555809682}, {2059049696,-609918325},
+{2042378310,-663608960}, {2024307180,-716844791}, {2004848691,-769589332},
+{1984016179,-821806435}, {1961823921,-873460313}, {1938287127,-924515564},
+{1913421927,-974937199}, {1887245364,-1024690661}, {1859775377,-1073741851},
+{1831030826,-1122057097}, {1801031311,-1169603450}, {1769797456,-1216348214},
+{1737350743,-1262259248}, {1703713340,-1307305194}, {1668908218,-1351455280},
+{1632959307,-1394679144}, {1595891331,-1436947067}, {1557729613,-1478230181},
+{1518500216,-1518500282}, {1478230113,-1557729677}, {1436946998,-1595891394},
+{1394679073,-1632959368}, {1351455207,-1668908277}, {1307305120,-1703713397},
+{1262259172,-1737350799}, {1216348136,-1769797510}, {1169603371,-1801031362},
+{1122057017,-1831030875}, {1073741769,-1859775424}, {1024690635,-1887245378},
+{974937230,-1913421912}, {924515422,-1938287195}, {873460227,-1961823959},
+{821806407,-1984016190}, {769589125,-2004848771}, {716844642,-2024307233},
+{663608871,-2042378339}, {609918296,-2059049705}, {555809715,-2074309903},
+{501319962,-2088148536}, {446486876,-2100555994}, {391347792,-2111523838},
+{335940246,-2121044593}, {280302715,-2129111646}, {224473078,-2135719516},
+{168489600,-2140863674}, {112390647,-2144540593}, {56214412,-2146747762},
+{2147483647,0}, {2144540595,-112390613}, {2135719506,-224473172},
+{2121044558,-335940465}, {2100555974,-446486968}, {2074309912,-555809682},
+{2042378310,-663608960}, {2004848691,-769589332}, {1961823921,-873460313},
+{1913421927,-974937199}, {1859775377,-1073741851}, {1801031311,-1169603450},
+{1737350743,-1262259248}, {1668908218,-1351455280}, {1595891331,-1436947067},
+{1518500216,-1518500282}, {1436946998,-1595891394}, {1351455207,-1668908277},
+{1262259172,-1737350799}, {1169603371,-1801031362}, {1073741769,-1859775424},
+{974937230,-1913421912}, {873460227,-1961823959}, {769589125,-2004848771},
+{663608871,-2042378339}, {555809715,-2074309903}, {446486876,-2100555994},
+{335940246,-2121044593}, {224473078,-2135719516}, {112390647,-2144540593},
+{-94,-2147483647}, {-112390835,-2144540584}, {-224473265,-2135719496},
+{-335940431,-2121044564}, {-446487060,-2100555955}, {-555809896,-2074309855},
+{-663609049,-2042378281}, {-769589300,-2004848703}, {-873460398,-1961823883},
+{-974937397,-1913421827}, {-1073741932,-1859775330}, {-1169603421,-1801031330},
+{-1262259116,-1737350839}, {-1351455453,-1668908078}, {-1436947137,-1595891268},
+{-1518500258,-1518500240}, {-1595891628,-1436946738}, {-1668908417,-1351455035},
+{-1737350854,-1262259096}, {-1801031344,-1169603400}, {-1859775343,-1073741910},
+{-1913422071,-974936918}, {-1961823997,-873460141}, {-2004848713,-769589276},
+{-2042378447,-663608538}, {-2074309994,-555809377}, {-2100556013,-446486785},
+{-2121044568,-335940406}, {-2135719499,-224473240}, {-2144540612,-112390298},
+{2147483647,0}, {2140863671,-168489630}, {2121044558,-335940465},
+{2088148500,-501320115}, {2042378310,-663608960}, {1984016179,-821806435},
+{1913421927,-974937199}, {1831030826,-1122057097}, {1737350743,-1262259248},
+{1632959307,-1394679144}, {1518500216,-1518500282}, {1394679073,-1632959368},
+{1262259172,-1737350799}, {1122057017,-1831030875}, {974937230,-1913421912},
+{821806407,-1984016190}, {663608871,-2042378339}, {501319962,-2088148536},
+{335940246,-2121044593}, {168489600,-2140863674}, {-94,-2147483647},
+{-168489787,-2140863659}, {-335940431,-2121044564}, {-501320144,-2088148493},
+{-663609049,-2042378281}, {-821806581,-1984016118}, {-974937397,-1913421827},
+{-1122057395,-1831030643}, {-1262259116,-1737350839}, {-1394679021,-1632959413},
+{-1518500258,-1518500240}, {-1632959429,-1394679001}, {-1737350854,-1262259096},
+{-1831030924,-1122056937}, {-1913422071,-974936918}, {-1984016324,-821806084},
+{-2042378447,-663608538}, {-2088148499,-501320119}, {-2121044568,-335940406},
+{-2140863681,-168489506}, {-2147483647,188}, {-2140863651,168489881},
+{-2121044509,335940777}, {-2088148411,501320484}, {-2042378331,663608895},
+{-1984016181,821806431}, {-1913421900,974937252}, {-1831030728,1122057257},
+{-1737350633,1262259400}, {-1632959185,1394679287}, {-1518499993,1518500506},
+{-1394678735,1632959656}, {-1262258813,1737351059}, {-1122056638,1831031107},
+{-974936606,1913422229}, {-821805761,1984016458}, {-663609179,2042378239},
+{-501320277,2088148461}, {-335940566,2121044542}, {-168489668,2140863668},
+};
+static const ne10_fft_cpx_int32_t ne10_twiddles_120[120] = {
+{0,0}, {2147483647,0}, {2147483647,0},
+{2147483647,0}, {1961823921,-873460313}, {1436946998,-1595891394},
+{2147483647,0}, {1436946998,-1595891394}, {-224473265,-2135719496},
+{2147483647,0}, {663608871,-2042378339}, {-1737350854,-1262259096},
+{2147483647,0}, {-224473265,-2135719496}, {-2100555935,446487152},
+{2147483647,0}, {2100555974,-446486968}, {1961823921,-873460313},
+{1737350743,-1262259248}, {1436946998,-1595891394}, {1073741769,-1859775424},
+{663608871,-2042378339}, {224473078,-2135719516}, {-224473265,-2135719496},
+{-663609049,-2042378281}, {-1073741932,-1859775330}, {-1436947137,-1595891268},
+{-1737350854,-1262259096}, {-1961823997,-873460141}, {-2100556013,-446486785},
+{2147483647,0}, {2144540595,-112390613}, {2135719506,-224473172},
+{2121044558,-335940465}, {2100555974,-446486968}, {2074309912,-555809682},
+{2042378310,-663608960}, {2004848691,-769589332}, {1961823921,-873460313},
+{1913421927,-974937199}, {1859775377,-1073741851}, {1801031311,-1169603450},
+{1737350743,-1262259248}, {1668908218,-1351455280}, {1595891331,-1436947067},
+{1518500216,-1518500282}, {1436946998,-1595891394}, {1351455207,-1668908277},
+{1262259172,-1737350799}, {1169603371,-1801031362}, {1073741769,-1859775424},
+{974937230,-1913421912}, {873460227,-1961823959}, {769589125,-2004848771},
+{663608871,-2042378339}, {555809715,-2074309903}, {446486876,-2100555994},
+{335940246,-2121044593}, {224473078,-2135719516}, {112390647,-2144540593},
+{2147483647,0}, {2135719506,-224473172}, {2100555974,-446486968},
+{2042378310,-663608960}, {1961823921,-873460313}, {1859775377,-1073741851},
+{1737350743,-1262259248}, {1595891331,-1436947067}, {1436946998,-1595891394},
+{1262259172,-1737350799}, {1073741769,-1859775424}, {873460227,-1961823959},
+{663608871,-2042378339}, {446486876,-2100555994}, {224473078,-2135719516},
+{-94,-2147483647}, {-224473265,-2135719496}, {-446487060,-2100555955},
+{-663609049,-2042378281}, {-873460398,-1961823883}, {-1073741932,-1859775330},
+{-1262259116,-1737350839}, {-1436947137,-1595891268}, {-1595891628,-1436946738},
+{-1737350854,-1262259096}, {-1859775343,-1073741910}, {-1961823997,-873460141},
+{-2042378447,-663608538}, {-2100556013,-446486785}, {-2135719499,-224473240},
+{2147483647,0}, {2121044558,-335940465}, {2042378310,-663608960},
+{1913421927,-974937199}, {1737350743,-1262259248}, {1518500216,-1518500282},
+{1262259172,-1737350799}, {974937230,-1913421912}, {663608871,-2042378339},
+{335940246,-2121044593}, {-94,-2147483647}, {-335940431,-2121044564},
+{-663609049,-2042378281}, {-974937397,-1913421827}, {-1262259116,-1737350839},
+{-1518500258,-1518500240}, {-1737350854,-1262259096}, {-1913422071,-974936918},
+{-2042378447,-663608538}, {-2121044568,-335940406}, {-2147483647,188},
+{-2121044509,335940777}, {-2042378331,663608895}, {-1913421900,974937252},
+{-1737350633,1262259400}, {-1518499993,1518500506}, {-1262258813,1737351059},
+{-974936606,1913422229}, {-663609179,2042378239}, {-335940566,2121044542},
+};
+static const ne10_fft_cpx_int32_t ne10_twiddles_60[60] = {
+{0,0}, {2147483647,0}, {2147483647,0},
+{2147483647,0}, {1961823921,-873460313}, {1436946998,-1595891394},
+{2147483647,0}, {1436946998,-1595891394}, {-224473265,-2135719496},
+{2147483647,0}, {663608871,-2042378339}, {-1737350854,-1262259096},
+{2147483647,0}, {-224473265,-2135719496}, {-2100555935,446487152},
+{2147483647,0}, {2135719506,-224473172}, {2100555974,-446486968},
+{2042378310,-663608960}, {1961823921,-873460313}, {1859775377,-1073741851},
+{1737350743,-1262259248}, {1595891331,-1436947067}, {1436946998,-1595891394},
+{1262259172,-1737350799}, {1073741769,-1859775424}, {873460227,-1961823959},
+{663608871,-2042378339}, {446486876,-2100555994}, {224473078,-2135719516},
+{2147483647,0}, {2100555974,-446486968}, {1961823921,-873460313},
+{1737350743,-1262259248}, {1436946998,-1595891394}, {1073741769,-1859775424},
+{663608871,-2042378339}, {224473078,-2135719516}, {-224473265,-2135719496},
+{-663609049,-2042378281}, {-1073741932,-1859775330}, {-1436947137,-1595891268},
+{-1737350854,-1262259096}, {-1961823997,-873460141}, {-2100556013,-446486785},
+{2147483647,0}, {2042378310,-663608960}, {1737350743,-1262259248},
+{1262259172,-1737350799}, {663608871,-2042378339}, {-94,-2147483647},
+{-663609049,-2042378281}, {-1262259116,-1737350839}, {-1737350854,-1262259096},
+{-2042378447,-663608538}, {-2147483647,188}, {-2042378331,663608895},
+{-1737350633,1262259400}, {-1262258813,1737351059}, {-663609179,2042378239},
+};
+static const ne10_fft_state_int32_t ne10_fft_state_int32_t_480 = {
+120,
+(ne10_int32_t *)ne10_factors_480,
+(ne10_fft_cpx_int32_t *)ne10_twiddles_480,
+NULL,
+(ne10_fft_cpx_int32_t *)&ne10_twiddles_480[120],
+};
+static const arch_fft_state cfg_arch_480 = {
+1,
+(void *)&ne10_fft_state_int32_t_480,
+};
+
+static const ne10_fft_state_int32_t ne10_fft_state_int32_t_240 = {
+60,
+(ne10_int32_t *)ne10_factors_240,
+(ne10_fft_cpx_int32_t *)ne10_twiddles_240,
+NULL,
+(ne10_fft_cpx_int32_t *)&ne10_twiddles_240[60],
+};
+static const arch_fft_state cfg_arch_240 = {
+1,
+(void *)&ne10_fft_state_int32_t_240,
+};
+
+static const ne10_fft_state_int32_t ne10_fft_state_int32_t_120 = {
+30,
+(ne10_int32_t *)ne10_factors_120,
+(ne10_fft_cpx_int32_t *)ne10_twiddles_120,
+NULL,
+(ne10_fft_cpx_int32_t *)&ne10_twiddles_120[30],
+};
+static const arch_fft_state cfg_arch_120 = {
+1,
+(void *)&ne10_fft_state_int32_t_120,
+};
+
+static const ne10_fft_state_int32_t ne10_fft_state_int32_t_60 = {
+15,
+(ne10_int32_t *)ne10_factors_60,
+(ne10_fft_cpx_int32_t *)ne10_twiddles_60,
+NULL,
+(ne10_fft_cpx_int32_t *)&ne10_twiddles_60[15],
+};
+static const arch_fft_state cfg_arch_60 = {
+1,
+(void *)&ne10_fft_state_int32_t_60,
+};
+
+#endif /* end NE10_FFT_PARAMS48000_960 */
--- /dev/null
+/* The contents of this file was automatically generated by dump_modes.c
+ with arguments: 48000 960 96000 1920
+ It contains static definitions for some pre-defined modes. */
+#include "modes.h"
+#include "rate.h"
+
+#ifdef HAVE_ARM_NE10
+#define OVERRIDE_FFT 1
+#include "static_modes_float_arm_ne10.h"
+#endif
+
+#ifndef DEF_WINDOW120
+#define DEF_WINDOW120
+static const celt_coef window120[120] = {
+6.7286966e-05f, 0.00060551348f, 0.0016815970f, 0.0032947962f, 0.0054439943f,
+0.0081276923f, 0.011344001f, 0.015090633f, 0.019364886f, 0.024163635f,
+0.029483315f, 0.035319905f, 0.041668911f, 0.048525347f, 0.055883718f,
+0.063737999f, 0.072081616f, 0.080907428f, 0.090207705f, 0.099974111f,
+0.11019769f, 0.12086883f, 0.13197729f, 0.14351214f, 0.15546177f,
+0.16781389f, 0.18055550f, 0.19367290f, 0.20715171f, 0.22097682f,
+0.23513243f, 0.24960208f, 0.26436860f, 0.27941419f, 0.29472040f,
+0.31026818f, 0.32603788f, 0.34200931f, 0.35816177f, 0.37447407f,
+0.39092462f, 0.40749142f, 0.42415215f, 0.44088423f, 0.45766484f,
+0.47447104f, 0.49127978f, 0.50806798f, 0.52481261f, 0.54149077f,
+0.55807973f, 0.57455701f, 0.59090049f, 0.60708841f, 0.62309951f,
+0.63891306f, 0.65450896f, 0.66986776f, 0.68497077f, 0.69980010f,
+0.71433873f, 0.72857055f, 0.74248043f, 0.75605425f, 0.76927895f,
+0.78214257f, 0.79463430f, 0.80674445f, 0.81846456f, 0.82978733f,
+0.84070669f, 0.85121779f, 0.86131698f, 0.87100183f, 0.88027111f,
+0.88912479f, 0.89756398f, 0.90559094f, 0.91320904f, 0.92042270f,
+0.92723738f, 0.93365955f, 0.93969656f, 0.94535671f, 0.95064907f,
+0.95558353f, 0.96017067f, 0.96442171f, 0.96834849f, 0.97196334f,
+0.97527906f, 0.97830883f, 0.98106616f, 0.98356480f, 0.98581869f,
+0.98784191f, 0.98964856f, 0.99125274f, 0.99266849f, 0.99390969f,
+0.99499004f, 0.99592297f, 0.99672162f, 0.99739874f, 0.99796667f,
+0.99843728f, 0.99882195f, 0.99913147f, 0.99937606f, 0.99956527f,
+0.99970802f, 0.99981248f, 0.99988613f, 0.99993565f, 0.99996697f,
+0.99998518f, 0.99999457f, 0.99999859f, 0.99999982f, 1.0000000f,
+};
+#endif
+
+#ifndef DEF_LOGN400
+#define DEF_LOGN400
+static const opus_int16 logN400[21] = {
+0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
+#endif
+
+#ifndef DEF_PULSE_CACHE50
+#define DEF_PULSE_CACHE50
+static const opus_int16 cache_index50[105] = {
+-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
+82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
+41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
+318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
+305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
+240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
+};
+static const unsigned char cache_bits50[392] = {
+40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
+31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
+51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
+66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
+64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
+94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
+124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
+97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
+142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
+28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
+153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
+229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
+166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
+86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
+25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
+185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
+110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
+74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
+163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
+228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
+90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
+87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
+106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
+224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
+182, 234, };
+static const unsigned char cache_caps50[168] = {
+224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
+178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
+240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
+160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
+138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
+204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
+185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
+207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
+188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
+193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
+204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
+140, 66, 40, };
+#endif
+
+#ifdef ENABLE_QEXT
+# ifndef DEF_QEXT_PULSE_CACHE50
+# define DEF_QEXT_PULSE_CACHE50
+static const opus_int16 qext_cache_index50[70] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 61, 61,
+61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 72, 72, 72,
+72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 80, 80, 80, 80,
+80, 80, 80, 80, 80, 80, 80, 80, 80, 80, };
+static const unsigned char qext_cache_bits50[86] = {
+40, 26, 45, 59, 70, 79, 87, 94, 100, 105, 110, 114, 118, 122, 125,
+128, 131, 136, 141, 146, 150, 153, 157, 160, 163, 168, 173, 178, 182, 185,
+189, 192, 195, 200, 205, 210, 214, 217, 221, 224, 227, 19, 34, 61, 83,
+101, 118, 132, 145, 157, 167, 177, 186, 194, 202, 209, 216, 222, 234, 245,
+254, 10, 42, 77, 107, 133, 157, 179, 200, 219, 236, 253, 7, 50, 93,
+131, 165, 197, 227, 255, 5, 58, 109, 155, 197, 237, };
+static const unsigned char qext_cache_caps50[112] = {
+159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 171,
+171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 167, 167, 167,
+167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 166, 166, 166, 166, 166,
+166, 166, 166, 166, 166, 166, 166, 166, 166, 163, 163, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 165, 165, 165, 165, 165, 165, 165,
+165, 165, 165, 165, 165, 165, 165, };
+# endif
+#endif
+
+#ifndef FFT_TWIDDLES48000_960
+#define FFT_TWIDDLES48000_960
+static const kiss_twiddle_cpx fft_twiddles48000_960[480] = {
+{1.0000000f, -0.0000000f}, {0.99991433f, -0.013089596f},
+{0.99965732f, -0.026176948f}, {0.99922904f, -0.039259816f},
+{0.99862953f, -0.052335956f}, {0.99785892f, -0.065403129f},
+{0.99691733f, -0.078459096f}, {0.99580493f, -0.091501619f},
+{0.99452190f, -0.10452846f}, {0.99306846f, -0.11753740f},
+{0.99144486f, -0.13052619f}, {0.98965139f, -0.14349262f},
+{0.98768834f, -0.15643447f}, {0.98555606f, -0.16934950f},
+{0.98325491f, -0.18223553f}, {0.98078528f, -0.19509032f},
+{0.97814760f, -0.20791169f}, {0.97534232f, -0.22069744f},
+{0.97236992f, -0.23344536f}, {0.96923091f, -0.24615329f},
+{0.96592583f, -0.25881905f}, {0.96245524f, -0.27144045f},
+{0.95881973f, -0.28401534f}, {0.95501994f, -0.29654157f},
+{0.95105652f, -0.30901699f}, {0.94693013f, -0.32143947f},
+{0.94264149f, -0.33380686f}, {0.93819134f, -0.34611706f},
+{0.93358043f, -0.35836795f}, {0.92880955f, -0.37055744f},
+{0.92387953f, -0.38268343f}, {0.91879121f, -0.39474386f},
+{0.91354546f, -0.40673664f}, {0.90814317f, -0.41865974f},
+{0.90258528f, -0.43051110f}, {0.89687274f, -0.44228869f},
+{0.89100652f, -0.45399050f}, {0.88498764f, -0.46561452f},
+{0.87881711f, -0.47715876f}, {0.87249601f, -0.48862124f},
+{0.86602540f, -0.50000000f}, {0.85940641f, -0.51129309f},
+{0.85264016f, -0.52249856f}, {0.84572782f, -0.53361452f},
+{0.83867057f, -0.54463904f}, {0.83146961f, -0.55557023f},
+{0.82412619f, -0.56640624f}, {0.81664156f, -0.57714519f},
+{0.80901699f, -0.58778525f}, {0.80125381f, -0.59832460f},
+{0.79335334f, -0.60876143f}, {0.78531693f, -0.61909395f},
+{0.77714596f, -0.62932039f}, {0.76884183f, -0.63943900f},
+{0.76040597f, -0.64944805f}, {0.75183981f, -0.65934582f},
+{0.74314483f, -0.66913061f}, {0.73432251f, -0.67880075f},
+{0.72537437f, -0.68835458f}, {0.71630194f, -0.69779046f},
+{0.70710678f, -0.70710678f}, {0.69779046f, -0.71630194f},
+{0.68835458f, -0.72537437f}, {0.67880075f, -0.73432251f},
+{0.66913061f, -0.74314483f}, {0.65934582f, -0.75183981f},
+{0.64944805f, -0.76040597f}, {0.63943900f, -0.76884183f},
+{0.62932039f, -0.77714596f}, {0.61909395f, -0.78531693f},
+{0.60876143f, -0.79335334f}, {0.59832460f, -0.80125381f},
+{0.58778525f, -0.80901699f}, {0.57714519f, -0.81664156f},
+{0.56640624f, -0.82412619f}, {0.55557023f, -0.83146961f},
+{0.54463904f, -0.83867057f}, {0.53361452f, -0.84572782f},
+{0.52249856f, -0.85264016f}, {0.51129309f, -0.85940641f},
+{0.50000000f, -0.86602540f}, {0.48862124f, -0.87249601f},
+{0.47715876f, -0.87881711f}, {0.46561452f, -0.88498764f},
+{0.45399050f, -0.89100652f}, {0.44228869f, -0.89687274f},
+{0.43051110f, -0.90258528f}, {0.41865974f, -0.90814317f},
+{0.40673664f, -0.91354546f}, {0.39474386f, -0.91879121f},
+{0.38268343f, -0.92387953f}, {0.37055744f, -0.92880955f},
+{0.35836795f, -0.93358043f}, {0.34611706f, -0.93819134f},
+{0.33380686f, -0.94264149f}, {0.32143947f, -0.94693013f},
+{0.30901699f, -0.95105652f}, {0.29654157f, -0.95501994f},
+{0.28401534f, -0.95881973f}, {0.27144045f, -0.96245524f},
+{0.25881905f, -0.96592583f}, {0.24615329f, -0.96923091f},
+{0.23344536f, -0.97236992f}, {0.22069744f, -0.97534232f},
+{0.20791169f, -0.97814760f}, {0.19509032f, -0.98078528f},
+{0.18223553f, -0.98325491f}, {0.16934950f, -0.98555606f},
+{0.15643447f, -0.98768834f}, {0.14349262f, -0.98965139f},
+{0.13052619f, -0.99144486f}, {0.11753740f, -0.99306846f},
+{0.10452846f, -0.99452190f}, {0.091501619f, -0.99580493f},
+{0.078459096f, -0.99691733f}, {0.065403129f, -0.99785892f},
+{0.052335956f, -0.99862953f}, {0.039259816f, -0.99922904f},
+{0.026176948f, -0.99965732f}, {0.013089596f, -0.99991433f},
+{6.1232340e-17f, -1.0000000f}, {-0.013089596f, -0.99991433f},
+{-0.026176948f, -0.99965732f}, {-0.039259816f, -0.99922904f},
+{-0.052335956f, -0.99862953f}, {-0.065403129f, -0.99785892f},
+{-0.078459096f, -0.99691733f}, {-0.091501619f, -0.99580493f},
+{-0.10452846f, -0.99452190f}, {-0.11753740f, -0.99306846f},
+{-0.13052619f, -0.99144486f}, {-0.14349262f, -0.98965139f},
+{-0.15643447f, -0.98768834f}, {-0.16934950f, -0.98555606f},
+{-0.18223553f, -0.98325491f}, {-0.19509032f, -0.98078528f},
+{-0.20791169f, -0.97814760f}, {-0.22069744f, -0.97534232f},
+{-0.23344536f, -0.97236992f}, {-0.24615329f, -0.96923091f},
+{-0.25881905f, -0.96592583f}, {-0.27144045f, -0.96245524f},
+{-0.28401534f, -0.95881973f}, {-0.29654157f, -0.95501994f},
+{-0.30901699f, -0.95105652f}, {-0.32143947f, -0.94693013f},
+{-0.33380686f, -0.94264149f}, {-0.34611706f, -0.93819134f},
+{-0.35836795f, -0.93358043f}, {-0.37055744f, -0.92880955f},
+{-0.38268343f, -0.92387953f}, {-0.39474386f, -0.91879121f},
+{-0.40673664f, -0.91354546f}, {-0.41865974f, -0.90814317f},
+{-0.43051110f, -0.90258528f}, {-0.44228869f, -0.89687274f},
+{-0.45399050f, -0.89100652f}, {-0.46561452f, -0.88498764f},
+{-0.47715876f, -0.87881711f}, {-0.48862124f, -0.87249601f},
+{-0.50000000f, -0.86602540f}, {-0.51129309f, -0.85940641f},
+{-0.52249856f, -0.85264016f}, {-0.53361452f, -0.84572782f},
+{-0.54463904f, -0.83867057f}, {-0.55557023f, -0.83146961f},
+{-0.56640624f, -0.82412619f}, {-0.57714519f, -0.81664156f},
+{-0.58778525f, -0.80901699f}, {-0.59832460f, -0.80125381f},
+{-0.60876143f, -0.79335334f}, {-0.61909395f, -0.78531693f},
+{-0.62932039f, -0.77714596f}, {-0.63943900f, -0.76884183f},
+{-0.64944805f, -0.76040597f}, {-0.65934582f, -0.75183981f},
+{-0.66913061f, -0.74314483f}, {-0.67880075f, -0.73432251f},
+{-0.68835458f, -0.72537437f}, {-0.69779046f, -0.71630194f},
+{-0.70710678f, -0.70710678f}, {-0.71630194f, -0.69779046f},
+{-0.72537437f, -0.68835458f}, {-0.73432251f, -0.67880075f},
+{-0.74314483f, -0.66913061f}, {-0.75183981f, -0.65934582f},
+{-0.76040597f, -0.64944805f}, {-0.76884183f, -0.63943900f},
+{-0.77714596f, -0.62932039f}, {-0.78531693f, -0.61909395f},
+{-0.79335334f, -0.60876143f}, {-0.80125381f, -0.59832460f},
+{-0.80901699f, -0.58778525f}, {-0.81664156f, -0.57714519f},
+{-0.82412619f, -0.56640624f}, {-0.83146961f, -0.55557023f},
+{-0.83867057f, -0.54463904f}, {-0.84572782f, -0.53361452f},
+{-0.85264016f, -0.52249856f}, {-0.85940641f, -0.51129309f},
+{-0.86602540f, -0.50000000f}, {-0.87249601f, -0.48862124f},
+{-0.87881711f, -0.47715876f}, {-0.88498764f, -0.46561452f},
+{-0.89100652f, -0.45399050f}, {-0.89687274f, -0.44228869f},
+{-0.90258528f, -0.43051110f}, {-0.90814317f, -0.41865974f},
+{-0.91354546f, -0.40673664f}, {-0.91879121f, -0.39474386f},
+{-0.92387953f, -0.38268343f}, {-0.92880955f, -0.37055744f},
+{-0.93358043f, -0.35836795f}, {-0.93819134f, -0.34611706f},
+{-0.94264149f, -0.33380686f}, {-0.94693013f, -0.32143947f},
+{-0.95105652f, -0.30901699f}, {-0.95501994f, -0.29654157f},
+{-0.95881973f, -0.28401534f}, {-0.96245524f, -0.27144045f},
+{-0.96592583f, -0.25881905f}, {-0.96923091f, -0.24615329f},
+{-0.97236992f, -0.23344536f}, {-0.97534232f, -0.22069744f},
+{-0.97814760f, -0.20791169f}, {-0.98078528f, -0.19509032f},
+{-0.98325491f, -0.18223553f}, {-0.98555606f, -0.16934950f},
+{-0.98768834f, -0.15643447f}, {-0.98965139f, -0.14349262f},
+{-0.99144486f, -0.13052619f}, {-0.99306846f, -0.11753740f},
+{-0.99452190f, -0.10452846f}, {-0.99580493f, -0.091501619f},
+{-0.99691733f, -0.078459096f}, {-0.99785892f, -0.065403129f},
+{-0.99862953f, -0.052335956f}, {-0.99922904f, -0.039259816f},
+{-0.99965732f, -0.026176948f}, {-0.99991433f, -0.013089596f},
+{-1.0000000f, -1.2246468e-16f}, {-0.99991433f, 0.013089596f},
+{-0.99965732f, 0.026176948f}, {-0.99922904f, 0.039259816f},
+{-0.99862953f, 0.052335956f}, {-0.99785892f, 0.065403129f},
+{-0.99691733f, 0.078459096f}, {-0.99580493f, 0.091501619f},
+{-0.99452190f, 0.10452846f}, {-0.99306846f, 0.11753740f},
+{-0.99144486f, 0.13052619f}, {-0.98965139f, 0.14349262f},
+{-0.98768834f, 0.15643447f}, {-0.98555606f, 0.16934950f},
+{-0.98325491f, 0.18223553f}, {-0.98078528f, 0.19509032f},
+{-0.97814760f, 0.20791169f}, {-0.97534232f, 0.22069744f},
+{-0.97236992f, 0.23344536f}, {-0.96923091f, 0.24615329f},
+{-0.96592583f, 0.25881905f}, {-0.96245524f, 0.27144045f},
+{-0.95881973f, 0.28401534f}, {-0.95501994f, 0.29654157f},
+{-0.95105652f, 0.30901699f}, {-0.94693013f, 0.32143947f},
+{-0.94264149f, 0.33380686f}, {-0.93819134f, 0.34611706f},
+{-0.93358043f, 0.35836795f}, {-0.92880955f, 0.37055744f},
+{-0.92387953f, 0.38268343f}, {-0.91879121f, 0.39474386f},
+{-0.91354546f, 0.40673664f}, {-0.90814317f, 0.41865974f},
+{-0.90258528f, 0.43051110f}, {-0.89687274f, 0.44228869f},
+{-0.89100652f, 0.45399050f}, {-0.88498764f, 0.46561452f},
+{-0.87881711f, 0.47715876f}, {-0.87249601f, 0.48862124f},
+{-0.86602540f, 0.50000000f}, {-0.85940641f, 0.51129309f},
+{-0.85264016f, 0.52249856f}, {-0.84572782f, 0.53361452f},
+{-0.83867057f, 0.54463904f}, {-0.83146961f, 0.55557023f},
+{-0.82412619f, 0.56640624f}, {-0.81664156f, 0.57714519f},
+{-0.80901699f, 0.58778525f}, {-0.80125381f, 0.59832460f},
+{-0.79335334f, 0.60876143f}, {-0.78531693f, 0.61909395f},
+{-0.77714596f, 0.62932039f}, {-0.76884183f, 0.63943900f},
+{-0.76040597f, 0.64944805f}, {-0.75183981f, 0.65934582f},
+{-0.74314483f, 0.66913061f}, {-0.73432251f, 0.67880075f},
+{-0.72537437f, 0.68835458f}, {-0.71630194f, 0.69779046f},
+{-0.70710678f, 0.70710678f}, {-0.69779046f, 0.71630194f},
+{-0.68835458f, 0.72537437f}, {-0.67880075f, 0.73432251f},
+{-0.66913061f, 0.74314483f}, {-0.65934582f, 0.75183981f},
+{-0.64944805f, 0.76040597f}, {-0.63943900f, 0.76884183f},
+{-0.62932039f, 0.77714596f}, {-0.61909395f, 0.78531693f},
+{-0.60876143f, 0.79335334f}, {-0.59832460f, 0.80125381f},
+{-0.58778525f, 0.80901699f}, {-0.57714519f, 0.81664156f},
+{-0.56640624f, 0.82412619f}, {-0.55557023f, 0.83146961f},
+{-0.54463904f, 0.83867057f}, {-0.53361452f, 0.84572782f},
+{-0.52249856f, 0.85264016f}, {-0.51129309f, 0.85940641f},
+{-0.50000000f, 0.86602540f}, {-0.48862124f, 0.87249601f},
+{-0.47715876f, 0.87881711f}, {-0.46561452f, 0.88498764f},
+{-0.45399050f, 0.89100652f}, {-0.44228869f, 0.89687274f},
+{-0.43051110f, 0.90258528f}, {-0.41865974f, 0.90814317f},
+{-0.40673664f, 0.91354546f}, {-0.39474386f, 0.91879121f},
+{-0.38268343f, 0.92387953f}, {-0.37055744f, 0.92880955f},
+{-0.35836795f, 0.93358043f}, {-0.34611706f, 0.93819134f},
+{-0.33380686f, 0.94264149f}, {-0.32143947f, 0.94693013f},
+{-0.30901699f, 0.95105652f}, {-0.29654157f, 0.95501994f},
+{-0.28401534f, 0.95881973f}, {-0.27144045f, 0.96245524f},
+{-0.25881905f, 0.96592583f}, {-0.24615329f, 0.96923091f},
+{-0.23344536f, 0.97236992f}, {-0.22069744f, 0.97534232f},
+{-0.20791169f, 0.97814760f}, {-0.19509032f, 0.98078528f},
+{-0.18223553f, 0.98325491f}, {-0.16934950f, 0.98555606f},
+{-0.15643447f, 0.98768834f}, {-0.14349262f, 0.98965139f},
+{-0.13052619f, 0.99144486f}, {-0.11753740f, 0.99306846f},
+{-0.10452846f, 0.99452190f}, {-0.091501619f, 0.99580493f},
+{-0.078459096f, 0.99691733f}, {-0.065403129f, 0.99785892f},
+{-0.052335956f, 0.99862953f}, {-0.039259816f, 0.99922904f},
+{-0.026176948f, 0.99965732f}, {-0.013089596f, 0.99991433f},
+{-1.8369702e-16f, 1.0000000f}, {0.013089596f, 0.99991433f},
+{0.026176948f, 0.99965732f}, {0.039259816f, 0.99922904f},
+{0.052335956f, 0.99862953f}, {0.065403129f, 0.99785892f},
+{0.078459096f, 0.99691733f}, {0.091501619f, 0.99580493f},
+{0.10452846f, 0.99452190f}, {0.11753740f, 0.99306846f},
+{0.13052619f, 0.99144486f}, {0.14349262f, 0.98965139f},
+{0.15643447f, 0.98768834f}, {0.16934950f, 0.98555606f},
+{0.18223553f, 0.98325491f}, {0.19509032f, 0.98078528f},
+{0.20791169f, 0.97814760f}, {0.22069744f, 0.97534232f},
+{0.23344536f, 0.97236992f}, {0.24615329f, 0.96923091f},
+{0.25881905f, 0.96592583f}, {0.27144045f, 0.96245524f},
+{0.28401534f, 0.95881973f}, {0.29654157f, 0.95501994f},
+{0.30901699f, 0.95105652f}, {0.32143947f, 0.94693013f},
+{0.33380686f, 0.94264149f}, {0.34611706f, 0.93819134f},
+{0.35836795f, 0.93358043f}, {0.37055744f, 0.92880955f},
+{0.38268343f, 0.92387953f}, {0.39474386f, 0.91879121f},
+{0.40673664f, 0.91354546f}, {0.41865974f, 0.90814317f},
+{0.43051110f, 0.90258528f}, {0.44228869f, 0.89687274f},
+{0.45399050f, 0.89100652f}, {0.46561452f, 0.88498764f},
+{0.47715876f, 0.87881711f}, {0.48862124f, 0.87249601f},
+{0.50000000f, 0.86602540f}, {0.51129309f, 0.85940641f},
+{0.52249856f, 0.85264016f}, {0.53361452f, 0.84572782f},
+{0.54463904f, 0.83867057f}, {0.55557023f, 0.83146961f},
+{0.56640624f, 0.82412619f}, {0.57714519f, 0.81664156f},
+{0.58778525f, 0.80901699f}, {0.59832460f, 0.80125381f},
+{0.60876143f, 0.79335334f}, {0.61909395f, 0.78531693f},
+{0.62932039f, 0.77714596f}, {0.63943900f, 0.76884183f},
+{0.64944805f, 0.76040597f}, {0.65934582f, 0.75183981f},
+{0.66913061f, 0.74314483f}, {0.67880075f, 0.73432251f},
+{0.68835458f, 0.72537437f}, {0.69779046f, 0.71630194f},
+{0.70710678f, 0.70710678f}, {0.71630194f, 0.69779046f},
+{0.72537437f, 0.68835458f}, {0.73432251f, 0.67880075f},
+{0.74314483f, 0.66913061f}, {0.75183981f, 0.65934582f},
+{0.76040597f, 0.64944805f}, {0.76884183f, 0.63943900f},
+{0.77714596f, 0.62932039f}, {0.78531693f, 0.61909395f},
+{0.79335334f, 0.60876143f}, {0.80125381f, 0.59832460f},
+{0.80901699f, 0.58778525f}, {0.81664156f, 0.57714519f},
+{0.82412619f, 0.56640624f}, {0.83146961f, 0.55557023f},
+{0.83867057f, 0.54463904f}, {0.84572782f, 0.53361452f},
+{0.85264016f, 0.52249856f}, {0.85940641f, 0.51129309f},
+{0.86602540f, 0.50000000f}, {0.87249601f, 0.48862124f},
+{0.87881711f, 0.47715876f}, {0.88498764f, 0.46561452f},
+{0.89100652f, 0.45399050f}, {0.89687274f, 0.44228869f},
+{0.90258528f, 0.43051110f}, {0.90814317f, 0.41865974f},
+{0.91354546f, 0.40673664f}, {0.91879121f, 0.39474386f},
+{0.92387953f, 0.38268343f}, {0.92880955f, 0.37055744f},
+{0.93358043f, 0.35836795f}, {0.93819134f, 0.34611706f},
+{0.94264149f, 0.33380686f}, {0.94693013f, 0.32143947f},
+{0.95105652f, 0.30901699f}, {0.95501994f, 0.29654157f},
+{0.95881973f, 0.28401534f}, {0.96245524f, 0.27144045f},
+{0.96592583f, 0.25881905f}, {0.96923091f, 0.24615329f},
+{0.97236992f, 0.23344536f}, {0.97534232f, 0.22069744f},
+{0.97814760f, 0.20791169f}, {0.98078528f, 0.19509032f},
+{0.98325491f, 0.18223553f}, {0.98555606f, 0.16934950f},
+{0.98768834f, 0.15643447f}, {0.98965139f, 0.14349262f},
+{0.99144486f, 0.13052619f}, {0.99306846f, 0.11753740f},
+{0.99452190f, 0.10452846f}, {0.99580493f, 0.091501619f},
+{0.99691733f, 0.078459096f}, {0.99785892f, 0.065403129f},
+{0.99862953f, 0.052335956f}, {0.99922904f, 0.039259816f},
+{0.99965732f, 0.026176948f}, {0.99991433f, 0.013089596f},
+};
+#ifndef FFT_BITREV480
+#define FFT_BITREV480
+static const opus_int16 fft_bitrev480[480] = {
+0, 96, 192, 288, 384, 32, 128, 224, 320, 416, 64, 160, 256, 352, 448,
+8, 104, 200, 296, 392, 40, 136, 232, 328, 424, 72, 168, 264, 360, 456,
+16, 112, 208, 304, 400, 48, 144, 240, 336, 432, 80, 176, 272, 368, 464,
+24, 120, 216, 312, 408, 56, 152, 248, 344, 440, 88, 184, 280, 376, 472,
+4, 100, 196, 292, 388, 36, 132, 228, 324, 420, 68, 164, 260, 356, 452,
+12, 108, 204, 300, 396, 44, 140, 236, 332, 428, 76, 172, 268, 364, 460,
+20, 116, 212, 308, 404, 52, 148, 244, 340, 436, 84, 180, 276, 372, 468,
+28, 124, 220, 316, 412, 60, 156, 252, 348, 444, 92, 188, 284, 380, 476,
+1, 97, 193, 289, 385, 33, 129, 225, 321, 417, 65, 161, 257, 353, 449,
+9, 105, 201, 297, 393, 41, 137, 233, 329, 425, 73, 169, 265, 361, 457,
+17, 113, 209, 305, 401, 49, 145, 241, 337, 433, 81, 177, 273, 369, 465,
+25, 121, 217, 313, 409, 57, 153, 249, 345, 441, 89, 185, 281, 377, 473,
+5, 101, 197, 293, 389, 37, 133, 229, 325, 421, 69, 165, 261, 357, 453,
+13, 109, 205, 301, 397, 45, 141, 237, 333, 429, 77, 173, 269, 365, 461,
+21, 117, 213, 309, 405, 53, 149, 245, 341, 437, 85, 181, 277, 373, 469,
+29, 125, 221, 317, 413, 61, 157, 253, 349, 445, 93, 189, 285, 381, 477,
+2, 98, 194, 290, 386, 34, 130, 226, 322, 418, 66, 162, 258, 354, 450,
+10, 106, 202, 298, 394, 42, 138, 234, 330, 426, 74, 170, 266, 362, 458,
+18, 114, 210, 306, 402, 50, 146, 242, 338, 434, 82, 178, 274, 370, 466,
+26, 122, 218, 314, 410, 58, 154, 250, 346, 442, 90, 186, 282, 378, 474,
+6, 102, 198, 294, 390, 38, 134, 230, 326, 422, 70, 166, 262, 358, 454,
+14, 110, 206, 302, 398, 46, 142, 238, 334, 430, 78, 174, 270, 366, 462,
+22, 118, 214, 310, 406, 54, 150, 246, 342, 438, 86, 182, 278, 374, 470,
+30, 126, 222, 318, 414, 62, 158, 254, 350, 446, 94, 190, 286, 382, 478,
+3, 99, 195, 291, 387, 35, 131, 227, 323, 419, 67, 163, 259, 355, 451,
+11, 107, 203, 299, 395, 43, 139, 235, 331, 427, 75, 171, 267, 363, 459,
+19, 115, 211, 307, 403, 51, 147, 243, 339, 435, 83, 179, 275, 371, 467,
+27, 123, 219, 315, 411, 59, 155, 251, 347, 443, 91, 187, 283, 379, 475,
+7, 103, 199, 295, 391, 39, 135, 231, 327, 423, 71, 167, 263, 359, 455,
+15, 111, 207, 303, 399, 47, 143, 239, 335, 431, 79, 175, 271, 367, 463,
+23, 119, 215, 311, 407, 55, 151, 247, 343, 439, 87, 183, 279, 375, 471,
+31, 127, 223, 319, 415, 63, 159, 255, 351, 447, 95, 191, 287, 383, 479,
+};
+#endif
+
+#ifndef FFT_BITREV240
+#define FFT_BITREV240
+static const opus_int16 fft_bitrev240[240] = {
+0, 48, 96, 144, 192, 16, 64, 112, 160, 208, 32, 80, 128, 176, 224,
+4, 52, 100, 148, 196, 20, 68, 116, 164, 212, 36, 84, 132, 180, 228,
+8, 56, 104, 152, 200, 24, 72, 120, 168, 216, 40, 88, 136, 184, 232,
+12, 60, 108, 156, 204, 28, 76, 124, 172, 220, 44, 92, 140, 188, 236,
+1, 49, 97, 145, 193, 17, 65, 113, 161, 209, 33, 81, 129, 177, 225,
+5, 53, 101, 149, 197, 21, 69, 117, 165, 213, 37, 85, 133, 181, 229,
+9, 57, 105, 153, 201, 25, 73, 121, 169, 217, 41, 89, 137, 185, 233,
+13, 61, 109, 157, 205, 29, 77, 125, 173, 221, 45, 93, 141, 189, 237,
+2, 50, 98, 146, 194, 18, 66, 114, 162, 210, 34, 82, 130, 178, 226,
+6, 54, 102, 150, 198, 22, 70, 118, 166, 214, 38, 86, 134, 182, 230,
+10, 58, 106, 154, 202, 26, 74, 122, 170, 218, 42, 90, 138, 186, 234,
+14, 62, 110, 158, 206, 30, 78, 126, 174, 222, 46, 94, 142, 190, 238,
+3, 51, 99, 147, 195, 19, 67, 115, 163, 211, 35, 83, 131, 179, 227,
+7, 55, 103, 151, 199, 23, 71, 119, 167, 215, 39, 87, 135, 183, 231,
+11, 59, 107, 155, 203, 27, 75, 123, 171, 219, 43, 91, 139, 187, 235,
+15, 63, 111, 159, 207, 31, 79, 127, 175, 223, 47, 95, 143, 191, 239,
+};
+#endif
+
+#ifndef FFT_BITREV120
+#define FFT_BITREV120
+static const opus_int16 fft_bitrev120[120] = {
+0, 24, 48, 72, 96, 8, 32, 56, 80, 104, 16, 40, 64, 88, 112,
+4, 28, 52, 76, 100, 12, 36, 60, 84, 108, 20, 44, 68, 92, 116,
+1, 25, 49, 73, 97, 9, 33, 57, 81, 105, 17, 41, 65, 89, 113,
+5, 29, 53, 77, 101, 13, 37, 61, 85, 109, 21, 45, 69, 93, 117,
+2, 26, 50, 74, 98, 10, 34, 58, 82, 106, 18, 42, 66, 90, 114,
+6, 30, 54, 78, 102, 14, 38, 62, 86, 110, 22, 46, 70, 94, 118,
+3, 27, 51, 75, 99, 11, 35, 59, 83, 107, 19, 43, 67, 91, 115,
+7, 31, 55, 79, 103, 15, 39, 63, 87, 111, 23, 47, 71, 95, 119,
+};
+#endif
+
+#ifndef FFT_BITREV60
+#define FFT_BITREV60
+static const opus_int16 fft_bitrev60[60] = {
+0, 12, 24, 36, 48, 4, 16, 28, 40, 52, 8, 20, 32, 44, 56,
+1, 13, 25, 37, 49, 5, 17, 29, 41, 53, 9, 21, 33, 45, 57,
+2, 14, 26, 38, 50, 6, 18, 30, 42, 54, 10, 22, 34, 46, 58,
+3, 15, 27, 39, 51, 7, 19, 31, 43, 55, 11, 23, 35, 47, 59,
+};
+#endif
+
+#ifndef FFT_STATE48000_960_0
+#define FFT_STATE48000_960_0
+static const kiss_fft_state fft_state48000_960_0 = {
+480, /* nfft */
+0.0020833334f, /* scale */
+-1, /* shift */
+{5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev480, /* bitrev */
+fft_twiddles48000_960, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_480,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE48000_960_1
+#define FFT_STATE48000_960_1
+static const kiss_fft_state fft_state48000_960_1 = {
+240, /* nfft */
+0.0041666669f, /* scale */
+1, /* shift */
+{5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev240, /* bitrev */
+fft_twiddles48000_960, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_240,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE48000_960_2
+#define FFT_STATE48000_960_2
+static const kiss_fft_state fft_state48000_960_2 = {
+120, /* nfft */
+0.0083333338f, /* scale */
+2, /* shift */
+{5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev120, /* bitrev */
+fft_twiddles48000_960, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_120,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE48000_960_3
+#define FFT_STATE48000_960_3
+static const kiss_fft_state fft_state48000_960_3 = {
+60, /* nfft */
+0.016666668f, /* scale */
+3, /* shift */
+{5, 12, 3, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev60, /* bitrev */
+fft_twiddles48000_960, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_60,
+#else
+NULL,
+#endif
+};
+#endif
+
+#endif
+
+#ifndef MDCT_TWIDDLES960
+#define MDCT_TWIDDLES960
+static const celt_coef mdct_twiddles960[1800] = {
+0.99999992f, 0.99999322f, 0.99997582f, 0.99994771f, 0.99990889f,
+0.99985936f, 0.99979913f, 0.99972818f, 0.99964653f, 0.99955418f,
+0.99945112f, 0.99933736f, 0.99921289f, 0.99907773f, 0.99893186f,
+0.99877530f, 0.99860804f, 0.99843009f, 0.99824144f, 0.99804211f,
+0.99783209f, 0.99761138f, 0.99737998f, 0.99713791f, 0.99688516f,
+0.99662173f, 0.99634763f, 0.99606285f, 0.99576741f, 0.99546131f,
+0.99514455f, 0.99481713f, 0.99447905f, 0.99413033f, 0.99377096f,
+0.99340095f, 0.99302029f, 0.99262901f, 0.99222709f, 0.99181455f,
+0.99139139f, 0.99095760f, 0.99051321f, 0.99005821f, 0.98959261f,
+0.98911641f, 0.98862961f, 0.98813223f, 0.98762427f, 0.98710573f,
+0.98657662f, 0.98603694f, 0.98548670f, 0.98492591f, 0.98435457f,
+0.98377269f, 0.98318028f, 0.98257734f, 0.98196387f, 0.98133989f,
+0.98070539f, 0.98006040f, 0.97940491f, 0.97873893f, 0.97806247f,
+0.97737554f, 0.97667813f, 0.97597027f, 0.97525196f, 0.97452320f,
+0.97378401f, 0.97303439f, 0.97227435f, 0.97150389f, 0.97072303f,
+0.96993178f, 0.96913014f, 0.96831812f, 0.96749573f, 0.96666298f,
+0.96581987f, 0.96496643f, 0.96410265f, 0.96322854f, 0.96234412f,
+0.96144939f, 0.96054437f, 0.95962906f, 0.95870347f, 0.95776762f,
+0.95682151f, 0.95586515f, 0.95489856f, 0.95392174f, 0.95293471f,
+0.95193746f, 0.95093003f, 0.94991241f, 0.94888462f, 0.94784667f,
+0.94679856f, 0.94574032f, 0.94467195f, 0.94359346f, 0.94250486f,
+0.94140618f, 0.94029741f, 0.93917857f, 0.93804967f, 0.93691073f,
+0.93576176f, 0.93460276f, 0.93343375f, 0.93225475f, 0.93106577f,
+0.92986681f, 0.92865789f, 0.92743903f, 0.92621024f, 0.92497153f,
+0.92372291f, 0.92246440f, 0.92119602f, 0.91991776f, 0.91862966f,
+0.91733172f, 0.91602395f, 0.91470637f, 0.91337900f, 0.91204185f,
+0.91069493f, 0.90933825f, 0.90797184f, 0.90659570f, 0.90520986f,
+0.90381432f, 0.90240910f, 0.90099422f, 0.89956969f, 0.89813553f,
+0.89669174f, 0.89523836f, 0.89377538f, 0.89230284f, 0.89082074f,
+0.88932910f, 0.88782793f, 0.88631726f, 0.88479710f, 0.88326746f,
+0.88172836f, 0.88017982f, 0.87862185f, 0.87705448f, 0.87547771f,
+0.87389156f, 0.87229606f, 0.87069121f, 0.86907704f, 0.86745357f,
+0.86582080f, 0.86417876f, 0.86252747f, 0.86086694f, 0.85919719f,
+0.85751824f, 0.85583010f, 0.85413281f, 0.85242636f, 0.85071078f,
+0.84898610f, 0.84725232f, 0.84550947f, 0.84375756f, 0.84199662f,
+0.84022666f, 0.83844771f, 0.83665977f, 0.83486287f, 0.83305704f,
+0.83124228f, 0.82941862f, 0.82758608f, 0.82574467f, 0.82389442f,
+0.82203535f, 0.82016748f, 0.81829082f, 0.81640540f, 0.81451123f,
+0.81260835f, 0.81069676f, 0.80877649f, 0.80684755f, 0.80490998f,
+0.80296379f, 0.80100899f, 0.79904562f, 0.79707370f, 0.79509323f,
+0.79310425f, 0.79110678f, 0.78910084f, 0.78708644f, 0.78506362f,
+0.78303239f, 0.78099277f, 0.77894479f, 0.77688847f, 0.77482382f,
+0.77275088f, 0.77066967f, 0.76858020f, 0.76648250f, 0.76437659f,
+0.76226250f, 0.76014024f, 0.75800984f, 0.75587132f, 0.75372471f,
+0.75157003f, 0.74940730f, 0.74723654f, 0.74505779f, 0.74287105f,
+0.74067635f, 0.73847373f, 0.73626320f, 0.73404478f, 0.73181850f,
+0.72958438f, 0.72734245f, 0.72509273f, 0.72283525f, 0.72057002f,
+0.71829708f, 0.71601644f, 0.71372814f, 0.71143220f, 0.70912863f,
+0.70681747f, 0.70449874f, 0.70217247f, 0.69983868f, 0.69749739f,
+0.69514863f, 0.69279243f, 0.69042881f, 0.68805780f, 0.68567941f,
+0.68329369f, 0.68090064f, 0.67850031f, 0.67609270f, 0.67367786f,
+0.67125580f, 0.66882656f, 0.66639015f, 0.66394661f, 0.66149595f,
+0.65903821f, 0.65657341f, 0.65410159f, 0.65162275f, 0.64913694f,
+0.64664418f, 0.64414449f, 0.64163790f, 0.63912444f, 0.63660414f,
+0.63407702f, 0.63154311f, 0.62900244f, 0.62645503f, 0.62390091f,
+0.62134011f, 0.61877265f, 0.61619857f, 0.61361789f, 0.61103064f,
+0.60843685f, 0.60583654f, 0.60322974f, 0.60061648f, 0.59799679f,
+0.59537069f, 0.59273822f, 0.59009940f, 0.58745427f, 0.58480284f,
+0.58214514f, 0.57948122f, 0.57681109f, 0.57413478f, 0.57145232f,
+0.56876374f, 0.56606907f, 0.56336834f, 0.56066158f, 0.55794881f,
+0.55523006f, 0.55250537f, 0.54977477f, 0.54703827f, 0.54429592f,
+0.54154774f, 0.53879376f, 0.53603401f, 0.53326852f, 0.53049731f,
+0.52772043f, 0.52493790f, 0.52214974f, 0.51935599f, 0.51655668f,
+0.51375184f, 0.51094149f, 0.50812568f, 0.50530442f, 0.50247775f,
+0.49964570f, 0.49680830f, 0.49396558f, 0.49111757f, 0.48826430f,
+0.48540580f, 0.48254210f, 0.47967323f, 0.47679923f, 0.47392012f,
+0.47103594f, 0.46814671f, 0.46525247f, 0.46235324f, 0.45944907f,
+0.45653997f, 0.45362599f, 0.45070714f, 0.44778347f, 0.44485501f,
+0.44192178f, 0.43898381f, 0.43604115f, 0.43309382f, 0.43014185f,
+0.42718527f, 0.42422412f, 0.42125842f, 0.41828822f, 0.41531353f,
+0.41233440f, 0.40935085f, 0.40636291f, 0.40337063f, 0.40037402f,
+0.39737313f, 0.39436798f, 0.39135861f, 0.38834505f, 0.38532733f,
+0.38230548f, 0.37927953f, 0.37624953f, 0.37321550f, 0.37017747f,
+0.36713547f, 0.36408955f, 0.36103972f, 0.35798603f, 0.35492850f,
+0.35186718f, 0.34880208f, 0.34573325f, 0.34266072f, 0.33958451f,
+0.33650468f, 0.33342123f, 0.33033422f, 0.32724367f, 0.32414961f,
+0.32105209f, 0.31795112f, 0.31484675f, 0.31173901f, 0.30862793f,
+0.30551354f, 0.30239588f, 0.29927499f, 0.29615089f, 0.29302362f,
+0.28989321f, 0.28675969f, 0.28362310f, 0.28048348f, 0.27734085f,
+0.27419526f, 0.27104672f, 0.26789529f, 0.26474098f, 0.26158384f,
+0.25842390f, 0.25526119f, 0.25209575f, 0.24892761f, 0.24575680f,
+0.24258336f, 0.23940732f, 0.23622872f, 0.23304759f, 0.22986396f,
+0.22667787f, 0.22348935f, 0.22029844f, 0.21710517f, 0.21390958f,
+0.21071169f, 0.20751155f, 0.20430919f, 0.20110463f, 0.19789793f,
+0.19468910f, 0.19147819f, 0.18826523f, 0.18505026f, 0.18183330f,
+0.17861439f, 0.17539357f, 0.17217088f, 0.16894634f, 0.16571999f,
+0.16249186f, 0.15926200f, 0.15603043f, 0.15279719f, 0.14956231f,
+0.14632583f, 0.14308778f, 0.13984820f, 0.13660713f, 0.13336459f,
+0.13012062f, 0.12687526f, 0.12362854f, 0.12038049f, 0.11713116f,
+0.11388057f, 0.11062877f, 0.10737578f, 0.10412163f, 0.10086638f,
+0.097610040f, 0.094352658f, 0.091094266f, 0.087834897f, 0.084574589f,
+0.081313374f, 0.078051289f, 0.074788367f, 0.071524645f, 0.068260157f,
+0.064994938f, 0.061729023f, 0.058462447f, 0.055195244f, 0.051927451f,
+0.048659101f, 0.045390231f, 0.042120874f, 0.038851066f, 0.035580842f,
+0.032310238f, 0.029039287f, 0.025768025f, 0.022496487f, 0.019224708f,
+0.015952723f, 0.012680568f, 0.0094082767f, 0.0061358846f, 0.0028634269f,
+-0.00040906153f, -0.0036815456f, -0.0069539902f, -0.010226360f, -0.013498621f,
+-0.016770737f, -0.020042673f, -0.023314395f, -0.026585867f, -0.029857055f,
+-0.033127923f, -0.036398436f, -0.039668559f, -0.042938257f, -0.046207495f,
+-0.049476239f, -0.052744453f, -0.056012102f, -0.059279151f, -0.062545565f,
+-0.065811309f, -0.069076349f, -0.072340649f, -0.075604174f, -0.078866890f,
+-0.082128761f, -0.085389752f, -0.088649829f, -0.091908956f, -0.095167100f,
+-0.098424224f, -0.10168029f, -0.10493528f, -0.10818913f, -0.11144183f,
+-0.11469334f, -0.11794361f, -0.12119263f, -0.12444034f, -0.12768673f,
+-0.13093174f, -0.13417536f, -0.13741753f, -0.14065824f, -0.14389744f,
+-0.14713510f, -0.15037118f, -0.15360565f, -0.15683848f, -0.16006962f,
+-0.16329906f, -0.16652674f, -0.16975264f, -0.17297673f, -0.17619896f,
+-0.17941930f, -0.18263772f, -0.18585419f, -0.18906866f, -0.19228112f,
+-0.19549151f, -0.19869981f, -0.20190598f, -0.20510998f, -0.20831180f,
+-0.21151138f, -0.21470869f, -0.21790371f, -0.22109639f, -0.22428671f,
+-0.22747462f, -0.23066010f, -0.23384310f, -0.23702361f, -0.24020157f,
+-0.24337696f, -0.24654975f, -0.24971989f, -0.25288736f, -0.25605213f,
+-0.25921415f, -0.26237339f, -0.26552983f, -0.26868342f, -0.27183413f,
+-0.27498193f, -0.27812679f, -0.28126867f, -0.28440754f, -0.28754336f,
+-0.29067610f, -0.29380573f, -0.29693221f, -0.30005551f, -0.30317560f,
+-0.30629245f, -0.30940601f, -0.31251626f, -0.31562316f, -0.31872668f,
+-0.32182679f, -0.32492345f, -0.32801664f, -0.33110631f, -0.33419243f,
+-0.33727497f, -0.34035391f, -0.34342920f, -0.34650081f, -0.34956871f,
+-0.35263286f, -0.35569324f, -0.35874981f, -0.36180254f, -0.36485139f,
+-0.36789634f, -0.37093735f, -0.37397438f, -0.37700741f, -0.38003640f,
+-0.38306132f, -0.38608214f, -0.38909883f, -0.39211135f, -0.39511967f,
+-0.39812375f, -0.40112358f, -0.40411910f, -0.40711031f, -0.41009715f,
+-0.41307959f, -0.41605762f, -0.41903119f, -0.42200027f, -0.42496483f,
+-0.42792484f, -0.43088027f, -0.43383109f, -0.43677726f, -0.43971875f,
+-0.44265553f, -0.44558757f, -0.44851484f, -0.45143731f, -0.45435494f,
+-0.45726770f, -0.46017557f, -0.46307851f, -0.46597650f, -0.46886949f,
+-0.47175746f, -0.47464038f, -0.47751821f, -0.48039093f, -0.48325851f,
+-0.48612091f, -0.48897811f, -0.49183006f, -0.49467676f, -0.49751815f,
+-0.50035422f, -0.50318492f, -0.50601024f, -0.50883014f, -0.51164459f,
+-0.51445356f, -0.51725703f, -0.52005495f, -0.52284730f, -0.52563406f,
+-0.52841518f, -0.53119065f, -0.53396043f, -0.53672449f, -0.53948280f,
+-0.54223533f, -0.54498206f, -0.54772295f, -0.55045797f, -0.55318710f,
+-0.55591031f, -0.55862756f, -0.56133883f, -0.56404409f, -0.56674331f,
+-0.56943646f, -0.57212351f, -0.57480443f, -0.57747920f, -0.58014778f,
+-0.58281015f, -0.58546628f, -0.58811614f, -0.59075970f, -0.59339694f,
+-0.59602782f, -0.59865231f, -0.60127040f, -0.60388204f, -0.60648722f,
+-0.60908591f, -0.61167807f, -0.61426368f, -0.61684271f, -0.61941514f,
+-0.62198093f, -0.62454007f, -0.62709251f, -0.62963824f, -0.63217722f,
+-0.63470944f, -0.63723486f, -0.63975345f, -0.64226519f, -0.64477006f,
+-0.64726802f, -0.64975905f, -0.65224312f, -0.65472020f, -0.65719027f,
+-0.65965331f, -0.66210928f, -0.66455816f, -0.66699992f, -0.66943454f,
+-0.67186199f, -0.67428225f, -0.67669528f, -0.67910107f, -0.68149959f,
+-0.68389080f, -0.68627470f, -0.68865124f, -0.69102041f, -0.69338218f,
+-0.69573652f, -0.69808341f, -0.70042283f, -0.70275474f, -0.70507913f,
+-0.70739597f, -0.70970524f, -0.71200690f, -0.71430093f, -0.71658732f,
+-0.71886604f, -0.72113705f, -0.72340034f, -0.72565589f, -0.72790366f,
+-0.73014364f, -0.73237580f, -0.73460012f, -0.73681657f, -0.73902513f,
+-0.74122577f, -0.74341848f, -0.74560322f, -0.74777998f, -0.74994874f,
+-0.75210946f, -0.75426212f, -0.75640671f, -0.75854320f, -0.76067157f,
+-0.76279178f, -0.76490383f, -0.76700769f, -0.76910334f, -0.77119075f,
+-0.77326989f, -0.77534076f, -0.77740333f, -0.77945757f, -0.78150346f,
+-0.78354098f, -0.78557011f, -0.78759083f, -0.78960312f, -0.79160694f,
+-0.79360229f, -0.79558915f, -0.79756748f, -0.79953727f, -0.80149850f,
+-0.80345114f, -0.80539518f, -0.80733060f, -0.80925737f, -0.81117547f,
+-0.81308489f, -0.81498559f, -0.81687757f, -0.81876081f, -0.82063527f,
+-0.82250095f, -0.82435781f, -0.82620585f, -0.82804505f, -0.82987537f,
+-0.83169681f, -0.83350933f, -0.83531294f, -0.83710760f, -0.83889329f,
+-0.84067000f, -0.84243770f, -0.84419639f, -0.84594603f, -0.84768662f,
+-0.84941812f, -0.85114053f, -0.85285383f, -0.85455799f, -0.85625300f,
+-0.85793884f, -0.85961549f, -0.86128294f, -0.86294116f, -0.86459014f,
+-0.86622986f, -0.86786031f, -0.86948146f, -0.87109330f, -0.87269581f,
+-0.87428898f, -0.87587278f, -0.87744720f, -0.87901223f, -0.88056784f,
+-0.88211402f, -0.88365076f, -0.88517803f, -0.88669582f, -0.88820412f,
+-0.88970290f, -0.89119216f, -0.89267187f, -0.89414203f, -0.89560260f,
+-0.89705359f, -0.89849497f, -0.89992673f, -0.90134885f, -0.90276131f,
+-0.90416411f, -0.90555723f, -0.90694065f, -0.90831436f, -0.90967833f,
+-0.91103257f, -0.91237705f, -0.91371176f, -0.91503669f, -0.91635181f,
+-0.91765712f, -0.91895261f, -0.92023825f, -0.92151404f, -0.92277996f,
+-0.92403600f, -0.92528214f, -0.92651837f, -0.92774468f, -0.92896106f,
+-0.93016748f, -0.93136395f, -0.93255044f, -0.93372694f, -0.93489345f,
+-0.93604994f, -0.93719641f, -0.93833284f, -0.93945922f, -0.94057555f,
+-0.94168180f, -0.94277796f, -0.94386403f, -0.94493999f, -0.94600583f,
+-0.94706154f, -0.94810711f, -0.94914252f, -0.95016777f, -0.95118284f,
+-0.95218773f, -0.95318242f, -0.95416690f, -0.95514117f, -0.95610520f,
+-0.95705900f, -0.95800255f, -0.95893583f, -0.95985885f, -0.96077159f,
+-0.96167404f, -0.96256619f, -0.96344803f, -0.96431956f, -0.96518076f,
+-0.96603162f, -0.96687213f, -0.96770230f, -0.96852209f, -0.96933152f,
+-0.97013057f, -0.97091922f, -0.97169748f, -0.97246533f, -0.97322277f,
+-0.97396979f, -0.97470637f, -0.97543252f, -0.97614822f, -0.97685347f,
+-0.97754825f, -0.97823257f, -0.97890641f, -0.97956977f, -0.98022263f,
+-0.98086500f, -0.98149687f, -0.98211822f, -0.98272906f, -0.98332937f,
+-0.98391915f, -0.98449840f, -0.98506710f, -0.98562525f, -0.98617285f,
+-0.98670988f, -0.98723635f, -0.98775225f, -0.98825757f, -0.98875230f,
+-0.98923645f, -0.98971000f, -0.99017295f, -0.99062530f, -0.99106704f,
+-0.99149817f, -0.99191868f, -0.99232857f, -0.99272783f, -0.99311645f,
+-0.99349445f, -0.99386180f, -0.99421851f, -0.99456457f, -0.99489998f,
+-0.99522474f, -0.99553884f, -0.99584227f, -0.99613505f, -0.99641715f,
+-0.99668858f, -0.99694934f, -0.99719943f, -0.99743883f, -0.99766756f,
+-0.99788559f, -0.99809295f, -0.99828961f, -0.99847558f, -0.99865086f,
+-0.99881544f, -0.99896933f, -0.99911252f, -0.99924501f, -0.99936680f,
+-0.99947789f, -0.99957827f, -0.99966795f, -0.99974692f, -0.99981519f,
+-0.99987275f, -0.99991960f, -0.99995574f, -0.99998118f, -0.99999590f,
+0.99999967f, 0.99997289f, 0.99990328f, 0.99979084f, 0.99963557f,
+0.99943748f, 0.99919658f, 0.99891288f, 0.99858638f, 0.99821711f,
+0.99780508f, 0.99735031f, 0.99685281f, 0.99631261f, 0.99572973f,
+0.99510420f, 0.99443605f, 0.99372529f, 0.99297196f, 0.99217610f,
+0.99133774f, 0.99045692f, 0.98953366f, 0.98856802f, 0.98756003f,
+0.98650973f, 0.98541718f, 0.98428242f, 0.98310549f, 0.98188645f,
+0.98062534f, 0.97932224f, 0.97797718f, 0.97659022f, 0.97516144f,
+0.97369088f, 0.97217861f, 0.97062469f, 0.96902920f, 0.96739220f,
+0.96571376f, 0.96399395f, 0.96223284f, 0.96043052f, 0.95858705f,
+0.95670253f, 0.95477702f, 0.95281061f, 0.95080338f, 0.94875543f,
+0.94666684f, 0.94453769f, 0.94236808f, 0.94015810f, 0.93790786f,
+0.93561743f, 0.93328693f, 0.93091644f, 0.92850608f, 0.92605595f,
+0.92356614f, 0.92103677f, 0.91846795f, 0.91585979f, 0.91321239f,
+0.91052587f, 0.90780035f, 0.90503595f, 0.90223277f, 0.89939095f,
+0.89651059f, 0.89359184f, 0.89063481f, 0.88763962f, 0.88460641f,
+0.88153531f, 0.87842644f, 0.87527995f, 0.87209596f, 0.86887462f,
+0.86561605f, 0.86232041f, 0.85898782f, 0.85561844f, 0.85221241f,
+0.84876987f, 0.84529098f, 0.84177587f, 0.83822471f, 0.83463763f,
+0.83101481f, 0.82735639f, 0.82366252f, 0.81993338f, 0.81616911f,
+0.81236987f, 0.80853584f, 0.80466718f, 0.80076404f, 0.79682660f,
+0.79285503f, 0.78884950f, 0.78481017f, 0.78073723f, 0.77663084f,
+0.77249118f, 0.76831844f, 0.76411277f, 0.75987438f, 0.75560344f,
+0.75130013f, 0.74696464f, 0.74259715f, 0.73819784f, 0.73376692f,
+0.72930457f, 0.72481097f, 0.72028632f, 0.71573083f, 0.71114467f,
+0.70652804f, 0.70188116f, 0.69720420f, 0.69249738f, 0.68776090f,
+0.68299495f, 0.67819975f, 0.67337550f, 0.66852240f, 0.66364066f,
+0.65873050f, 0.65379211f, 0.64882573f, 0.64383154f, 0.63880978f,
+0.63376065f, 0.62868438f, 0.62358117f, 0.61845126f, 0.61329485f,
+0.60811216f, 0.60290343f, 0.59766888f, 0.59240872f, 0.58712318f,
+0.58181249f, 0.57647688f, 0.57111658f, 0.56573181f, 0.56032281f,
+0.55488980f, 0.54943303f, 0.54395272f, 0.53844911f, 0.53292243f,
+0.52737292f, 0.52180083f, 0.51620638f, 0.51058981f, 0.50495138f,
+0.49929132f, 0.49360987f, 0.48790727f, 0.48218377f, 0.47643962f,
+0.47067506f, 0.46489034f, 0.45908570f, 0.45326139f, 0.44741768f,
+0.44155479f, 0.43567299f, 0.42977253f, 0.42385365f, 0.41791662f,
+0.41196169f, 0.40598911f, 0.39999914f, 0.39399204f, 0.38796806f,
+0.38192746f, 0.37587050f, 0.36979743f, 0.36370853f, 0.35760405f,
+0.35148424f, 0.34534939f, 0.33919973f, 0.33303555f, 0.32685710f,
+0.32066465f, 0.31445847f, 0.30823881f, 0.30200595f, 0.29576015f,
+0.28950169f, 0.28323082f, 0.27694782f, 0.27065295f, 0.26434649f,
+0.25802871f, 0.25169988f, 0.24536026f, 0.23901013f, 0.23264977f,
+0.22627944f, 0.21989941f, 0.21350997f, 0.20711138f, 0.20070391f,
+0.19428785f, 0.18786347f, 0.18143104f, 0.17499084f, 0.16854314f,
+0.16208822f, 0.15562636f, 0.14915783f, 0.14268292f, 0.13620189f,
+0.12971502f, 0.12322260f, 0.11672491f, 0.11022221f, 0.10371479f,
+0.097202924f, 0.090686897f, 0.084166986f, 0.077643468f, 0.071116625f,
+0.064586736f, 0.058054080f, 0.051518937f, 0.044981587f, 0.038442310f,
+0.031901387f, 0.025359097f, 0.018815721f, 0.012271538f, 0.0057268303f,
+-0.00081812300f, -0.0073630412f, -0.013907644f, -0.020451651f, -0.026994782f,
+-0.033536757f, -0.040077295f, -0.046616116f, -0.053152941f, -0.059687488f,
+-0.066219479f, -0.072748633f, -0.079274670f, -0.085797312f, -0.092316279f,
+-0.098831291f, -0.10534207f, -0.11184834f, -0.11834981f, -0.12484622f,
+-0.13133727f, -0.13782270f, -0.14430223f, -0.15077558f, -0.15724246f,
+-0.16370261f, -0.17015575f, -0.17660160f, -0.18303989f, -0.18947033f,
+-0.19589266f, -0.20230660f, -0.20871187f, -0.21510820f, -0.22149531f,
+-0.22787294f, -0.23424080f, -0.24059864f, -0.24694616f, -0.25328311f,
+-0.25960920f, -0.26592418f, -0.27222777f, -0.27851969f, -0.28479968f,
+-0.29106748f, -0.29732280f, -0.30356539f, -0.30979497f, -0.31601129f,
+-0.32221406f, -0.32840304f, -0.33457794f, -0.34073852f, -0.34688450f,
+-0.35301562f, -0.35913161f, -0.36523223f, -0.37131719f, -0.37738626f,
+-0.38343915f, -0.38947562f, -0.39549541f, -0.40149825f, -0.40748390f,
+-0.41345209f, -0.41940257f, -0.42533508f, -0.43124938f, -0.43714520f,
+-0.44302229f, -0.44888041f, -0.45471930f, -0.46053871f, -0.46633839f,
+-0.47211810f, -0.47787758f, -0.48361659f, -0.48933489f, -0.49503222f,
+-0.50070835f, -0.50636303f, -0.51199602f, -0.51760707f, -0.52319595f,
+-0.52876243f, -0.53430625f, -0.53982718f, -0.54532499f, -0.55079944f,
+-0.55625029f, -0.56167732f, -0.56708028f, -0.57245896f, -0.57781311f,
+-0.58314251f, -0.58844693f, -0.59372614f, -0.59897992f, -0.60420805f,
+-0.60941029f, -0.61458642f, -0.61973623f, -0.62485949f, -0.62995598f,
+-0.63502549f, -0.64006780f, -0.64508268f, -0.65006994f, -0.65502934f,
+-0.65996069f, -0.66486377f, -0.66973837f, -0.67458427f, -0.67940128f,
+-0.68418919f, -0.68894779f, -0.69367688f, -0.69837625f, -0.70304571f,
+-0.70768504f, -0.71229407f, -0.71687258f, -0.72142039f, -0.72593729f,
+-0.73042309f, -0.73487761f, -0.73930064f, -0.74369201f, -0.74805152f,
+-0.75237898f, -0.75667422f, -0.76093704f, -0.76516727f, -0.76936471f,
+-0.77352921f, -0.77766056f, -0.78175861f, -0.78582316f, -0.78985406f,
+-0.79385112f, -0.79781417f, -0.80174305f, -0.80563758f, -0.80949760f,
+-0.81332295f, -0.81711346f, -0.82086896f, -0.82458930f, -0.82827432f,
+-0.83192386f, -0.83553776f, -0.83911587f, -0.84265803f, -0.84616410f,
+-0.84963392f, -0.85306735f, -0.85646423f, -0.85982442f, -0.86314779f,
+-0.86643418f, -0.86968345f, -0.87289547f, -0.87607009f, -0.87920719f,
+-0.88230663f, -0.88536827f, -0.88839199f, -0.89137765f, -0.89432512f,
+-0.89723429f, -0.90010502f, -0.90293719f, -0.90573069f, -0.90848539f,
+-0.91120117f, -0.91387791f, -0.91651551f, -0.91911385f, -0.92167282f,
+-0.92419231f, -0.92667220f, -0.92911240f, -0.93151280f, -0.93387330f,
+-0.93619380f, -0.93847419f, -0.94071438f, -0.94291427f, -0.94507377f,
+-0.94719279f, -0.94927123f, -0.95130901f, -0.95330604f, -0.95526223f,
+-0.95717750f, -0.95905177f, -0.96088496f, -0.96267699f, -0.96442777f,
+-0.96613725f, -0.96780534f, -0.96943197f, -0.97101707f, -0.97256058f,
+-0.97406243f, -0.97552255f, -0.97694089f, -0.97831737f, -0.97965195f,
+-0.98094456f, -0.98219515f, -0.98340367f, -0.98457006f, -0.98569428f,
+-0.98677627f, -0.98781599f, -0.98881340f, -0.98976845f, -0.99068110f,
+-0.99155132f, -0.99237906f, -0.99316428f, -0.99390697f, -0.99460708f,
+-0.99526458f, -0.99587945f, -0.99645166f, -0.99698119f, -0.99746801f,
+-0.99791210f, -0.99831344f, -0.99867202f, -0.99898782f, -0.99926082f,
+-0.99949102f, -0.99967841f, -0.99982297f, -0.99992470f, -0.99998360f,
+0.99999866f, 0.99989157f, 0.99961315f, 0.99916346f, 0.99854256f,
+0.99775057f, 0.99678762f, 0.99565388f, 0.99434953f, 0.99287481f,
+0.99122996f, 0.98941527f, 0.98743105f, 0.98527764f, 0.98295541f,
+0.98046475f, 0.97780610f, 0.97497990f, 0.97198664f, 0.96882685f,
+0.96550104f, 0.96200980f, 0.95835373f, 0.95453345f, 0.95054962f,
+0.94640291f, 0.94209404f, 0.93762375f, 0.93299280f, 0.92820199f,
+0.92325213f, 0.91814408f, 0.91287871f, 0.90745693f, 0.90187965f,
+0.89614785f, 0.89026249f, 0.88422459f, 0.87803519f, 0.87169533f,
+0.86520612f, 0.85856866f, 0.85178409f, 0.84485357f, 0.83777828f,
+0.83055945f, 0.82319831f, 0.81569611f, 0.80805415f, 0.80027373f,
+0.79235620f, 0.78430289f, 0.77611520f, 0.76779452f, 0.75934229f,
+0.75075995f, 0.74204897f, 0.73321084f, 0.72424708f, 0.71515923f,
+0.70594883f, 0.69661748f, 0.68716676f, 0.67759830f, 0.66791374f,
+0.65811474f, 0.64820297f, 0.63818013f, 0.62804795f, 0.61780815f,
+0.60746249f, 0.59701275f, 0.58646072f, 0.57580819f, 0.56505701f,
+0.55420900f, 0.54326604f, 0.53222998f, 0.52110274f, 0.50988620f,
+0.49858230f, 0.48719297f, 0.47572016f, 0.46416584f, 0.45253199f,
+0.44082059f, 0.42903367f, 0.41717323f, 0.40524131f, 0.39323996f,
+0.38117123f, 0.36903718f, 0.35683990f, 0.34458148f, 0.33226402f,
+0.31988962f, 0.30746042f, 0.29497853f, 0.28244610f, 0.26986527f,
+0.25723821f, 0.24456706f, 0.23185402f, 0.21910124f, 0.20631092f,
+0.19348526f, 0.18062644f, 0.16773667f, 0.15481816f, 0.14187312f,
+0.12890377f, 0.11591234f, 0.10290104f, 0.089872115f, 0.076827789f,
+0.063770300f, 0.050701883f, 0.037624779f, 0.024541229f, 0.011453473f,
+-0.0016362454f, -0.014725683f, -0.027812598f, -0.040894747f, -0.053969889f,
+-0.067035784f, -0.080090192f, -0.093130877f, -0.10615561f, -0.11916214f,
+-0.13214826f, -0.14511174f, -0.15805036f, -0.17096189f, -0.18384413f,
+-0.19669487f, -0.20951190f, -0.22229304f, -0.23503609f, -0.24773886f,
+-0.26039919f, -0.27301490f, -0.28558383f, -0.29810383f, -0.31057274f,
+-0.32298845f, -0.33534881f, -0.34765171f, -0.35989504f, -0.37207670f,
+-0.38419461f, -0.39624670f, -0.40823088f, -0.42014512f, -0.43198737f,
+-0.44375560f, -0.45544780f, -0.46706195f, -0.47859608f, -0.49004821f,
+-0.50141636f, -0.51269860f, -0.52389299f, -0.53499762f, -0.54601058f,
+-0.55692998f, -0.56775395f, -0.57848064f, -0.58910822f, -0.59963485f,
+-0.61005873f, -0.62037809f, -0.63059115f, -0.64069616f, -0.65069139f,
+-0.66057513f, -0.67034568f, -0.68000137f, -0.68954054f, -0.69896157f,
+-0.70826283f, -0.71744274f, -0.72649972f, -0.73543221f, -0.74423869f,
+-0.75291765f, -0.76146760f, -0.76988708f, -0.77817464f, -0.78632887f,
+-0.79434836f, -0.80223175f, -0.80997767f, -0.81758481f, -0.82505187f,
+-0.83237755f, -0.83956061f, -0.84659981f, -0.85349396f, -0.86024186f,
+-0.86684237f, -0.87329434f, -0.87959669f, -0.88574831f, -0.89174817f,
+-0.89759523f, -0.90328850f, -0.90882699f, -0.91420976f, -0.91943588f,
+-0.92450446f, -0.92941463f, -0.93416555f, -0.93875641f, -0.94318642f,
+-0.94745482f, -0.95156087f, -0.95550388f, -0.95928317f, -0.96289809f,
+-0.96634802f, -0.96963238f, -0.97275059f, -0.97570213f, -0.97848649f,
+-0.98110318f, -0.98355177f, -0.98583184f, -0.98794298f, -0.98988485f,
+-0.99165711f, -0.99325945f, -0.99469160f, -0.99595331f, -0.99704438f,
+-0.99796460f, -0.99871383f, -0.99929194f, -0.99969882f, -0.99993441f,
+0.99999465f, 0.99956631f, 0.99845292f, 0.99665524f, 0.99417450f,
+0.99101241f, 0.98717112f, 0.98265328f, 0.97746197f, 0.97160077f,
+0.96507367f, 0.95788516f, 0.95004017f, 0.94154407f, 0.93240267f,
+0.92262226f, 0.91220953f, 0.90117161f, 0.88951608f, 0.87725091f,
+0.86438452f, 0.85092573f, 0.83688375f, 0.82226822f, 0.80708914f,
+0.79135693f, 0.77508236f, 0.75827658f, 0.74095113f, 0.72311786f,
+0.70478900f, 0.68597711f, 0.66669509f, 0.64695615f, 0.62677382f,
+0.60616193f, 0.58513461f, 0.56370626f, 0.54189158f, 0.51970551f,
+0.49716327f, 0.47428029f, 0.45107226f, 0.42755509f, 0.40374490f,
+0.37965800f, 0.35531090f, 0.33072029f, 0.30590302f, 0.28087610f,
+0.25565668f, 0.23026205f, 0.20470960f, 0.17901686f, 0.15320143f,
+0.12728100f, 0.10127334f, 0.075196277f, 0.049067674f, 0.022905443f,
+-0.0032724865f, -0.029448173f, -0.055603678f, -0.081721074f, -0.10778246f,
+-0.13376998f, -0.15966582f, -0.18545224f, -0.21111155f, -0.23662618f,
+-0.26197864f, -0.28715155f, -0.31212766f, -0.33688985f, -0.36142116f,
+-0.38570477f, -0.40972403f, -0.43346249f, -0.45690388f, -0.48003212f,
+-0.50283138f, -0.52528602f, -0.54738066f, -0.56910015f, -0.59042960f,
+-0.61135441f, -0.63186022f, -0.65193299f, -0.67155895f, -0.69072467f,
+-0.70941699f, -0.72762312f, -0.74533057f, -0.76252720f, -0.77920124f,
+-0.79534126f, -0.81093618f, -0.82597533f, -0.84044840f, -0.85434547f,
+-0.86765701f, -0.88037390f, -0.89248743f, -0.90398929f, -0.91487161f,
+-0.92512691f, -0.93474818f, -0.94372882f, -0.95206268f, -0.95974404f,
+-0.96676764f, -0.97312866f, -0.97882275f, -0.98384601f, -0.98819498f,
+-0.99186670f, -0.99485864f, -0.99716875f, -0.99879546f, -0.99973764f,
+};
+#endif
+
+static const CELTMode mode48000_960_120 = {
+48000, /* Fs */
+120, /* overlap */
+21, /* nbEBands */
+21, /* effEBands */
+{0.85000610f, 0.0000000f, 1.0000000f, 1.0000000f, }, /* preemph */
+eband5ms, /* eBands */
+3, /* maxLM */
+8, /* nbShortMdcts */
+120, /* shortMdctSize */
+11, /* nbAllocVectors */
+band_allocation, /* allocVectors */
+logN400, /* logN */
+window120, /* window */
+{1920, 3, {&fft_state48000_960_0, &fft_state48000_960_1, &fft_state48000_960_2, &fft_state48000_960_3, }, mdct_twiddles960}, /* mdct */
+{392, cache_index50, cache_bits50, cache_caps50}, /* cache */
+#ifdef ENABLE_QEXT
+{86, qext_cache_index50, qext_cache_bits50, qext_cache_caps50}, /* qext_cache */
+#endif
+};
+
+#ifdef ENABLE_QEXT
+#ifndef DEF_WINDOW240
+#define DEF_WINDOW240
+static const celt_coef window240[240] = {
+1.6821922e-05f, 0.00015139297f, 0.00042051200f, 0.00082413284f, 0.0013621862f,
+0.0020345793f, 0.0028411964f, 0.0037818978f, 0.0048565203f, 0.0060648765f,
+0.0074067550f, 0.0088819198f, 0.010490110f, 0.012231040f, 0.014104398f,
+0.016109846f, 0.018247021f, 0.020515533f, 0.022914963f, 0.025444867f,
+0.028104770f, 0.030894170f, 0.033812535f, 0.036859304f, 0.040033885f,
+0.043335654f, 0.046763958f, 0.050318110f, 0.053997389f, 0.057801044f,
+0.061728287f, 0.065778297f, 0.069950217f, 0.074243155f, 0.078656182f,
+0.083188331f, 0.087838600f, 0.092605946f, 0.097489289f, 0.10248751f,
+0.10759945f, 0.11282390f, 0.11815964f, 0.12360536f, 0.12915977f,
+0.13482147f, 0.14058908f, 0.14646113f, 0.15243614f, 0.15851256f,
+0.16468882f, 0.17096330f, 0.17733432f, 0.18380017f, 0.19035910f,
+0.19700930f, 0.20374894f, 0.21057612f, 0.21748892f, 0.22448537f,
+0.23156343f, 0.23872106f, 0.24595615f, 0.25326656f, 0.26065010f,
+0.26810455f, 0.27562763f, 0.28321704f, 0.29087045f, 0.29858546f,
+0.30635965f, 0.31419058f, 0.32207574f, 0.33001263f, 0.33799866f,
+0.34603127f, 0.35410783f, 0.36222570f, 0.37038219f, 0.37857460f,
+0.38680022f, 0.39505629f, 0.40334003f, 0.41164867f, 0.41997939f,
+0.42832937f, 0.43669576f, 0.44507572f, 0.45346639f, 0.46186489f,
+0.47026835f, 0.47867389f, 0.48707862f, 0.49547965f, 0.50387411f,
+0.51225912f, 0.52063179f, 0.52898927f, 0.53732871f, 0.54564725f,
+0.55394208f, 0.56221039f, 0.57044938f, 0.57865628f, 0.58682836f,
+0.59496289f, 0.60305718f, 0.61110858f, 0.61911445f, 0.62707221f,
+0.63497931f, 0.64283322f, 0.65063147f, 0.65837163f, 0.66605132f,
+0.67366820f, 0.68121999f, 0.68870444f, 0.69611937f, 0.70346266f,
+0.71073222f, 0.71792606f, 0.72504220f, 0.73207877f, 0.73903393f,
+0.74590592f, 0.75269303f, 0.75939364f, 0.76600617f, 0.77252915f,
+0.77896113f, 0.78530077f, 0.79154678f, 0.79769796f, 0.80375317f,
+0.80971135f, 0.81557152f, 0.82133276f, 0.82699424f, 0.83255520f,
+0.83801496f, 0.84337291f, 0.84862851f, 0.85378132f, 0.85883095f,
+0.86377710f, 0.86861954f, 0.87335813f, 0.87799277f, 0.88252347f,
+0.88695029f, 0.89127338f, 0.89549294f, 0.89960926f, 0.90362268f,
+0.90753364f, 0.91134262f, 0.91505017f, 0.91865692f, 0.92216354f,
+0.92557078f, 0.92887945f, 0.93209042f, 0.93520460f, 0.93822298f,
+0.94114659f, 0.94397652f, 0.94671390f, 0.94935993f, 0.95191584f,
+0.95438290f, 0.95676245f, 0.95905584f, 0.96126449f, 0.96338982f,
+0.96543334f, 0.96739653f, 0.96928096f, 0.97108818f, 0.97281981f,
+0.97447746f, 0.97606279f, 0.97757746f, 0.97902317f, 0.98040162f,
+0.98171453f, 0.98296363f, 0.98415067f, 0.98527740f, 0.98634557f,
+0.98735696f, 0.98831332f, 0.98921643f, 0.99006803f, 0.99086991f,
+0.99162380f, 0.99233145f, 0.99299461f, 0.99361500f, 0.99419433f,
+0.99473429f, 0.99523657f, 0.99570284f, 0.99613472f, 0.99653384f,
+0.99690180f, 0.99724017f, 0.99755048f, 0.99783426f, 0.99809299f,
+0.99832812f, 0.99854108f, 0.99873324f, 0.99890597f, 0.99906057f,
+0.99919832f, 0.99932046f, 0.99942819f, 0.99952266f, 0.99960498f,
+0.99967623f, 0.99973742f, 0.99978953f, 0.99983351f, 0.99987023f,
+0.99990053f, 0.99992520f, 0.99994498f, 0.99996055f, 0.99997257f,
+0.99998161f, 0.99998821f, 0.99999285f, 0.99999596f, 0.99999793f,
+0.99999907f, 0.99999966f, 0.99999991f, 0.99999999f, 1.0000000f,
+};
+#endif
+
+#ifndef DEF_LOGN400
+#define DEF_LOGN400
+static const opus_int16 logN400[21] = {
+0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
+#endif
+
+#ifndef DEF_PULSE_CACHE50
+#define DEF_PULSE_CACHE50
+static const opus_int16 cache_index50[105] = {
+-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
+82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
+41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
+318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
+305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
+240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
+};
+static const unsigned char cache_bits50[392] = {
+40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
+31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
+51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
+66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
+64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
+94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
+124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
+97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
+142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
+28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
+153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
+229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
+166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
+86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
+25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
+185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
+110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
+74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
+163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
+228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
+90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
+87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
+106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
+224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
+182, 234, };
+static const unsigned char cache_caps50[168] = {
+224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
+178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
+240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
+160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
+138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
+204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
+185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
+207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
+188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
+193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
+204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
+140, 66, 40, };
+#endif
+
+#ifdef ENABLE_QEXT
+# ifndef DEF_QEXT_PULSE_CACHE50
+# define DEF_QEXT_PULSE_CACHE50
+static const opus_int16 qext_cache_index50[70] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 61, 61,
+61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 72, 72, 72,
+72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 80, 80, 80, 80,
+80, 80, 80, 80, 80, 80, 80, 80, 80, 80, };
+static const unsigned char qext_cache_bits50[86] = {
+40, 26, 45, 59, 70, 79, 87, 94, 100, 105, 110, 114, 118, 122, 125,
+128, 131, 136, 141, 146, 150, 153, 157, 160, 163, 168, 173, 178, 182, 185,
+189, 192, 195, 200, 205, 210, 214, 217, 221, 224, 227, 19, 34, 61, 83,
+101, 118, 132, 145, 157, 167, 177, 186, 194, 202, 209, 216, 222, 234, 245,
+254, 10, 42, 77, 107, 133, 157, 179, 200, 219, 236, 253, 7, 50, 93,
+131, 165, 197, 227, 255, 5, 58, 109, 155, 197, 237, };
+static const unsigned char qext_cache_caps50[112] = {
+159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 171,
+171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 167, 167, 167,
+167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 166, 166, 166, 166, 166,
+166, 166, 166, 166, 166, 166, 166, 166, 166, 163, 163, 163, 163, 163, 163,
+163, 163, 163, 163, 163, 163, 163, 163, 165, 165, 165, 165, 165, 165, 165,
+165, 165, 165, 165, 165, 165, 165, };
+# endif
+#endif
+
+#ifndef FFT_TWIDDLES96000_1920
+#define FFT_TWIDDLES96000_1920
+static const kiss_twiddle_cpx fft_twiddles96000_1920[960] = {
+{1.0000000f, -0.0000000f}, {0.99997858f, -0.0065449380f},
+{0.99991433f, -0.013089596f}, {0.99980724f, -0.019633692f},
+{0.99965732f, -0.026176948f}, {0.99946459f, -0.032719083f},
+{0.99922904f, -0.039259816f}, {0.99895068f, -0.045798867f},
+{0.99862953f, -0.052335956f}, {0.99826561f, -0.058870804f},
+{0.99785892f, -0.065403129f}, {0.99740949f, -0.071932653f},
+{0.99691733f, -0.078459096f}, {0.99638247f, -0.084982177f},
+{0.99580493f, -0.091501619f}, {0.99518473f, -0.098017140f},
+{0.99452190f, -0.10452846f}, {0.99381646f, -0.11103531f},
+{0.99306846f, -0.11753740f}, {0.99227791f, -0.12403445f},
+{0.99144486f, -0.13052619f}, {0.99056934f, -0.13701234f},
+{0.98965139f, -0.14349262f}, {0.98869104f, -0.14996676f},
+{0.98768834f, -0.15643447f}, {0.98664333f, -0.16289547f},
+{0.98555606f, -0.16934950f}, {0.98442657f, -0.17579628f},
+{0.98325491f, -0.18223553f}, {0.98204113f, -0.18866696f},
+{0.98078528f, -0.19509032f}, {0.97948742f, -0.20150532f},
+{0.97814760f, -0.20791169f}, {0.97676588f, -0.21430915f},
+{0.97534232f, -0.22069744f}, {0.97387698f, -0.22707626f},
+{0.97236992f, -0.23344536f}, {0.97082121f, -0.23980446f},
+{0.96923091f, -0.24615329f}, {0.96759909f, -0.25249158f},
+{0.96592583f, -0.25881905f}, {0.96421118f, -0.26513543f},
+{0.96245524f, -0.27144045f}, {0.96065806f, -0.27773385f},
+{0.95881973f, -0.28401534f}, {0.95694034f, -0.29028468f},
+{0.95501994f, -0.29654157f}, {0.95305864f, -0.30278577f},
+{0.95105652f, -0.30901699f}, {0.94901365f, -0.31523498f},
+{0.94693013f, -0.32143947f}, {0.94480605f, -0.32763018f},
+{0.94264149f, -0.33380686f}, {0.94043656f, -0.33996924f},
+{0.93819134f, -0.34611706f}, {0.93590593f, -0.35225005f},
+{0.93358043f, -0.35836795f}, {0.93121493f, -0.36447050f},
+{0.92880955f, -0.37055744f}, {0.92636438f, -0.37662850f},
+{0.92387953f, -0.38268343f}, {0.92135511f, -0.38872197f},
+{0.91879121f, -0.39474386f}, {0.91618796f, -0.40074883f},
+{0.91354546f, -0.40673664f}, {0.91086382f, -0.41270703f},
+{0.90814317f, -0.41865974f}, {0.90538362f, -0.42459451f},
+{0.90258528f, -0.43051110f}, {0.89974828f, -0.43640924f},
+{0.89687274f, -0.44228869f}, {0.89395878f, -0.44814919f},
+{0.89100652f, -0.45399050f}, {0.88801610f, -0.45981236f},
+{0.88498764f, -0.46561452f}, {0.88192126f, -0.47139674f},
+{0.87881711f, -0.47715876f}, {0.87567532f, -0.48290034f},
+{0.87249601f, -0.48862124f}, {0.86927932f, -0.49432121f},
+{0.86602540f, -0.50000000f}, {0.86273439f, -0.50565737f},
+{0.85940641f, -0.51129309f}, {0.85604162f, -0.51690690f},
+{0.85264016f, -0.52249856f}, {0.84920218f, -0.52806785f},
+{0.84572782f, -0.53361452f}, {0.84221723f, -0.53913832f},
+{0.83867057f, -0.54463904f}, {0.83508798f, -0.55011642f},
+{0.83146961f, -0.55557023f}, {0.82781563f, -0.56100025f},
+{0.82412619f, -0.56640624f}, {0.82040144f, -0.57178796f},
+{0.81664156f, -0.57714519f}, {0.81284668f, -0.58247770f},
+{0.80901699f, -0.58778525f}, {0.80515265f, -0.59306763f},
+{0.80125381f, -0.59832460f}, {0.79732065f, -0.60355594f},
+{0.79335334f, -0.60876143f}, {0.78935204f, -0.61394084f},
+{0.78531693f, -0.61909395f}, {0.78124818f, -0.62422054f},
+{0.77714596f, -0.62932039f}, {0.77301045f, -0.63439328f},
+{0.76884183f, -0.63943900f}, {0.76464028f, -0.64445733f},
+{0.76040597f, -0.64944805f}, {0.75613908f, -0.65441095f},
+{0.75183981f, -0.65934582f}, {0.74750833f, -0.66425244f},
+{0.74314483f, -0.66913061f}, {0.73874949f, -0.67398011f},
+{0.73432251f, -0.67880075f}, {0.72986407f, -0.68359230f},
+{0.72537437f, -0.68835458f}, {0.72085360f, -0.69308736f},
+{0.71630194f, -0.69779046f}, {0.71171961f, -0.70246367f},
+{0.70710678f, -0.70710678f}, {0.70246367f, -0.71171961f},
+{0.69779046f, -0.71630194f}, {0.69308736f, -0.72085360f},
+{0.68835458f, -0.72537437f}, {0.68359230f, -0.72986407f},
+{0.67880075f, -0.73432251f}, {0.67398011f, -0.73874949f},
+{0.66913061f, -0.74314483f}, {0.66425244f, -0.74750833f},
+{0.65934582f, -0.75183981f}, {0.65441095f, -0.75613908f},
+{0.64944805f, -0.76040597f}, {0.64445733f, -0.76464028f},
+{0.63943900f, -0.76884183f}, {0.63439328f, -0.77301045f},
+{0.62932039f, -0.77714596f}, {0.62422054f, -0.78124818f},
+{0.61909395f, -0.78531693f}, {0.61394084f, -0.78935204f},
+{0.60876143f, -0.79335334f}, {0.60355594f, -0.79732065f},
+{0.59832460f, -0.80125381f}, {0.59306763f, -0.80515265f},
+{0.58778525f, -0.80901699f}, {0.58247770f, -0.81284668f},
+{0.57714519f, -0.81664156f}, {0.57178796f, -0.82040144f},
+{0.56640624f, -0.82412619f}, {0.56100025f, -0.82781563f},
+{0.55557023f, -0.83146961f}, {0.55011642f, -0.83508798f},
+{0.54463904f, -0.83867057f}, {0.53913832f, -0.84221723f},
+{0.53361452f, -0.84572782f}, {0.52806785f, -0.84920218f},
+{0.52249856f, -0.85264016f}, {0.51690690f, -0.85604162f},
+{0.51129309f, -0.85940641f}, {0.50565737f, -0.86273439f},
+{0.50000000f, -0.86602540f}, {0.49432121f, -0.86927932f},
+{0.48862124f, -0.87249601f}, {0.48290034f, -0.87567532f},
+{0.47715876f, -0.87881711f}, {0.47139674f, -0.88192126f},
+{0.46561452f, -0.88498764f}, {0.45981236f, -0.88801610f},
+{0.45399050f, -0.89100652f}, {0.44814919f, -0.89395878f},
+{0.44228869f, -0.89687274f}, {0.43640924f, -0.89974828f},
+{0.43051110f, -0.90258528f}, {0.42459451f, -0.90538362f},
+{0.41865974f, -0.90814317f}, {0.41270703f, -0.91086382f},
+{0.40673664f, -0.91354546f}, {0.40074883f, -0.91618796f},
+{0.39474386f, -0.91879121f}, {0.38872197f, -0.92135511f},
+{0.38268343f, -0.92387953f}, {0.37662850f, -0.92636438f},
+{0.37055744f, -0.92880955f}, {0.36447050f, -0.93121493f},
+{0.35836795f, -0.93358043f}, {0.35225005f, -0.93590593f},
+{0.34611706f, -0.93819134f}, {0.33996924f, -0.94043656f},
+{0.33380686f, -0.94264149f}, {0.32763018f, -0.94480605f},
+{0.32143947f, -0.94693013f}, {0.31523498f, -0.94901365f},
+{0.30901699f, -0.95105652f}, {0.30278577f, -0.95305864f},
+{0.29654157f, -0.95501994f}, {0.29028468f, -0.95694034f},
+{0.28401534f, -0.95881973f}, {0.27773385f, -0.96065806f},
+{0.27144045f, -0.96245524f}, {0.26513543f, -0.96421118f},
+{0.25881905f, -0.96592583f}, {0.25249158f, -0.96759909f},
+{0.24615329f, -0.96923091f}, {0.23980446f, -0.97082121f},
+{0.23344536f, -0.97236992f}, {0.22707626f, -0.97387698f},
+{0.22069744f, -0.97534232f}, {0.21430915f, -0.97676588f},
+{0.20791169f, -0.97814760f}, {0.20150532f, -0.97948742f},
+{0.19509032f, -0.98078528f}, {0.18866696f, -0.98204113f},
+{0.18223553f, -0.98325491f}, {0.17579628f, -0.98442657f},
+{0.16934950f, -0.98555606f}, {0.16289547f, -0.98664333f},
+{0.15643447f, -0.98768834f}, {0.14996676f, -0.98869104f},
+{0.14349262f, -0.98965139f}, {0.13701234f, -0.99056934f},
+{0.13052619f, -0.99144486f}, {0.12403445f, -0.99227791f},
+{0.11753740f, -0.99306846f}, {0.11103531f, -0.99381646f},
+{0.10452846f, -0.99452190f}, {0.098017140f, -0.99518473f},
+{0.091501619f, -0.99580493f}, {0.084982177f, -0.99638247f},
+{0.078459096f, -0.99691733f}, {0.071932653f, -0.99740949f},
+{0.065403129f, -0.99785892f}, {0.058870804f, -0.99826561f},
+{0.052335956f, -0.99862953f}, {0.045798867f, -0.99895068f},
+{0.039259816f, -0.99922904f}, {0.032719083f, -0.99946459f},
+{0.026176948f, -0.99965732f}, {0.019633692f, -0.99980724f},
+{0.013089596f, -0.99991433f}, {0.0065449380f, -0.99997858f},
+{6.1232340e-17f, -1.0000000f}, {-0.0065449380f, -0.99997858f},
+{-0.013089596f, -0.99991433f}, {-0.019633692f, -0.99980724f},
+{-0.026176948f, -0.99965732f}, {-0.032719083f, -0.99946459f},
+{-0.039259816f, -0.99922904f}, {-0.045798867f, -0.99895068f},
+{-0.052335956f, -0.99862953f}, {-0.058870804f, -0.99826561f},
+{-0.065403129f, -0.99785892f}, {-0.071932653f, -0.99740949f},
+{-0.078459096f, -0.99691733f}, {-0.084982177f, -0.99638247f},
+{-0.091501619f, -0.99580493f}, {-0.098017140f, -0.99518473f},
+{-0.10452846f, -0.99452190f}, {-0.11103531f, -0.99381646f},
+{-0.11753740f, -0.99306846f}, {-0.12403445f, -0.99227791f},
+{-0.13052619f, -0.99144486f}, {-0.13701234f, -0.99056934f},
+{-0.14349262f, -0.98965139f}, {-0.14996676f, -0.98869104f},
+{-0.15643447f, -0.98768834f}, {-0.16289547f, -0.98664333f},
+{-0.16934950f, -0.98555606f}, {-0.17579628f, -0.98442657f},
+{-0.18223553f, -0.98325491f}, {-0.18866696f, -0.98204113f},
+{-0.19509032f, -0.98078528f}, {-0.20150532f, -0.97948742f},
+{-0.20791169f, -0.97814760f}, {-0.21430915f, -0.97676588f},
+{-0.22069744f, -0.97534232f}, {-0.22707626f, -0.97387698f},
+{-0.23344536f, -0.97236992f}, {-0.23980446f, -0.97082121f},
+{-0.24615329f, -0.96923091f}, {-0.25249158f, -0.96759909f},
+{-0.25881905f, -0.96592583f}, {-0.26513543f, -0.96421118f},
+{-0.27144045f, -0.96245524f}, {-0.27773385f, -0.96065806f},
+{-0.28401534f, -0.95881973f}, {-0.29028468f, -0.95694034f},
+{-0.29654157f, -0.95501994f}, {-0.30278577f, -0.95305864f},
+{-0.30901699f, -0.95105652f}, {-0.31523498f, -0.94901365f},
+{-0.32143947f, -0.94693013f}, {-0.32763018f, -0.94480605f},
+{-0.33380686f, -0.94264149f}, {-0.33996924f, -0.94043656f},
+{-0.34611706f, -0.93819134f}, {-0.35225005f, -0.93590593f},
+{-0.35836795f, -0.93358043f}, {-0.36447050f, -0.93121493f},
+{-0.37055744f, -0.92880955f}, {-0.37662850f, -0.92636438f},
+{-0.38268343f, -0.92387953f}, {-0.38872197f, -0.92135511f},
+{-0.39474386f, -0.91879121f}, {-0.40074883f, -0.91618796f},
+{-0.40673664f, -0.91354546f}, {-0.41270703f, -0.91086382f},
+{-0.41865974f, -0.90814317f}, {-0.42459451f, -0.90538362f},
+{-0.43051110f, -0.90258528f}, {-0.43640924f, -0.89974828f},
+{-0.44228869f, -0.89687274f}, {-0.44814919f, -0.89395878f},
+{-0.45399050f, -0.89100652f}, {-0.45981236f, -0.88801610f},
+{-0.46561452f, -0.88498764f}, {-0.47139674f, -0.88192126f},
+{-0.47715876f, -0.87881711f}, {-0.48290034f, -0.87567532f},
+{-0.48862124f, -0.87249601f}, {-0.49432121f, -0.86927932f},
+{-0.50000000f, -0.86602540f}, {-0.50565737f, -0.86273439f},
+{-0.51129309f, -0.85940641f}, {-0.51690690f, -0.85604162f},
+{-0.52249856f, -0.85264016f}, {-0.52806785f, -0.84920218f},
+{-0.53361452f, -0.84572782f}, {-0.53913832f, -0.84221723f},
+{-0.54463904f, -0.83867057f}, {-0.55011642f, -0.83508798f},
+{-0.55557023f, -0.83146961f}, {-0.56100025f, -0.82781563f},
+{-0.56640624f, -0.82412619f}, {-0.57178796f, -0.82040144f},
+{-0.57714519f, -0.81664156f}, {-0.58247770f, -0.81284668f},
+{-0.58778525f, -0.80901699f}, {-0.59306763f, -0.80515265f},
+{-0.59832460f, -0.80125381f}, {-0.60355594f, -0.79732065f},
+{-0.60876143f, -0.79335334f}, {-0.61394084f, -0.78935204f},
+{-0.61909395f, -0.78531693f}, {-0.62422054f, -0.78124818f},
+{-0.62932039f, -0.77714596f}, {-0.63439328f, -0.77301045f},
+{-0.63943900f, -0.76884183f}, {-0.64445733f, -0.76464028f},
+{-0.64944805f, -0.76040597f}, {-0.65441095f, -0.75613908f},
+{-0.65934582f, -0.75183981f}, {-0.66425244f, -0.74750833f},
+{-0.66913061f, -0.74314483f}, {-0.67398011f, -0.73874949f},
+{-0.67880075f, -0.73432251f}, {-0.68359230f, -0.72986407f},
+{-0.68835458f, -0.72537437f}, {-0.69308736f, -0.72085360f},
+{-0.69779046f, -0.71630194f}, {-0.70246367f, -0.71171961f},
+{-0.70710678f, -0.70710678f}, {-0.71171961f, -0.70246367f},
+{-0.71630194f, -0.69779046f}, {-0.72085360f, -0.69308736f},
+{-0.72537437f, -0.68835458f}, {-0.72986407f, -0.68359230f},
+{-0.73432251f, -0.67880075f}, {-0.73874949f, -0.67398011f},
+{-0.74314483f, -0.66913061f}, {-0.74750833f, -0.66425244f},
+{-0.75183981f, -0.65934582f}, {-0.75613908f, -0.65441095f},
+{-0.76040597f, -0.64944805f}, {-0.76464028f, -0.64445733f},
+{-0.76884183f, -0.63943900f}, {-0.77301045f, -0.63439328f},
+{-0.77714596f, -0.62932039f}, {-0.78124818f, -0.62422054f},
+{-0.78531693f, -0.61909395f}, {-0.78935204f, -0.61394084f},
+{-0.79335334f, -0.60876143f}, {-0.79732065f, -0.60355594f},
+{-0.80125381f, -0.59832460f}, {-0.80515265f, -0.59306763f},
+{-0.80901699f, -0.58778525f}, {-0.81284668f, -0.58247770f},
+{-0.81664156f, -0.57714519f}, {-0.82040144f, -0.57178796f},
+{-0.82412619f, -0.56640624f}, {-0.82781563f, -0.56100025f},
+{-0.83146961f, -0.55557023f}, {-0.83508798f, -0.55011642f},
+{-0.83867057f, -0.54463904f}, {-0.84221723f, -0.53913832f},
+{-0.84572782f, -0.53361452f}, {-0.84920218f, -0.52806785f},
+{-0.85264016f, -0.52249856f}, {-0.85604162f, -0.51690690f},
+{-0.85940641f, -0.51129309f}, {-0.86273439f, -0.50565737f},
+{-0.86602540f, -0.50000000f}, {-0.86927932f, -0.49432121f},
+{-0.87249601f, -0.48862124f}, {-0.87567532f, -0.48290034f},
+{-0.87881711f, -0.47715876f}, {-0.88192126f, -0.47139674f},
+{-0.88498764f, -0.46561452f}, {-0.88801610f, -0.45981236f},
+{-0.89100652f, -0.45399050f}, {-0.89395878f, -0.44814919f},
+{-0.89687274f, -0.44228869f}, {-0.89974828f, -0.43640924f},
+{-0.90258528f, -0.43051110f}, {-0.90538362f, -0.42459451f},
+{-0.90814317f, -0.41865974f}, {-0.91086382f, -0.41270703f},
+{-0.91354546f, -0.40673664f}, {-0.91618796f, -0.40074883f},
+{-0.91879121f, -0.39474386f}, {-0.92135511f, -0.38872197f},
+{-0.92387953f, -0.38268343f}, {-0.92636438f, -0.37662850f},
+{-0.92880955f, -0.37055744f}, {-0.93121493f, -0.36447050f},
+{-0.93358043f, -0.35836795f}, {-0.93590593f, -0.35225005f},
+{-0.93819134f, -0.34611706f}, {-0.94043656f, -0.33996924f},
+{-0.94264149f, -0.33380686f}, {-0.94480605f, -0.32763018f},
+{-0.94693013f, -0.32143947f}, {-0.94901365f, -0.31523498f},
+{-0.95105652f, -0.30901699f}, {-0.95305864f, -0.30278577f},
+{-0.95501994f, -0.29654157f}, {-0.95694034f, -0.29028468f},
+{-0.95881973f, -0.28401534f}, {-0.96065806f, -0.27773385f},
+{-0.96245524f, -0.27144045f}, {-0.96421118f, -0.26513543f},
+{-0.96592583f, -0.25881905f}, {-0.96759909f, -0.25249158f},
+{-0.96923091f, -0.24615329f}, {-0.97082121f, -0.23980446f},
+{-0.97236992f, -0.23344536f}, {-0.97387698f, -0.22707626f},
+{-0.97534232f, -0.22069744f}, {-0.97676588f, -0.21430915f},
+{-0.97814760f, -0.20791169f}, {-0.97948742f, -0.20150532f},
+{-0.98078528f, -0.19509032f}, {-0.98204113f, -0.18866696f},
+{-0.98325491f, -0.18223553f}, {-0.98442657f, -0.17579628f},
+{-0.98555606f, -0.16934950f}, {-0.98664333f, -0.16289547f},
+{-0.98768834f, -0.15643447f}, {-0.98869104f, -0.14996676f},
+{-0.98965139f, -0.14349262f}, {-0.99056934f, -0.13701234f},
+{-0.99144486f, -0.13052619f}, {-0.99227791f, -0.12403445f},
+{-0.99306846f, -0.11753740f}, {-0.99381646f, -0.11103531f},
+{-0.99452190f, -0.10452846f}, {-0.99518473f, -0.098017140f},
+{-0.99580493f, -0.091501619f}, {-0.99638247f, -0.084982177f},
+{-0.99691733f, -0.078459096f}, {-0.99740949f, -0.071932653f},
+{-0.99785892f, -0.065403129f}, {-0.99826561f, -0.058870804f},
+{-0.99862953f, -0.052335956f}, {-0.99895068f, -0.045798867f},
+{-0.99922904f, -0.039259816f}, {-0.99946459f, -0.032719083f},
+{-0.99965732f, -0.026176948f}, {-0.99980724f, -0.019633692f},
+{-0.99991433f, -0.013089596f}, {-0.99997858f, -0.0065449380f},
+{-1.0000000f, -1.2246468e-16f}, {-0.99997858f, 0.0065449380f},
+{-0.99991433f, 0.013089596f}, {-0.99980724f, 0.019633692f},
+{-0.99965732f, 0.026176948f}, {-0.99946459f, 0.032719083f},
+{-0.99922904f, 0.039259816f}, {-0.99895068f, 0.045798867f},
+{-0.99862953f, 0.052335956f}, {-0.99826561f, 0.058870804f},
+{-0.99785892f, 0.065403129f}, {-0.99740949f, 0.071932653f},
+{-0.99691733f, 0.078459096f}, {-0.99638247f, 0.084982177f},
+{-0.99580493f, 0.091501619f}, {-0.99518473f, 0.098017140f},
+{-0.99452190f, 0.10452846f}, {-0.99381646f, 0.11103531f},
+{-0.99306846f, 0.11753740f}, {-0.99227791f, 0.12403445f},
+{-0.99144486f, 0.13052619f}, {-0.99056934f, 0.13701234f},
+{-0.98965139f, 0.14349262f}, {-0.98869104f, 0.14996676f},
+{-0.98768834f, 0.15643447f}, {-0.98664333f, 0.16289547f},
+{-0.98555606f, 0.16934950f}, {-0.98442657f, 0.17579628f},
+{-0.98325491f, 0.18223553f}, {-0.98204113f, 0.18866696f},
+{-0.98078528f, 0.19509032f}, {-0.97948742f, 0.20150532f},
+{-0.97814760f, 0.20791169f}, {-0.97676588f, 0.21430915f},
+{-0.97534232f, 0.22069744f}, {-0.97387698f, 0.22707626f},
+{-0.97236992f, 0.23344536f}, {-0.97082121f, 0.23980446f},
+{-0.96923091f, 0.24615329f}, {-0.96759909f, 0.25249158f},
+{-0.96592583f, 0.25881905f}, {-0.96421118f, 0.26513543f},
+{-0.96245524f, 0.27144045f}, {-0.96065806f, 0.27773385f},
+{-0.95881973f, 0.28401534f}, {-0.95694034f, 0.29028468f},
+{-0.95501994f, 0.29654157f}, {-0.95305864f, 0.30278577f},
+{-0.95105652f, 0.30901699f}, {-0.94901365f, 0.31523498f},
+{-0.94693013f, 0.32143947f}, {-0.94480605f, 0.32763018f},
+{-0.94264149f, 0.33380686f}, {-0.94043656f, 0.33996924f},
+{-0.93819134f, 0.34611706f}, {-0.93590593f, 0.35225005f},
+{-0.93358043f, 0.35836795f}, {-0.93121493f, 0.36447050f},
+{-0.92880955f, 0.37055744f}, {-0.92636438f, 0.37662850f},
+{-0.92387953f, 0.38268343f}, {-0.92135511f, 0.38872197f},
+{-0.91879121f, 0.39474386f}, {-0.91618796f, 0.40074883f},
+{-0.91354546f, 0.40673664f}, {-0.91086382f, 0.41270703f},
+{-0.90814317f, 0.41865974f}, {-0.90538362f, 0.42459451f},
+{-0.90258528f, 0.43051110f}, {-0.89974828f, 0.43640924f},
+{-0.89687274f, 0.44228869f}, {-0.89395878f, 0.44814919f},
+{-0.89100652f, 0.45399050f}, {-0.88801610f, 0.45981236f},
+{-0.88498764f, 0.46561452f}, {-0.88192126f, 0.47139674f},
+{-0.87881711f, 0.47715876f}, {-0.87567532f, 0.48290034f},
+{-0.87249601f, 0.48862124f}, {-0.86927932f, 0.49432121f},
+{-0.86602540f, 0.50000000f}, {-0.86273439f, 0.50565737f},
+{-0.85940641f, 0.51129309f}, {-0.85604162f, 0.51690690f},
+{-0.85264016f, 0.52249856f}, {-0.84920218f, 0.52806785f},
+{-0.84572782f, 0.53361452f}, {-0.84221723f, 0.53913832f},
+{-0.83867057f, 0.54463904f}, {-0.83508798f, 0.55011642f},
+{-0.83146961f, 0.55557023f}, {-0.82781563f, 0.56100025f},
+{-0.82412619f, 0.56640624f}, {-0.82040144f, 0.57178796f},
+{-0.81664156f, 0.57714519f}, {-0.81284668f, 0.58247770f},
+{-0.80901699f, 0.58778525f}, {-0.80515265f, 0.59306763f},
+{-0.80125381f, 0.59832460f}, {-0.79732065f, 0.60355594f},
+{-0.79335334f, 0.60876143f}, {-0.78935204f, 0.61394084f},
+{-0.78531693f, 0.61909395f}, {-0.78124818f, 0.62422054f},
+{-0.77714596f, 0.62932039f}, {-0.77301045f, 0.63439328f},
+{-0.76884183f, 0.63943900f}, {-0.76464028f, 0.64445733f},
+{-0.76040597f, 0.64944805f}, {-0.75613908f, 0.65441095f},
+{-0.75183981f, 0.65934582f}, {-0.74750833f, 0.66425244f},
+{-0.74314483f, 0.66913061f}, {-0.73874949f, 0.67398011f},
+{-0.73432251f, 0.67880075f}, {-0.72986407f, 0.68359230f},
+{-0.72537437f, 0.68835458f}, {-0.72085360f, 0.69308736f},
+{-0.71630194f, 0.69779046f}, {-0.71171961f, 0.70246367f},
+{-0.70710678f, 0.70710678f}, {-0.70246367f, 0.71171961f},
+{-0.69779046f, 0.71630194f}, {-0.69308736f, 0.72085360f},
+{-0.68835458f, 0.72537437f}, {-0.68359230f, 0.72986407f},
+{-0.67880075f, 0.73432251f}, {-0.67398011f, 0.73874949f},
+{-0.66913061f, 0.74314483f}, {-0.66425244f, 0.74750833f},
+{-0.65934582f, 0.75183981f}, {-0.65441095f, 0.75613908f},
+{-0.64944805f, 0.76040597f}, {-0.64445733f, 0.76464028f},
+{-0.63943900f, 0.76884183f}, {-0.63439328f, 0.77301045f},
+{-0.62932039f, 0.77714596f}, {-0.62422054f, 0.78124818f},
+{-0.61909395f, 0.78531693f}, {-0.61394084f, 0.78935204f},
+{-0.60876143f, 0.79335334f}, {-0.60355594f, 0.79732065f},
+{-0.59832460f, 0.80125381f}, {-0.59306763f, 0.80515265f},
+{-0.58778525f, 0.80901699f}, {-0.58247770f, 0.81284668f},
+{-0.57714519f, 0.81664156f}, {-0.57178796f, 0.82040144f},
+{-0.56640624f, 0.82412619f}, {-0.56100025f, 0.82781563f},
+{-0.55557023f, 0.83146961f}, {-0.55011642f, 0.83508798f},
+{-0.54463904f, 0.83867057f}, {-0.53913832f, 0.84221723f},
+{-0.53361452f, 0.84572782f}, {-0.52806785f, 0.84920218f},
+{-0.52249856f, 0.85264016f}, {-0.51690690f, 0.85604162f},
+{-0.51129309f, 0.85940641f}, {-0.50565737f, 0.86273439f},
+{-0.50000000f, 0.86602540f}, {-0.49432121f, 0.86927932f},
+{-0.48862124f, 0.87249601f}, {-0.48290034f, 0.87567532f},
+{-0.47715876f, 0.87881711f}, {-0.47139674f, 0.88192126f},
+{-0.46561452f, 0.88498764f}, {-0.45981236f, 0.88801610f},
+{-0.45399050f, 0.89100652f}, {-0.44814919f, 0.89395878f},
+{-0.44228869f, 0.89687274f}, {-0.43640924f, 0.89974828f},
+{-0.43051110f, 0.90258528f}, {-0.42459451f, 0.90538362f},
+{-0.41865974f, 0.90814317f}, {-0.41270703f, 0.91086382f},
+{-0.40673664f, 0.91354546f}, {-0.40074883f, 0.91618796f},
+{-0.39474386f, 0.91879121f}, {-0.38872197f, 0.92135511f},
+{-0.38268343f, 0.92387953f}, {-0.37662850f, 0.92636438f},
+{-0.37055744f, 0.92880955f}, {-0.36447050f, 0.93121493f},
+{-0.35836795f, 0.93358043f}, {-0.35225005f, 0.93590593f},
+{-0.34611706f, 0.93819134f}, {-0.33996924f, 0.94043656f},
+{-0.33380686f, 0.94264149f}, {-0.32763018f, 0.94480605f},
+{-0.32143947f, 0.94693013f}, {-0.31523498f, 0.94901365f},
+{-0.30901699f, 0.95105652f}, {-0.30278577f, 0.95305864f},
+{-0.29654157f, 0.95501994f}, {-0.29028468f, 0.95694034f},
+{-0.28401534f, 0.95881973f}, {-0.27773385f, 0.96065806f},
+{-0.27144045f, 0.96245524f}, {-0.26513543f, 0.96421118f},
+{-0.25881905f, 0.96592583f}, {-0.25249158f, 0.96759909f},
+{-0.24615329f, 0.96923091f}, {-0.23980446f, 0.97082121f},
+{-0.23344536f, 0.97236992f}, {-0.22707626f, 0.97387698f},
+{-0.22069744f, 0.97534232f}, {-0.21430915f, 0.97676588f},
+{-0.20791169f, 0.97814760f}, {-0.20150532f, 0.97948742f},
+{-0.19509032f, 0.98078528f}, {-0.18866696f, 0.98204113f},
+{-0.18223553f, 0.98325491f}, {-0.17579628f, 0.98442657f},
+{-0.16934950f, 0.98555606f}, {-0.16289547f, 0.98664333f},
+{-0.15643447f, 0.98768834f}, {-0.14996676f, 0.98869104f},
+{-0.14349262f, 0.98965139f}, {-0.13701234f, 0.99056934f},
+{-0.13052619f, 0.99144486f}, {-0.12403445f, 0.99227791f},
+{-0.11753740f, 0.99306846f}, {-0.11103531f, 0.99381646f},
+{-0.10452846f, 0.99452190f}, {-0.098017140f, 0.99518473f},
+{-0.091501619f, 0.99580493f}, {-0.084982177f, 0.99638247f},
+{-0.078459096f, 0.99691733f}, {-0.071932653f, 0.99740949f},
+{-0.065403129f, 0.99785892f}, {-0.058870804f, 0.99826561f},
+{-0.052335956f, 0.99862953f}, {-0.045798867f, 0.99895068f},
+{-0.039259816f, 0.99922904f}, {-0.032719083f, 0.99946459f},
+{-0.026176948f, 0.99965732f}, {-0.019633692f, 0.99980724f},
+{-0.013089596f, 0.99991433f}, {-0.0065449380f, 0.99997858f},
+{-1.8369702e-16f, 1.0000000f}, {0.0065449380f, 0.99997858f},
+{0.013089596f, 0.99991433f}, {0.019633692f, 0.99980724f},
+{0.026176948f, 0.99965732f}, {0.032719083f, 0.99946459f},
+{0.039259816f, 0.99922904f}, {0.045798867f, 0.99895068f},
+{0.052335956f, 0.99862953f}, {0.058870804f, 0.99826561f},
+{0.065403129f, 0.99785892f}, {0.071932653f, 0.99740949f},
+{0.078459096f, 0.99691733f}, {0.084982177f, 0.99638247f},
+{0.091501619f, 0.99580493f}, {0.098017140f, 0.99518473f},
+{0.10452846f, 0.99452190f}, {0.11103531f, 0.99381646f},
+{0.11753740f, 0.99306846f}, {0.12403445f, 0.99227791f},
+{0.13052619f, 0.99144486f}, {0.13701234f, 0.99056934f},
+{0.14349262f, 0.98965139f}, {0.14996676f, 0.98869104f},
+{0.15643447f, 0.98768834f}, {0.16289547f, 0.98664333f},
+{0.16934950f, 0.98555606f}, {0.17579628f, 0.98442657f},
+{0.18223553f, 0.98325491f}, {0.18866696f, 0.98204113f},
+{0.19509032f, 0.98078528f}, {0.20150532f, 0.97948742f},
+{0.20791169f, 0.97814760f}, {0.21430915f, 0.97676588f},
+{0.22069744f, 0.97534232f}, {0.22707626f, 0.97387698f},
+{0.23344536f, 0.97236992f}, {0.23980446f, 0.97082121f},
+{0.24615329f, 0.96923091f}, {0.25249158f, 0.96759909f},
+{0.25881905f, 0.96592583f}, {0.26513543f, 0.96421118f},
+{0.27144045f, 0.96245524f}, {0.27773385f, 0.96065806f},
+{0.28401534f, 0.95881973f}, {0.29028468f, 0.95694034f},
+{0.29654157f, 0.95501994f}, {0.30278577f, 0.95305864f},
+{0.30901699f, 0.95105652f}, {0.31523498f, 0.94901365f},
+{0.32143947f, 0.94693013f}, {0.32763018f, 0.94480605f},
+{0.33380686f, 0.94264149f}, {0.33996924f, 0.94043656f},
+{0.34611706f, 0.93819134f}, {0.35225005f, 0.93590593f},
+{0.35836795f, 0.93358043f}, {0.36447050f, 0.93121493f},
+{0.37055744f, 0.92880955f}, {0.37662850f, 0.92636438f},
+{0.38268343f, 0.92387953f}, {0.38872197f, 0.92135511f},
+{0.39474386f, 0.91879121f}, {0.40074883f, 0.91618796f},
+{0.40673664f, 0.91354546f}, {0.41270703f, 0.91086382f},
+{0.41865974f, 0.90814317f}, {0.42459451f, 0.90538362f},
+{0.43051110f, 0.90258528f}, {0.43640924f, 0.89974828f},
+{0.44228869f, 0.89687274f}, {0.44814919f, 0.89395878f},
+{0.45399050f, 0.89100652f}, {0.45981236f, 0.88801610f},
+{0.46561452f, 0.88498764f}, {0.47139674f, 0.88192126f},
+{0.47715876f, 0.87881711f}, {0.48290034f, 0.87567532f},
+{0.48862124f, 0.87249601f}, {0.49432121f, 0.86927932f},
+{0.50000000f, 0.86602540f}, {0.50565737f, 0.86273439f},
+{0.51129309f, 0.85940641f}, {0.51690690f, 0.85604162f},
+{0.52249856f, 0.85264016f}, {0.52806785f, 0.84920218f},
+{0.53361452f, 0.84572782f}, {0.53913832f, 0.84221723f},
+{0.54463904f, 0.83867057f}, {0.55011642f, 0.83508798f},
+{0.55557023f, 0.83146961f}, {0.56100025f, 0.82781563f},
+{0.56640624f, 0.82412619f}, {0.57178796f, 0.82040144f},
+{0.57714519f, 0.81664156f}, {0.58247770f, 0.81284668f},
+{0.58778525f, 0.80901699f}, {0.59306763f, 0.80515265f},
+{0.59832460f, 0.80125381f}, {0.60355594f, 0.79732065f},
+{0.60876143f, 0.79335334f}, {0.61394084f, 0.78935204f},
+{0.61909395f, 0.78531693f}, {0.62422054f, 0.78124818f},
+{0.62932039f, 0.77714596f}, {0.63439328f, 0.77301045f},
+{0.63943900f, 0.76884183f}, {0.64445733f, 0.76464028f},
+{0.64944805f, 0.76040597f}, {0.65441095f, 0.75613908f},
+{0.65934582f, 0.75183981f}, {0.66425244f, 0.74750833f},
+{0.66913061f, 0.74314483f}, {0.67398011f, 0.73874949f},
+{0.67880075f, 0.73432251f}, {0.68359230f, 0.72986407f},
+{0.68835458f, 0.72537437f}, {0.69308736f, 0.72085360f},
+{0.69779046f, 0.71630194f}, {0.70246367f, 0.71171961f},
+{0.70710678f, 0.70710678f}, {0.71171961f, 0.70246367f},
+{0.71630194f, 0.69779046f}, {0.72085360f, 0.69308736f},
+{0.72537437f, 0.68835458f}, {0.72986407f, 0.68359230f},
+{0.73432251f, 0.67880075f}, {0.73874949f, 0.67398011f},
+{0.74314483f, 0.66913061f}, {0.74750833f, 0.66425244f},
+{0.75183981f, 0.65934582f}, {0.75613908f, 0.65441095f},
+{0.76040597f, 0.64944805f}, {0.76464028f, 0.64445733f},
+{0.76884183f, 0.63943900f}, {0.77301045f, 0.63439328f},
+{0.77714596f, 0.62932039f}, {0.78124818f, 0.62422054f},
+{0.78531693f, 0.61909395f}, {0.78935204f, 0.61394084f},
+{0.79335334f, 0.60876143f}, {0.79732065f, 0.60355594f},
+{0.80125381f, 0.59832460f}, {0.80515265f, 0.59306763f},
+{0.80901699f, 0.58778525f}, {0.81284668f, 0.58247770f},
+{0.81664156f, 0.57714519f}, {0.82040144f, 0.57178796f},
+{0.82412619f, 0.56640624f}, {0.82781563f, 0.56100025f},
+{0.83146961f, 0.55557023f}, {0.83508798f, 0.55011642f},
+{0.83867057f, 0.54463904f}, {0.84221723f, 0.53913832f},
+{0.84572782f, 0.53361452f}, {0.84920218f, 0.52806785f},
+{0.85264016f, 0.52249856f}, {0.85604162f, 0.51690690f},
+{0.85940641f, 0.51129309f}, {0.86273439f, 0.50565737f},
+{0.86602540f, 0.50000000f}, {0.86927932f, 0.49432121f},
+{0.87249601f, 0.48862124f}, {0.87567532f, 0.48290034f},
+{0.87881711f, 0.47715876f}, {0.88192126f, 0.47139674f},
+{0.88498764f, 0.46561452f}, {0.88801610f, 0.45981236f},
+{0.89100652f, 0.45399050f}, {0.89395878f, 0.44814919f},
+{0.89687274f, 0.44228869f}, {0.89974828f, 0.43640924f},
+{0.90258528f, 0.43051110f}, {0.90538362f, 0.42459451f},
+{0.90814317f, 0.41865974f}, {0.91086382f, 0.41270703f},
+{0.91354546f, 0.40673664f}, {0.91618796f, 0.40074883f},
+{0.91879121f, 0.39474386f}, {0.92135511f, 0.38872197f},
+{0.92387953f, 0.38268343f}, {0.92636438f, 0.37662850f},
+{0.92880955f, 0.37055744f}, {0.93121493f, 0.36447050f},
+{0.93358043f, 0.35836795f}, {0.93590593f, 0.35225005f},
+{0.93819134f, 0.34611706f}, {0.94043656f, 0.33996924f},
+{0.94264149f, 0.33380686f}, {0.94480605f, 0.32763018f},
+{0.94693013f, 0.32143947f}, {0.94901365f, 0.31523498f},
+{0.95105652f, 0.30901699f}, {0.95305864f, 0.30278577f},
+{0.95501994f, 0.29654157f}, {0.95694034f, 0.29028468f},
+{0.95881973f, 0.28401534f}, {0.96065806f, 0.27773385f},
+{0.96245524f, 0.27144045f}, {0.96421118f, 0.26513543f},
+{0.96592583f, 0.25881905f}, {0.96759909f, 0.25249158f},
+{0.96923091f, 0.24615329f}, {0.97082121f, 0.23980446f},
+{0.97236992f, 0.23344536f}, {0.97387698f, 0.22707626f},
+{0.97534232f, 0.22069744f}, {0.97676588f, 0.21430915f},
+{0.97814760f, 0.20791169f}, {0.97948742f, 0.20150532f},
+{0.98078528f, 0.19509032f}, {0.98204113f, 0.18866696f},
+{0.98325491f, 0.18223553f}, {0.98442657f, 0.17579628f},
+{0.98555606f, 0.16934950f}, {0.98664333f, 0.16289547f},
+{0.98768834f, 0.15643447f}, {0.98869104f, 0.14996676f},
+{0.98965139f, 0.14349262f}, {0.99056934f, 0.13701234f},
+{0.99144486f, 0.13052619f}, {0.99227791f, 0.12403445f},
+{0.99306846f, 0.11753740f}, {0.99381646f, 0.11103531f},
+{0.99452190f, 0.10452846f}, {0.99518473f, 0.098017140f},
+{0.99580493f, 0.091501619f}, {0.99638247f, 0.084982177f},
+{0.99691733f, 0.078459096f}, {0.99740949f, 0.071932653f},
+{0.99785892f, 0.065403129f}, {0.99826561f, 0.058870804f},
+{0.99862953f, 0.052335956f}, {0.99895068f, 0.045798867f},
+{0.99922904f, 0.039259816f}, {0.99946459f, 0.032719083f},
+{0.99965732f, 0.026176948f}, {0.99980724f, 0.019633692f},
+{0.99991433f, 0.013089596f}, {0.99997858f, 0.0065449380f},
+};
+#ifndef FFT_BITREV960
+#define FFT_BITREV960
+static const opus_int16 fft_bitrev960[960] = {
+0, 192, 384, 576, 768, 64, 256, 448, 640, 832, 128, 320, 512, 704, 896,
+16, 208, 400, 592, 784, 80, 272, 464, 656, 848, 144, 336, 528, 720, 912,
+32, 224, 416, 608, 800, 96, 288, 480, 672, 864, 160, 352, 544, 736, 928,
+48, 240, 432, 624, 816, 112, 304, 496, 688, 880, 176, 368, 560, 752, 944,
+4, 196, 388, 580, 772, 68, 260, 452, 644, 836, 132, 324, 516, 708, 900,
+20, 212, 404, 596, 788, 84, 276, 468, 660, 852, 148, 340, 532, 724, 916,
+36, 228, 420, 612, 804, 100, 292, 484, 676, 868, 164, 356, 548, 740, 932,
+52, 244, 436, 628, 820, 116, 308, 500, 692, 884, 180, 372, 564, 756, 948,
+8, 200, 392, 584, 776, 72, 264, 456, 648, 840, 136, 328, 520, 712, 904,
+24, 216, 408, 600, 792, 88, 280, 472, 664, 856, 152, 344, 536, 728, 920,
+40, 232, 424, 616, 808, 104, 296, 488, 680, 872, 168, 360, 552, 744, 936,
+56, 248, 440, 632, 824, 120, 312, 504, 696, 888, 184, 376, 568, 760, 952,
+12, 204, 396, 588, 780, 76, 268, 460, 652, 844, 140, 332, 524, 716, 908,
+28, 220, 412, 604, 796, 92, 284, 476, 668, 860, 156, 348, 540, 732, 924,
+44, 236, 428, 620, 812, 108, 300, 492, 684, 876, 172, 364, 556, 748, 940,
+60, 252, 444, 636, 828, 124, 316, 508, 700, 892, 188, 380, 572, 764, 956,
+1, 193, 385, 577, 769, 65, 257, 449, 641, 833, 129, 321, 513, 705, 897,
+17, 209, 401, 593, 785, 81, 273, 465, 657, 849, 145, 337, 529, 721, 913,
+33, 225, 417, 609, 801, 97, 289, 481, 673, 865, 161, 353, 545, 737, 929,
+49, 241, 433, 625, 817, 113, 305, 497, 689, 881, 177, 369, 561, 753, 945,
+5, 197, 389, 581, 773, 69, 261, 453, 645, 837, 133, 325, 517, 709, 901,
+21, 213, 405, 597, 789, 85, 277, 469, 661, 853, 149, 341, 533, 725, 917,
+37, 229, 421, 613, 805, 101, 293, 485, 677, 869, 165, 357, 549, 741, 933,
+53, 245, 437, 629, 821, 117, 309, 501, 693, 885, 181, 373, 565, 757, 949,
+9, 201, 393, 585, 777, 73, 265, 457, 649, 841, 137, 329, 521, 713, 905,
+25, 217, 409, 601, 793, 89, 281, 473, 665, 857, 153, 345, 537, 729, 921,
+41, 233, 425, 617, 809, 105, 297, 489, 681, 873, 169, 361, 553, 745, 937,
+57, 249, 441, 633, 825, 121, 313, 505, 697, 889, 185, 377, 569, 761, 953,
+13, 205, 397, 589, 781, 77, 269, 461, 653, 845, 141, 333, 525, 717, 909,
+29, 221, 413, 605, 797, 93, 285, 477, 669, 861, 157, 349, 541, 733, 925,
+45, 237, 429, 621, 813, 109, 301, 493, 685, 877, 173, 365, 557, 749, 941,
+61, 253, 445, 637, 829, 125, 317, 509, 701, 893, 189, 381, 573, 765, 957,
+2, 194, 386, 578, 770, 66, 258, 450, 642, 834, 130, 322, 514, 706, 898,
+18, 210, 402, 594, 786, 82, 274, 466, 658, 850, 146, 338, 530, 722, 914,
+34, 226, 418, 610, 802, 98, 290, 482, 674, 866, 162, 354, 546, 738, 930,
+50, 242, 434, 626, 818, 114, 306, 498, 690, 882, 178, 370, 562, 754, 946,
+6, 198, 390, 582, 774, 70, 262, 454, 646, 838, 134, 326, 518, 710, 902,
+22, 214, 406, 598, 790, 86, 278, 470, 662, 854, 150, 342, 534, 726, 918,
+38, 230, 422, 614, 806, 102, 294, 486, 678, 870, 166, 358, 550, 742, 934,
+54, 246, 438, 630, 822, 118, 310, 502, 694, 886, 182, 374, 566, 758, 950,
+10, 202, 394, 586, 778, 74, 266, 458, 650, 842, 138, 330, 522, 714, 906,
+26, 218, 410, 602, 794, 90, 282, 474, 666, 858, 154, 346, 538, 730, 922,
+42, 234, 426, 618, 810, 106, 298, 490, 682, 874, 170, 362, 554, 746, 938,
+58, 250, 442, 634, 826, 122, 314, 506, 698, 890, 186, 378, 570, 762, 954,
+14, 206, 398, 590, 782, 78, 270, 462, 654, 846, 142, 334, 526, 718, 910,
+30, 222, 414, 606, 798, 94, 286, 478, 670, 862, 158, 350, 542, 734, 926,
+46, 238, 430, 622, 814, 110, 302, 494, 686, 878, 174, 366, 558, 750, 942,
+62, 254, 446, 638, 830, 126, 318, 510, 702, 894, 190, 382, 574, 766, 958,
+3, 195, 387, 579, 771, 67, 259, 451, 643, 835, 131, 323, 515, 707, 899,
+19, 211, 403, 595, 787, 83, 275, 467, 659, 851, 147, 339, 531, 723, 915,
+35, 227, 419, 611, 803, 99, 291, 483, 675, 867, 163, 355, 547, 739, 931,
+51, 243, 435, 627, 819, 115, 307, 499, 691, 883, 179, 371, 563, 755, 947,
+7, 199, 391, 583, 775, 71, 263, 455, 647, 839, 135, 327, 519, 711, 903,
+23, 215, 407, 599, 791, 87, 279, 471, 663, 855, 151, 343, 535, 727, 919,
+39, 231, 423, 615, 807, 103, 295, 487, 679, 871, 167, 359, 551, 743, 935,
+55, 247, 439, 631, 823, 119, 311, 503, 695, 887, 183, 375, 567, 759, 951,
+11, 203, 395, 587, 779, 75, 267, 459, 651, 843, 139, 331, 523, 715, 907,
+27, 219, 411, 603, 795, 91, 283, 475, 667, 859, 155, 347, 539, 731, 923,
+43, 235, 427, 619, 811, 107, 299, 491, 683, 875, 171, 363, 555, 747, 939,
+59, 251, 443, 635, 827, 123, 315, 507, 699, 891, 187, 379, 571, 763, 955,
+15, 207, 399, 591, 783, 79, 271, 463, 655, 847, 143, 335, 527, 719, 911,
+31, 223, 415, 607, 799, 95, 287, 479, 671, 863, 159, 351, 543, 735, 927,
+47, 239, 431, 623, 815, 111, 303, 495, 687, 879, 175, 367, 559, 751, 943,
+63, 255, 447, 639, 831, 127, 319, 511, 703, 895, 191, 383, 575, 767, 959,
+};
+#endif
+
+#ifndef FFT_BITREV480
+#define FFT_BITREV480
+static const opus_int16 fft_bitrev480[480] = {
+0, 96, 192, 288, 384, 32, 128, 224, 320, 416, 64, 160, 256, 352, 448,
+8, 104, 200, 296, 392, 40, 136, 232, 328, 424, 72, 168, 264, 360, 456,
+16, 112, 208, 304, 400, 48, 144, 240, 336, 432, 80, 176, 272, 368, 464,
+24, 120, 216, 312, 408, 56, 152, 248, 344, 440, 88, 184, 280, 376, 472,
+4, 100, 196, 292, 388, 36, 132, 228, 324, 420, 68, 164, 260, 356, 452,
+12, 108, 204, 300, 396, 44, 140, 236, 332, 428, 76, 172, 268, 364, 460,
+20, 116, 212, 308, 404, 52, 148, 244, 340, 436, 84, 180, 276, 372, 468,
+28, 124, 220, 316, 412, 60, 156, 252, 348, 444, 92, 188, 284, 380, 476,
+1, 97, 193, 289, 385, 33, 129, 225, 321, 417, 65, 161, 257, 353, 449,
+9, 105, 201, 297, 393, 41, 137, 233, 329, 425, 73, 169, 265, 361, 457,
+17, 113, 209, 305, 401, 49, 145, 241, 337, 433, 81, 177, 273, 369, 465,
+25, 121, 217, 313, 409, 57, 153, 249, 345, 441, 89, 185, 281, 377, 473,
+5, 101, 197, 293, 389, 37, 133, 229, 325, 421, 69, 165, 261, 357, 453,
+13, 109, 205, 301, 397, 45, 141, 237, 333, 429, 77, 173, 269, 365, 461,
+21, 117, 213, 309, 405, 53, 149, 245, 341, 437, 85, 181, 277, 373, 469,
+29, 125, 221, 317, 413, 61, 157, 253, 349, 445, 93, 189, 285, 381, 477,
+2, 98, 194, 290, 386, 34, 130, 226, 322, 418, 66, 162, 258, 354, 450,
+10, 106, 202, 298, 394, 42, 138, 234, 330, 426, 74, 170, 266, 362, 458,
+18, 114, 210, 306, 402, 50, 146, 242, 338, 434, 82, 178, 274, 370, 466,
+26, 122, 218, 314, 410, 58, 154, 250, 346, 442, 90, 186, 282, 378, 474,
+6, 102, 198, 294, 390, 38, 134, 230, 326, 422, 70, 166, 262, 358, 454,
+14, 110, 206, 302, 398, 46, 142, 238, 334, 430, 78, 174, 270, 366, 462,
+22, 118, 214, 310, 406, 54, 150, 246, 342, 438, 86, 182, 278, 374, 470,
+30, 126, 222, 318, 414, 62, 158, 254, 350, 446, 94, 190, 286, 382, 478,
+3, 99, 195, 291, 387, 35, 131, 227, 323, 419, 67, 163, 259, 355, 451,
+11, 107, 203, 299, 395, 43, 139, 235, 331, 427, 75, 171, 267, 363, 459,
+19, 115, 211, 307, 403, 51, 147, 243, 339, 435, 83, 179, 275, 371, 467,
+27, 123, 219, 315, 411, 59, 155, 251, 347, 443, 91, 187, 283, 379, 475,
+7, 103, 199, 295, 391, 39, 135, 231, 327, 423, 71, 167, 263, 359, 455,
+15, 111, 207, 303, 399, 47, 143, 239, 335, 431, 79, 175, 271, 367, 463,
+23, 119, 215, 311, 407, 55, 151, 247, 343, 439, 87, 183, 279, 375, 471,
+31, 127, 223, 319, 415, 63, 159, 255, 351, 447, 95, 191, 287, 383, 479,
+};
+#endif
+
+#ifndef FFT_BITREV240
+#define FFT_BITREV240
+static const opus_int16 fft_bitrev240[240] = {
+0, 48, 96, 144, 192, 16, 64, 112, 160, 208, 32, 80, 128, 176, 224,
+4, 52, 100, 148, 196, 20, 68, 116, 164, 212, 36, 84, 132, 180, 228,
+8, 56, 104, 152, 200, 24, 72, 120, 168, 216, 40, 88, 136, 184, 232,
+12, 60, 108, 156, 204, 28, 76, 124, 172, 220, 44, 92, 140, 188, 236,
+1, 49, 97, 145, 193, 17, 65, 113, 161, 209, 33, 81, 129, 177, 225,
+5, 53, 101, 149, 197, 21, 69, 117, 165, 213, 37, 85, 133, 181, 229,
+9, 57, 105, 153, 201, 25, 73, 121, 169, 217, 41, 89, 137, 185, 233,
+13, 61, 109, 157, 205, 29, 77, 125, 173, 221, 45, 93, 141, 189, 237,
+2, 50, 98, 146, 194, 18, 66, 114, 162, 210, 34, 82, 130, 178, 226,
+6, 54, 102, 150, 198, 22, 70, 118, 166, 214, 38, 86, 134, 182, 230,
+10, 58, 106, 154, 202, 26, 74, 122, 170, 218, 42, 90, 138, 186, 234,
+14, 62, 110, 158, 206, 30, 78, 126, 174, 222, 46, 94, 142, 190, 238,
+3, 51, 99, 147, 195, 19, 67, 115, 163, 211, 35, 83, 131, 179, 227,
+7, 55, 103, 151, 199, 23, 71, 119, 167, 215, 39, 87, 135, 183, 231,
+11, 59, 107, 155, 203, 27, 75, 123, 171, 219, 43, 91, 139, 187, 235,
+15, 63, 111, 159, 207, 31, 79, 127, 175, 223, 47, 95, 143, 191, 239,
+};
+#endif
+
+#ifndef FFT_BITREV120
+#define FFT_BITREV120
+static const opus_int16 fft_bitrev120[120] = {
+0, 24, 48, 72, 96, 8, 32, 56, 80, 104, 16, 40, 64, 88, 112,
+4, 28, 52, 76, 100, 12, 36, 60, 84, 108, 20, 44, 68, 92, 116,
+1, 25, 49, 73, 97, 9, 33, 57, 81, 105, 17, 41, 65, 89, 113,
+5, 29, 53, 77, 101, 13, 37, 61, 85, 109, 21, 45, 69, 93, 117,
+2, 26, 50, 74, 98, 10, 34, 58, 82, 106, 18, 42, 66, 90, 114,
+6, 30, 54, 78, 102, 14, 38, 62, 86, 110, 22, 46, 70, 94, 118,
+3, 27, 51, 75, 99, 11, 35, 59, 83, 107, 19, 43, 67, 91, 115,
+7, 31, 55, 79, 103, 15, 39, 63, 87, 111, 23, 47, 71, 95, 119,
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_0
+#define FFT_STATE96000_1920_0
+static const kiss_fft_state fft_state96000_1920_0 = {
+960, /* nfft */
+0.0010416667f, /* scale */
+-1, /* shift */
+{5, 192, 3, 64, 4, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev960, /* bitrev */
+fft_twiddles96000_1920, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_960,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_1
+#define FFT_STATE96000_1920_1
+static const kiss_fft_state fft_state96000_1920_1 = {
+480, /* nfft */
+0.0020833334f, /* scale */
+1, /* shift */
+{5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev480, /* bitrev */
+fft_twiddles96000_1920, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_480,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_2
+#define FFT_STATE96000_1920_2
+static const kiss_fft_state fft_state96000_1920_2 = {
+240, /* nfft */
+0.0041666669f, /* scale */
+2, /* shift */
+{5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev240, /* bitrev */
+fft_twiddles96000_1920, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_240,
+#else
+NULL,
+#endif
+};
+#endif
+
+#ifndef FFT_STATE96000_1920_3
+#define FFT_STATE96000_1920_3
+static const kiss_fft_state fft_state96000_1920_3 = {
+120, /* nfft */
+0.0083333338f, /* scale */
+3, /* shift */
+{5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
+fft_bitrev120, /* bitrev */
+fft_twiddles96000_1920, /* bitrev */
+#ifdef OVERRIDE_FFT
+(arch_fft_state *)&cfg_arch_120,
+#else
+NULL,
+#endif
+};
+#endif
+
+#endif
+
+#ifndef MDCT_TWIDDLES1920
+#define MDCT_TWIDDLES1920
+static const celt_coef mdct_twiddles1920[3600] = {
+0.99999998f, 0.99999831f, 0.99999396f, 0.99998693f, 0.99997722f,
+0.99996484f, 0.99994978f, 0.99993204f, 0.99991163f, 0.99988854f,
+0.99986277f, 0.99983433f, 0.99980320f, 0.99976941f, 0.99973293f,
+0.99969378f, 0.99965195f, 0.99960745f, 0.99956026f, 0.99951041f,
+0.99945787f, 0.99940267f, 0.99934478f, 0.99928422f, 0.99922099f,
+0.99915507f, 0.99908649f, 0.99901523f, 0.99894129f, 0.99886468f,
+0.99878540f, 0.99870344f, 0.99861881f, 0.99853150f, 0.99844153f,
+0.99834887f, 0.99825355f, 0.99815555f, 0.99805488f, 0.99795154f,
+0.99784553f, 0.99773684f, 0.99762548f, 0.99751146f, 0.99739476f,
+0.99727539f, 0.99715335f, 0.99702864f, 0.99690127f, 0.99677122f,
+0.99663850f, 0.99650312f, 0.99636507f, 0.99622435f, 0.99608096f,
+0.99593491f, 0.99578619f, 0.99563481f, 0.99548076f, 0.99532404f,
+0.99516466f, 0.99500261f, 0.99483790f, 0.99467053f, 0.99450050f,
+0.99432780f, 0.99415244f, 0.99397441f, 0.99379373f, 0.99361039f,
+0.99342438f, 0.99323572f, 0.99304440f, 0.99285041f, 0.99265377f,
+0.99245448f, 0.99225252f, 0.99204791f, 0.99184064f, 0.99163072f,
+0.99141814f, 0.99120291f, 0.99098503f, 0.99076449f, 0.99054130f,
+0.99031545f, 0.99008696f, 0.98985581f, 0.98962202f, 0.98938557f,
+0.98914648f, 0.98890474f, 0.98866035f, 0.98841331f, 0.98816363f,
+0.98791130f, 0.98765632f, 0.98739871f, 0.98713845f, 0.98687554f,
+0.98660999f, 0.98634181f, 0.98607098f, 0.98579751f, 0.98552140f,
+0.98524265f, 0.98496127f, 0.98467725f, 0.98439059f, 0.98410130f,
+0.98380937f, 0.98351481f, 0.98321761f, 0.98291779f, 0.98261533f,
+0.98231024f, 0.98200252f, 0.98169217f, 0.98137919f, 0.98106359f,
+0.98074536f, 0.98042450f, 0.98010102f, 0.97977491f, 0.97944619f,
+0.97911483f, 0.97878086f, 0.97844427f, 0.97810506f, 0.97776322f,
+0.97741878f, 0.97707171f, 0.97672203f, 0.97636973f, 0.97601482f,
+0.97565730f, 0.97529716f, 0.97493441f, 0.97456906f, 0.97420109f,
+0.97383051f, 0.97345733f, 0.97308154f, 0.97270315f, 0.97232215f,
+0.97193855f, 0.97155235f, 0.97116355f, 0.97077214f, 0.97037814f,
+0.96998154f, 0.96958234f, 0.96918054f, 0.96877615f, 0.96836917f,
+0.96795960f, 0.96754743f, 0.96713267f, 0.96671533f, 0.96629539f,
+0.96587287f, 0.96544776f, 0.96502007f, 0.96458979f, 0.96415693f,
+0.96372149f, 0.96328347f, 0.96284288f, 0.96239970f, 0.96195394f,
+0.96150562f, 0.96105471f, 0.96060124f, 0.96014519f, 0.95968657f,
+0.95922538f, 0.95876162f, 0.95829530f, 0.95782641f, 0.95735496f,
+0.95688094f, 0.95640437f, 0.95592523f, 0.95544353f, 0.95495927f,
+0.95447246f, 0.95398309f, 0.95349117f, 0.95299669f, 0.95249967f,
+0.95200009f, 0.95149797f, 0.95099329f, 0.95048607f, 0.94997631f,
+0.94946400f, 0.94894915f, 0.94843176f, 0.94791184f, 0.94738937f,
+0.94686437f, 0.94633683f, 0.94580676f, 0.94527415f, 0.94473902f,
+0.94420135f, 0.94366116f, 0.94311844f, 0.94257320f, 0.94202543f,
+0.94147514f, 0.94092233f, 0.94036700f, 0.93980916f, 0.93924879f,
+0.93868592f, 0.93812052f, 0.93755262f, 0.93698221f, 0.93640929f,
+0.93583386f, 0.93525593f, 0.93467549f, 0.93409255f, 0.93350711f,
+0.93291917f, 0.93232873f, 0.93173580f, 0.93114037f, 0.93054245f,
+0.92994204f, 0.92933913f, 0.92873374f, 0.92812587f, 0.92751550f,
+0.92690266f, 0.92628733f, 0.92566953f, 0.92504924f, 0.92442648f,
+0.92380124f, 0.92317353f, 0.92254335f, 0.92191070f, 0.92127558f,
+0.92063799f, 0.91999794f, 0.91935543f, 0.91871045f, 0.91806302f,
+0.91741313f, 0.91676078f, 0.91610597f, 0.91544872f, 0.91478901f,
+0.91412685f, 0.91346225f, 0.91279520f, 0.91212571f, 0.91145377f,
+0.91077939f, 0.91010258f, 0.90942333f, 0.90874164f, 0.90805753f,
+0.90737098f, 0.90668200f, 0.90599059f, 0.90529676f, 0.90460050f,
+0.90390183f, 0.90320073f, 0.90249721f, 0.90179128f, 0.90108293f,
+0.90037218f, 0.89965901f, 0.89894343f, 0.89822544f, 0.89750505f,
+0.89678226f, 0.89605707f, 0.89532948f, 0.89459949f, 0.89386710f,
+0.89313232f, 0.89239515f, 0.89165560f, 0.89091365f, 0.89016932f,
+0.88942261f, 0.88867351f, 0.88792204f, 0.88716818f, 0.88641196f,
+0.88565336f, 0.88489239f, 0.88412905f, 0.88336334f, 0.88259527f,
+0.88182483f, 0.88105203f, 0.88027688f, 0.87949937f, 0.87871950f,
+0.87793728f, 0.87715271f, 0.87636579f, 0.87557653f, 0.87478492f,
+0.87399097f, 0.87319468f, 0.87239605f, 0.87159509f, 0.87079179f,
+0.86998616f, 0.86917820f, 0.86836792f, 0.86755531f, 0.86674037f,
+0.86592312f, 0.86510355f, 0.86428166f, 0.86345746f, 0.86263095f,
+0.86180212f, 0.86097099f, 0.86013756f, 0.85930182f, 0.85846378f,
+0.85762344f, 0.85678081f, 0.85593588f, 0.85508866f, 0.85423915f,
+0.85338736f, 0.85253328f, 0.85167692f, 0.85081827f, 0.84995735f,
+0.84909416f, 0.84822869f, 0.84736095f, 0.84649094f, 0.84561866f,
+0.84474412f, 0.84386732f, 0.84298826f, 0.84210695f, 0.84122337f,
+0.84033755f, 0.83944948f, 0.83855915f, 0.83766659f, 0.83677178f,
+0.83587473f, 0.83497544f, 0.83407392f, 0.83317016f, 0.83226418f,
+0.83135596f, 0.83044552f, 0.82953286f, 0.82861797f, 0.82770087f,
+0.82678155f, 0.82586002f, 0.82493628f, 0.82401032f, 0.82308217f,
+0.82215180f, 0.82121924f, 0.82028448f, 0.81934752f, 0.81840837f,
+0.81746703f, 0.81652349f, 0.81557778f, 0.81462988f, 0.81367979f,
+0.81272753f, 0.81177310f, 0.81081649f, 0.80985771f, 0.80889676f,
+0.80793364f, 0.80696837f, 0.80600093f, 0.80503133f, 0.80405958f,
+0.80308568f, 0.80210962f, 0.80113142f, 0.80015107f, 0.79916858f,
+0.79818396f, 0.79719719f, 0.79620829f, 0.79521726f, 0.79422410f,
+0.79322881f, 0.79223140f, 0.79123187f, 0.79023022f, 0.78922646f,
+0.78822058f, 0.78721259f, 0.78620249f, 0.78519029f, 0.78417599f,
+0.78315958f, 0.78214108f, 0.78112049f, 0.78009781f, 0.77907303f,
+0.77804617f, 0.77701723f, 0.77598621f, 0.77495311f, 0.77391793f,
+0.77288068f, 0.77184137f, 0.77079998f, 0.76975654f, 0.76871103f,
+0.76766347f, 0.76661384f, 0.76556217f, 0.76450845f, 0.76345268f,
+0.76239487f, 0.76133501f, 0.76027312f, 0.75920919f, 0.75814323f,
+0.75707524f, 0.75600522f, 0.75493318f, 0.75385911f, 0.75278303f,
+0.75170494f, 0.75062483f, 0.74954271f, 0.74845858f, 0.74737245f,
+0.74628432f, 0.74519419f, 0.74410207f, 0.74300795f, 0.74191185f,
+0.74081376f, 0.73971368f, 0.73861163f, 0.73750759f, 0.73640158f,
+0.73529361f, 0.73418366f, 0.73307175f, 0.73195787f, 0.73084203f,
+0.72972424f, 0.72860450f, 0.72748280f, 0.72635916f, 0.72523357f,
+0.72410604f, 0.72297657f, 0.72184516f, 0.72071182f, 0.71957656f,
+0.71843936f, 0.71730025f, 0.71615921f, 0.71501625f, 0.71387138f,
+0.71272460f, 0.71157592f, 0.71042532f, 0.70927283f, 0.70811843f,
+0.70696214f, 0.70580396f, 0.70464389f, 0.70348193f, 0.70231808f,
+0.70115236f, 0.69998476f, 0.69881528f, 0.69764394f, 0.69647073f,
+0.69529565f, 0.69411871f, 0.69293991f, 0.69175926f, 0.69057675f,
+0.68939240f, 0.68820620f, 0.68701816f, 0.68582828f, 0.68463656f,
+0.68344301f, 0.68224763f, 0.68105042f, 0.67985139f, 0.67865054f,
+0.67744787f, 0.67624339f, 0.67503710f, 0.67382900f, 0.67261910f,
+0.67140739f, 0.67019389f, 0.66897860f, 0.66776151f, 0.66654264f,
+0.66532198f, 0.66409954f, 0.66287532f, 0.66164932f, 0.66042156f,
+0.65919203f, 0.65796073f, 0.65672767f, 0.65549285f, 0.65425628f,
+0.65301796f, 0.65177788f, 0.65053607f, 0.64929251f, 0.64804721f,
+0.64680018f, 0.64555141f, 0.64430092f, 0.64304871f, 0.64179477f,
+0.64053911f, 0.63928174f, 0.63802265f, 0.63676186f, 0.63549936f,
+0.63423517f, 0.63296927f, 0.63170168f, 0.63043240f, 0.62916143f,
+0.62788877f, 0.62661444f, 0.62533842f, 0.62406074f, 0.62278138f,
+0.62150035f, 0.62021766f, 0.61893331f, 0.61764731f, 0.61635965f,
+0.61507034f, 0.61377938f, 0.61248678f, 0.61119254f, 0.60989666f,
+0.60859915f, 0.60730001f, 0.60599925f, 0.60469686f, 0.60339285f,
+0.60208723f, 0.60078000f, 0.59947115f, 0.59816071f, 0.59684866f,
+0.59553501f, 0.59421977f, 0.59290294f, 0.59158452f, 0.59026452f,
+0.58894293f, 0.58761977f, 0.58629504f, 0.58496873f, 0.58364086f,
+0.58231143f, 0.58098044f, 0.57964789f, 0.57831380f, 0.57697815f,
+0.57564096f, 0.57430223f, 0.57296196f, 0.57162015f, 0.57027682f,
+0.56893195f, 0.56758557f, 0.56623767f, 0.56488825f, 0.56353731f,
+0.56218487f, 0.56083093f, 0.55947548f, 0.55811853f, 0.55676009f,
+0.55540016f, 0.55403874f, 0.55267584f, 0.55131146f, 0.54994560f,
+0.54857827f, 0.54720948f, 0.54583921f, 0.54446749f, 0.54309431f,
+0.54171967f, 0.54034359f, 0.53896605f, 0.53758708f, 0.53620666f,
+0.53482481f, 0.53344153f, 0.53205682f, 0.53067068f, 0.52928312f,
+0.52789415f, 0.52650377f, 0.52511197f, 0.52371877f, 0.52232416f,
+0.52092816f, 0.51953076f, 0.51813197f, 0.51673180f, 0.51533024f,
+0.51392730f, 0.51252299f, 0.51111730f, 0.50971025f, 0.50830183f,
+0.50689204f, 0.50548091f, 0.50406842f, 0.50265458f, 0.50123939f,
+0.49982286f, 0.49840499f, 0.49698579f, 0.49556526f, 0.49414340f,
+0.49272022f, 0.49129572f, 0.48986991f, 0.48844278f, 0.48701434f,
+0.48558461f, 0.48415357f, 0.48272123f, 0.48128760f, 0.47985269f,
+0.47841649f, 0.47697901f, 0.47554025f, 0.47410021f, 0.47265891f,
+0.47121635f, 0.46977252f, 0.46832743f, 0.46688109f, 0.46543350f,
+0.46398467f, 0.46253459f, 0.46108327f, 0.45963072f, 0.45817694f,
+0.45672193f, 0.45526570f, 0.45380825f, 0.45234959f, 0.45088971f,
+0.44942863f, 0.44796634f, 0.44650286f, 0.44503818f, 0.44357230f,
+0.44210524f, 0.44063700f, 0.43916758f, 0.43769698f, 0.43622521f,
+0.43475227f, 0.43327816f, 0.43180290f, 0.43032648f, 0.42884891f,
+0.42737019f, 0.42589033f, 0.42440932f, 0.42292718f, 0.42144391f,
+0.41995951f, 0.41847399f, 0.41698734f, 0.41549958f, 0.41401070f,
+0.41252072f, 0.41102963f, 0.40953745f, 0.40804416f, 0.40654979f,
+0.40505432f, 0.40355777f, 0.40206014f, 0.40056144f, 0.39906166f,
+0.39756081f, 0.39605890f, 0.39455593f, 0.39305190f, 0.39154682f,
+0.39004069f, 0.38853352f, 0.38702530f, 0.38551605f, 0.38400577f,
+0.38249446f, 0.38098213f, 0.37946878f, 0.37795441f, 0.37643902f,
+0.37492263f, 0.37340524f, 0.37188685f, 0.37036746f, 0.36884708f,
+0.36732571f, 0.36580336f, 0.36428003f, 0.36275572f, 0.36123045f,
+0.35970420f, 0.35817700f, 0.35664883f, 0.35511971f, 0.35358964f,
+0.35205862f, 0.35052666f, 0.34899376f, 0.34745992f, 0.34592516f,
+0.34438947f, 0.34285286f, 0.34131533f, 0.33977688f, 0.33823753f,
+0.33669727f, 0.33515611f, 0.33361405f, 0.33207110f, 0.33052726f,
+0.32898254f, 0.32743693f, 0.32589045f, 0.32434309f, 0.32279487f,
+0.32124578f, 0.31969583f, 0.31814503f, 0.31659338f, 0.31504087f,
+0.31348753f, 0.31193334f, 0.31037832f, 0.30882247f, 0.30726579f,
+0.30570829f, 0.30414997f, 0.30259083f, 0.30103089f, 0.29947014f,
+0.29790859f, 0.29634624f, 0.29478309f, 0.29321916f, 0.29165445f,
+0.29008895f, 0.28852267f, 0.28695563f, 0.28538781f, 0.28381923f,
+0.28224989f, 0.28067980f, 0.27910895f, 0.27753736f, 0.27596502f,
+0.27439194f, 0.27281813f, 0.27124359f, 0.26966833f, 0.26809234f,
+0.26651563f, 0.26493821f, 0.26336008f, 0.26178125f, 0.26020171f,
+0.25862148f, 0.25704055f, 0.25545894f, 0.25387664f, 0.25229367f,
+0.25071002f, 0.24912569f, 0.24754070f, 0.24595505f, 0.24436874f,
+0.24278177f, 0.24119416f, 0.23960590f, 0.23801699f, 0.23642745f,
+0.23483728f, 0.23324648f, 0.23165505f, 0.23006301f, 0.22847034f,
+0.22687707f, 0.22528319f, 0.22368870f, 0.22209362f, 0.22049794f,
+0.21890167f, 0.21730482f, 0.21570738f, 0.21410937f, 0.21251078f,
+0.21091163f, 0.20931191f, 0.20771163f, 0.20611079f, 0.20450940f,
+0.20290746f, 0.20130498f, 0.19970196f, 0.19809841f, 0.19649433f,
+0.19488972f, 0.19328459f, 0.19167894f, 0.19007277f, 0.18846610f,
+0.18685893f, 0.18525125f, 0.18364308f, 0.18203442f, 0.18042526f,
+0.17881563f, 0.17720552f, 0.17559493f, 0.17398387f, 0.17237235f,
+0.17076037f, 0.16914792f, 0.16753503f, 0.16592169f, 0.16430790f,
+0.16269367f, 0.16107901f, 0.15946391f, 0.15784839f, 0.15623245f,
+0.15461609f, 0.15299931f, 0.15138213f, 0.14976453f, 0.14814654f,
+0.14652815f, 0.14490937f, 0.14329020f, 0.14167065f, 0.14005072f,
+0.13843041f, 0.13680974f, 0.13518869f, 0.13356729f, 0.13194552f,
+0.13032341f, 0.12870094f, 0.12707813f, 0.12545498f, 0.12383150f,
+0.12220768f, 0.12058354f, 0.11895907f, 0.11733428f, 0.11570918f,
+0.11408377f, 0.11245806f, 0.11083204f, 0.10920573f, 0.10757912f,
+0.10595223f, 0.10432505f, 0.10269759f, 0.10106986f, 0.099441861f,
+0.097813592f, 0.096185062f, 0.094556275f, 0.092927234f, 0.091297944f,
+0.089668410f, 0.088038636f, 0.086408626f, 0.084778385f, 0.083147917f,
+0.081517226f, 0.079886317f, 0.078255194f, 0.076623861f, 0.074992324f,
+0.073360585f, 0.071728651f, 0.070096524f, 0.068464209f, 0.066831712f,
+0.065199035f, 0.063566184f, 0.061933162f, 0.060299975f, 0.058666626f,
+0.057033121f, 0.055399462f, 0.053765655f, 0.052131705f, 0.050497614f,
+0.048863389f, 0.047229033f, 0.045594550f, 0.043959945f, 0.042325222f,
+0.040690387f, 0.039055442f, 0.037420393f, 0.035785243f, 0.034149998f,
+0.032514661f, 0.030879237f, 0.029243731f, 0.027608146f, 0.025972487f,
+0.024336759f, 0.022700965f, 0.021065111f, 0.019429201f, 0.017793238f,
+0.016157228f, 0.014521174f, 0.012885082f, 0.011248955f, 0.0096127982f,
+0.0079766155f, 0.0063404114f, 0.0047041904f, 0.0030679568f, 0.0014317149f,
+-0.00020453077f, -0.0018407759f, -0.0034770161f, -0.0051132470f, -0.0067494642f,
+-0.0083856634f, -0.010021840f, -0.011657990f, -0.013294109f, -0.014930192f,
+-0.016566235f, -0.018202233f, -0.019838183f, -0.021474080f, -0.023109920f,
+-0.024745697f, -0.026381408f, -0.028017049f, -0.029652615f, -0.031288101f,
+-0.032923503f, -0.034558818f, -0.036194040f, -0.037829164f, -0.039464188f,
+-0.041099106f, -0.042733914f, -0.044368607f, -0.046003182f, -0.047637634f,
+-0.049271958f, -0.050906150f, -0.052540206f, -0.054174121f, -0.055807891f,
+-0.057441512f, -0.059074978f, -0.060708287f, -0.062341433f, -0.063974413f,
+-0.065607221f, -0.067239853f, -0.068872305f, -0.070504573f, -0.072136653f,
+-0.073768539f, -0.075400227f, -0.077031714f, -0.078662994f, -0.080294064f,
+-0.081924919f, -0.083555555f, -0.085185966f, -0.086816150f, -0.088446102f,
+-0.090075816f, -0.091705289f, -0.093334517f, -0.094963495f, -0.096592219f,
+-0.098220684f, -0.099848886f, -0.10147682f, -0.10310448f, -0.10473187f,
+-0.10635898f, -0.10798580f, -0.10961233f, -0.11123857f, -0.11286451f,
+-0.11449015f, -0.11611549f, -0.11774051f, -0.11936521f, -0.12098960f,
+-0.12261367f, -0.12423740f, -0.12586080f, -0.12748387f, -0.12910659f,
+-0.13072897f, -0.13235100f, -0.13397267f, -0.13559399f, -0.13721494f,
+-0.13883553f, -0.14045574f, -0.14207558f, -0.14369503f, -0.14531411f,
+-0.14693279f, -0.14855108f, -0.15016897f, -0.15178646f, -0.15340354f,
+-0.15502022f, -0.15663647f, -0.15825231f, -0.15986773f, -0.16148271f,
+-0.16309727f, -0.16471139f, -0.16632506f, -0.16793829f, -0.16955108f,
+-0.17116340f, -0.17277527f, -0.17438668f, -0.17599762f, -0.17760809f,
+-0.17921808f, -0.18082760f, -0.18243663f, -0.18404517f, -0.18565322f,
+-0.18726077f, -0.18886782f, -0.19047436f, -0.19208040f, -0.19368592f,
+-0.19529092f, -0.19689540f, -0.19849935f, -0.20010277f, -0.20170565f,
+-0.20330800f, -0.20490980f, -0.20651105f, -0.20811175f, -0.20971189f,
+-0.21131147f, -0.21291048f, -0.21450893f, -0.21610680f, -0.21770409f,
+-0.21930080f, -0.22089692f, -0.22249245f, -0.22408738f, -0.22568172f,
+-0.22727545f, -0.22886857f, -0.23046108f, -0.23205297f, -0.23364424f,
+-0.23523488f, -0.23682490f, -0.23841428f, -0.24000302f, -0.24159112f,
+-0.24317858f, -0.24476538f, -0.24635153f, -0.24793701f, -0.24952184f,
+-0.25110599f, -0.25268948f, -0.25427228f, -0.25585441f, -0.25743585f,
+-0.25901660f, -0.26059666f, -0.26217602f, -0.26375468f, -0.26533263f,
+-0.26690987f, -0.26848640f, -0.27006221f, -0.27163730f, -0.27321165f,
+-0.27478528f, -0.27635817f, -0.27793032f, -0.27950173f, -0.28107239f,
+-0.28264230f, -0.28421145f, -0.28577984f, -0.28734746f, -0.28891431f,
+-0.29048039f, -0.29204570f, -0.29361022f, -0.29517395f, -0.29673690f,
+-0.29829905f, -0.29986040f, -0.30142095f, -0.30298069f, -0.30453962f,
+-0.30609774f, -0.30765504f, -0.30921151f, -0.31076715f, -0.31232197f,
+-0.31387594f, -0.31542908f, -0.31698137f, -0.31853281f, -0.32008340f,
+-0.32163313f, -0.32318201f, -0.32473001f, -0.32627715f, -0.32782341f,
+-0.32936880f, -0.33091330f, -0.33245692f, -0.33399965f, -0.33554149f,
+-0.33708242f, -0.33862245f, -0.34016158f, -0.34169980f, -0.34323710f,
+-0.34477348f, -0.34630894f, -0.34784347f, -0.34937707f, -0.35090974f,
+-0.35244146f, -0.35397224f, -0.35550208f, -0.35703096f, -0.35855889f,
+-0.36008585f, -0.36161186f, -0.36313689f, -0.36466095f, -0.36618404f,
+-0.36770615f, -0.36922727f, -0.37074740f, -0.37226654f, -0.37378468f,
+-0.37530183f, -0.37681796f, -0.37833309f, -0.37984721f, -0.38136031f,
+-0.38287239f, -0.38438344f, -0.38589346f, -0.38740245f, -0.38891041f,
+-0.39041732f, -0.39192319f, -0.39342800f, -0.39493177f, -0.39643448f,
+-0.39793612f, -0.39943670f, -0.40093621f, -0.40243465f, -0.40393201f,
+-0.40542829f, -0.40692348f, -0.40841759f, -0.40991060f, -0.41140251f,
+-0.41289332f, -0.41438303f, -0.41587162f, -0.41735911f, -0.41884547f,
+-0.42033072f, -0.42181484f, -0.42329782f, -0.42477968f, -0.42626040f,
+-0.42773998f, -0.42921841f, -0.43069569f, -0.43217182f, -0.43364680f,
+-0.43512061f, -0.43659326f, -0.43806474f, -0.43953504f, -0.44100417f,
+-0.44247212f, -0.44393888f, -0.44540446f, -0.44686884f, -0.44833203f,
+-0.44979401f, -0.45125479f, -0.45271437f, -0.45417273f, -0.45562987f,
+-0.45708580f, -0.45854050f, -0.45999398f, -0.46144622f, -0.46289723f,
+-0.46434699f, -0.46579552f, -0.46724280f, -0.46868882f, -0.47013359f,
+-0.47157711f, -0.47301936f, -0.47446034f, -0.47590006f, -0.47733850f,
+-0.47877566f, -0.48021154f, -0.48164613f, -0.48307944f, -0.48451145f,
+-0.48594216f, -0.48737158f, -0.48879968f, -0.49022648f, -0.49165197f,
+-0.49307614f, -0.49449899f, -0.49592052f, -0.49734072f, -0.49875959f,
+-0.50017712f, -0.50159331f, -0.50300816f, -0.50442167f, -0.50583382f,
+-0.50724462f, -0.50865406f, -0.51006214f, -0.51146885f, -0.51287419f,
+-0.51427817f, -0.51568076f, -0.51708197f, -0.51848180f, -0.51988024f,
+-0.52127729f, -0.52267294f, -0.52406720f, -0.52546005f, -0.52685149f,
+-0.52824153f, -0.52963015f, -0.53101735f, -0.53240313f, -0.53378748f,
+-0.53517041f, -0.53655190f, -0.53793196f, -0.53931057f, -0.54068774f,
+-0.54206347f, -0.54343774f, -0.54481056f, -0.54618192f, -0.54755181f,
+-0.54892024f, -0.55028721f, -0.55165269f, -0.55301671f, -0.55437924f,
+-0.55574028f, -0.55709984f, -0.55845791f, -0.55981448f, -0.56116955f,
+-0.56252312f, -0.56387519f, -0.56522574f, -0.56657478f, -0.56792231f,
+-0.56926831f, -0.57061279f, -0.57195575f, -0.57329717f, -0.57463705f,
+-0.57597540f, -0.57731221f, -0.57864747f, -0.57998118f, -0.58131334f,
+-0.58264394f, -0.58397298f, -0.58530046f, -0.58662637f, -0.58795071f,
+-0.58927348f, -0.59059466f, -0.59191427f, -0.59323230f, -0.59454873f,
+-0.59586357f, -0.59717682f, -0.59848847f, -0.59979852f, -0.60110696f,
+-0.60241379f, -0.60371901f, -0.60502261f, -0.60632459f, -0.60762495f,
+-0.60892368f, -0.61022078f, -0.61151625f, -0.61281008f, -0.61410227f,
+-0.61539282f, -0.61668172f, -0.61796896f, -0.61925456f, -0.62053849f,
+-0.62182077f, -0.62310138f, -0.62438032f, -0.62565759f, -0.62693318f,
+-0.62820709f, -0.62947933f, -0.63074988f, -0.63201874f, -0.63328590f,
+-0.63455138f, -0.63581515f, -0.63707722f, -0.63833758f, -0.63959624f,
+-0.64085318f, -0.64210841f, -0.64336192f, -0.64461371f, -0.64586377f,
+-0.64711210f, -0.64835870f, -0.64960356f, -0.65084668f, -0.65208807f,
+-0.65332770f, -0.65456559f, -0.65580172f, -0.65703610f, -0.65826872f,
+-0.65949958f, -0.66072867f, -0.66195599f, -0.66318154f, -0.66440531f,
+-0.66562731f, -0.66684752f, -0.66806595f, -0.66928259f, -0.67049744f,
+-0.67171049f, -0.67292174f, -0.67413119f, -0.67533884f, -0.67654468f,
+-0.67774871f, -0.67895092f, -0.68015132f, -0.68134989f, -0.68254664f,
+-0.68374157f, -0.68493466f, -0.68612592f, -0.68731534f, -0.68850292f,
+-0.68968866f, -0.69087255f, -0.69205460f, -0.69323478f, -0.69441312f,
+-0.69558959f, -0.69676420f, -0.69793695f, -0.69910783f, -0.70027684f,
+-0.70144397f, -0.70260922f, -0.70377259f, -0.70493408f, -0.70609368f,
+-0.70725139f, -0.70840721f, -0.70956113f, -0.71071315f, -0.71186327f,
+-0.71301148f, -0.71415778f, -0.71530217f, -0.71644465f, -0.71758521f,
+-0.71872384f, -0.71986055f, -0.72099534f, -0.72212819f, -0.72325912f,
+-0.72438810f, -0.72551515f, -0.72664025f, -0.72776341f, -0.72888462f,
+-0.73000387f, -0.73112118f, -0.73223652f, -0.73334991f, -0.73446133f,
+-0.73557079f, -0.73667827f, -0.73778379f, -0.73888732f, -0.73998888f,
+-0.74108846f, -0.74218606f, -0.74328167f, -0.74437529f, -0.74546691f,
+-0.74655654f, -0.74764417f, -0.74872980f, -0.74981342f, -0.75089504f,
+-0.75197465f, -0.75305224f, -0.75412782f, -0.75520138f, -0.75627291f,
+-0.75734242f, -0.75840991f, -0.75947536f, -0.76053878f, -0.76160017f,
+-0.76265951f, -0.76371681f, -0.76477207f, -0.76582528f, -0.76687644f,
+-0.76792555f, -0.76897260f, -0.77001759f, -0.77106052f, -0.77210139f,
+-0.77314019f, -0.77417692f, -0.77521158f, -0.77624416f, -0.77727466f,
+-0.77830308f, -0.77932942f, -0.78035367f, -0.78137584f, -0.78239591f,
+-0.78341388f, -0.78442976f, -0.78544354f, -0.78645521f, -0.78746478f,
+-0.78847224f, -0.78947760f, -0.79048083f, -0.79148195f, -0.79248095f,
+-0.79347783f, -0.79447259f, -0.79546522f, -0.79645572f, -0.79744408f,
+-0.79843031f, -0.79941441f, -0.80039636f, -0.80137617f, -0.80235384f,
+-0.80332935f, -0.80430272f, -0.80527393f, -0.80624299f, -0.80720989f,
+-0.80817462f, -0.80913720f, -0.81009760f, -0.81105584f, -0.81201191f,
+-0.81296580f, -0.81391752f, -0.81486706f, -0.81581441f, -0.81675958f,
+-0.81770257f, -0.81864336f, -0.81958197f, -0.82051837f, -0.82145259f,
+-0.82238460f, -0.82331441f, -0.82424202f, -0.82516742f, -0.82609061f,
+-0.82701159f, -0.82793036f, -0.82884690f, -0.82976123f, -0.83067334f,
+-0.83158323f, -0.83249088f, -0.83339631f, -0.83429951f, -0.83520047f,
+-0.83609920f, -0.83699569f, -0.83788994f, -0.83878195f, -0.83967171f,
+-0.84055922f, -0.84144448f, -0.84232749f, -0.84320824f, -0.84408674f,
+-0.84496297f, -0.84583694f, -0.84670865f, -0.84757810f, -0.84844527f,
+-0.84931017f, -0.85017280f, -0.85103315f, -0.85189122f, -0.85274701f,
+-0.85360052f, -0.85445175f, -0.85530068f, -0.85614733f, -0.85699168f,
+-0.85783374f, -0.85867350f, -0.85951097f, -0.86034613f, -0.86117899f,
+-0.86200954f, -0.86283779f, -0.86366373f, -0.86448735f, -0.86530866f,
+-0.86612765f, -0.86694432f, -0.86775868f, -0.86857071f, -0.86938041f,
+-0.87018779f, -0.87099283f, -0.87179555f, -0.87259593f, -0.87339397f,
+-0.87418968f, -0.87498304f, -0.87577407f, -0.87656274f, -0.87734907f,
+-0.87813306f, -0.87891469f, -0.87969397f, -0.88047089f, -0.88124545f,
+-0.88201766f, -0.88278751f, -0.88355499f, -0.88432010f, -0.88508285f,
+-0.88584323f, -0.88660124f, -0.88735687f, -0.88811013f, -0.88886101f,
+-0.88960951f, -0.89035563f, -0.89109936f, -0.89184071f, -0.89257967f,
+-0.89331624f, -0.89405042f, -0.89478221f, -0.89551160f, -0.89623859f,
+-0.89696318f, -0.89768538f, -0.89840516f, -0.89912255f, -0.89983752f,
+-0.90055009f, -0.90126025f, -0.90196799f, -0.90267332f, -0.90337623f,
+-0.90407672f, -0.90477479f, -0.90547044f, -0.90616367f, -0.90685447f,
+-0.90754284f, -0.90822878f, -0.90891229f, -0.90959337f, -0.91027201f,
+-0.91094822f, -0.91162198f, -0.91229331f, -0.91296219f, -0.91362863f,
+-0.91429262f, -0.91495417f, -0.91561326f, -0.91626990f, -0.91692409f,
+-0.91757583f, -0.91822511f, -0.91887193f, -0.91951629f, -0.92015819f,
+-0.92079762f, -0.92143459f, -0.92206909f, -0.92270113f, -0.92333069f,
+-0.92395778f, -0.92458240f, -0.92520454f, -0.92582421f, -0.92644140f,
+-0.92705610f, -0.92766833f, -0.92827807f, -0.92888532f, -0.92949009f,
+-0.93009237f, -0.93069216f, -0.93128946f, -0.93188427f, -0.93247658f,
+-0.93306639f, -0.93365370f, -0.93423852f, -0.93482083f, -0.93540065f,
+-0.93597795f, -0.93655275f, -0.93712505f, -0.93769483f, -0.93826211f,
+-0.93882687f, -0.93938912f, -0.93994885f, -0.94050607f, -0.94106077f,
+-0.94161295f, -0.94216261f, -0.94270975f, -0.94325436f, -0.94379644f,
+-0.94433601f, -0.94487304f, -0.94540754f, -0.94593951f, -0.94646895f,
+-0.94699585f, -0.94752022f, -0.94804206f, -0.94856135f, -0.94907810f,
+-0.94959232f, -0.95010399f, -0.95061312f, -0.95111970f, -0.95162374f,
+-0.95212522f, -0.95262416f, -0.95312055f, -0.95361439f, -0.95410567f,
+-0.95459440f, -0.95508058f, -0.95556419f, -0.95604525f, -0.95652375f,
+-0.95699969f, -0.95747306f, -0.95794388f, -0.95841212f, -0.95887780f,
+-0.95934092f, -0.95980146f, -0.96025944f, -0.96071485f, -0.96116768f,
+-0.96161794f, -0.96206562f, -0.96251073f, -0.96295327f, -0.96339322f,
+-0.96383060f, -0.96426539f, -0.96469760f, -0.96512723f, -0.96555428f,
+-0.96597874f, -0.96640062f, -0.96681991f, -0.96723660f, -0.96765071f,
+-0.96806223f, -0.96847116f, -0.96887749f, -0.96928124f, -0.96968238f,
+-0.97008093f, -0.97047688f, -0.97087024f, -0.97126099f, -0.97164914f,
+-0.97203470f, -0.97241765f, -0.97279799f, -0.97317574f, -0.97355087f,
+-0.97392340f, -0.97429333f, -0.97466064f, -0.97502535f, -0.97538744f,
+-0.97574692f, -0.97610379f, -0.97645805f, -0.97680969f, -0.97715872f,
+-0.97750513f, -0.97784893f, -0.97819010f, -0.97852866f, -0.97886460f,
+-0.97919792f, -0.97952861f, -0.97985669f, -0.98018214f, -0.98050496f,
+-0.98082516f, -0.98114274f, -0.98145768f, -0.98177000f, -0.98207970f,
+-0.98238676f, -0.98269119f, -0.98299299f, -0.98329216f, -0.98358870f,
+-0.98388260f, -0.98417387f, -0.98446250f, -0.98474850f, -0.98503186f,
+-0.98531259f, -0.98559068f, -0.98586612f, -0.98613893f, -0.98640910f,
+-0.98667663f, -0.98694151f, -0.98720376f, -0.98746336f, -0.98772032f,
+-0.98797463f, -0.98822630f, -0.98847532f, -0.98872169f, -0.98896542f,
+-0.98920650f, -0.98944493f, -0.98968071f, -0.98991385f, -0.99014433f,
+-0.99037216f, -0.99059734f, -0.99081987f, -0.99103975f, -0.99125697f,
+-0.99147154f, -0.99168345f, -0.99189271f, -0.99209931f, -0.99230326f,
+-0.99250455f, -0.99270318f, -0.99289916f, -0.99309248f, -0.99328313f,
+-0.99347113f, -0.99365647f, -0.99383915f, -0.99401917f, -0.99419653f,
+-0.99437122f, -0.99454325f, -0.99471262f, -0.99487933f, -0.99504337f,
+-0.99520475f, -0.99536347f, -0.99551952f, -0.99567290f, -0.99582362f,
+-0.99597167f, -0.99611706f, -0.99625978f, -0.99639983f, -0.99653722f,
+-0.99667193f, -0.99680398f, -0.99693336f, -0.99706007f, -0.99718411f,
+-0.99730548f, -0.99742418f, -0.99754021f, -0.99765357f, -0.99776426f,
+-0.99787228f, -0.99797763f, -0.99808030f, -0.99818030f, -0.99827763f,
+-0.99837229f, -0.99846427f, -0.99855358f, -0.99864022f, -0.99872418f,
+-0.99880547f, -0.99888409f, -0.99896003f, -0.99903329f, -0.99910389f,
+-0.99917180f, -0.99923705f, -0.99929961f, -0.99935950f, -0.99941672f,
+-0.99947126f, -0.99952312f, -0.99957231f, -0.99961882f, -0.99966266f,
+-0.99970382f, -0.99974230f, -0.99977811f, -0.99981124f, -0.99984169f,
+-0.99986946f, -0.99989456f, -0.99991698f, -0.99993673f, -0.99995380f,
+-0.99996819f, -0.99997990f, -0.99998894f, -0.99999529f, -0.99999898f,
+0.99999992f, 0.99999322f, 0.99997582f, 0.99994771f, 0.99990889f,
+0.99985936f, 0.99979913f, 0.99972818f, 0.99964653f, 0.99955418f,
+0.99945112f, 0.99933736f, 0.99921289f, 0.99907773f, 0.99893186f,
+0.99877530f, 0.99860804f, 0.99843009f, 0.99824144f, 0.99804211f,
+0.99783209f, 0.99761138f, 0.99737998f, 0.99713791f, 0.99688516f,
+0.99662173f, 0.99634763f, 0.99606285f, 0.99576741f, 0.99546131f,
+0.99514455f, 0.99481713f, 0.99447905f, 0.99413033f, 0.99377096f,
+0.99340095f, 0.99302029f, 0.99262901f, 0.99222709f, 0.99181455f,
+0.99139139f, 0.99095760f, 0.99051321f, 0.99005821f, 0.98959261f,
+0.98911641f, 0.98862961f, 0.98813223f, 0.98762427f, 0.98710573f,
+0.98657662f, 0.98603694f, 0.98548670f, 0.98492591f, 0.98435457f,
+0.98377269f, 0.98318028f, 0.98257734f, 0.98196387f, 0.98133989f,
+0.98070539f, 0.98006040f, 0.97940491f, 0.97873893f, 0.97806247f,
+0.97737554f, 0.97667813f, 0.97597027f, 0.97525196f, 0.97452320f,
+0.97378401f, 0.97303439f, 0.97227435f, 0.97150389f, 0.97072303f,
+0.96993178f, 0.96913014f, 0.96831812f, 0.96749573f, 0.96666298f,
+0.96581987f, 0.96496643f, 0.96410265f, 0.96322854f, 0.96234412f,
+0.96144939f, 0.96054437f, 0.95962906f, 0.95870347f, 0.95776762f,
+0.95682151f, 0.95586515f, 0.95489856f, 0.95392174f, 0.95293471f,
+0.95193746f, 0.95093003f, 0.94991241f, 0.94888462f, 0.94784667f,
+0.94679856f, 0.94574032f, 0.94467195f, 0.94359346f, 0.94250486f,
+0.94140618f, 0.94029741f, 0.93917857f, 0.93804967f, 0.93691073f,
+0.93576176f, 0.93460276f, 0.93343375f, 0.93225475f, 0.93106577f,
+0.92986681f, 0.92865789f, 0.92743903f, 0.92621024f, 0.92497153f,
+0.92372291f, 0.92246440f, 0.92119602f, 0.91991776f, 0.91862966f,
+0.91733172f, 0.91602395f, 0.91470637f, 0.91337900f, 0.91204185f,
+0.91069493f, 0.90933825f, 0.90797184f, 0.90659570f, 0.90520986f,
+0.90381432f, 0.90240910f, 0.90099422f, 0.89956969f, 0.89813553f,
+0.89669174f, 0.89523836f, 0.89377538f, 0.89230284f, 0.89082074f,
+0.88932910f, 0.88782793f, 0.88631726f, 0.88479710f, 0.88326746f,
+0.88172836f, 0.88017982f, 0.87862185f, 0.87705448f, 0.87547771f,
+0.87389156f, 0.87229606f, 0.87069121f, 0.86907704f, 0.86745357f,
+0.86582080f, 0.86417876f, 0.86252747f, 0.86086694f, 0.85919719f,
+0.85751824f, 0.85583010f, 0.85413281f, 0.85242636f, 0.85071078f,
+0.84898610f, 0.84725232f, 0.84550947f, 0.84375756f, 0.84199662f,
+0.84022666f, 0.83844771f, 0.83665977f, 0.83486287f, 0.83305704f,
+0.83124228f, 0.82941862f, 0.82758608f, 0.82574467f, 0.82389442f,
+0.82203535f, 0.82016748f, 0.81829082f, 0.81640540f, 0.81451123f,
+0.81260835f, 0.81069676f, 0.80877649f, 0.80684755f, 0.80490998f,
+0.80296379f, 0.80100899f, 0.79904562f, 0.79707370f, 0.79509323f,
+0.79310425f, 0.79110678f, 0.78910084f, 0.78708644f, 0.78506362f,
+0.78303239f, 0.78099277f, 0.77894479f, 0.77688847f, 0.77482382f,
+0.77275088f, 0.77066967f, 0.76858020f, 0.76648250f, 0.76437659f,
+0.76226250f, 0.76014024f, 0.75800984f, 0.75587132f, 0.75372471f,
+0.75157003f, 0.74940730f, 0.74723654f, 0.74505779f, 0.74287105f,
+0.74067635f, 0.73847373f, 0.73626320f, 0.73404478f, 0.73181850f,
+0.72958438f, 0.72734245f, 0.72509273f, 0.72283525f, 0.72057002f,
+0.71829708f, 0.71601644f, 0.71372814f, 0.71143220f, 0.70912863f,
+0.70681747f, 0.70449874f, 0.70217247f, 0.69983868f, 0.69749739f,
+0.69514863f, 0.69279243f, 0.69042881f, 0.68805780f, 0.68567941f,
+0.68329369f, 0.68090064f, 0.67850031f, 0.67609270f, 0.67367786f,
+0.67125580f, 0.66882656f, 0.66639015f, 0.66394661f, 0.66149595f,
+0.65903821f, 0.65657341f, 0.65410159f, 0.65162275f, 0.64913694f,
+0.64664418f, 0.64414449f, 0.64163790f, 0.63912444f, 0.63660414f,
+0.63407702f, 0.63154311f, 0.62900244f, 0.62645503f, 0.62390091f,
+0.62134011f, 0.61877265f, 0.61619857f, 0.61361789f, 0.61103064f,
+0.60843685f, 0.60583654f, 0.60322974f, 0.60061648f, 0.59799679f,
+0.59537069f, 0.59273822f, 0.59009940f, 0.58745427f, 0.58480284f,
+0.58214514f, 0.57948122f, 0.57681109f, 0.57413478f, 0.57145232f,
+0.56876374f, 0.56606907f, 0.56336834f, 0.56066158f, 0.55794881f,
+0.55523006f, 0.55250537f, 0.54977477f, 0.54703827f, 0.54429592f,
+0.54154774f, 0.53879376f, 0.53603401f, 0.53326852f, 0.53049731f,
+0.52772043f, 0.52493790f, 0.52214974f, 0.51935599f, 0.51655668f,
+0.51375184f, 0.51094149f, 0.50812568f, 0.50530442f, 0.50247775f,
+0.49964570f, 0.49680830f, 0.49396558f, 0.49111757f, 0.48826430f,
+0.48540580f, 0.48254210f, 0.47967323f, 0.47679923f, 0.47392012f,
+0.47103594f, 0.46814671f, 0.46525247f, 0.46235324f, 0.45944907f,
+0.45653997f, 0.45362599f, 0.45070714f, 0.44778347f, 0.44485501f,
+0.44192178f, 0.43898381f, 0.43604115f, 0.43309382f, 0.43014185f,
+0.42718527f, 0.42422412f, 0.42125842f, 0.41828822f, 0.41531353f,
+0.41233440f, 0.40935085f, 0.40636291f, 0.40337063f, 0.40037402f,
+0.39737313f, 0.39436798f, 0.39135861f, 0.38834505f, 0.38532733f,
+0.38230548f, 0.37927953f, 0.37624953f, 0.37321550f, 0.37017747f,
+0.36713547f, 0.36408955f, 0.36103972f, 0.35798603f, 0.35492850f,
+0.35186718f, 0.34880208f, 0.34573325f, 0.34266072f, 0.33958451f,
+0.33650468f, 0.33342123f, 0.33033422f, 0.32724367f, 0.32414961f,
+0.32105209f, 0.31795112f, 0.31484675f, 0.31173901f, 0.30862793f,
+0.30551354f, 0.30239588f, 0.29927499f, 0.29615089f, 0.29302362f,
+0.28989321f, 0.28675969f, 0.28362310f, 0.28048348f, 0.27734085f,
+0.27419526f, 0.27104672f, 0.26789529f, 0.26474098f, 0.26158384f,
+0.25842390f, 0.25526119f, 0.25209575f, 0.24892761f, 0.24575680f,
+0.24258336f, 0.23940732f, 0.23622872f, 0.23304759f, 0.22986396f,
+0.22667787f, 0.22348935f, 0.22029844f, 0.21710517f, 0.21390958f,
+0.21071169f, 0.20751155f, 0.20430919f, 0.20110463f, 0.19789793f,
+0.19468910f, 0.19147819f, 0.18826523f, 0.18505026f, 0.18183330f,
+0.17861439f, 0.17539357f, 0.17217088f, 0.16894634f, 0.16571999f,
+0.16249186f, 0.15926200f, 0.15603043f, 0.15279719f, 0.14956231f,
+0.14632583f, 0.14308778f, 0.13984820f, 0.13660713f, 0.13336459f,
+0.13012062f, 0.12687526f, 0.12362854f, 0.12038049f, 0.11713116f,
+0.11388057f, 0.11062877f, 0.10737578f, 0.10412163f, 0.10086638f,
+0.097610040f, 0.094352658f, 0.091094266f, 0.087834897f, 0.084574589f,
+0.081313374f, 0.078051289f, 0.074788367f, 0.071524645f, 0.068260157f,
+0.064994938f, 0.061729023f, 0.058462447f, 0.055195244f, 0.051927451f,
+0.048659101f, 0.045390231f, 0.042120874f, 0.038851066f, 0.035580842f,
+0.032310238f, 0.029039287f, 0.025768025f, 0.022496487f, 0.019224708f,
+0.015952723f, 0.012680568f, 0.0094082767f, 0.0061358846f, 0.0028634269f,
+-0.00040906153f, -0.0036815456f, -0.0069539902f, -0.010226360f, -0.013498621f,
+-0.016770737f, -0.020042673f, -0.023314395f, -0.026585867f, -0.029857055f,
+-0.033127923f, -0.036398436f, -0.039668559f, -0.042938257f, -0.046207495f,
+-0.049476239f, -0.052744453f, -0.056012102f, -0.059279151f, -0.062545565f,
+-0.065811309f, -0.069076349f, -0.072340649f, -0.075604174f, -0.078866890f,
+-0.082128761f, -0.085389752f, -0.088649829f, -0.091908956f, -0.095167100f,
+-0.098424224f, -0.10168029f, -0.10493528f, -0.10818913f, -0.11144183f,
+-0.11469334f, -0.11794361f, -0.12119263f, -0.12444034f, -0.12768673f,
+-0.13093174f, -0.13417536f, -0.13741753f, -0.14065824f, -0.14389744f,
+-0.14713510f, -0.15037118f, -0.15360565f, -0.15683848f, -0.16006962f,
+-0.16329906f, -0.16652674f, -0.16975264f, -0.17297673f, -0.17619896f,
+-0.17941930f, -0.18263772f, -0.18585419f, -0.18906866f, -0.19228112f,
+-0.19549151f, -0.19869981f, -0.20190598f, -0.20510998f, -0.20831180f,
+-0.21151138f, -0.21470869f, -0.21790371f, -0.22109639f, -0.22428671f,
+-0.22747462f, -0.23066010f, -0.23384310f, -0.23702361f, -0.24020157f,
+-0.24337696f, -0.24654975f, -0.24971989f, -0.25288736f, -0.25605213f,
+-0.25921415f, -0.26237339f, -0.26552983f, -0.26868342f, -0.27183413f,
+-0.27498193f, -0.27812679f, -0.28126867f, -0.28440754f, -0.28754336f,
+-0.29067610f, -0.29380573f, -0.29693221f, -0.30005551f, -0.30317560f,
+-0.30629245f, -0.30940601f, -0.31251626f, -0.31562316f, -0.31872668f,
+-0.32182679f, -0.32492345f, -0.32801664f, -0.33110631f, -0.33419243f,
+-0.33727497f, -0.34035391f, -0.34342920f, -0.34650081f, -0.34956871f,
+-0.35263286f, -0.35569324f, -0.35874981f, -0.36180254f, -0.36485139f,
+-0.36789634f, -0.37093735f, -0.37397438f, -0.37700741f, -0.38003640f,
+-0.38306132f, -0.38608214f, -0.38909883f, -0.39211135f, -0.39511967f,
+-0.39812375f, -0.40112358f, -0.40411910f, -0.40711031f, -0.41009715f,
+-0.41307959f, -0.41605762f, -0.41903119f, -0.42200027f, -0.42496483f,
+-0.42792484f, -0.43088027f, -0.43383109f, -0.43677726f, -0.43971875f,
+-0.44265553f, -0.44558757f, -0.44851484f, -0.45143731f, -0.45435494f,
+-0.45726770f, -0.46017557f, -0.46307851f, -0.46597650f, -0.46886949f,
+-0.47175746f, -0.47464038f, -0.47751821f, -0.48039093f, -0.48325851f,
+-0.48612091f, -0.48897811f, -0.49183006f, -0.49467676f, -0.49751815f,
+-0.50035422f, -0.50318492f, -0.50601024f, -0.50883014f, -0.51164459f,
+-0.51445356f, -0.51725703f, -0.52005495f, -0.52284730f, -0.52563406f,
+-0.52841518f, -0.53119065f, -0.53396043f, -0.53672449f, -0.53948280f,
+-0.54223533f, -0.54498206f, -0.54772295f, -0.55045797f, -0.55318710f,
+-0.55591031f, -0.55862756f, -0.56133883f, -0.56404409f, -0.56674331f,
+-0.56943646f, -0.57212351f, -0.57480443f, -0.57747920f, -0.58014778f,
+-0.58281015f, -0.58546628f, -0.58811614f, -0.59075970f, -0.59339694f,
+-0.59602782f, -0.59865231f, -0.60127040f, -0.60388204f, -0.60648722f,
+-0.60908591f, -0.61167807f, -0.61426368f, -0.61684271f, -0.61941514f,
+-0.62198093f, -0.62454007f, -0.62709251f, -0.62963824f, -0.63217722f,
+-0.63470944f, -0.63723486f, -0.63975345f, -0.64226519f, -0.64477006f,
+-0.64726802f, -0.64975905f, -0.65224312f, -0.65472020f, -0.65719027f,
+-0.65965331f, -0.66210928f, -0.66455816f, -0.66699992f, -0.66943454f,
+-0.67186199f, -0.67428225f, -0.67669528f, -0.67910107f, -0.68149959f,
+-0.68389080f, -0.68627470f, -0.68865124f, -0.69102041f, -0.69338218f,
+-0.69573652f, -0.69808341f, -0.70042283f, -0.70275474f, -0.70507913f,
+-0.70739597f, -0.70970524f, -0.71200690f, -0.71430093f, -0.71658732f,
+-0.71886604f, -0.72113705f, -0.72340034f, -0.72565589f, -0.72790366f,
+-0.73014364f, -0.73237580f, -0.73460012f, -0.73681657f, -0.73902513f,
+-0.74122577f, -0.74341848f, -0.74560322f, -0.74777998f, -0.74994874f,
+-0.75210946f, -0.75426212f, -0.75640671f, -0.75854320f, -0.76067157f,
+-0.76279178f, -0.76490383f, -0.76700769f, -0.76910334f, -0.77119075f,
+-0.77326989f, -0.77534076f, -0.77740333f, -0.77945757f, -0.78150346f,
+-0.78354098f, -0.78557011f, -0.78759083f, -0.78960312f, -0.79160694f,
+-0.79360229f, -0.79558915f, -0.79756748f, -0.79953727f, -0.80149850f,
+-0.80345114f, -0.80539518f, -0.80733060f, -0.80925737f, -0.81117547f,
+-0.81308489f, -0.81498559f, -0.81687757f, -0.81876081f, -0.82063527f,
+-0.82250095f, -0.82435781f, -0.82620585f, -0.82804505f, -0.82987537f,
+-0.83169681f, -0.83350933f, -0.83531294f, -0.83710760f, -0.83889329f,
+-0.84067000f, -0.84243770f, -0.84419639f, -0.84594603f, -0.84768662f,
+-0.84941812f, -0.85114053f, -0.85285383f, -0.85455799f, -0.85625300f,
+-0.85793884f, -0.85961549f, -0.86128294f, -0.86294116f, -0.86459014f,
+-0.86622986f, -0.86786031f, -0.86948146f, -0.87109330f, -0.87269581f,
+-0.87428898f, -0.87587278f, -0.87744720f, -0.87901223f, -0.88056784f,
+-0.88211402f, -0.88365076f, -0.88517803f, -0.88669582f, -0.88820412f,
+-0.88970290f, -0.89119216f, -0.89267187f, -0.89414203f, -0.89560260f,
+-0.89705359f, -0.89849497f, -0.89992673f, -0.90134885f, -0.90276131f,
+-0.90416411f, -0.90555723f, -0.90694065f, -0.90831436f, -0.90967833f,
+-0.91103257f, -0.91237705f, -0.91371176f, -0.91503669f, -0.91635181f,
+-0.91765712f, -0.91895261f, -0.92023825f, -0.92151404f, -0.92277996f,
+-0.92403600f, -0.92528214f, -0.92651837f, -0.92774468f, -0.92896106f,
+-0.93016748f, -0.93136395f, -0.93255044f, -0.93372694f, -0.93489345f,
+-0.93604994f, -0.93719641f, -0.93833284f, -0.93945922f, -0.94057555f,
+-0.94168180f, -0.94277796f, -0.94386403f, -0.94493999f, -0.94600583f,
+-0.94706154f, -0.94810711f, -0.94914252f, -0.95016777f, -0.95118284f,
+-0.95218773f, -0.95318242f, -0.95416690f, -0.95514117f, -0.95610520f,
+-0.95705900f, -0.95800255f, -0.95893583f, -0.95985885f, -0.96077159f,
+-0.96167404f, -0.96256619f, -0.96344803f, -0.96431956f, -0.96518076f,
+-0.96603162f, -0.96687213f, -0.96770230f, -0.96852209f, -0.96933152f,
+-0.97013057f, -0.97091922f, -0.97169748f, -0.97246533f, -0.97322277f,
+-0.97396979f, -0.97470637f, -0.97543252f, -0.97614822f, -0.97685347f,
+-0.97754825f, -0.97823257f, -0.97890641f, -0.97956977f, -0.98022263f,
+-0.98086500f, -0.98149687f, -0.98211822f, -0.98272906f, -0.98332937f,
+-0.98391915f, -0.98449840f, -0.98506710f, -0.98562525f, -0.98617285f,
+-0.98670988f, -0.98723635f, -0.98775225f, -0.98825757f, -0.98875230f,
+-0.98923645f, -0.98971000f, -0.99017295f, -0.99062530f, -0.99106704f,
+-0.99149817f, -0.99191868f, -0.99232857f, -0.99272783f, -0.99311645f,
+-0.99349445f, -0.99386180f, -0.99421851f, -0.99456457f, -0.99489998f,
+-0.99522474f, -0.99553884f, -0.99584227f, -0.99613505f, -0.99641715f,
+-0.99668858f, -0.99694934f, -0.99719943f, -0.99743883f, -0.99766756f,
+-0.99788559f, -0.99809295f, -0.99828961f, -0.99847558f, -0.99865086f,
+-0.99881544f, -0.99896933f, -0.99911252f, -0.99924501f, -0.99936680f,
+-0.99947789f, -0.99957827f, -0.99966795f, -0.99974692f, -0.99981519f,
+-0.99987275f, -0.99991960f, -0.99995574f, -0.99998118f, -0.99999590f,
+0.99999967f, 0.99997289f, 0.99990328f, 0.99979084f, 0.99963557f,
+0.99943748f, 0.99919658f, 0.99891288f, 0.99858638f, 0.99821711f,
+0.99780508f, 0.99735031f, 0.99685281f, 0.99631261f, 0.99572973f,
+0.99510420f, 0.99443605f, 0.99372529f, 0.99297196f, 0.99217610f,
+0.99133774f, 0.99045692f, 0.98953366f, 0.98856802f, 0.98756003f,
+0.98650973f, 0.98541718f, 0.98428242f, 0.98310549f, 0.98188645f,
+0.98062534f, 0.97932224f, 0.97797718f, 0.97659022f, 0.97516144f,
+0.97369088f, 0.97217861f, 0.97062469f, 0.96902920f, 0.96739220f,
+0.96571376f, 0.96399395f, 0.96223284f, 0.96043052f, 0.95858705f,
+0.95670253f, 0.95477702f, 0.95281061f, 0.95080338f, 0.94875543f,
+0.94666684f, 0.94453769f, 0.94236808f, 0.94015810f, 0.93790786f,
+0.93561743f, 0.93328693f, 0.93091644f, 0.92850608f, 0.92605595f,
+0.92356614f, 0.92103677f, 0.91846795f, 0.91585979f, 0.91321239f,
+0.91052587f, 0.90780035f, 0.90503595f, 0.90223277f, 0.89939095f,
+0.89651059f, 0.89359184f, 0.89063481f, 0.88763962f, 0.88460641f,
+0.88153531f, 0.87842644f, 0.87527995f, 0.87209596f, 0.86887462f,
+0.86561605f, 0.86232041f, 0.85898782f, 0.85561844f, 0.85221241f,
+0.84876987f, 0.84529098f, 0.84177587f, 0.83822471f, 0.83463763f,
+0.83101481f, 0.82735639f, 0.82366252f, 0.81993338f, 0.81616911f,
+0.81236987f, 0.80853584f, 0.80466718f, 0.80076404f, 0.79682660f,
+0.79285503f, 0.78884950f, 0.78481017f, 0.78073723f, 0.77663084f,
+0.77249118f, 0.76831844f, 0.76411277f, 0.75987438f, 0.75560344f,
+0.75130013f, 0.74696464f, 0.74259715f, 0.73819784f, 0.73376692f,
+0.72930457f, 0.72481097f, 0.72028632f, 0.71573083f, 0.71114467f,
+0.70652804f, 0.70188116f, 0.69720420f, 0.69249738f, 0.68776090f,
+0.68299495f, 0.67819975f, 0.67337550f, 0.66852240f, 0.66364066f,
+0.65873050f, 0.65379211f, 0.64882573f, 0.64383154f, 0.63880978f,
+0.63376065f, 0.62868438f, 0.62358117f, 0.61845126f, 0.61329485f,
+0.60811216f, 0.60290343f, 0.59766888f, 0.59240872f, 0.58712318f,
+0.58181249f, 0.57647688f, 0.57111658f, 0.56573181f, 0.56032281f,
+0.55488980f, 0.54943303f, 0.54395272f, 0.53844911f, 0.53292243f,
+0.52737292f, 0.52180083f, 0.51620638f, 0.51058981f, 0.50495138f,
+0.49929132f, 0.49360987f, 0.48790727f, 0.48218377f, 0.47643962f,
+0.47067506f, 0.46489034f, 0.45908570f, 0.45326139f, 0.44741768f,
+0.44155479f, 0.43567299f, 0.42977253f, 0.42385365f, 0.41791662f,
+0.41196169f, 0.40598911f, 0.39999914f, 0.39399204f, 0.38796806f,
+0.38192746f, 0.37587050f, 0.36979743f, 0.36370853f, 0.35760405f,
+0.35148424f, 0.34534939f, 0.33919973f, 0.33303555f, 0.32685710f,
+0.32066465f, 0.31445847f, 0.30823881f, 0.30200595f, 0.29576015f,
+0.28950169f, 0.28323082f, 0.27694782f, 0.27065295f, 0.26434649f,
+0.25802871f, 0.25169988f, 0.24536026f, 0.23901013f, 0.23264977f,
+0.22627944f, 0.21989941f, 0.21350997f, 0.20711138f, 0.20070391f,
+0.19428785f, 0.18786347f, 0.18143104f, 0.17499084f, 0.16854314f,
+0.16208822f, 0.15562636f, 0.14915783f, 0.14268292f, 0.13620189f,
+0.12971502f, 0.12322260f, 0.11672491f, 0.11022221f, 0.10371479f,
+0.097202924f, 0.090686897f, 0.084166986f, 0.077643468f, 0.071116625f,
+0.064586736f, 0.058054080f, 0.051518937f, 0.044981587f, 0.038442310f,
+0.031901387f, 0.025359097f, 0.018815721f, 0.012271538f, 0.0057268303f,
+-0.00081812300f, -0.0073630412f, -0.013907644f, -0.020451651f, -0.026994782f,
+-0.033536757f, -0.040077295f, -0.046616116f, -0.053152941f, -0.059687488f,
+-0.066219479f, -0.072748633f, -0.079274670f, -0.085797312f, -0.092316279f,
+-0.098831291f, -0.10534207f, -0.11184834f, -0.11834981f, -0.12484622f,
+-0.13133727f, -0.13782270f, -0.14430223f, -0.15077558f, -0.15724246f,
+-0.16370261f, -0.17015575f, -0.17660160f, -0.18303989f, -0.18947033f,
+-0.19589266f, -0.20230660f, -0.20871187f, -0.21510820f, -0.22149531f,
+-0.22787294f, -0.23424080f, -0.24059864f, -0.24694616f, -0.25328311f,
+-0.25960920f, -0.26592418f, -0.27222777f, -0.27851969f, -0.28479968f,
+-0.29106748f, -0.29732280f, -0.30356539f, -0.30979497f, -0.31601129f,
+-0.32221406f, -0.32840304f, -0.33457794f, -0.34073852f, -0.34688450f,
+-0.35301562f, -0.35913161f, -0.36523223f, -0.37131719f, -0.37738626f,
+-0.38343915f, -0.38947562f, -0.39549541f, -0.40149825f, -0.40748390f,
+-0.41345209f, -0.41940257f, -0.42533508f, -0.43124938f, -0.43714520f,
+-0.44302229f, -0.44888041f, -0.45471930f, -0.46053871f, -0.46633839f,
+-0.47211810f, -0.47787758f, -0.48361659f, -0.48933489f, -0.49503222f,
+-0.50070835f, -0.50636303f, -0.51199602f, -0.51760707f, -0.52319595f,
+-0.52876243f, -0.53430625f, -0.53982718f, -0.54532499f, -0.55079944f,
+-0.55625029f, -0.56167732f, -0.56708028f, -0.57245896f, -0.57781311f,
+-0.58314251f, -0.58844693f, -0.59372614f, -0.59897992f, -0.60420805f,
+-0.60941029f, -0.61458642f, -0.61973623f, -0.62485949f, -0.62995598f,
+-0.63502549f, -0.64006780f, -0.64508268f, -0.65006994f, -0.65502934f,
+-0.65996069f, -0.66486377f, -0.66973837f, -0.67458427f, -0.67940128f,
+-0.68418919f, -0.68894779f, -0.69367688f, -0.69837625f, -0.70304571f,
+-0.70768504f, -0.71229407f, -0.71687258f, -0.72142039f, -0.72593729f,
+-0.73042309f, -0.73487761f, -0.73930064f, -0.74369201f, -0.74805152f,
+-0.75237898f, -0.75667422f, -0.76093704f, -0.76516727f, -0.76936471f,
+-0.77352921f, -0.77766056f, -0.78175861f, -0.78582316f, -0.78985406f,
+-0.79385112f, -0.79781417f, -0.80174305f, -0.80563758f, -0.80949760f,
+-0.81332295f, -0.81711346f, -0.82086896f, -0.82458930f, -0.82827432f,
+-0.83192386f, -0.83553776f, -0.83911587f, -0.84265803f, -0.84616410f,
+-0.84963392f, -0.85306735f, -0.85646423f, -0.85982442f, -0.86314779f,
+-0.86643418f, -0.86968345f, -0.87289547f, -0.87607009f, -0.87920719f,
+-0.88230663f, -0.88536827f, -0.88839199f, -0.89137765f, -0.89432512f,
+-0.89723429f, -0.90010502f, -0.90293719f, -0.90573069f, -0.90848539f,
+-0.91120117f, -0.91387791f, -0.91651551f, -0.91911385f, -0.92167282f,
+-0.92419231f, -0.92667220f, -0.92911240f, -0.93151280f, -0.93387330f,
+-0.93619380f, -0.93847419f, -0.94071438f, -0.94291427f, -0.94507377f,
+-0.94719279f, -0.94927123f, -0.95130901f, -0.95330604f, -0.95526223f,
+-0.95717750f, -0.95905177f, -0.96088496f, -0.96267699f, -0.96442777f,
+-0.96613725f, -0.96780534f, -0.96943197f, -0.97101707f, -0.97256058f,
+-0.97406243f, -0.97552255f, -0.97694089f, -0.97831737f, -0.97965195f,
+-0.98094456f, -0.98219515f, -0.98340367f, -0.98457006f, -0.98569428f,
+-0.98677627f, -0.98781599f, -0.98881340f, -0.98976845f, -0.99068110f,
+-0.99155132f, -0.99237906f, -0.99316428f, -0.99390697f, -0.99460708f,
+-0.99526458f, -0.99587945f, -0.99645166f, -0.99698119f, -0.99746801f,
+-0.99791210f, -0.99831344f, -0.99867202f, -0.99898782f, -0.99926082f,
+-0.99949102f, -0.99967841f, -0.99982297f, -0.99992470f, -0.99998360f,
+0.99999866f, 0.99989157f, 0.99961315f, 0.99916346f, 0.99854256f,
+0.99775057f, 0.99678762f, 0.99565388f, 0.99434953f, 0.99287481f,
+0.99122996f, 0.98941527f, 0.98743105f, 0.98527764f, 0.98295541f,
+0.98046475f, 0.97780610f, 0.97497990f, 0.97198664f, 0.96882685f,
+0.96550104f, 0.96200980f, 0.95835373f, 0.95453345f, 0.95054962f,
+0.94640291f, 0.94209404f, 0.93762375f, 0.93299280f, 0.92820199f,
+0.92325213f, 0.91814408f, 0.91287871f, 0.90745693f, 0.90187965f,
+0.89614785f, 0.89026249f, 0.88422459f, 0.87803519f, 0.87169533f,
+0.86520612f, 0.85856866f, 0.85178409f, 0.84485357f, 0.83777828f,
+0.83055945f, 0.82319831f, 0.81569611f, 0.80805415f, 0.80027373f,
+0.79235620f, 0.78430289f, 0.77611520f, 0.76779452f, 0.75934229f,
+0.75075995f, 0.74204897f, 0.73321084f, 0.72424708f, 0.71515923f,
+0.70594883f, 0.69661748f, 0.68716676f, 0.67759830f, 0.66791374f,
+0.65811474f, 0.64820297f, 0.63818013f, 0.62804795f, 0.61780815f,
+0.60746249f, 0.59701275f, 0.58646072f, 0.57580819f, 0.56505701f,
+0.55420900f, 0.54326604f, 0.53222998f, 0.52110274f, 0.50988620f,
+0.49858230f, 0.48719297f, 0.47572016f, 0.46416584f, 0.45253199f,
+0.44082059f, 0.42903367f, 0.41717323f, 0.40524131f, 0.39323996f,
+0.38117123f, 0.36903718f, 0.35683990f, 0.34458148f, 0.33226402f,
+0.31988962f, 0.30746042f, 0.29497853f, 0.28244610f, 0.26986527f,
+0.25723821f, 0.24456706f, 0.23185402f, 0.21910124f, 0.20631092f,
+0.19348526f, 0.18062644f, 0.16773667f, 0.15481816f, 0.14187312f,
+0.12890377f, 0.11591234f, 0.10290104f, 0.089872115f, 0.076827789f,
+0.063770300f, 0.050701883f, 0.037624779f, 0.024541229f, 0.011453473f,
+-0.0016362454f, -0.014725683f, -0.027812598f, -0.040894747f, -0.053969889f,
+-0.067035784f, -0.080090192f, -0.093130877f, -0.10615561f, -0.11916214f,
+-0.13214826f, -0.14511174f, -0.15805036f, -0.17096189f, -0.18384413f,
+-0.19669487f, -0.20951190f, -0.22229304f, -0.23503609f, -0.24773886f,
+-0.26039919f, -0.27301490f, -0.28558383f, -0.29810383f, -0.31057274f,
+-0.32298845f, -0.33534881f, -0.34765171f, -0.35989504f, -0.37207670f,
+-0.38419461f, -0.39624670f, -0.40823088f, -0.42014512f, -0.43198737f,
+-0.44375560f, -0.45544780f, -0.46706195f, -0.47859608f, -0.49004821f,
+-0.50141636f, -0.51269860f, -0.52389299f, -0.53499762f, -0.54601058f,
+-0.55692998f, -0.56775395f, -0.57848064f, -0.58910822f, -0.59963485f,
+-0.61005873f, -0.62037809f, -0.63059115f, -0.64069616f, -0.65069139f,
+-0.66057513f, -0.67034568f, -0.68000137f, -0.68954054f, -0.69896157f,
+-0.70826283f, -0.71744274f, -0.72649972f, -0.73543221f, -0.74423869f,
+-0.75291765f, -0.76146760f, -0.76988708f, -0.77817464f, -0.78632887f,
+-0.79434836f, -0.80223175f, -0.80997767f, -0.81758481f, -0.82505187f,
+-0.83237755f, -0.83956061f, -0.84659981f, -0.85349396f, -0.86024186f,
+-0.86684237f, -0.87329434f, -0.87959669f, -0.88574831f, -0.89174817f,
+-0.89759523f, -0.90328850f, -0.90882699f, -0.91420976f, -0.91943588f,
+-0.92450446f, -0.92941463f, -0.93416555f, -0.93875641f, -0.94318642f,
+-0.94745482f, -0.95156087f, -0.95550388f, -0.95928317f, -0.96289809f,
+-0.96634802f, -0.96963238f, -0.97275059f, -0.97570213f, -0.97848649f,
+-0.98110318f, -0.98355177f, -0.98583184f, -0.98794298f, -0.98988485f,
+-0.99165711f, -0.99325945f, -0.99469160f, -0.99595331f, -0.99704438f,
+-0.99796460f, -0.99871383f, -0.99929194f, -0.99969882f, -0.99993441f,
+};
+#endif
+
+static const CELTMode mode96000_1920_240 = {
+96000, /* Fs */
+240, /* overlap */
+21, /* nbEBands */
+21, /* effEBands */
+{0.92300415f, 0.22000122f, 1.5128347f, 0.66101074f, }, /* preemph */
+eband5ms, /* eBands */
+3, /* maxLM */
+8, /* nbShortMdcts */
+240, /* shortMdctSize */
+11, /* nbAllocVectors */
+band_allocation, /* allocVectors */
+logN400, /* logN */
+window240, /* window */
+{3840, 3, {&fft_state96000_1920_0, &fft_state96000_1920_1, &fft_state96000_1920_2, &fft_state96000_1920_3, }, mdct_twiddles1920}, /* mdct */
+{392, cache_index50, cache_bits50, cache_caps50}, /* cache */
+#ifdef ENABLE_QEXT
+{86, qext_cache_index50, qext_cache_bits50, qext_cache_caps50}, /* qext_cache */
+#endif
+};
+#endif /* ENABLE_QEXT */
+
+/* List of all the available modes */
+#ifdef ENABLE_QEXT
+#define TOTAL_MODES 2
+static const CELTMode * const static_mode_list[TOTAL_MODES] = {
+&mode48000_960_120,
+&mode96000_1920_240,
+};
+#else
+#define TOTAL_MODES 1
+static const CELTMode * const static_mode_list[TOTAL_MODES] = {
+&mode48000_960_120,
+};
+#endif
--- /dev/null
+/* The contents of this file was automatically generated by
+ * dump_mode_arm_ne10.c with arguments: 48000 960
+ * It contains static definitions for some pre-defined modes. */
+#include <NE10_types.h>
+
+#ifndef NE10_FFT_PARAMS48000_960
+#define NE10_FFT_PARAMS48000_960
+static const ne10_int32_t ne10_factors_480[64] = {
+4, 40, 4, 30, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, };
+static const ne10_int32_t ne10_factors_240[64] = {
+3, 20, 4, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, };
+static const ne10_int32_t ne10_factors_120[64] = {
+3, 10, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, };
+static const ne10_int32_t ne10_factors_60[64] = {
+2, 5, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, };
+static const ne10_fft_cpx_float32_t ne10_twiddles_480[480] = {
+{1.0000000f,0.0000000f}, {1.0000000f,-0.0000000f}, {1.0000000f,-0.0000000f},
+{1.0000000f,-0.0000000f}, {0.91354543f,-0.40673664f}, {0.66913056f,-0.74314487f},
+{1.0000000f,-0.0000000f}, {0.66913056f,-0.74314487f}, {-0.10452851f,-0.99452192f},
+{1.0000000f,-0.0000000f}, {0.30901697f,-0.95105654f}, {-0.80901700f,-0.58778518f},
+{1.0000000f,-0.0000000f}, {-0.10452851f,-0.99452192f}, {-0.97814757f,0.20791179f},
+{1.0000000f,-0.0000000f}, {0.97814763f,-0.20791170f}, {0.91354543f,-0.40673664f},
+{0.80901700f,-0.58778524f}, {0.66913056f,-0.74314487f}, {0.49999997f,-0.86602545f},
+{0.30901697f,-0.95105654f}, {0.10452842f,-0.99452192f}, {-0.10452851f,-0.99452192f},
+{-0.30901703f,-0.95105648f}, {-0.50000006f,-0.86602533f}, {-0.66913068f,-0.74314475f},
+{-0.80901700f,-0.58778518f}, {-0.91354549f,-0.40673658f}, {-0.97814763f,-0.20791161f},
+{1.0000000f,-0.0000000f}, {0.99862951f,-0.052335959f}, {0.99452192f,-0.10452846f},
+{0.98768836f,-0.15643448f}, {0.97814763f,-0.20791170f}, {0.96592581f,-0.25881904f},
+{0.95105648f,-0.30901700f}, {0.93358040f,-0.35836795f}, {0.91354543f,-0.40673664f},
+{0.89100653f,-0.45399052f}, {0.86602545f,-0.50000000f}, {0.83867055f,-0.54463905f},
+{0.80901700f,-0.58778524f}, {0.77714598f,-0.62932038f}, {0.74314475f,-0.66913062f},
+{0.70710677f,-0.70710683f}, {0.66913056f,-0.74314487f}, {0.62932038f,-0.77714598f},
+{0.58778524f,-0.80901700f}, {0.54463899f,-0.83867055f}, {0.49999997f,-0.86602545f},
+{0.45399052f,-0.89100653f}, {0.40673661f,-0.91354549f}, {0.35836786f,-0.93358046f},
+{0.30901697f,-0.95105654f}, {0.25881907f,-0.96592581f}, {0.20791166f,-0.97814763f},
+{0.15643437f,-0.98768836f}, {0.10452842f,-0.99452192f}, {0.052335974f,-0.99862951f},
+{1.0000000f,-0.0000000f}, {0.99452192f,-0.10452846f}, {0.97814763f,-0.20791170f},
+{0.95105648f,-0.30901700f}, {0.91354543f,-0.40673664f}, {0.86602545f,-0.50000000f},
+{0.80901700f,-0.58778524f}, {0.74314475f,-0.66913062f}, {0.66913056f,-0.74314487f},
+{0.58778524f,-0.80901700f}, {0.49999997f,-0.86602545f}, {0.40673661f,-0.91354549f},
+{0.30901697f,-0.95105654f}, {0.20791166f,-0.97814763f}, {0.10452842f,-0.99452192f},
+{-4.3711388e-08f,-1.0000000f}, {-0.10452851f,-0.99452192f}, {-0.20791174f,-0.97814757f},
+{-0.30901703f,-0.95105648f}, {-0.40673670f,-0.91354543f}, {-0.50000006f,-0.86602533f},
+{-0.58778518f,-0.80901700f}, {-0.66913068f,-0.74314475f}, {-0.74314493f,-0.66913044f},
+{-0.80901700f,-0.58778518f}, {-0.86602539f,-0.50000006f}, {-0.91354549f,-0.40673658f},
+{-0.95105654f,-0.30901679f}, {-0.97814763f,-0.20791161f}, {-0.99452192f,-0.10452849f},
+{1.0000000f,-0.0000000f}, {0.98768836f,-0.15643448f}, {0.95105648f,-0.30901700f},
+{0.89100653f,-0.45399052f}, {0.80901700f,-0.58778524f}, {0.70710677f,-0.70710683f},
+{0.58778524f,-0.80901700f}, {0.45399052f,-0.89100653f}, {0.30901697f,-0.95105654f},
+{0.15643437f,-0.98768836f}, {-4.3711388e-08f,-1.0000000f}, {-0.15643445f,-0.98768836f},
+{-0.30901703f,-0.95105648f}, {-0.45399061f,-0.89100647f}, {-0.58778518f,-0.80901700f},
+{-0.70710677f,-0.70710677f}, {-0.80901700f,-0.58778518f}, {-0.89100659f,-0.45399037f},
+{-0.95105654f,-0.30901679f}, {-0.98768836f,-0.15643445f}, {-1.0000000f,8.7422777e-08f},
+{-0.98768830f,0.15643461f}, {-0.95105654f,0.30901697f}, {-0.89100653f,0.45399055f},
+{-0.80901694f,0.58778536f}, {-0.70710665f,0.70710689f}, {-0.58778507f,0.80901712f},
+{-0.45399022f,0.89100665f}, {-0.30901709f,0.95105648f}, {-0.15643452f,0.98768830f},
+{1.0000000f,-0.0000000f}, {0.99991435f,-0.013089596f}, {0.99965733f,-0.026176950f},
+{0.99922901f,-0.039259817f}, {0.99862951f,-0.052335959f}, {0.99785894f,-0.065403134f},
+{0.99691731f,-0.078459099f}, {0.99580491f,-0.091501623f}, {0.99452192f,-0.10452846f},
+{0.99306846f,-0.11753740f}, {0.99144489f,-0.13052620f}, {0.98965138f,-0.14349262f},
+{0.98768836f,-0.15643448f}, {0.98555607f,-0.16934951f}, {0.98325491f,-0.18223552f},
+{0.98078525f,-0.19509032f}, {0.97814763f,-0.20791170f}, {0.97534233f,-0.22069745f},
+{0.97236991f,-0.23344538f}, {0.96923089f,-0.24615330f}, {0.96592581f,-0.25881904f},
+{0.96245521f,-0.27144045f}, {0.95881975f,-0.28401536f}, {0.95501995f,-0.29654160f},
+{0.95105648f,-0.30901700f}, {0.94693011f,-0.32143945f}, {0.94264150f,-0.33380687f},
+{0.93819129f,-0.34611708f}, {0.93358040f,-0.35836795f}, {0.92880952f,-0.37055743f},
+{0.92387956f,-0.38268346f}, {0.91879117f,-0.39474389f}, {0.91354543f,-0.40673664f},
+{0.90814316f,-0.41865975f}, {0.90258527f,-0.43051112f}, {0.89687270f,-0.44228873f},
+{0.89100653f,-0.45399052f}, {0.88498765f,-0.46561453f}, {0.87881708f,-0.47715878f},
+{0.87249601f,-0.48862126f}, {0.86602545f,-0.50000000f}, {0.85940641f,-0.51129311f},
+{0.85264015f,-0.52249855f}, {0.84572786f,-0.53361452f}, {0.83867055f,-0.54463905f},
+{0.83146960f,-0.55557024f}, {0.82412618f,-0.56640625f}, {0.81664151f,-0.57714522f},
+{0.80901700f,-0.58778524f}, {0.80125380f,-0.59832460f}, {0.79335332f,-0.60876143f},
+{0.78531694f,-0.61909395f}, {0.77714598f,-0.62932038f}, {0.76884180f,-0.63943899f},
+{0.76040596f,-0.64944810f}, {0.75183982f,-0.65934587f}, {0.74314475f,-0.66913062f},
+{0.73432249f,-0.67880076f}, {0.72537434f,-0.68835455f}, {0.71630192f,-0.69779050f},
+{0.70710677f,-0.70710683f}, {0.69779044f,-0.71630198f}, {0.68835455f,-0.72537440f},
+{0.67880070f,-0.73432255f}, {0.66913056f,-0.74314487f}, {0.65934581f,-0.75183982f},
+{0.64944804f,-0.76040596f}, {0.63943899f,-0.76884186f}, {0.62932038f,-0.77714598f},
+{0.61909395f,-0.78531694f}, {0.60876137f,-0.79335338f}, {0.59832460f,-0.80125386f},
+{0.58778524f,-0.80901700f}, {0.57714516f,-0.81664151f}, {0.56640625f,-0.82412618f},
+{0.55557019f,-0.83146960f}, {0.54463899f,-0.83867055f}, {0.53361452f,-0.84572786f},
+{0.52249849f,-0.85264015f}, {0.51129311f,-0.85940641f}, {0.49999997f,-0.86602545f},
+{0.48862118f,-0.87249601f}, {0.47715876f,-0.87881708f}, {0.46561447f,-0.88498765f},
+{0.45399052f,-0.89100653f}, {0.44228867f,-0.89687276f}, {0.43051103f,-0.90258533f},
+{0.41865975f,-0.90814316f}, {0.40673661f,-0.91354549f}, {0.39474380f,-0.91879129f},
+{0.38268343f,-0.92387956f}, {0.37055740f,-0.92880958f}, {0.35836786f,-0.93358046f},
+{0.34611705f,-0.93819135f}, {0.33380681f,-0.94264150f}, {0.32143947f,-0.94693011f},
+{0.30901697f,-0.95105654f}, {0.29654151f,-0.95501995f}, {0.28401533f,-0.95881975f},
+{0.27144039f,-0.96245527f}, {0.25881907f,-0.96592581f}, {0.24615327f,-0.96923089f},
+{0.23344530f,-0.97236991f}, {0.22069745f,-0.97534233f}, {0.20791166f,-0.97814763f},
+{0.19509023f,-0.98078531f}, {0.18223552f,-0.98325491f}, {0.16934945f,-0.98555607f},
+{0.15643437f,-0.98768836f}, {0.14349259f,-0.98965138f}, {0.13052613f,-0.99144489f},
+{0.11753740f,-0.99306846f}, {0.10452842f,-0.99452192f}, {0.091501534f,-0.99580491f},
+{0.078459084f,-0.99691731f}, {0.065403074f,-0.99785894f}, {0.052335974f,-0.99862951f},
+{0.039259788f,-0.99922901f}, {0.026176875f,-0.99965733f}, {0.013089597f,-0.99991435f},
+{1.0000000f,-0.0000000f}, {0.99965733f,-0.026176950f}, {0.99862951f,-0.052335959f},
+{0.99691731f,-0.078459099f}, {0.99452192f,-0.10452846f}, {0.99144489f,-0.13052620f},
+{0.98768836f,-0.15643448f}, {0.98325491f,-0.18223552f}, {0.97814763f,-0.20791170f},
+{0.97236991f,-0.23344538f}, {0.96592581f,-0.25881904f}, {0.95881975f,-0.28401536f},
+{0.95105648f,-0.30901700f}, {0.94264150f,-0.33380687f}, {0.93358040f,-0.35836795f},
+{0.92387956f,-0.38268346f}, {0.91354543f,-0.40673664f}, {0.90258527f,-0.43051112f},
+{0.89100653f,-0.45399052f}, {0.87881708f,-0.47715878f}, {0.86602545f,-0.50000000f},
+{0.85264015f,-0.52249855f}, {0.83867055f,-0.54463905f}, {0.82412618f,-0.56640625f},
+{0.80901700f,-0.58778524f}, {0.79335332f,-0.60876143f}, {0.77714598f,-0.62932038f},
+{0.76040596f,-0.64944810f}, {0.74314475f,-0.66913062f}, {0.72537434f,-0.68835455f},
+{0.70710677f,-0.70710683f}, {0.68835455f,-0.72537440f}, {0.66913056f,-0.74314487f},
+{0.64944804f,-0.76040596f}, {0.62932038f,-0.77714598f}, {0.60876137f,-0.79335338f},
+{0.58778524f,-0.80901700f}, {0.56640625f,-0.82412618f}, {0.54463899f,-0.83867055f},
+{0.52249849f,-0.85264015f}, {0.49999997f,-0.86602545f}, {0.47715876f,-0.87881708f},
+{0.45399052f,-0.89100653f}, {0.43051103f,-0.90258533f}, {0.40673661f,-0.91354549f},
+{0.38268343f,-0.92387956f}, {0.35836786f,-0.93358046f}, {0.33380681f,-0.94264150f},
+{0.30901697f,-0.95105654f}, {0.28401533f,-0.95881975f}, {0.25881907f,-0.96592581f},
+{0.23344530f,-0.97236991f}, {0.20791166f,-0.97814763f}, {0.18223552f,-0.98325491f},
+{0.15643437f,-0.98768836f}, {0.13052613f,-0.99144489f}, {0.10452842f,-0.99452192f},
+{0.078459084f,-0.99691731f}, {0.052335974f,-0.99862951f}, {0.026176875f,-0.99965733f},
+{-4.3711388e-08f,-1.0000000f}, {-0.026176963f,-0.99965733f}, {-0.052336060f,-0.99862951f},
+{-0.078459173f,-0.99691731f}, {-0.10452851f,-0.99452192f}, {-0.13052621f,-0.99144489f},
+{-0.15643445f,-0.98768836f}, {-0.18223560f,-0.98325491f}, {-0.20791174f,-0.97814757f},
+{-0.23344538f,-0.97236991f}, {-0.25881916f,-0.96592581f}, {-0.28401542f,-0.95881969f},
+{-0.30901703f,-0.95105648f}, {-0.33380687f,-0.94264150f}, {-0.35836795f,-0.93358040f},
+{-0.38268352f,-0.92387950f}, {-0.40673670f,-0.91354543f}, {-0.43051112f,-0.90258527f},
+{-0.45399061f,-0.89100647f}, {-0.47715873f,-0.87881708f}, {-0.50000006f,-0.86602533f},
+{-0.52249867f,-0.85264009f}, {-0.54463905f,-0.83867055f}, {-0.56640631f,-0.82412612f},
+{-0.58778518f,-0.80901700f}, {-0.60876143f,-0.79335332f}, {-0.62932050f,-0.77714586f},
+{-0.64944804f,-0.76040596f}, {-0.66913068f,-0.74314475f}, {-0.68835467f,-0.72537428f},
+{-0.70710677f,-0.70710677f}, {-0.72537446f,-0.68835449f}, {-0.74314493f,-0.66913044f},
+{-0.76040596f,-0.64944804f}, {-0.77714604f,-0.62932026f}, {-0.79335332f,-0.60876143f},
+{-0.80901700f,-0.58778518f}, {-0.82412624f,-0.56640613f}, {-0.83867055f,-0.54463899f},
+{-0.85264021f,-0.52249849f}, {-0.86602539f,-0.50000006f}, {-0.87881714f,-0.47715873f},
+{-0.89100659f,-0.45399037f}, {-0.90258527f,-0.43051112f}, {-0.91354549f,-0.40673658f},
+{-0.92387956f,-0.38268328f}, {-0.93358040f,-0.35836792f}, {-0.94264150f,-0.33380675f},
+{-0.95105654f,-0.30901679f}, {-0.95881975f,-0.28401530f}, {-0.96592587f,-0.25881892f},
+{-0.97236991f,-0.23344538f}, {-0.97814763f,-0.20791161f}, {-0.98325491f,-0.18223536f},
+{-0.98768836f,-0.15643445f}, {-0.99144489f,-0.13052608f}, {-0.99452192f,-0.10452849f},
+{-0.99691737f,-0.078459039f}, {-0.99862957f,-0.052335810f}, {-0.99965733f,-0.026176952f},
+{1.0000000f,-0.0000000f}, {0.99922901f,-0.039259817f}, {0.99691731f,-0.078459099f},
+{0.99306846f,-0.11753740f}, {0.98768836f,-0.15643448f}, {0.98078525f,-0.19509032f},
+{0.97236991f,-0.23344538f}, {0.96245521f,-0.27144045f}, {0.95105648f,-0.30901700f},
+{0.93819129f,-0.34611708f}, {0.92387956f,-0.38268346f}, {0.90814316f,-0.41865975f},
+{0.89100653f,-0.45399052f}, {0.87249601f,-0.48862126f}, {0.85264015f,-0.52249855f},
+{0.83146960f,-0.55557024f}, {0.80901700f,-0.58778524f}, {0.78531694f,-0.61909395f},
+{0.76040596f,-0.64944810f}, {0.73432249f,-0.67880076f}, {0.70710677f,-0.70710683f},
+{0.67880070f,-0.73432255f}, {0.64944804f,-0.76040596f}, {0.61909395f,-0.78531694f},
+{0.58778524f,-0.80901700f}, {0.55557019f,-0.83146960f}, {0.52249849f,-0.85264015f},
+{0.48862118f,-0.87249601f}, {0.45399052f,-0.89100653f}, {0.41865975f,-0.90814316f},
+{0.38268343f,-0.92387956f}, {0.34611705f,-0.93819135f}, {0.30901697f,-0.95105654f},
+{0.27144039f,-0.96245527f}, {0.23344530f,-0.97236991f}, {0.19509023f,-0.98078531f},
+{0.15643437f,-0.98768836f}, {0.11753740f,-0.99306846f}, {0.078459084f,-0.99691731f},
+{0.039259788f,-0.99922901f}, {-4.3711388e-08f,-1.0000000f}, {-0.039259877f,-0.99922901f},
+{-0.078459173f,-0.99691731f}, {-0.11753749f,-0.99306846f}, {-0.15643445f,-0.98768836f},
+{-0.19509032f,-0.98078525f}, {-0.23344538f,-0.97236991f}, {-0.27144048f,-0.96245521f},
+{-0.30901703f,-0.95105648f}, {-0.34611711f,-0.93819129f}, {-0.38268352f,-0.92387950f},
+{-0.41865984f,-0.90814310f}, {-0.45399061f,-0.89100647f}, {-0.48862135f,-0.87249595f},
+{-0.52249867f,-0.85264009f}, {-0.55557036f,-0.83146954f}, {-0.58778518f,-0.80901700f},
+{-0.61909389f,-0.78531694f}, {-0.64944804f,-0.76040596f}, {-0.67880076f,-0.73432249f},
+{-0.70710677f,-0.70710677f}, {-0.73432249f,-0.67880070f}, {-0.76040596f,-0.64944804f},
+{-0.78531694f,-0.61909389f}, {-0.80901700f,-0.58778518f}, {-0.83146966f,-0.55557019f},
+{-0.85264021f,-0.52249849f}, {-0.87249607f,-0.48862115f}, {-0.89100659f,-0.45399037f},
+{-0.90814322f,-0.41865960f}, {-0.92387956f,-0.38268328f}, {-0.93819135f,-0.34611690f},
+{-0.95105654f,-0.30901679f}, {-0.96245521f,-0.27144048f}, {-0.97236991f,-0.23344538f},
+{-0.98078531f,-0.19509031f}, {-0.98768836f,-0.15643445f}, {-0.99306846f,-0.11753736f},
+{-0.99691737f,-0.078459039f}, {-0.99922901f,-0.039259743f}, {-1.0000000f,8.7422777e-08f},
+{-0.99922901f,0.039259918f}, {-0.99691731f,0.078459218f}, {-0.99306846f,0.11753753f},
+{-0.98768830f,0.15643461f}, {-0.98078525f,0.19509049f}, {-0.97236985f,0.23344554f},
+{-0.96245515f,0.27144065f}, {-0.95105654f,0.30901697f}, {-0.93819135f,0.34611705f},
+{-0.92387956f,0.38268346f}, {-0.90814316f,0.41865975f}, {-0.89100653f,0.45399055f},
+{-0.87249601f,0.48862129f}, {-0.85264015f,0.52249861f}, {-0.83146960f,0.55557030f},
+{-0.80901694f,0.58778536f}, {-0.78531688f,0.61909401f}, {-0.76040590f,0.64944816f},
+{-0.73432243f,0.67880082f}, {-0.70710665f,0.70710689f}, {-0.67880058f,0.73432261f},
+{-0.64944792f,0.76040608f}, {-0.61909378f,0.78531706f}, {-0.58778507f,0.80901712f},
+{-0.55557001f,0.83146977f}, {-0.52249837f,0.85264033f}, {-0.48862100f,0.87249613f},
+{-0.45399022f,0.89100665f}, {-0.41865945f,0.90814328f}, {-0.38268313f,0.92387968f},
+{-0.34611672f,0.93819147f}, {-0.30901709f,0.95105648f}, {-0.27144054f,0.96245521f},
+{-0.23344545f,0.97236991f}, {-0.19509038f,0.98078525f}, {-0.15643452f,0.98768830f},
+{-0.11753743f,0.99306846f}, {-0.078459114f,0.99691731f}, {-0.039259821f,0.99922901f},
+};
+static const ne10_fft_cpx_float32_t ne10_twiddles_240[240] = {
+{1.0000000f,0.0000000f}, {1.0000000f,-0.0000000f}, {1.0000000f,-0.0000000f},
+{1.0000000f,-0.0000000f}, {0.91354543f,-0.40673664f}, {0.66913056f,-0.74314487f},
+{1.0000000f,-0.0000000f}, {0.66913056f,-0.74314487f}, {-0.10452851f,-0.99452192f},
+{1.0000000f,-0.0000000f}, {0.30901697f,-0.95105654f}, {-0.80901700f,-0.58778518f},
+{1.0000000f,-0.0000000f}, {-0.10452851f,-0.99452192f}, {-0.97814757f,0.20791179f},
+{1.0000000f,-0.0000000f}, {0.99452192f,-0.10452846f}, {0.97814763f,-0.20791170f},
+{0.95105648f,-0.30901700f}, {0.91354543f,-0.40673664f}, {0.86602545f,-0.50000000f},
+{0.80901700f,-0.58778524f}, {0.74314475f,-0.66913062f}, {0.66913056f,-0.74314487f},
+{0.58778524f,-0.80901700f}, {0.49999997f,-0.86602545f}, {0.40673661f,-0.91354549f},
+{0.30901697f,-0.95105654f}, {0.20791166f,-0.97814763f}, {0.10452842f,-0.99452192f},
+{1.0000000f,-0.0000000f}, {0.97814763f,-0.20791170f}, {0.91354543f,-0.40673664f},
+{0.80901700f,-0.58778524f}, {0.66913056f,-0.74314487f}, {0.49999997f,-0.86602545f},
+{0.30901697f,-0.95105654f}, {0.10452842f,-0.99452192f}, {-0.10452851f,-0.99452192f},
+{-0.30901703f,-0.95105648f}, {-0.50000006f,-0.86602533f}, {-0.66913068f,-0.74314475f},
+{-0.80901700f,-0.58778518f}, {-0.91354549f,-0.40673658f}, {-0.97814763f,-0.20791161f},
+{1.0000000f,-0.0000000f}, {0.95105648f,-0.30901700f}, {0.80901700f,-0.58778524f},
+{0.58778524f,-0.80901700f}, {0.30901697f,-0.95105654f}, {-4.3711388e-08f,-1.0000000f},
+{-0.30901703f,-0.95105648f}, {-0.58778518f,-0.80901700f}, {-0.80901700f,-0.58778518f},
+{-0.95105654f,-0.30901679f}, {-1.0000000f,8.7422777e-08f}, {-0.95105654f,0.30901697f},
+{-0.80901694f,0.58778536f}, {-0.58778507f,0.80901712f}, {-0.30901709f,0.95105648f},
+{1.0000000f,-0.0000000f}, {0.99965733f,-0.026176950f}, {0.99862951f,-0.052335959f},
+{0.99691731f,-0.078459099f}, {0.99452192f,-0.10452846f}, {0.99144489f,-0.13052620f},
+{0.98768836f,-0.15643448f}, {0.98325491f,-0.18223552f}, {0.97814763f,-0.20791170f},
+{0.97236991f,-0.23344538f}, {0.96592581f,-0.25881904f}, {0.95881975f,-0.28401536f},
+{0.95105648f,-0.30901700f}, {0.94264150f,-0.33380687f}, {0.93358040f,-0.35836795f},
+{0.92387956f,-0.38268346f}, {0.91354543f,-0.40673664f}, {0.90258527f,-0.43051112f},
+{0.89100653f,-0.45399052f}, {0.87881708f,-0.47715878f}, {0.86602545f,-0.50000000f},
+{0.85264015f,-0.52249855f}, {0.83867055f,-0.54463905f}, {0.82412618f,-0.56640625f},
+{0.80901700f,-0.58778524f}, {0.79335332f,-0.60876143f}, {0.77714598f,-0.62932038f},
+{0.76040596f,-0.64944810f}, {0.74314475f,-0.66913062f}, {0.72537434f,-0.68835455f},
+{0.70710677f,-0.70710683f}, {0.68835455f,-0.72537440f}, {0.66913056f,-0.74314487f},
+{0.64944804f,-0.76040596f}, {0.62932038f,-0.77714598f}, {0.60876137f,-0.79335338f},
+{0.58778524f,-0.80901700f}, {0.56640625f,-0.82412618f}, {0.54463899f,-0.83867055f},
+{0.52249849f,-0.85264015f}, {0.49999997f,-0.86602545f}, {0.47715876f,-0.87881708f},
+{0.45399052f,-0.89100653f}, {0.43051103f,-0.90258533f}, {0.40673661f,-0.91354549f},
+{0.38268343f,-0.92387956f}, {0.35836786f,-0.93358046f}, {0.33380681f,-0.94264150f},
+{0.30901697f,-0.95105654f}, {0.28401533f,-0.95881975f}, {0.25881907f,-0.96592581f},
+{0.23344530f,-0.97236991f}, {0.20791166f,-0.97814763f}, {0.18223552f,-0.98325491f},
+{0.15643437f,-0.98768836f}, {0.13052613f,-0.99144489f}, {0.10452842f,-0.99452192f},
+{0.078459084f,-0.99691731f}, {0.052335974f,-0.99862951f}, {0.026176875f,-0.99965733f},
+{1.0000000f,-0.0000000f}, {0.99862951f,-0.052335959f}, {0.99452192f,-0.10452846f},
+{0.98768836f,-0.15643448f}, {0.97814763f,-0.20791170f}, {0.96592581f,-0.25881904f},
+{0.95105648f,-0.30901700f}, {0.93358040f,-0.35836795f}, {0.91354543f,-0.40673664f},
+{0.89100653f,-0.45399052f}, {0.86602545f,-0.50000000f}, {0.83867055f,-0.54463905f},
+{0.80901700f,-0.58778524f}, {0.77714598f,-0.62932038f}, {0.74314475f,-0.66913062f},
+{0.70710677f,-0.70710683f}, {0.66913056f,-0.74314487f}, {0.62932038f,-0.77714598f},
+{0.58778524f,-0.80901700f}, {0.54463899f,-0.83867055f}, {0.49999997f,-0.86602545f},
+{0.45399052f,-0.89100653f}, {0.40673661f,-0.91354549f}, {0.35836786f,-0.93358046f},
+{0.30901697f,-0.95105654f}, {0.25881907f,-0.96592581f}, {0.20791166f,-0.97814763f},
+{0.15643437f,-0.98768836f}, {0.10452842f,-0.99452192f}, {0.052335974f,-0.99862951f},
+{-4.3711388e-08f,-1.0000000f}, {-0.052336060f,-0.99862951f}, {-0.10452851f,-0.99452192f},
+{-0.15643445f,-0.98768836f}, {-0.20791174f,-0.97814757f}, {-0.25881916f,-0.96592581f},
+{-0.30901703f,-0.95105648f}, {-0.35836795f,-0.93358040f}, {-0.40673670f,-0.91354543f},
+{-0.45399061f,-0.89100647f}, {-0.50000006f,-0.86602533f}, {-0.54463905f,-0.83867055f},
+{-0.58778518f,-0.80901700f}, {-0.62932050f,-0.77714586f}, {-0.66913068f,-0.74314475f},
+{-0.70710677f,-0.70710677f}, {-0.74314493f,-0.66913044f}, {-0.77714604f,-0.62932026f},
+{-0.80901700f,-0.58778518f}, {-0.83867055f,-0.54463899f}, {-0.86602539f,-0.50000006f},
+{-0.89100659f,-0.45399037f}, {-0.91354549f,-0.40673658f}, {-0.93358040f,-0.35836792f},
+{-0.95105654f,-0.30901679f}, {-0.96592587f,-0.25881892f}, {-0.97814763f,-0.20791161f},
+{-0.98768836f,-0.15643445f}, {-0.99452192f,-0.10452849f}, {-0.99862957f,-0.052335810f},
+{1.0000000f,-0.0000000f}, {0.99691731f,-0.078459099f}, {0.98768836f,-0.15643448f},
+{0.97236991f,-0.23344538f}, {0.95105648f,-0.30901700f}, {0.92387956f,-0.38268346f},
+{0.89100653f,-0.45399052f}, {0.85264015f,-0.52249855f}, {0.80901700f,-0.58778524f},
+{0.76040596f,-0.64944810f}, {0.70710677f,-0.70710683f}, {0.64944804f,-0.76040596f},
+{0.58778524f,-0.80901700f}, {0.52249849f,-0.85264015f}, {0.45399052f,-0.89100653f},
+{0.38268343f,-0.92387956f}, {0.30901697f,-0.95105654f}, {0.23344530f,-0.97236991f},
+{0.15643437f,-0.98768836f}, {0.078459084f,-0.99691731f}, {-4.3711388e-08f,-1.0000000f},
+{-0.078459173f,-0.99691731f}, {-0.15643445f,-0.98768836f}, {-0.23344538f,-0.97236991f},
+{-0.30901703f,-0.95105648f}, {-0.38268352f,-0.92387950f}, {-0.45399061f,-0.89100647f},
+{-0.52249867f,-0.85264009f}, {-0.58778518f,-0.80901700f}, {-0.64944804f,-0.76040596f},
+{-0.70710677f,-0.70710677f}, {-0.76040596f,-0.64944804f}, {-0.80901700f,-0.58778518f},
+{-0.85264021f,-0.52249849f}, {-0.89100659f,-0.45399037f}, {-0.92387956f,-0.38268328f},
+{-0.95105654f,-0.30901679f}, {-0.97236991f,-0.23344538f}, {-0.98768836f,-0.15643445f},
+{-0.99691737f,-0.078459039f}, {-1.0000000f,8.7422777e-08f}, {-0.99691731f,0.078459218f},
+{-0.98768830f,0.15643461f}, {-0.97236985f,0.23344554f}, {-0.95105654f,0.30901697f},
+{-0.92387956f,0.38268346f}, {-0.89100653f,0.45399055f}, {-0.85264015f,0.52249861f},
+{-0.80901694f,0.58778536f}, {-0.76040590f,0.64944816f}, {-0.70710665f,0.70710689f},
+{-0.64944792f,0.76040608f}, {-0.58778507f,0.80901712f}, {-0.52249837f,0.85264033f},
+{-0.45399022f,0.89100665f}, {-0.38268313f,0.92387968f}, {-0.30901709f,0.95105648f},
+{-0.23344545f,0.97236991f}, {-0.15643452f,0.98768830f}, {-0.078459114f,0.99691731f},
+};
+static const ne10_fft_cpx_float32_t ne10_twiddles_120[120] = {
+{1.0000000f,0.0000000f}, {1.0000000f,-0.0000000f}, {1.0000000f,-0.0000000f},
+{1.0000000f,-0.0000000f}, {0.91354543f,-0.40673664f}, {0.66913056f,-0.74314487f},
+{1.0000000f,-0.0000000f}, {0.66913056f,-0.74314487f}, {-0.10452851f,-0.99452192f},
+{1.0000000f,-0.0000000f}, {0.30901697f,-0.95105654f}, {-0.80901700f,-0.58778518f},
+{1.0000000f,-0.0000000f}, {-0.10452851f,-0.99452192f}, {-0.97814757f,0.20791179f},
+{1.0000000f,-0.0000000f}, {0.97814763f,-0.20791170f}, {0.91354543f,-0.40673664f},
+{0.80901700f,-0.58778524f}, {0.66913056f,-0.74314487f}, {0.49999997f,-0.86602545f},
+{0.30901697f,-0.95105654f}, {0.10452842f,-0.99452192f}, {-0.10452851f,-0.99452192f},
+{-0.30901703f,-0.95105648f}, {-0.50000006f,-0.86602533f}, {-0.66913068f,-0.74314475f},
+{-0.80901700f,-0.58778518f}, {-0.91354549f,-0.40673658f}, {-0.97814763f,-0.20791161f},
+{1.0000000f,-0.0000000f}, {0.99862951f,-0.052335959f}, {0.99452192f,-0.10452846f},
+{0.98768836f,-0.15643448f}, {0.97814763f,-0.20791170f}, {0.96592581f,-0.25881904f},
+{0.95105648f,-0.30901700f}, {0.93358040f,-0.35836795f}, {0.91354543f,-0.40673664f},
+{0.89100653f,-0.45399052f}, {0.86602545f,-0.50000000f}, {0.83867055f,-0.54463905f},
+{0.80901700f,-0.58778524f}, {0.77714598f,-0.62932038f}, {0.74314475f,-0.66913062f},
+{0.70710677f,-0.70710683f}, {0.66913056f,-0.74314487f}, {0.62932038f,-0.77714598f},
+{0.58778524f,-0.80901700f}, {0.54463899f,-0.83867055f}, {0.49999997f,-0.86602545f},
+{0.45399052f,-0.89100653f}, {0.40673661f,-0.91354549f}, {0.35836786f,-0.93358046f},
+{0.30901697f,-0.95105654f}, {0.25881907f,-0.96592581f}, {0.20791166f,-0.97814763f},
+{0.15643437f,-0.98768836f}, {0.10452842f,-0.99452192f}, {0.052335974f,-0.99862951f},
+{1.0000000f,-0.0000000f}, {0.99452192f,-0.10452846f}, {0.97814763f,-0.20791170f},
+{0.95105648f,-0.30901700f}, {0.91354543f,-0.40673664f}, {0.86602545f,-0.50000000f},
+{0.80901700f,-0.58778524f}, {0.74314475f,-0.66913062f}, {0.66913056f,-0.74314487f},
+{0.58778524f,-0.80901700f}, {0.49999997f,-0.86602545f}, {0.40673661f,-0.91354549f},
+{0.30901697f,-0.95105654f}, {0.20791166f,-0.97814763f}, {0.10452842f,-0.99452192f},
+{-4.3711388e-08f,-1.0000000f}, {-0.10452851f,-0.99452192f}, {-0.20791174f,-0.97814757f},
+{-0.30901703f,-0.95105648f}, {-0.40673670f,-0.91354543f}, {-0.50000006f,-0.86602533f},
+{-0.58778518f,-0.80901700f}, {-0.66913068f,-0.74314475f}, {-0.74314493f,-0.66913044f},
+{-0.80901700f,-0.58778518f}, {-0.86602539f,-0.50000006f}, {-0.91354549f,-0.40673658f},
+{-0.95105654f,-0.30901679f}, {-0.97814763f,-0.20791161f}, {-0.99452192f,-0.10452849f},
+{1.0000000f,-0.0000000f}, {0.98768836f,-0.15643448f}, {0.95105648f,-0.30901700f},
+{0.89100653f,-0.45399052f}, {0.80901700f,-0.58778524f}, {0.70710677f,-0.70710683f},
+{0.58778524f,-0.80901700f}, {0.45399052f,-0.89100653f}, {0.30901697f,-0.95105654f},
+{0.15643437f,-0.98768836f}, {-4.3711388e-08f,-1.0000000f}, {-0.15643445f,-0.98768836f},
+{-0.30901703f,-0.95105648f}, {-0.45399061f,-0.89100647f}, {-0.58778518f,-0.80901700f},
+{-0.70710677f,-0.70710677f}, {-0.80901700f,-0.58778518f}, {-0.89100659f,-0.45399037f},
+{-0.95105654f,-0.30901679f}, {-0.98768836f,-0.15643445f}, {-1.0000000f,8.7422777e-08f},
+{-0.98768830f,0.15643461f}, {-0.95105654f,0.30901697f}, {-0.89100653f,0.45399055f},
+{-0.80901694f,0.58778536f}, {-0.70710665f,0.70710689f}, {-0.58778507f,0.80901712f},
+{-0.45399022f,0.89100665f}, {-0.30901709f,0.95105648f}, {-0.15643452f,0.98768830f},
+};
+static const ne10_fft_cpx_float32_t ne10_twiddles_60[60] = {
+{1.0000000f,0.0000000f}, {1.0000000f,-0.0000000f}, {1.0000000f,-0.0000000f},
+{1.0000000f,-0.0000000f}, {0.91354543f,-0.40673664f}, {0.66913056f,-0.74314487f},
+{1.0000000f,-0.0000000f}, {0.66913056f,-0.74314487f}, {-0.10452851f,-0.99452192f},
+{1.0000000f,-0.0000000f}, {0.30901697f,-0.95105654f}, {-0.80901700f,-0.58778518f},
+{1.0000000f,-0.0000000f}, {-0.10452851f,-0.99452192f}, {-0.97814757f,0.20791179f},
+{1.0000000f,-0.0000000f}, {0.99452192f,-0.10452846f}, {0.97814763f,-0.20791170f},
+{0.95105648f,-0.30901700f}, {0.91354543f,-0.40673664f}, {0.86602545f,-0.50000000f},
+{0.80901700f,-0.58778524f}, {0.74314475f,-0.66913062f}, {0.66913056f,-0.74314487f},
+{0.58778524f,-0.80901700f}, {0.49999997f,-0.86602545f}, {0.40673661f,-0.91354549f},
+{0.30901697f,-0.95105654f}, {0.20791166f,-0.97814763f}, {0.10452842f,-0.99452192f},
+{1.0000000f,-0.0000000f}, {0.97814763f,-0.20791170f}, {0.91354543f,-0.40673664f},
+{0.80901700f,-0.58778524f}, {0.66913056f,-0.74314487f}, {0.49999997f,-0.86602545f},
+{0.30901697f,-0.95105654f}, {0.10452842f,-0.99452192f}, {-0.10452851f,-0.99452192f},
+{-0.30901703f,-0.95105648f}, {-0.50000006f,-0.86602533f}, {-0.66913068f,-0.74314475f},
+{-0.80901700f,-0.58778518f}, {-0.91354549f,-0.40673658f}, {-0.97814763f,-0.20791161f},
+{1.0000000f,-0.0000000f}, {0.95105648f,-0.30901700f}, {0.80901700f,-0.58778524f},
+{0.58778524f,-0.80901700f}, {0.30901697f,-0.95105654f}, {-4.3711388e-08f,-1.0000000f},
+{-0.30901703f,-0.95105648f}, {-0.58778518f,-0.80901700f}, {-0.80901700f,-0.58778518f},
+{-0.95105654f,-0.30901679f}, {-1.0000000f,8.7422777e-08f}, {-0.95105654f,0.30901697f},
+{-0.80901694f,0.58778536f}, {-0.58778507f,0.80901712f}, {-0.30901709f,0.95105648f},
+};
+static const ne10_fft_state_float32_t ne10_fft_state_float32_t_480 = {
+120,
+(ne10_int32_t *)ne10_factors_480,
+(ne10_fft_cpx_float32_t *)ne10_twiddles_480,
+NULL,
+(ne10_fft_cpx_float32_t *)&ne10_twiddles_480[120],
+/* is_forward_scaled = true */
+(ne10_int32_t) 1,
+/* is_backward_scaled = false */
+(ne10_int32_t) 0,
+};
+static const arch_fft_state cfg_arch_480 = {
+1,
+(void *)&ne10_fft_state_float32_t_480,
+};
+
+static const ne10_fft_state_float32_t ne10_fft_state_float32_t_240 = {
+60,
+(ne10_int32_t *)ne10_factors_240,
+(ne10_fft_cpx_float32_t *)ne10_twiddles_240,
+NULL,
+(ne10_fft_cpx_float32_t *)&ne10_twiddles_240[60],
+/* is_forward_scaled = true */
+(ne10_int32_t) 1,
+/* is_backward_scaled = false */
+(ne10_int32_t) 0,
+};
+static const arch_fft_state cfg_arch_240 = {
+1,
+(void *)&ne10_fft_state_float32_t_240,
+};
+
+static const ne10_fft_state_float32_t ne10_fft_state_float32_t_120 = {
+30,
+(ne10_int32_t *)ne10_factors_120,
+(ne10_fft_cpx_float32_t *)ne10_twiddles_120,
+NULL,
+(ne10_fft_cpx_float32_t *)&ne10_twiddles_120[30],
+/* is_forward_scaled = true */
+(ne10_int32_t) 1,
+/* is_backward_scaled = false */
+(ne10_int32_t) 0,
+};
+static const arch_fft_state cfg_arch_120 = {
+1,
+(void *)&ne10_fft_state_float32_t_120,
+};
+
+static const ne10_fft_state_float32_t ne10_fft_state_float32_t_60 = {
+15,
+(ne10_int32_t *)ne10_factors_60,
+(ne10_fft_cpx_float32_t *)ne10_twiddles_60,
+NULL,
+(ne10_fft_cpx_float32_t *)&ne10_twiddles_60[15],
+/* is_forward_scaled = true */
+(ne10_int32_t) 1,
+/* is_backward_scaled = false */
+(ne10_int32_t) 0,
+};
+static const arch_fft_state cfg_arch_60 = {
+1,
+(void *)&ne10_fft_state_float32_t_60,
+};
+
+#endif /* end NE10_FFT_PARAMS48000_960 */
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mathops.h"
+#include "cwrs.h"
+#include "vq.h"
+#include "arch.h"
+#include "os_support.h"
+#include "bands.h"
+#include "rate.h"
+#include "pitch.h"
+#include "SigProc_FIX.h"
+
+#if defined(FIXED_POINT)
+void norm_scaleup(celt_norm *X, int N, int shift) {
+ int i;
+ celt_assert(shift >= 0);
+ if (shift <= 0) return;
+ for (i=0;i<N;i++) X[i] = SHL32(X[i], shift);
+}
+
+void norm_scaledown(celt_norm *X, int N, int shift) {
+ int i;
+ celt_assert(shift >= 0);
+ if (shift <= 0) return;
+ for (i=0;i<N;i++) X[i] = PSHR32(X[i], shift);
+}
+
+opus_val32 celt_inner_prod_norm(const celt_norm *x, const celt_norm *y, int len, int arch) {
+ int i;
+ opus_val32 sum = 0;
+ (void)arch;
+ for (i=0;i<len;i++) sum += x[i]*y[i];
+ return sum;
+}
+opus_val32 celt_inner_prod_norm_shift(const celt_norm *x, const celt_norm *y, int len, int arch) {
+ int i;
+ opus_val64 sum = 0;
+ (void)arch;
+ for (i=0;i<len;i++) sum += x[i]*(opus_val64)y[i];
+ return sum>>2*(NORM_SHIFT-14);
+}
+#endif
+
+#ifndef OVERRIDE_vq_exp_rotation1
+static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s)
+{
+ int i;
+ opus_val16 ms;
+ celt_norm *Xptr;
+ Xptr = X;
+ ms = NEG16(s);
+ norm_scaledown(X, len, NORM_SHIFT-14);
+ for (i=0;i<len-stride;i++)
+ {
+ celt_norm x1, x2;
+ x1 = Xptr[0];
+ x2 = Xptr[stride];
+ Xptr[stride] = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x2), s, x1), 15));
+ *Xptr++ = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x1), ms, x2), 15));
+ }
+ Xptr = &X[len-2*stride-1];
+ for (i=len-2*stride-1;i>=0;i--)
+ {
+ celt_norm x1, x2;
+ x1 = Xptr[0];
+ x2 = Xptr[stride];
+ Xptr[stride] = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x2), s, x1), 15));
+ *Xptr-- = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x1), ms, x2), 15));
+ }
+ norm_scaleup(X, len, NORM_SHIFT-14);
+}
+#endif /* OVERRIDE_vq_exp_rotation1 */
+
+void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
+{
+ static const int SPREAD_FACTOR[3]={15,10,5};
+ int i;
+ opus_val16 c, s;
+ opus_val16 gain, theta;
+ int stride2=0;
+ int factor;
+
+ if (2*K>=len || spread==SPREAD_NONE)
+ return;
+ factor = SPREAD_FACTOR[spread-1];
+
+ gain = celt_div((opus_val32)MULT16_16(Q15_ONE,len),(opus_val32)(len+factor*K));
+ theta = HALF16(MULT16_16_Q15(gain,gain));
+
+ c = celt_cos_norm(EXTEND32(theta));
+ s = celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /* sin(theta) */
+
+ if (len>=8*stride)
+ {
+ stride2 = 1;
+ /* This is just a simple (equivalent) way of computing sqrt(len/stride) with rounding.
+ It's basically incrementing long as (stride2+0.5)^2 < len/stride. */
+ while ((stride2*stride2+stride2)*stride + (stride>>2) < len)
+ stride2++;
+ }
+ /*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for
+ extract_collapse_mask().*/
+ len = celt_udiv(len, stride);
+ for (i=0;i<stride;i++)
+ {
+ if (dir < 0)
+ {
+ if (stride2)
+ exp_rotation1(X+i*len, len, stride2, s, c);
+ exp_rotation1(X+i*len, len, 1, c, s);
+ } else {
+ exp_rotation1(X+i*len, len, 1, c, -s);
+ if (stride2)
+ exp_rotation1(X+i*len, len, stride2, s, -c);
+ }
+ }
+}
+
+/** Normalizes the decoded integer pvq codeword to unit norm. */
+static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X,
+ int N, opus_val32 Ryy, opus_val32 gain, int shift)
+{
+ int i;
+#ifdef FIXED_POINT
+ int k;
+#endif
+ opus_val32 t;
+ opus_val32 g;
+
+#ifdef FIXED_POINT
+ k = celt_ilog2(Ryy)>>1;
+#endif
+ t = VSHR32(Ryy, 2*(k-7)-15);
+ g = MULT32_32_Q31(celt_rsqrt_norm32(t),gain);
+ i=0;
+ (void)shift;
+#if defined(FIXED_POINT) && defined(ENABLE_QEXT)
+ if (shift>0) {
+ int tot_shift = NORM_SHIFT+1-k-shift;
+ if (tot_shift >= 0) {
+ do X[i] = MULT32_32_Q31(g, SHL32(iy[i], tot_shift));
+ while (++i < N);
+ } else {
+ do X[i] = MULT32_32_Q31(g, PSHR32(iy[i], -tot_shift));
+ while (++i < N);
+ }
+ } else
+#endif
+ do X[i] = VSHR32(MULT16_32_Q15(iy[i], g), k+15-NORM_SHIFT);
+ while (++i < N);
+}
+
+static unsigned extract_collapse_mask(int *iy, int N, int B)
+{
+ unsigned collapse_mask;
+ int N0;
+ int i;
+ if (B<=1)
+ return 1;
+ /*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for
+ exp_rotation().*/
+ N0 = celt_udiv(N, B);
+ collapse_mask = 0;
+ i=0; do {
+ int j;
+ unsigned tmp=0;
+ j=0; do {
+ tmp |= iy[i*N0+j];
+ } while (++j<N0);
+ collapse_mask |= (tmp!=0)<<i;
+ } while (++i<B);
+ return collapse_mask;
+}
+
+opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
+{
+ VARDECL(celt_norm, y);
+ VARDECL(int, signx);
+ int i, j;
+ int pulsesLeft;
+ opus_val32 sum;
+ opus_val32 xy;
+ opus_val16 yy;
+ SAVE_STACK;
+
+ (void)arch;
+ ALLOC(y, N, celt_norm);
+ ALLOC(signx, N, int);
+#ifdef FIXED_POINT
+ {
+ int shift = (celt_ilog2(1+celt_inner_prod_norm_shift(X, X, N, arch))+1)/2;
+ shift = IMAX(0, shift+(NORM_SHIFT-14)-14);
+ norm_scaledown(X, N, shift);
+ }
+#endif
+ /* Get rid of the sign */
+ sum = 0;
+ j=0; do {
+ signx[j] = X[j]<0;
+ /* OPT: Make sure the compiler doesn't use a branch on ABS16(). */
+ X[j] = ABS16(X[j]);
+ iy[j] = 0;
+ y[j] = 0;
+ } while (++j<N);
+
+ xy = yy = 0;
+
+ pulsesLeft = K;
+
+ /* Do a pre-search by projecting on the pyramid */
+ if (K > (N>>1))
+ {
+ opus_val16 rcp;
+ j=0; do {
+ sum += X[j];
+ } while (++j<N);
+
+ /* If X is too small, just replace it with a pulse at 0 */
+#ifdef FIXED_POINT
+ if (sum <= K)
+#else
+ /* Prevents infinities and NaNs from causing too many pulses
+ to be allocated. 64 is an approximation of infinity here. */
+ if (!(sum > EPSILON && sum < 64))
+#endif
+ {
+ X[0] = QCONST16(1.f,14);
+ j=1; do
+ X[j]=0;
+ while (++j<N);
+ sum = QCONST16(1.f,14);
+ }
+#ifdef FIXED_POINT
+ rcp = EXTRACT16(MULT16_32_Q16(K, celt_rcp(sum)));
+#else
+ /* Using K+e with e < 1 guarantees we cannot get more than K pulses. */
+ rcp = EXTRACT16(MULT16_32_Q16(K+0.8f, celt_rcp(sum)));
+#endif
+ j=0; do {
+#ifdef FIXED_POINT
+ /* It's really important to round *towards zero* here */
+ iy[j] = MULT16_16_Q15(X[j],rcp);
+#else
+ iy[j] = (int)floor(rcp*X[j]);
+#endif
+ y[j] = (celt_norm)iy[j];
+ yy = MAC16_16(yy, y[j],y[j]);
+ xy = MAC16_16(xy, X[j],y[j]);
+ y[j] *= 2;
+ pulsesLeft -= iy[j];
+ } while (++j<N);
+ }
+ celt_sig_assert(pulsesLeft>=0);
+
+ /* This should never happen, but just in case it does (e.g. on silence)
+ we fill the first bin with pulses. */
+#ifdef FIXED_POINT_DEBUG
+ celt_sig_assert(pulsesLeft<=N+3);
+#endif
+ if (pulsesLeft > N+3)
+ {
+ opus_val16 tmp = (opus_val16)pulsesLeft;
+ yy = MAC16_16(yy, tmp, tmp);
+ yy = MAC16_16(yy, tmp, y[0]);
+ iy[0] += pulsesLeft;
+ pulsesLeft=0;
+ }
+
+ for (i=0;i<pulsesLeft;i++)
+ {
+ opus_val16 Rxy, Ryy;
+ int best_id;
+ opus_val32 best_num;
+ opus_val16 best_den;
+#ifdef FIXED_POINT
+ int rshift;
+#endif
+#ifdef FIXED_POINT
+ rshift = 1+celt_ilog2(K-pulsesLeft+i+1);
+#endif
+ best_id = 0;
+ /* The squared magnitude term gets added anyway, so we might as well
+ add it outside the loop */
+ yy = ADD16(yy, 1);
+
+ /* Calculations for position 0 are out of the loop, in part to reduce
+ mispredicted branches (since the if condition is usually false)
+ in the loop. */
+ /* Temporary sums of the new pulse(s) */
+ Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[0])),rshift));
+ /* We're multiplying y[j] by two so we don't have to do it here */
+ Ryy = ADD16(yy, y[0]);
+
+ /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
+ Rxy is positive because the sign is pre-computed) */
+ Rxy = MULT16_16_Q15(Rxy,Rxy);
+ best_den = Ryy;
+ best_num = Rxy;
+ j=1;
+ do {
+ /* Temporary sums of the new pulse(s) */
+ Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[j])),rshift));
+ /* We're multiplying y[j] by two so we don't have to do it here */
+ Ryy = ADD16(yy, y[j]);
+
+ /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
+ Rxy is positive because the sign is pre-computed) */
+ Rxy = MULT16_16_Q15(Rxy,Rxy);
+ /* The idea is to check for num/den >= best_num/best_den, but that way
+ we can do it without any division */
+ /* OPT: It's not clear whether a cmov is faster than a branch here
+ since the condition is more often false than true and using
+ a cmov introduces data dependencies across iterations. The optimal
+ choice may be architecture-dependent. */
+ if (opus_unlikely(MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num)))
+ {
+ best_den = Ryy;
+ best_num = Rxy;
+ best_id = j;
+ }
+ } while (++j<N);
+
+ /* Updating the sums of the new pulse(s) */
+ xy = ADD32(xy, EXTEND32(X[best_id]));
+ /* We're multiplying y[j] by two so we don't have to do it here */
+ yy = ADD16(yy, y[best_id]);
+
+ /* Only now that we've made the final choice, update y/iy */
+ /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
+ y[best_id] += 2;
+ iy[best_id]++;
+ }
+
+ /* Put the original sign back */
+ j=0;
+ do {
+ /*iy[j] = signx[j] ? -iy[j] : iy[j];*/
+ /* OPT: The is more likely to be compiled without a branch than the code above
+ but has the same performance otherwise. */
+ iy[j] = (iy[j]^-signx[j]) + signx[j];
+ } while (++j<N);
+ RESTORE_STACK;
+ return yy;
+}
+
+#ifdef ENABLE_QEXT
+#include "macros.h"
+
+static opus_val32 op_pvq_search_N2(const celt_norm *X, int *iy, int *up_iy, int K, int up, int *refine, int shift) {
+ opus_val32 sum;
+ opus_val32 rcp_sum;
+ int offset;
+ sum = ABS32(X[0]) + ABS32(X[1]);
+ if (sum < EPSILON) {
+ iy[0] = K;
+ up_iy[0] = up*K;
+ iy[1]=up_iy[1]=0;
+ *refine=0;
+#ifdef FIXED_POINT
+ return (opus_val64)K*K*up*up>>2*shift;
+#else
+ (void)shift;
+ return K*(float)K*up*up;
+#endif
+ }
+#ifdef FIXED_POINT
+ int sum_shift;
+ opus_val32 X0;
+ sum_shift = 30-celt_ilog2(sum);
+ rcp_sum = celt_rcp_norm32(SHL32(sum, sum_shift));
+ X0 = MULT32_32_Q31(SHL32(X[0], sum_shift), rcp_sum);
+ iy[0] = PSHR32(MULT32_32_Q31(SHL32(K, 8), X0), 7);
+ up_iy[0] = PSHR32(MULT32_32_Q31(SHL32(up*K, 8), X0), 7);
+#else
+ rcp_sum = 1.f/sum;
+ iy[0] = (int)floor(.5f+K*X[0]*rcp_sum);
+ up_iy[0] = (int)floor(.5f+up*K*X[0]*rcp_sum);
+#endif
+ up_iy[0] = IMAX(up*iy[0] - (up-1)/2, IMIN(up*iy[0] + (up-1)/2, up_iy[0]));
+ offset = up_iy[0] - up*iy[0];
+ iy[1] = K-abs(iy[0]);
+ up_iy[1] = up*K-abs(up_iy[0]);
+ if (X[1] < 0) {
+ iy[1] = -iy[1];
+ up_iy[1] = -up_iy[1];
+ offset = -offset;
+ }
+ *refine = offset;
+#ifdef FIXED_POINT
+ return (up_iy[0]*(opus_val64)up_iy[0] + up_iy[1]*(opus_val64)up_iy[1] + (1<<2*shift>>1))>>2*shift;
+#else
+ return up_iy[0]*(opus_val64)up_iy[0] + up_iy[1]*(opus_val64)up_iy[1];
+#endif
+}
+
+static int op_pvq_refine(const opus_val32 *Xn, int *iy, int *iy0, int K, int up, int margin, int N) {
+ int i;
+ int dir;
+ VARDECL(opus_val32, rounding);
+ int iysum = 0;
+ SAVE_STACK;
+ ALLOC(rounding, N, opus_val32);
+ for (i=0;i<N;i++) {
+ opus_val32 tmp;
+ tmp = MULT32_32_Q31(SHL32(K, 8), Xn[i]);
+#ifdef FIXED_POINT
+ iy[i] = (tmp+64) >> 7;
+#else
+ iy[i] = (int)floor(.5+tmp);
+#endif
+ rounding[i] = tmp - SHL32(iy[i], 7);
+ }
+ if (iy != iy0) {
+ for (i=0;i<N;i++) iy[i] = IMIN(up*iy0[i]+up-1, IMAX(up*iy0[i]-up+1, iy[i]));
+ }
+ for (i=0;i<N;i++) iysum += iy[i];
+ if (abs(iysum - K) > 32) {
+ RESTORE_STACK;
+ return 1;
+ }
+ dir = iysum < K ? 1 : -1;
+ while (iysum != K) {
+ opus_val32 roundval=-1000000*dir;
+ int roundpos=0;
+ for (i=0;i<N;i++) {
+ if ((rounding[i]-roundval)*dir > 0 && abs(iy[i]-up*iy0[i]) < (margin-1) && !(dir==-1 && iy[i] == 0)) {
+ roundval = rounding[i];
+ roundpos = i;
+ }
+ }
+ iy[roundpos] += dir;
+ rounding[roundpos] -= SHL32(dir, 15);
+ iysum+=dir;
+ }
+ RESTORE_STACK;
+ return 0;
+}
+
+static opus_val32 op_pvq_search_extra(const celt_norm *X, int *iy, int *up_iy, int K, int up, int *refine, int N, int shift) {
+ opus_val32 rcp_sum;
+ opus_val32 sum=0;
+ int i;
+ int failed=0;
+ opus_val64 yy=0;
+ VARDECL(opus_val32, Xn);
+ SAVE_STACK;
+ for (i=0;i<N;i++) sum += ABS32(X[i]);
+ ALLOC(Xn, N, opus_val32);
+ if (sum < EPSILON)
+ failed = 1;
+ else {
+#ifdef FIXED_POINT
+ int sum_shift = 30-celt_ilog2(sum);
+ rcp_sum = celt_rcp_norm32(SHL32(sum, sum_shift));
+ for (i=0;i<N;i++) {
+ Xn[i] = MULT32_32_Q31(SHL32(ABS32(X[i]), sum_shift), rcp_sum);
+ }
+#else
+ rcp_sum = celt_rcp(sum);
+ for (i=0;i<N;i++) {
+ Xn[i] = ABS32(X[i])*rcp_sum;
+ }
+#endif
+ }
+ failed = failed || op_pvq_refine(Xn, iy, iy, K, 1, K+1, N);
+ failed = failed || op_pvq_refine(Xn, up_iy, iy, up*K, up, up, N);
+ if (failed) {
+ iy[0] = K;
+ for (i=1;i<N;i++) iy[i] = 0;
+ up_iy[0] = up*K;
+ for (i=1;i<N;i++) up_iy[i] = 0;
+ }
+ for (i=0;i<N;i++) {
+ yy += up_iy[i]*(opus_val64)up_iy[i];
+ if (X[i] < 0) {
+ iy[i] = -iy[i];
+ up_iy[i] = -up_iy[i];
+ }
+ refine[i] = up_iy[i]-up*iy[i];
+ }
+ RESTORE_STACK;
+#ifdef FIXED_POINT
+ return (yy + (1<<2*shift>>1))>>2*shift;
+#else
+ (void)shift;
+ return yy;
+#endif
+}
+#endif
+
+#ifdef ENABLE_QEXT
+/* Take advantage of the fact that "large" refine values are much less likely
+ than smaller ones. */
+static void ec_enc_refine(ec_enc *enc, opus_int32 refine, opus_int32 up, int extra_bits, int use_entropy) {
+ int large;
+ large = abs(refine)>up/2;
+ ec_enc_bit_logp(enc, large, use_entropy ? 3 : 1);
+ if (large) {
+ ec_enc_bits(enc, refine < 0, 1);
+ ec_enc_bits(enc, abs(refine)-up/2-1, extra_bits-1);
+ } else {
+ ec_enc_bits(enc, refine+up/2, extra_bits);
+ }
+}
+
+static int ec_dec_refine(ec_enc *dec, opus_int32 up, int extra_bits, int use_entropy) {
+ int large, refine;
+ large = ec_dec_bit_logp(dec, use_entropy ? 3 : 1);
+ if (large) {
+ int sign = ec_dec_bits(dec, 1);
+ refine = ec_dec_bits(dec, extra_bits-1) + up/2+1;
+ if (sign) refine = -refine;
+ } else {
+ refine = (opus_int32)ec_dec_bits(dec, extra_bits)-up/2;
+ }
+ return refine;
+}
+#endif
+
+unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
+ opus_val32 gain, int resynth
+ ARG_QEXT(ec_enc *ext_enc) ARG_QEXT(int extra_bits), int arch)
+{
+ VARDECL(int, iy);
+ opus_val32 yy;
+ unsigned collapse_mask;
+#ifdef ENABLE_QEXT
+ int yy_shift = 0;
+#endif
+ SAVE_STACK;
+
+ celt_assert2(K>0, "alg_quant() needs at least one pulse");
+ celt_assert2(N>1, "alg_quant() needs at least two dimensions");
+
+ /* Covers vectorization by up to 4. */
+ ALLOC(iy, N+3, int);
+
+ exp_rotation(X, N, 1, B, K, spread);
+
+#ifdef ENABLE_QEXT
+ if (N==2 && extra_bits >= 2) {
+ int refine;
+ int up_iy[2];
+ int up;
+ yy_shift = IMAX(0, extra_bits-7);
+ up = (1<<extra_bits)-1;
+ yy = op_pvq_search_N2(X, iy, up_iy, K, up, &refine, yy_shift);
+ collapse_mask = extract_collapse_mask(up_iy, N, B);
+ encode_pulses(iy, N, K, enc);
+ ec_enc_uint(ext_enc, refine+(up-1)/2, up);
+ if (resynth)
+ normalise_residual(up_iy, X, N, yy, gain, yy_shift);
+ } else if (extra_bits >= 2) {
+ int i;
+ VARDECL(int, up_iy);
+ VARDECL(int, refine);
+ int up, use_entropy;
+ ALLOC(up_iy, N, int);
+ ALLOC(refine, N, int);
+ yy_shift = IMAX(0, extra_bits-7);
+ up = (1<<extra_bits)-1;
+ yy = op_pvq_search_extra(X, iy, up_iy, K, up, refine, N, yy_shift);
+ collapse_mask = extract_collapse_mask(up_iy, N, B);
+ encode_pulses(iy, N, K, enc);
+ use_entropy = (ext_enc->storage*8 - ec_tell(ext_enc)) > (unsigned)(N-1)*(extra_bits+3)+1;
+ for (i=0;i<N-1;i++) ec_enc_refine(ext_enc, refine[i], up, extra_bits, use_entropy);
+ if (iy[N-1]==0) ec_enc_bits(ext_enc, up_iy[N-1]<0, 1);
+ if (resynth)
+ normalise_residual(up_iy, X, N, yy, gain, yy_shift);
+ } else
+#endif
+ {
+ yy = op_pvq_search(X, iy, K, N, arch);
+ collapse_mask = extract_collapse_mask(iy, N, B);
+ encode_pulses(iy, N, K, enc);
+ if (resynth)
+ normalise_residual(iy, X, N, yy, gain, 0);
+ }
+
+ if (resynth)
+ exp_rotation(X, N, -1, B, K, spread);
+
+ RESTORE_STACK;
+ return collapse_mask;
+}
+
+/** Decode pulse vector and combine the result with the pitch vector to produce
+ the final normalised signal in the current band. */
+unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
+ ec_dec *dec, opus_val32 gain
+ ARG_QEXT(ec_enc *ext_dec) ARG_QEXT(int extra_bits))
+{
+ opus_val32 Ryy;
+ unsigned collapse_mask;
+ VARDECL(int, iy);
+ int yy_shift=0;
+ SAVE_STACK;
+
+ celt_assert2(K>0, "alg_unquant() needs at least one pulse");
+ celt_assert2(N>1, "alg_unquant() needs at least two dimensions");
+ ALLOC(iy, N, int);
+ Ryy = decode_pulses(iy, N, K, dec);
+#ifdef ENABLE_QEXT
+ if (N==2 && extra_bits >= 2) {
+ int up;
+ int refine;
+ yy_shift = IMAX(0, extra_bits-7);
+ up = (1<<extra_bits)-1;
+ refine = (opus_int32)ec_dec_uint(ext_dec, up) - (up-1)/2;
+ iy[0] *= up;
+ iy[1] *= up;
+ if (iy[1] == 0) {
+ iy[1] = (iy[0] > 0) ? -refine : refine;
+ iy[0] += (refine*(opus_int64)iy[0] > 0) ? -refine : refine;
+ } else if (iy[1] > 0) {
+ iy[0] += refine;
+ iy[1] -= refine*(iy[0]>0?1:-1);
+ } else {
+ iy[0] -= refine;
+ iy[1] -= refine*(iy[0]>0?1:-1);
+ }
+#ifdef FIXED_POINT
+ Ryy = (iy[0]*(opus_val64)iy[0] + iy[1]*(opus_val64)iy[1] + (1<<2*yy_shift>>1)) >> 2*yy_shift;
+#else
+ Ryy = iy[0]*(opus_val64)iy[0] + iy[1]*(opus_val64)iy[1];
+#endif
+ } else if (extra_bits >= 2) {
+ int i;
+ opus_val64 yy64;
+ VARDECL(int, refine);
+ int up, use_entropy;
+ int sign=0;
+ ALLOC(refine, N, int);
+ yy_shift = IMAX(0, extra_bits-7);
+ up = (1<<extra_bits)-1;
+ use_entropy = (ext_dec->storage*8 - ec_tell(ext_dec)) > (unsigned)(N-1)*(extra_bits+3)+1;
+ for (i=0;i<N-1;i++) refine[i] = ec_dec_refine(ext_dec, up, extra_bits, use_entropy);
+ if (iy[N-1]==0) sign = ec_dec_bits(ext_dec, 1);
+ else sign = iy[N-1] < 0;
+ for (i=0;i<N-1;i++) {
+ iy[i] = iy[i]*up + refine[i];
+ }
+ iy[N-1] = up*K;
+ for (i=0;i<N-1;i++) iy[N-1] -= abs(iy[i]);
+ if (sign) iy[N-1] = -iy[N-1];
+ yy64 = 0;
+ for (i=0;i<N;i++) yy64 += iy[i]*(opus_val64)iy[i];
+#ifdef FIXED_POINT
+ Ryy = (yy64 + (1<<2*yy_shift>>1)) >> 2*yy_shift;
+#else
+ Ryy = yy64;
+#endif
+ }
+#endif
+ normalise_residual(iy, X, N, Ryy, gain, yy_shift);
+ exp_rotation(X, N, -1, B, K, spread);
+ collapse_mask = extract_collapse_mask(iy, N, B);
+ RESTORE_STACK;
+ return collapse_mask;
+}
+
+#ifndef OVERRIDE_renormalise_vector
+void renormalise_vector(celt_norm *X, int N, opus_val32 gain, int arch)
+{
+ int i;
+#ifdef FIXED_POINT
+ int k;
+#endif
+ opus_val32 E;
+ opus_val16 g;
+ opus_val32 t;
+ celt_norm *xptr;
+ norm_scaledown(X, N, NORM_SHIFT-14);
+ E = EPSILON + celt_inner_prod_norm(X, X, N, arch);
+#ifdef FIXED_POINT
+ k = celt_ilog2(E)>>1;
+#endif
+ t = VSHR32(E, 2*(k-7));
+ g = MULT32_32_Q31(celt_rsqrt_norm(t),gain);
+
+ xptr = X;
+ for (i=0;i<N;i++)
+ {
+ *xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+15-14));
+ xptr++;
+ }
+ norm_scaleup(X, N, NORM_SHIFT-14);
+ /*return celt_sqrt(E);*/
+}
+#endif /* OVERRIDE_renormalise_vector */
+
+opus_int32 stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch)
+{
+ int i;
+ int itheta;
+ opus_val32 mid, side;
+ opus_val32 Emid, Eside;
+
+ Emid = Eside = 0;
+ if (stereo)
+ {
+ for (i=0;i<N;i++)
+ {
+ celt_norm m, s;
+ m = PSHR32(ADD32(X[i], Y[i]), NORM_SHIFT-13);
+ s = PSHR32(SUB32(X[i], Y[i]), NORM_SHIFT-13);
+ Emid = MAC16_16(Emid, m, m);
+ Eside = MAC16_16(Eside, s, s);
+ }
+ } else {
+ Emid += celt_inner_prod_norm_shift(X, X, N, arch);
+ Eside += celt_inner_prod_norm_shift(Y, Y, N, arch);
+ }
+ mid = celt_sqrt32(Emid);
+ side = celt_sqrt32(Eside);
+#if defined(FIXED_POINT)
+ itheta = celt_atan2p_norm(side, mid);
+#else
+ itheta = (int)floor(.5f+65536.f*16384*celt_atan2p_norm(side,mid));
+#endif
+
+ return itheta;
+}
+
+#ifdef ENABLE_QEXT
+
+static void cubic_synthesis(celt_norm *X, int *iy, int N, int K, int face, int sign, opus_val32 gain) {
+ int i;
+ opus_val32 sum=0;
+ opus_val32 mag;
+#ifdef FIXED_POINT
+ int sum_shift;
+ int shift = IMAX(celt_ilog2(K) + celt_ilog2(N)/2 - 13, 0);
+#endif
+ for (i=0;i<N;i++) {
+ X[i] = (1+2*iy[i])-K;
+ }
+ X[face] = sign ? -K : K;
+ for (i=0;i<N;i++) {
+ sum += PSHR32(MULT16_16(X[i],X[i]), 2*shift);
+ }
+#ifdef FIXED_POINT
+ sum_shift = (29-celt_ilog2(sum))>>1;
+ mag = celt_rsqrt_norm32(SHL32(sum, 2*sum_shift+1));
+ for (i=0;i<N;i++) {
+ X[i] = VSHR32(MULT16_32_Q15(X[i],MULT32_32_Q31(mag,gain)), shift-sum_shift+29-NORM_SHIFT);
+ }
+#else
+ mag = 1.f/sqrt(sum);
+ for (i=0;i<N;i++) {
+ X[i] *= mag*gain;
+ }
+#endif
+}
+
+unsigned cubic_quant(celt_norm *X, int N, int res, int B, ec_enc *enc, opus_val32 gain, int resynth) {
+ int i;
+ int face=0;
+ int K;
+ VARDECL(int, iy);
+ celt_norm faceval=-1;
+ opus_val32 norm;
+ int sign;
+ SAVE_STACK;
+ ALLOC(iy, N, int);
+ K = 1<<res;
+ /* Using odd K on transients to avoid adding pre-echo. */
+ if (B!=1) K=IMAX(1, K-1);
+ if (K==1) {
+ if (resynth) OPUS_CLEAR(X, N);
+ RESTORE_STACK;
+ return 0;
+ }
+ for (i=0;i<N;i++) {
+ if (ABS32(X[i]) > faceval) {
+ faceval = ABS32(X[i]);
+ face = i;
+ }
+ }
+ sign = X[face]<0;
+ ec_enc_uint(enc, face, N);
+ ec_enc_bits(enc, sign, 1);
+#ifdef FIXED_POINT
+ if (faceval != 0) {
+ int face_shift = 30-celt_ilog2(faceval);
+ norm = celt_rcp_norm32(SHL32(faceval, face_shift));
+ norm = MULT16_32_Q15(K, norm);
+ for (i=0;i<N;i++) {
+ /* By computing X[i]+faceval inside the shift, the result is guaranteed non-negative. */
+ iy[i] = IMIN(K-1, (MULT32_32_Q31(SHL32(X[i]+faceval, face_shift-1), norm)) >> 15);
+ }
+ } else {
+ OPUS_CLEAR(iy, N);
+ }
+#else
+ norm = .5f*K/(faceval+EPSILON);
+ for (i=0;i<N;i++) {
+ iy[i] = IMIN(K-1, (int)floor((X[i]+faceval)*norm));
+ }
+#endif
+ for (i=0;i<N;i++) {
+ if (i != face) ec_enc_bits(enc, iy[i], res);
+ }
+ if (resynth) {
+ cubic_synthesis(X, iy, N, K, face, sign, gain);
+ }
+ RESTORE_STACK;
+ return (1<<B)-1;
+}
+
+unsigned cubic_unquant(celt_norm *X, int N, int res, int B, ec_dec *dec, opus_val32 gain) {
+ int i;
+ int face;
+ int sign;
+ int K;
+ VARDECL(int, iy);
+ SAVE_STACK;
+ ALLOC(iy, N, int);
+ K = 1<<res;
+ /* Using odd K on transients to avoid adding pre-echo. */
+ if (B!=1) K=IMAX(1, K-1);
+ if (K==1) {
+ OPUS_CLEAR(X, N);
+ RESTORE_STACK;
+ return 0;
+ }
+ face = ec_dec_uint(dec, N);
+ sign = ec_dec_bits(dec, 1);
+ for (i=0;i<N;i++) {
+ if (i != face) iy[i] = ec_dec_bits(dec, res);
+ }
+ iy[face]=0;
+ cubic_synthesis(X, iy, N, K, face, sign, gain);
+ RESTORE_STACK;
+ return (1<<B)-1;
+}
+#endif
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/**
+ @file vq.h
+ @brief Vector quantisation of the residual
+ */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 VQ_H
+#define VQ_H
+
+#include "entenc.h"
+#include "entdec.h"
+#include "modes.h"
+
+#if (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT))
+#include "x86/vq_sse.h"
+#endif
+
+#if defined(FIXED_POINT)
+opus_val32 celt_inner_prod_norm(const celt_norm *x, const celt_norm *y, int len, int arch);
+opus_val32 celt_inner_prod_norm_shift(const celt_norm *x, const celt_norm *y, int len, int arch);
+
+void norm_scaleup(celt_norm *X, int N, int shift);
+void norm_scaledown(celt_norm *X, int N, int shift);
+
+#else
+#define celt_inner_prod_norm celt_inner_prod
+#define celt_inner_prod_norm_shift celt_inner_prod
+#define norm_scaleup(X, N, shift)
+#define norm_scaledown(X, N, shift)
+#endif
+
+void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread);
+
+opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch);
+
+#if !defined(OVERRIDE_OP_PVQ_SEARCH)
+#define op_pvq_search(x, iy, K, N, arch) \
+ (op_pvq_search_c(x, iy, K, N, arch))
+#endif
+
+/** Algebraic pulse-vector quantiser. The signal x is replaced by the sum of
+ * the pitch and a combination of pulses such that its norm is still equal
+ * to 1. This is the function that will typically require the most CPU.
+ * @param X Residual signal to quantise/encode (returns quantised version)
+ * @param N Number of samples to encode
+ * @param K Number of pulses to use
+ * @param enc Entropy encoder state
+ * @ret A mask indicating which blocks in the band received pulses
+*/
+unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
+ opus_val32 gain, int resynth
+ ARG_QEXT(ec_enc *ext_enc) ARG_QEXT(int extra_bits), int arch);
+
+/** Algebraic pulse decoder
+ * @param X Decoded normalised spectrum (returned)
+ * @param N Number of samples to decode
+ * @param K Number of pulses to use
+ * @param dec Entropy decoder state
+ * @ret A mask indicating which blocks in the band received pulses
+ */
+unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
+ ec_dec *dec, opus_val32 gain
+ ARG_QEXT(ec_enc *ext_dec) ARG_QEXT(int extra_bits));
+
+void renormalise_vector(celt_norm *X, int N, opus_val32 gain, int arch);
+
+opus_int32 stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch);
+
+unsigned cubic_quant(celt_norm *X, int N, int K, int B, ec_enc *enc, opus_val32 gain, int resynth);
+unsigned cubic_unquant(celt_norm *X, int N, int K, int B, ec_dec *dec, opus_val32 gain);
+
+#endif /* VQ_H */
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 CELT_LPC_SSE_H
+#define CELT_LPC_SSE_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT)
+
+void celt_fir_sse4_1(
+ const opus_val16 *x,
+ const opus_val16 *num,
+ opus_val16 *y,
+ int N,
+ int ord,
+ int arch);
+
+#if defined(OPUS_X86_PRESUME_SSE4_1)
+#define OVERRIDE_CELT_FIR
+#define celt_fir(x, num, y, N, ord, arch) \
+ ((void)arch, celt_fir_sse4_1(x, num, y, N, ord, arch))
+
+#elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_val16 *x,
+ const opus_val16 *num,
+ opus_val16 *y,
+ int N,
+ int ord,
+ int arch);
+
+#define OVERRIDE_CELT_FIR
+# define celt_fir(x, num, y, N, ord, arch) \
+ ((*CELT_FIR_IMPL[(arch) & OPUS_ARCHMASK])(x, num, y, N, ord, arch))
+
+#endif
+#endif
+
+#endif
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+#include <smmintrin.h>
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "pitch.h"
+#include "x86cpu.h"
+
+#if defined(FIXED_POINT)
+
+void celt_fir_sse4_1(const opus_val16 *x,
+ const opus_val16 *num,
+ opus_val16 *y,
+ int N,
+ int ord,
+ int arch)
+{
+ int i,j;
+ VARDECL(opus_val16, rnum);
+
+ __m128i vecNoA;
+ opus_int32 noA ;
+ SAVE_STACK;
+
+ ALLOC(rnum, ord, opus_val16);
+ for(i=0;i<ord;i++)
+ rnum[i] = num[ord-i-1];
+ noA = EXTEND32(1) << SIG_SHIFT >> 1;
+ vecNoA = _mm_set_epi32(noA, noA, noA, noA);
+
+ for (i=0;i<N-3;i+=4)
+ {
+ opus_val32 sums[4] = {0};
+ __m128i vecSum, vecX;
+#if defined(OPUS_CHECK_ASM)
+ {
+ opus_val32 sums_c[4] = {0};
+ xcorr_kernel_c(rnum, x+i-ord, sums_c, ord);
+#endif
+ xcorr_kernel(rnum, x+i-ord, sums, ord, arch);
+#if defined(OPUS_CHECK_ASM)
+ celt_assert(memcmp(sums, sums_c, sizeof(sums)) == 0);
+ }
+#endif
+ vecSum = _mm_loadu_si128((__m128i *)(void*)sums);
+ vecSum = _mm_add_epi32(vecSum, vecNoA);
+ vecSum = _mm_srai_epi32(vecSum, SIG_SHIFT);
+ vecX = OP_CVTEPI16_EPI32_M64(x + i);
+ vecSum = _mm_add_epi32(vecSum, vecX);
+ vecSum = _mm_packs_epi32(vecSum, vecSum);
+ _mm_storel_epi64((__m128i *)(void *)(y + i), vecSum);
+ }
+ for (;i<N;i++)
+ {
+ opus_val32 sum = 0;
+ for (j=0;j<ord;j++)
+ sum = MAC16_16(sum, rnum[j], x[i+j-ord]);
+ y[i] = SATURATE16(ADD32(EXTEND32(x[i]), PSHR32(sum, SIG_SHIFT)));
+ }
+
+ RESTORE_STACK;
+}
+
+#endif
--- /dev/null
+/* Copyright (c) 2023 Amazon */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <immintrin.h>
+#include "x86cpu.h"
+#include "pitch.h"
+
+#if defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(FIXED_POINT)
+
+/* Like the "regular" xcorr_kernel(), but computes 8 results at a time. */
+static void xcorr_kernel_avx(const float *x, const float *y, float sum[8], int len)
+{
+ __m256 xsum0, xsum1, xsum2, xsum3, xsum4, xsum5, xsum6, xsum7;
+ xsum7 = xsum6 = xsum5 = xsum4 = xsum3 = xsum2 = xsum1 = xsum0 = _mm256_setzero_ps();
+ int i;
+ __m256 x0;
+ /* Compute 8 inner products using partial sums. */
+ for (i=0;i<len-7;i+=8)
+ {
+ x0 = _mm256_loadu_ps(x+i);
+ xsum0 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i ), xsum0);
+ xsum1 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+1), xsum1);
+ xsum2 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+2), xsum2);
+ xsum3 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+3), xsum3);
+ xsum4 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+4), xsum4);
+ xsum5 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+5), xsum5);
+ xsum6 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+6), xsum6);
+ xsum7 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+7), xsum7);
+ }
+ if (i != len) {
+ static const int mask[15] = {-1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0};
+ __m256i m;
+ m = _mm256_loadu_si256((__m256i*)(void*)(mask + 7+i-len));
+ x0 = _mm256_maskload_ps(x+i, m);
+ xsum0 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i , m), xsum0);
+ xsum1 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+1, m), xsum1);
+ xsum2 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+2, m), xsum2);
+ xsum3 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+3, m), xsum3);
+ xsum4 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+4, m), xsum4);
+ xsum5 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+5, m), xsum5);
+ xsum6 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+6, m), xsum6);
+ xsum7 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+7, m), xsum7);
+ }
+ /* 8 horizontal adds. */
+ /* Compute [0 4] [1 5] [2 6] [3 7] */
+ xsum0 = _mm256_add_ps(_mm256_permute2f128_ps(xsum0, xsum4, 2<<4), _mm256_permute2f128_ps(xsum0, xsum4, 1 | (3<<4)));
+ xsum1 = _mm256_add_ps(_mm256_permute2f128_ps(xsum1, xsum5, 2<<4), _mm256_permute2f128_ps(xsum1, xsum5, 1 | (3<<4)));
+ xsum2 = _mm256_add_ps(_mm256_permute2f128_ps(xsum2, xsum6, 2<<4), _mm256_permute2f128_ps(xsum2, xsum6, 1 | (3<<4)));
+ xsum3 = _mm256_add_ps(_mm256_permute2f128_ps(xsum3, xsum7, 2<<4), _mm256_permute2f128_ps(xsum3, xsum7, 1 | (3<<4)));
+ /* Compute [0 1 4 5] [2 3 6 7] */
+ xsum0 = _mm256_hadd_ps(xsum0, xsum1);
+ xsum1 = _mm256_hadd_ps(xsum2, xsum3);
+ /* Compute [0 1 2 3 4 5 6 7] */
+ xsum0 = _mm256_hadd_ps(xsum0, xsum1);
+ _mm256_storeu_ps(sum, xsum0);
+}
+
+void celt_pitch_xcorr_avx2(const float *_x, const float *_y, float *xcorr, int len, int max_pitch, int arch)
+{
+ int i;
+ celt_assert(max_pitch>0);
+ (void)arch;
+ for (i=0;i<max_pitch-7;i+=8)
+ {
+ xcorr_kernel_avx(_x, _y+i, &xcorr[i], len);
+ }
+ for (;i<max_pitch;i++)
+ {
+ xcorr[i] = celt_inner_prod(_x, _y+i, len, arch);
+ }
+}
+
+#endif
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "macros.h"
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "pitch.h"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)
+
+#include <xmmintrin.h>
+#include "arch.h"
+
+void xcorr_kernel_sse(const opus_val16 *x, const opus_val16 *y, opus_val32 sum[4], int len)
+{
+ int j;
+ __m128 xsum1, xsum2;
+ xsum1 = _mm_loadu_ps(sum);
+ xsum2 = _mm_setzero_ps();
+
+ for (j = 0; j < len-3; j += 4)
+ {
+ __m128 x0 = _mm_loadu_ps(x+j);
+ __m128 yj = _mm_loadu_ps(y+j);
+ __m128 y3 = _mm_loadu_ps(y+j+3);
+
+ xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0x00),yj));
+ xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0x55),
+ _mm_shuffle_ps(yj,y3,0x49)));
+ xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0xaa),
+ _mm_shuffle_ps(yj,y3,0x9e)));
+ xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0xff),y3));
+ }
+ if (j < len)
+ {
+ xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_load1_ps(x+j),_mm_loadu_ps(y+j)));
+ if (++j < len)
+ {
+ xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(_mm_load1_ps(x+j),_mm_loadu_ps(y+j)));
+ if (++j < len)
+ {
+ xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_load1_ps(x+j),_mm_loadu_ps(y+j)));
+ }
+ }
+ }
+ _mm_storeu_ps(sum,_mm_add_ps(xsum1,xsum2));
+}
+
+
+void dual_inner_prod_sse(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
+ int N, opus_val32 *xy1, opus_val32 *xy2)
+{
+ int i;
+ __m128 xsum1, xsum2;
+ xsum1 = _mm_setzero_ps();
+ xsum2 = _mm_setzero_ps();
+ for (i=0;i<N-3;i+=4)
+ {
+ __m128 xi = _mm_loadu_ps(x+i);
+ __m128 y1i = _mm_loadu_ps(y01+i);
+ __m128 y2i = _mm_loadu_ps(y02+i);
+ xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(xi, y1i));
+ xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(xi, y2i));
+ }
+ /* Horizontal sum */
+ xsum1 = _mm_add_ps(xsum1, _mm_movehl_ps(xsum1, xsum1));
+ xsum1 = _mm_add_ss(xsum1, _mm_shuffle_ps(xsum1, xsum1, 0x55));
+ _mm_store_ss(xy1, xsum1);
+ xsum2 = _mm_add_ps(xsum2, _mm_movehl_ps(xsum2, xsum2));
+ xsum2 = _mm_add_ss(xsum2, _mm_shuffle_ps(xsum2, xsum2, 0x55));
+ _mm_store_ss(xy2, xsum2);
+ for (;i<N;i++)
+ {
+ *xy1 = MAC16_16(*xy1, x[i], y01[i]);
+ *xy2 = MAC16_16(*xy2, x[i], y02[i]);
+ }
+}
+
+opus_val32 celt_inner_prod_sse(const opus_val16 *x, const opus_val16 *y,
+ int N)
+{
+ int i;
+ float xy;
+ __m128 sum;
+ sum = _mm_setzero_ps();
+ /* FIXME: We should probably go 8-way and use 2 sums. */
+ for (i=0;i<N-3;i+=4)
+ {
+ __m128 xi = _mm_loadu_ps(x+i);
+ __m128 yi = _mm_loadu_ps(y+i);
+ sum = _mm_add_ps(sum,_mm_mul_ps(xi, yi));
+ }
+ /* Horizontal sum */
+ sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum));
+ sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55));
+ _mm_store_ss(&xy, sum);
+ for (;i<N;i++)
+ {
+ xy = MAC16_16(xy, x[i], y[i]);
+ }
+ return xy;
+}
+
+void comb_filter_const_sse(opus_val32 *y, opus_val32 *x, int T, int N,
+ opus_val16 g10, opus_val16 g11, opus_val16 g12)
+{
+ int i;
+ __m128 x0v;
+ __m128 g10v, g11v, g12v;
+ g10v = _mm_load1_ps(&g10);
+ g11v = _mm_load1_ps(&g11);
+ g12v = _mm_load1_ps(&g12);
+ x0v = _mm_loadu_ps(&x[-T-2]);
+ for (i=0;i<N-3;i+=4)
+ {
+ __m128 yi, yi2, x1v, x2v, x3v, x4v;
+ const opus_val32 *xp = &x[i-T-2];
+ yi = _mm_loadu_ps(x+i);
+ x4v = _mm_loadu_ps(xp+4);
+#if 0
+ /* Slower version with all loads */
+ x1v = _mm_loadu_ps(xp+1);
+ x2v = _mm_loadu_ps(xp+2);
+ x3v = _mm_loadu_ps(xp+3);
+#else
+ x2v = _mm_shuffle_ps(x0v, x4v, 0x4e);
+ x1v = _mm_shuffle_ps(x0v, x2v, 0x99);
+ x3v = _mm_shuffle_ps(x2v, x4v, 0x99);
+#endif
+
+ yi = _mm_add_ps(yi, _mm_mul_ps(g10v,x2v));
+#if 0 /* Set to 1 to make it bit-exact with the non-SSE version */
+ yi = _mm_add_ps(yi, _mm_mul_ps(g11v,_mm_add_ps(x3v,x1v)));
+ yi = _mm_add_ps(yi, _mm_mul_ps(g12v,_mm_add_ps(x4v,x0v)));
+#else
+ /* Use partial sums */
+ yi2 = _mm_add_ps(_mm_mul_ps(g11v,_mm_add_ps(x3v,x1v)),
+ _mm_mul_ps(g12v,_mm_add_ps(x4v,x0v)));
+ yi = _mm_add_ps(yi, yi2);
+#endif
+ x0v=x4v;
+ _mm_storeu_ps(y+i, yi);
+ }
+#ifdef CUSTOM_MODES
+ for (;i<N;i++)
+ {
+ y[i] = x[i]
+ + MULT16_32_Q15(g10,x[i-T])
+ + MULT16_32_Q15(g11,ADD32(x[i-T+1],x[i-T-1]))
+ + MULT16_32_Q15(g12,ADD32(x[i-T+2],x[i-T-2]));
+ }
+#endif
+}
+
+
+#endif
--- /dev/null
+/* Copyright (c) 2013 Jean-Marc Valin and John Ridges
+ Copyright (c) 2014, Cisco Systems, INC MingXiang WeiZhou MinPeng YanWang*/
+/**
+ @file pitch_sse.h
+ @brief Pitch analysis
+ */
+
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 PITCH_SSE_H
+#define PITCH_SSE_H
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT)
+void xcorr_kernel_sse4_1(
+ const opus_int16 *x,
+ const opus_int16 *y,
+ opus_val32 sum[4],
+ int len);
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)
+void xcorr_kernel_sse(
+ const opus_val16 *x,
+ const opus_val16 *y,
+ opus_val32 sum[4],
+ int len);
+#endif
+
+#if defined(OPUS_X86_PRESUME_SSE4_1) && defined(FIXED_POINT)
+#define OVERRIDE_XCORR_KERNEL
+#define xcorr_kernel(x, y, sum, len, arch) \
+ ((void)arch, xcorr_kernel_sse4_1(x, y, sum, len))
+
+#elif defined(OPUS_X86_PRESUME_SSE) && !defined(FIXED_POINT)
+#define OVERRIDE_XCORR_KERNEL
+#define xcorr_kernel(x, y, sum, len, arch) \
+ ((void)arch, xcorr_kernel_sse(x, y, sum, len))
+
+#elif defined(OPUS_HAVE_RTCD) && ((defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT)) || (defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)))
+
+extern void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_val16 *x,
+ const opus_val16 *y,
+ opus_val32 sum[4],
+ int len);
+
+#define OVERRIDE_XCORR_KERNEL
+#define xcorr_kernel(x, y, sum, len, arch) \
+ ((*XCORR_KERNEL_IMPL[(arch) & OPUS_ARCHMASK])(x, y, sum, len))
+
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT)
+opus_val32 celt_inner_prod_sse4_1(
+ const opus_int16 *x,
+ const opus_int16 *y,
+ int N);
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE2) && defined(FIXED_POINT)
+opus_val32 celt_inner_prod_sse2(
+ const opus_int16 *x,
+ const opus_int16 *y,
+ int N);
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)
+opus_val32 celt_inner_prod_sse(
+ const opus_val16 *x,
+ const opus_val16 *y,
+ int N);
+#endif
+
+
+#if defined(OPUS_X86_PRESUME_SSE4_1) && defined(FIXED_POINT)
+#define OVERRIDE_CELT_INNER_PROD
+#define celt_inner_prod(x, y, N, arch) \
+ ((void)arch, celt_inner_prod_sse4_1(x, y, N))
+
+#elif defined(OPUS_X86_PRESUME_SSE2) && defined(FIXED_POINT) && !defined(OPUS_X86_MAY_HAVE_SSE4_1)
+#define OVERRIDE_CELT_INNER_PROD
+#define celt_inner_prod(x, y, N, arch) \
+ ((void)arch, celt_inner_prod_sse2(x, y, N))
+
+#elif defined(OPUS_X86_PRESUME_SSE) && !defined(FIXED_POINT)
+#define OVERRIDE_CELT_INNER_PROD
+#define celt_inner_prod(x, y, N, arch) \
+ ((void)arch, celt_inner_prod_sse(x, y, N))
+
+
+#elif defined(OPUS_HAVE_RTCD) && (((defined(OPUS_X86_MAY_HAVE_SSE4_1) || defined(OPUS_X86_MAY_HAVE_SSE2)) && defined(FIXED_POINT)) || \
+ (defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)))
+
+extern opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_val16 *x,
+ const opus_val16 *y,
+ int N);
+
+#define OVERRIDE_CELT_INNER_PROD
+#define celt_inner_prod(x, y, N, arch) \
+ ((*CELT_INNER_PROD_IMPL[(arch) & OPUS_ARCHMASK])(x, y, N))
+
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)
+
+void dual_inner_prod_sse(const opus_val16 *x,
+ const opus_val16 *y01,
+ const opus_val16 *y02,
+ int N,
+ opus_val32 *xy1,
+ opus_val32 *xy2);
+
+void comb_filter_const_sse(opus_val32 *y,
+ opus_val32 *x,
+ int T,
+ int N,
+ opus_val16 g10,
+ opus_val16 g11,
+ opus_val16 g12);
+
+
+#if defined(OPUS_X86_PRESUME_SSE)
+#define OVERRIDE_DUAL_INNER_PROD
+#define OVERRIDE_COMB_FILTER_CONST
+# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) \
+ ((void)(arch),dual_inner_prod_sse(x, y01, y02, N, xy1, xy2))
+
+# define comb_filter_const(y, x, T, N, g10, g11, g12, arch) \
+ ((void)(arch),comb_filter_const_sse(y, x, T, N, g10, g11, g12))
+#elif defined(OPUS_HAVE_RTCD)
+
+#define OVERRIDE_DUAL_INNER_PROD
+#define OVERRIDE_COMB_FILTER_CONST
+extern void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_val16 *x,
+ const opus_val16 *y01,
+ const opus_val16 *y02,
+ int N,
+ opus_val32 *xy1,
+ opus_val32 *xy2);
+
+#define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) \
+ ((*DUAL_INNER_PROD_IMPL[(arch) & OPUS_ARCHMASK])(x, y01, y02, N, xy1, xy2))
+
+extern void (*const COMB_FILTER_CONST_IMPL[OPUS_ARCHMASK + 1])(
+ opus_val32 *y,
+ opus_val32 *x,
+ int T,
+ int N,
+ opus_val16 g10,
+ opus_val16 g11,
+ opus_val16 g12);
+
+#define comb_filter_const(y, x, T, N, g10, g11, g12, arch) \
+ ((*COMB_FILTER_CONST_IMPL[(arch) & OPUS_ARCHMASK])(y, x, T, N, g10, g11, g12))
+
+#define NON_STATIC_COMB_FILTER_CONST_C
+
+#endif
+
+void celt_pitch_xcorr_avx2(const float *_x, const float *_y, float *xcorr, int len, int max_pitch, int arch);
+
+#if defined(OPUS_X86_PRESUME_AVX2)
+
+#define OVERRIDE_PITCH_XCORR
+# define celt_pitch_xcorr celt_pitch_xcorr_avx2
+
+#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_X86_MAY_HAVE_AVX2)
+
+#define OVERRIDE_PITCH_XCORR
+extern void (*const PITCH_XCORR_IMPL[OPUS_ARCHMASK + 1])(
+ const float *_x,
+ const float *_y,
+ float *xcorr,
+ int len,
+ int max_pitch,
+ int arch
+ );
+
+#define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
+ ((*PITCH_XCORR_IMPL[(arch) & OPUS_ARCHMASK])(_x, _y, xcorr, len, max_pitch, arch))
+
+
+#endif /* OPUS_X86_PRESUME_AVX2 && !OPUS_HAVE_RTCD */
+
+#endif /* OPUS_X86_MAY_HAVE_SSE && !FIXED_POINT */
+
+#endif
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+
+#include "macros.h"
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "pitch.h"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE2) && defined(FIXED_POINT)
+opus_val32 celt_inner_prod_sse2(const opus_val16 *x, const opus_val16 *y,
+ int N)
+{
+ opus_int i, dataSize16;
+ opus_int32 sum;
+
+ __m128i inVec1_76543210, inVec1_FEDCBA98, acc1;
+ __m128i inVec2_76543210, inVec2_FEDCBA98, acc2;
+
+ sum = 0;
+ dataSize16 = N & ~15;
+
+ acc1 = _mm_setzero_si128();
+ acc2 = _mm_setzero_si128();
+
+ for (i=0;i<dataSize16;i+=16)
+ {
+ inVec1_76543210 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 0]));
+ inVec2_76543210 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 0]));
+
+ inVec1_FEDCBA98 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 8]));
+ inVec2_FEDCBA98 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 8]));
+
+ inVec1_76543210 = _mm_madd_epi16(inVec1_76543210, inVec2_76543210);
+ inVec1_FEDCBA98 = _mm_madd_epi16(inVec1_FEDCBA98, inVec2_FEDCBA98);
+
+ acc1 = _mm_add_epi32(acc1, inVec1_76543210);
+ acc2 = _mm_add_epi32(acc2, inVec1_FEDCBA98);
+ }
+
+ acc1 = _mm_add_epi32( acc1, acc2 );
+
+ if (N - i >= 8)
+ {
+ inVec1_76543210 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 0]));
+ inVec2_76543210 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 0]));
+
+ inVec1_76543210 = _mm_madd_epi16(inVec1_76543210, inVec2_76543210);
+
+ acc1 = _mm_add_epi32(acc1, inVec1_76543210);
+ i += 8;
+ }
+
+ acc1 = _mm_add_epi32(acc1, _mm_unpackhi_epi64( acc1, acc1));
+ acc1 = _mm_add_epi32(acc1, _mm_shufflelo_epi16( acc1, 0x0E));
+ sum += _mm_cvtsi128_si32(acc1);
+
+ for (;i<N;i++) {
+ sum = silk_SMLABB(sum, x[i], y[i]);
+ }
+
+ return sum;
+}
+#endif
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+
+#include "macros.h"
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "pitch.h"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT)
+#include <smmintrin.h>
+#include "x86cpu.h"
+
+opus_val32 celt_inner_prod_sse4_1(const opus_val16 *x, const opus_val16 *y,
+ int N)
+{
+ opus_int i, dataSize16;
+ opus_int32 sum;
+ __m128i inVec1_76543210, inVec1_FEDCBA98, acc1;
+ __m128i inVec2_76543210, inVec2_FEDCBA98, acc2;
+ __m128i inVec1_3210, inVec2_3210;
+
+ sum = 0;
+ dataSize16 = N & ~15;
+
+ acc1 = _mm_setzero_si128();
+ acc2 = _mm_setzero_si128();
+
+ for (i=0;i<dataSize16;i+=16) {
+ inVec1_76543210 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 0]));
+ inVec2_76543210 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 0]));
+
+ inVec1_FEDCBA98 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 8]));
+ inVec2_FEDCBA98 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 8]));
+
+ inVec1_76543210 = _mm_madd_epi16(inVec1_76543210, inVec2_76543210);
+ inVec1_FEDCBA98 = _mm_madd_epi16(inVec1_FEDCBA98, inVec2_FEDCBA98);
+
+ acc1 = _mm_add_epi32(acc1, inVec1_76543210);
+ acc2 = _mm_add_epi32(acc2, inVec1_FEDCBA98);
+ }
+
+ acc1 = _mm_add_epi32(acc1, acc2);
+
+ if (N - i >= 8)
+ {
+ inVec1_76543210 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 0]));
+ inVec2_76543210 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 0]));
+
+ inVec1_76543210 = _mm_madd_epi16(inVec1_76543210, inVec2_76543210);
+
+ acc1 = _mm_add_epi32(acc1, inVec1_76543210);
+ i += 8;
+ }
+
+ if (N - i >= 4)
+ {
+ inVec1_3210 = OP_CVTEPI16_EPI32_M64(&x[i + 0]);
+ inVec2_3210 = OP_CVTEPI16_EPI32_M64(&y[i + 0]);
+
+ inVec1_3210 = _mm_mullo_epi32(inVec1_3210, inVec2_3210);
+
+ acc1 = _mm_add_epi32(acc1, inVec1_3210);
+ i += 4;
+ }
+
+ acc1 = _mm_add_epi32(acc1, _mm_unpackhi_epi64(acc1, acc1));
+ acc1 = _mm_add_epi32(acc1, _mm_shufflelo_epi16(acc1, 0x0E));
+
+ sum += _mm_cvtsi128_si32(acc1);
+
+ for (;i<N;i++)
+ {
+ sum = silk_SMLABB(sum, x[i], y[i]);
+ }
+
+ return sum;
+}
+
+void xcorr_kernel_sse4_1(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[ 4 ], int len)
+{
+ int j;
+
+ __m128i vecX, vecX0, vecX1, vecX2, vecX3;
+ __m128i vecY0, vecY1, vecY2, vecY3;
+ __m128i sum0, sum1, sum2, sum3, vecSum;
+ __m128i initSum;
+
+#ifdef OPUS_CHECK_ASM
+ opus_val32 sum_c[4];
+ for (j=0;j<4;j++) {
+ sum_c[j] = sum[j];
+ }
+ xcorr_kernel_c(x, y, sum_c, len);
+#endif
+
+ celt_assert(len >= 3);
+
+ sum0 = _mm_setzero_si128();
+ sum1 = _mm_setzero_si128();
+ sum2 = _mm_setzero_si128();
+ sum3 = _mm_setzero_si128();
+
+ for (j=0;j<(len-7);j+=8)
+ {
+ vecX = _mm_loadu_si128((__m128i *)(void*)(&x[j + 0]));
+ vecY0 = _mm_loadu_si128((__m128i *)(void*)(&y[j + 0]));
+ vecY1 = _mm_loadu_si128((__m128i *)(void*)(&y[j + 1]));
+ vecY2 = _mm_loadu_si128((__m128i *)(void*)(&y[j + 2]));
+ vecY3 = _mm_loadu_si128((__m128i *)(void*)(&y[j + 3]));
+
+ sum0 = _mm_add_epi32(sum0, _mm_madd_epi16(vecX, vecY0));
+ sum1 = _mm_add_epi32(sum1, _mm_madd_epi16(vecX, vecY1));
+ sum2 = _mm_add_epi32(sum2, _mm_madd_epi16(vecX, vecY2));
+ sum3 = _mm_add_epi32(sum3, _mm_madd_epi16(vecX, vecY3));
+ }
+
+ sum0 = _mm_add_epi32(sum0, _mm_unpackhi_epi64( sum0, sum0));
+ sum0 = _mm_add_epi32(sum0, _mm_shufflelo_epi16( sum0, 0x0E));
+
+ sum1 = _mm_add_epi32(sum1, _mm_unpackhi_epi64( sum1, sum1));
+ sum1 = _mm_add_epi32(sum1, _mm_shufflelo_epi16( sum1, 0x0E));
+
+ sum2 = _mm_add_epi32(sum2, _mm_unpackhi_epi64( sum2, sum2));
+ sum2 = _mm_add_epi32(sum2, _mm_shufflelo_epi16( sum2, 0x0E));
+
+ sum3 = _mm_add_epi32(sum3, _mm_unpackhi_epi64( sum3, sum3));
+ sum3 = _mm_add_epi32(sum3, _mm_shufflelo_epi16( sum3, 0x0E));
+
+ vecSum = _mm_unpacklo_epi64(_mm_unpacklo_epi32(sum0, sum1),
+ _mm_unpacklo_epi32(sum2, sum3));
+
+ for (;j<(len-3);j+=4)
+ {
+ vecX = OP_CVTEPI16_EPI32_M64(&x[j + 0]);
+ vecX0 = _mm_shuffle_epi32(vecX, 0x00);
+ vecX1 = _mm_shuffle_epi32(vecX, 0x55);
+ vecX2 = _mm_shuffle_epi32(vecX, 0xaa);
+ vecX3 = _mm_shuffle_epi32(vecX, 0xff);
+
+ vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]);
+ vecY1 = OP_CVTEPI16_EPI32_M64(&y[j + 1]);
+ vecY2 = OP_CVTEPI16_EPI32_M64(&y[j + 2]);
+ vecY3 = OP_CVTEPI16_EPI32_M64(&y[j + 3]);
+
+ sum0 = _mm_mullo_epi32(vecX0, vecY0);
+ sum1 = _mm_mullo_epi32(vecX1, vecY1);
+ sum2 = _mm_mullo_epi32(vecX2, vecY2);
+ sum3 = _mm_mullo_epi32(vecX3, vecY3);
+
+ sum0 = _mm_add_epi32(sum0, sum1);
+ sum2 = _mm_add_epi32(sum2, sum3);
+ vecSum = _mm_add_epi32(vecSum, sum0);
+ vecSum = _mm_add_epi32(vecSum, sum2);
+ }
+
+ vecX = OP_CVTEPI16_EPI32_M64(&x[len - 4]);
+ if (len - j == 3)
+ {
+ vecX0 = _mm_shuffle_epi32(vecX, 0x55);
+ vecX1 = _mm_shuffle_epi32(vecX, 0xaa);
+ vecX2 = _mm_shuffle_epi32(vecX, 0xff);
+
+ vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]);
+ vecY1 = OP_CVTEPI16_EPI32_M64(&y[j + 1]);
+ vecY2 = OP_CVTEPI16_EPI32_M64(&y[j + 2]);
+
+ sum0 = _mm_mullo_epi32(vecX0, vecY0);
+ sum1 = _mm_mullo_epi32(vecX1, vecY1);
+ sum2 = _mm_mullo_epi32(vecX2, vecY2);
+
+ vecSum = _mm_add_epi32(vecSum, sum0);
+ vecSum = _mm_add_epi32(vecSum, sum1);
+ vecSum = _mm_add_epi32(vecSum, sum2);
+ }
+ else if (len - j == 2)
+ {
+ vecX0 = _mm_shuffle_epi32(vecX, 0xaa);
+ vecX1 = _mm_shuffle_epi32(vecX, 0xff);
+
+ vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]);
+ vecY1 = OP_CVTEPI16_EPI32_M64(&y[j + 1]);
+
+ sum0 = _mm_mullo_epi32(vecX0, vecY0);
+ sum1 = _mm_mullo_epi32(vecX1, vecY1);
+
+ vecSum = _mm_add_epi32(vecSum, sum0);
+ vecSum = _mm_add_epi32(vecSum, sum1);
+ }
+ else if (len - j == 1)
+ {
+ vecX0 = _mm_shuffle_epi32(vecX, 0xff);
+
+ vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]);
+
+ sum0 = _mm_mullo_epi32(vecX0, vecY0);
+
+ vecSum = _mm_add_epi32(vecSum, sum0);
+ }
+
+ initSum = _mm_loadu_si128((__m128i *)(void*)(&sum[0]));
+ initSum = _mm_add_epi32(initSum, vecSum);
+ _mm_storeu_si128((__m128i *)(void*)sum, initSum);
+
+#ifdef OPUS_CHECK_ASM
+ celt_assert(!memcmp(sum_c, sum, sizeof(sum_c)));
+#endif
+}
+#endif
--- /dev/null
+/* Copyright (c) 2016 Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 VQ_SSE_H
+#define VQ_SSE_H
+
+#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT)
+
+opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch);
+
+#if defined(OPUS_X86_PRESUME_SSE2)
+
+#define OVERRIDE_OP_PVQ_SEARCH
+#define op_pvq_search(x, iy, K, N, arch) \
+ (op_pvq_search_sse2(x, iy, K, N, arch))
+
+#elif defined(OPUS_HAVE_RTCD)
+
+#define OVERRIDE_OP_PVQ_SEARCH
+extern opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])(
+ celt_norm *_X, int *iy, int K, int N, int arch);
+
+# define op_pvq_search(X, iy, K, N, arch) \
+ ((*OP_PVQ_SEARCH_IMPL[(arch) & OPUS_ARCHMASK])(X, iy, K, N, arch))
+
+#endif
+#endif
+
+#endif
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Copyright (c) 2007-2016 Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "vq.h"
+#include "x86cpu.h"
+
+
+#ifndef FIXED_POINT
+
+opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch)
+{
+ int i, j;
+ int pulsesLeft;
+ float xy, yy;
+ VARDECL(celt_norm, y);
+ VARDECL(celt_norm, X);
+ VARDECL(float, signy);
+ __m128 signmask;
+ __m128 sums;
+ __m128i fours;
+ SAVE_STACK;
+
+ (void)arch;
+ /* All bits set to zero, except for the sign bit. */
+ signmask = _mm_set_ps1(-0.f);
+ fours = _mm_set_epi32(4, 4, 4, 4);
+ ALLOC(y, N+3, celt_norm);
+ ALLOC(X, N+3, celt_norm);
+ ALLOC(signy, N+3, float);
+
+ OPUS_COPY(X, _X, N);
+ X[N] = X[N+1] = X[N+2] = 0;
+ sums = _mm_setzero_ps();
+ for (j=0;j<N;j+=4)
+ {
+ __m128 x4, s4;
+ x4 = _mm_loadu_ps(&X[j]);
+ s4 = _mm_cmplt_ps(x4, _mm_setzero_ps());
+ /* Get rid of the sign */
+ x4 = _mm_andnot_ps(signmask, x4);
+ sums = _mm_add_ps(sums, x4);
+ /* Clear y and iy in case we don't do the projection. */
+ _mm_storeu_ps(&y[j], _mm_setzero_ps());
+ _mm_storeu_si128((__m128i*)(void*)&iy[j], _mm_setzero_si128());
+ _mm_storeu_ps(&X[j], x4);
+ _mm_storeu_ps(&signy[j], s4);
+ }
+ sums = _mm_add_ps(sums, _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(1, 0, 3, 2)));
+ sums = _mm_add_ps(sums, _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(2, 3, 0, 1)));
+
+ xy = yy = 0;
+
+ pulsesLeft = K;
+
+ /* Do a pre-search by projecting on the pyramid */
+ if (K > (N>>1))
+ {
+ __m128i pulses_sum;
+ __m128 yy4, xy4;
+ __m128 rcp4;
+ opus_val32 sum = _mm_cvtss_f32(sums);
+ /* If X is too small, just replace it with a pulse at 0 */
+ /* Prevents infinities and NaNs from causing too many pulses
+ to be allocated. 64 is an approximation of infinity here. */
+ if (!(sum > EPSILON && sum < 64))
+ {
+ X[0] = QCONST16(1.f,14);
+ j=1; do
+ X[j]=0;
+ while (++j<N);
+ sums = _mm_set_ps1(1.f);
+ }
+ /* Using K+e with e < 1 guarantees we cannot get more than K pulses. */
+ rcp4 = _mm_mul_ps(_mm_set_ps1((float)(K+.8)), _mm_rcp_ps(sums));
+ xy4 = yy4 = _mm_setzero_ps();
+ pulses_sum = _mm_setzero_si128();
+ for (j=0;j<N;j+=4)
+ {
+ __m128 rx4, x4, y4;
+ __m128i iy4;
+ x4 = _mm_loadu_ps(&X[j]);
+ rx4 = _mm_mul_ps(x4, rcp4);
+ iy4 = _mm_cvttps_epi32(rx4);
+ pulses_sum = _mm_add_epi32(pulses_sum, iy4);
+ _mm_storeu_si128((__m128i*)(void*)&iy[j], iy4);
+ y4 = _mm_cvtepi32_ps(iy4);
+ xy4 = _mm_add_ps(xy4, _mm_mul_ps(x4, y4));
+ yy4 = _mm_add_ps(yy4, _mm_mul_ps(y4, y4));
+ /* double the y[] vector so we don't have to do it in the search loop. */
+ _mm_storeu_ps(&y[j], _mm_add_ps(y4, y4));
+ }
+ pulses_sum = _mm_add_epi32(pulses_sum, _mm_shuffle_epi32(pulses_sum, _MM_SHUFFLE(1, 0, 3, 2)));
+ pulses_sum = _mm_add_epi32(pulses_sum, _mm_shuffle_epi32(pulses_sum, _MM_SHUFFLE(2, 3, 0, 1)));
+ pulsesLeft -= _mm_cvtsi128_si32(pulses_sum);
+ xy4 = _mm_add_ps(xy4, _mm_shuffle_ps(xy4, xy4, _MM_SHUFFLE(1, 0, 3, 2)));
+ xy4 = _mm_add_ps(xy4, _mm_shuffle_ps(xy4, xy4, _MM_SHUFFLE(2, 3, 0, 1)));
+ xy = _mm_cvtss_f32(xy4);
+ yy4 = _mm_add_ps(yy4, _mm_shuffle_ps(yy4, yy4, _MM_SHUFFLE(1, 0, 3, 2)));
+ yy4 = _mm_add_ps(yy4, _mm_shuffle_ps(yy4, yy4, _MM_SHUFFLE(2, 3, 0, 1)));
+ yy = _mm_cvtss_f32(yy4);
+ }
+ X[N] = X[N+1] = X[N+2] = -100;
+ y[N] = y[N+1] = y[N+2] = 100;
+ celt_sig_assert(pulsesLeft>=0);
+
+ /* This should never happen, but just in case it does (e.g. on silence)
+ we fill the first bin with pulses. */
+ if (pulsesLeft > N+3)
+ {
+ opus_val16 tmp = (opus_val16)pulsesLeft;
+ yy = MAC16_16(yy, tmp, tmp);
+ yy = MAC16_16(yy, tmp, y[0]);
+ iy[0] += pulsesLeft;
+ pulsesLeft=0;
+ }
+
+ for (i=0;i<pulsesLeft;i++)
+ {
+ int best_id;
+ __m128 xy4, yy4;
+ __m128 max, max2;
+ __m128i count;
+ __m128i pos;
+ /* The squared magnitude term gets added anyway, so we might as well
+ add it outside the loop */
+ yy = ADD16(yy, 1);
+ xy4 = _mm_load1_ps(&xy);
+ yy4 = _mm_load1_ps(&yy);
+ max = _mm_setzero_ps();
+ pos = _mm_setzero_si128();
+ count = _mm_set_epi32(3, 2, 1, 0);
+ for (j=0;j<N;j+=4)
+ {
+ __m128 x4, y4, r4;
+ x4 = _mm_loadu_ps(&X[j]);
+ y4 = _mm_loadu_ps(&y[j]);
+ x4 = _mm_add_ps(x4, xy4);
+ y4 = _mm_add_ps(y4, yy4);
+ y4 = _mm_rsqrt_ps(y4);
+ r4 = _mm_mul_ps(x4, y4);
+ /* Update the index of the max. */
+ pos = _mm_max_epi16(pos, _mm_and_si128(count, _mm_castps_si128(_mm_cmpgt_ps(r4, max))));
+ /* Update the max. */
+ max = _mm_max_ps(max, r4);
+ /* Update the indices (+4) */
+ count = _mm_add_epi32(count, fours);
+ }
+ /* Horizontal max */
+ max2 = _mm_max_ps(max, _mm_shuffle_ps(max, max, _MM_SHUFFLE(1, 0, 3, 2)));
+ max2 = _mm_max_ps(max2, _mm_shuffle_ps(max2, max2, _MM_SHUFFLE(2, 3, 0, 1)));
+ /* Now that max2 contains the max at all positions, look at which value(s) of the
+ partial max is equal to the global max. */
+ pos = _mm_and_si128(pos, _mm_castps_si128(_mm_cmpeq_ps(max, max2)));
+ pos = _mm_max_epi16(pos, _mm_unpackhi_epi64(pos, pos));
+ pos = _mm_max_epi16(pos, _mm_shufflelo_epi16(pos, _MM_SHUFFLE(1, 0, 3, 2)));
+ best_id = _mm_cvtsi128_si32(pos);
+
+ /* Updating the sums of the new pulse(s) */
+ xy = ADD32(xy, EXTEND32(X[best_id]));
+ /* We're multiplying y[j] by two so we don't have to do it here */
+ yy = ADD16(yy, y[best_id]);
+
+ /* Only now that we've made the final choice, update y/iy */
+ /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
+ y[best_id] += 2;
+ iy[best_id]++;
+ }
+
+ /* Put the original sign back */
+ for (j=0;j<N;j+=4)
+ {
+ __m128i y4;
+ __m128i s4;
+ y4 = _mm_loadu_si128((__m128i*)(void*)&iy[j]);
+ s4 = _mm_castps_si128(_mm_loadu_ps(&signy[j]));
+ y4 = _mm_xor_si128(_mm_add_epi32(y4, s4), s4);
+ _mm_storeu_si128((__m128i*)(void*)&iy[j], y4);
+ }
+ RESTORE_STACK;
+ return yy;
+}
+
+#endif
--- /dev/null
+/* Copyright (c) 2023 Amazon */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef _MSC_VER
+
+# ifdef OPUS_X86_MAY_HAVE_SSE
+# ifndef __SSE__
+# define __SSE__
+# endif
+# endif
+
+# ifdef OPUS_X86_MAY_HAVE_SSE2
+# ifndef __SSE2__
+# define __SSE2__
+# endif
+# endif
+
+# ifdef OPUS_X86_MAY_HAVE_SSE4_1
+# ifndef __SSE4_1__
+# define __SSE4_1__
+# endif
+# endif
+
+#endif
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include "x86/x86cpu.h"
+#include "celt_lpc.h"
+#include "pitch.h"
+#include "pitch_sse.h"
+#include "vq.h"
+
+#if defined(OPUS_HAVE_RTCD)
+
+# if defined(FIXED_POINT)
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)
+
+void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_val16 *x,
+ const opus_val16 *num,
+ opus_val16 *y,
+ int N,
+ int ord,
+ int arch
+) = {
+ celt_fir_c, /* non-sse */
+ celt_fir_c,
+ celt_fir_c,
+ MAY_HAVE_SSE4_1(celt_fir), /* sse4.1 */
+ MAY_HAVE_SSE4_1(celt_fir) /* avx */
+};
+
+void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_val16 *x,
+ const opus_val16 *y,
+ opus_val32 sum[4],
+ int len
+) = {
+ xcorr_kernel_c, /* non-sse */
+ xcorr_kernel_c,
+ xcorr_kernel_c,
+ MAY_HAVE_SSE4_1(xcorr_kernel), /* sse4.1 */
+ MAY_HAVE_SSE4_1(xcorr_kernel) /* avx */
+};
+
+#endif
+
+#if (defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
+ (!defined(OPUS_X86_MAY_HAVE_SSE_4_1) && defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2))
+
+opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_val16 *x,
+ const opus_val16 *y,
+ int N
+) = {
+ celt_inner_prod_c, /* non-sse */
+ celt_inner_prod_c,
+ MAY_HAVE_SSE2(celt_inner_prod),
+ MAY_HAVE_SSE4_1(celt_inner_prod), /* sse4.1 */
+ MAY_HAVE_SSE4_1(celt_inner_prod) /* avx */
+};
+
+#endif
+
+# else
+
+#if defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2)
+
+void (*const PITCH_XCORR_IMPL[OPUS_ARCHMASK + 1])(
+ const float *_x,
+ const float *_y,
+ float *xcorr,
+ int len,
+ int max_pitch,
+ int arch
+) = {
+ celt_pitch_xcorr_c, /* non-sse */
+ celt_pitch_xcorr_c,
+ celt_pitch_xcorr_c,
+ celt_pitch_xcorr_c,
+ MAY_HAVE_AVX2(celt_pitch_xcorr)
+};
+
+#endif
+
+
+#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)
+
+void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_val16 *x,
+ const opus_val16 *y,
+ opus_val32 sum[4],
+ int len
+) = {
+ xcorr_kernel_c, /* non-sse */
+ MAY_HAVE_SSE(xcorr_kernel),
+ MAY_HAVE_SSE(xcorr_kernel),
+ MAY_HAVE_SSE(xcorr_kernel),
+ MAY_HAVE_SSE(xcorr_kernel)
+};
+
+opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_val16 *x,
+ const opus_val16 *y,
+ int N
+) = {
+ celt_inner_prod_c, /* non-sse */
+ MAY_HAVE_SSE(celt_inner_prod),
+ MAY_HAVE_SSE(celt_inner_prod),
+ MAY_HAVE_SSE(celt_inner_prod),
+ MAY_HAVE_SSE(celt_inner_prod)
+};
+
+void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_val16 *x,
+ const opus_val16 *y01,
+ const opus_val16 *y02,
+ int N,
+ opus_val32 *xy1,
+ opus_val32 *xy2
+) = {
+ dual_inner_prod_c, /* non-sse */
+ MAY_HAVE_SSE(dual_inner_prod),
+ MAY_HAVE_SSE(dual_inner_prod),
+ MAY_HAVE_SSE(dual_inner_prod),
+ MAY_HAVE_SSE(dual_inner_prod)
+};
+
+void (*const COMB_FILTER_CONST_IMPL[OPUS_ARCHMASK + 1])(
+ opus_val32 *y,
+ opus_val32 *x,
+ int T,
+ int N,
+ opus_val16 g10,
+ opus_val16 g11,
+ opus_val16 g12
+) = {
+ comb_filter_const_c, /* non-sse */
+ MAY_HAVE_SSE(comb_filter_const),
+ MAY_HAVE_SSE(comb_filter_const),
+ MAY_HAVE_SSE(comb_filter_const),
+ MAY_HAVE_SSE(comb_filter_const)
+};
+
+
+#endif
+
+#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)
+opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])(
+ celt_norm *_X, int *iy, int K, int N, int arch
+) = {
+ op_pvq_search_c, /* non-sse */
+ op_pvq_search_c,
+ MAY_HAVE_SSE2(op_pvq_search),
+ MAY_HAVE_SSE2(op_pvq_search),
+ MAY_HAVE_SSE2(op_pvq_search)
+};
+#endif
+
+#endif
+#endif
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cpu_support.h"
+#include "macros.h"
+#include "main.h"
+#include "pitch.h"
+#include "x86cpu.h"
+
+#if defined(OPUS_HAVE_RTCD) && \
+ ((defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)) || \
+ (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) || \
+ (defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
+ (defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2)))
+
+#if defined(_MSC_VER)
+
+#include <intrin.h>
+static _inline void cpuid(unsigned int CPUInfo[4], unsigned int InfoType)
+{
+ __cpuid((int*)CPUInfo, InfoType);
+}
+
+#else
+
+#if defined(CPU_INFO_BY_C)
+#include <cpuid.h>
+#endif
+
+static void cpuid(unsigned int CPUInfo[4], unsigned int InfoType)
+{
+#if defined(CPU_INFO_BY_ASM)
+#if defined(__i386__) && defined(__PIC__)
+/* %ebx is PIC register in 32-bit, so mustn't clobber it. */
+ __asm__ __volatile__ (
+ "xchg %%ebx, %1\n"
+ "cpuid\n"
+ "xchg %%ebx, %1\n":
+ "=a" (CPUInfo[0]),
+ "=r" (CPUInfo[1]),
+ "=c" (CPUInfo[2]),
+ "=d" (CPUInfo[3]) :
+ /* We clear ECX to avoid a valgrind false-positive prior to v3.17.0. */
+ "0" (InfoType), "2" (0)
+ );
+#else
+ __asm__ __volatile__ (
+ "cpuid":
+ "=a" (CPUInfo[0]),
+ "=b" (CPUInfo[1]),
+ "=c" (CPUInfo[2]),
+ "=d" (CPUInfo[3]) :
+ /* We clear ECX to avoid a valgrind false-positive prior to v3.17.0. */
+ "0" (InfoType), "2" (0)
+ );
+#endif
+#elif defined(CPU_INFO_BY_C)
+ /* We use __get_cpuid_count to clear ECX to avoid a valgrind false-positive
+ prior to v3.17.0.*/
+ if (!__get_cpuid_count(InfoType, 0, &(CPUInfo[0]), &(CPUInfo[1]), &(CPUInfo[2]), &(CPUInfo[3]))) {
+ /* Our function cannot fail, but __get_cpuid{_count} can.
+ Returning all zeroes will effectively disable all SIMD, which is
+ what we want on CPUs that don't support CPUID. */
+ CPUInfo[3] = CPUInfo[2] = CPUInfo[1] = CPUInfo[0] = 0;
+ }
+#else
+# error "Configured to use x86 RTCD, but no CPU detection method available. " \
+ "Reconfigure with --disable-rtcd (or send patches)."
+#endif
+}
+
+#endif
+
+typedef struct CPU_Feature{
+ /* SIMD: 128-bit */
+ int HW_SSE;
+ int HW_SSE2;
+ int HW_SSE41;
+ /* SIMD: 256-bit */
+ int HW_AVX2;
+} CPU_Feature;
+
+static void opus_cpu_feature_check(CPU_Feature *cpu_feature)
+{
+ unsigned int info[4];
+ unsigned int nIds = 0;
+
+ cpuid(info, 0);
+ nIds = info[0];
+
+ if (nIds >= 1){
+ cpuid(info, 1);
+ cpu_feature->HW_SSE = (info[3] & (1 << 25)) != 0;
+ cpu_feature->HW_SSE2 = (info[3] & (1 << 26)) != 0;
+ cpu_feature->HW_SSE41 = (info[2] & (1 << 19)) != 0;
+ cpu_feature->HW_AVX2 = (info[2] & (1 << 28)) != 0 && (info[2] & (1 << 12)) != 0;
+ if (cpu_feature->HW_AVX2 && nIds >= 7) {
+ cpuid(info, 7);
+ cpu_feature->HW_AVX2 = cpu_feature->HW_AVX2 && (info[1] & (1 << 5)) != 0;
+ } else {
+ cpu_feature->HW_AVX2 = 0;
+ }
+ }
+ else {
+ cpu_feature->HW_SSE = 0;
+ cpu_feature->HW_SSE2 = 0;
+ cpu_feature->HW_SSE41 = 0;
+ cpu_feature->HW_AVX2 = 0;
+ }
+}
+
+static int opus_select_arch_impl(void)
+{
+ CPU_Feature cpu_feature;
+ int arch;
+
+ opus_cpu_feature_check(&cpu_feature);
+
+ arch = 0;
+ if (!cpu_feature.HW_SSE)
+ {
+ return arch;
+ }
+ arch++;
+
+ if (!cpu_feature.HW_SSE2)
+ {
+ return arch;
+ }
+ arch++;
+
+ if (!cpu_feature.HW_SSE41)
+ {
+ return arch;
+ }
+ arch++;
+
+ if (!cpu_feature.HW_AVX2)
+ {
+ return arch;
+ }
+ arch++;
+
+ return arch;
+}
+
+int opus_select_arch(void) {
+ int arch = opus_select_arch_impl();
+#ifdef FUZZING
+ /* Randomly downgrade the architecture. */
+ arch = rand()%(arch+1);
+#endif
+ return arch;
+}
+
+#endif
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#if !defined(X86CPU_H)
+# define X86CPU_H
+
+# if defined(OPUS_X86_MAY_HAVE_SSE)
+# define MAY_HAVE_SSE(name) name ## _sse
+# else
+# define MAY_HAVE_SSE(name) name ## _c
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE2)
+# define MAY_HAVE_SSE2(name) name ## _sse2
+# else
+# define MAY_HAVE_SSE2(name) name ## _c
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+# define MAY_HAVE_SSE4_1(name) name ## _sse4_1
+# else
+# define MAY_HAVE_SSE4_1(name) name ## _c
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_AVX2)
+# define MAY_HAVE_AVX2(name) name ## _avx2
+# else
+# define MAY_HAVE_AVX2(name) name ## _c
+# endif
+
+# if defined(OPUS_HAVE_RTCD) && \
+ ((defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)) || \
+ (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) || \
+ (defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
+ (defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2)))
+int opus_select_arch(void);
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE2)
+# include "opus_defines.h"
+
+/*MOVD should not impose any alignment restrictions, but the C standard does,
+ and UBSan will report errors if we actually make unaligned accesses.
+ Use this to work around those restrictions (which should hopefully all get
+ optimized to a single MOVD instruction).
+ GCC implemented _mm_loadu_si32() since GCC 11; HOWEVER, there is a bug!
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99754
+ LLVM implemented _mm_loadu_si32() since Clang 8.0, however the
+ __clang_major__ version number macro is unreliable, as vendors
+ (specifically, Apple) will use different numbering schemes than upstream.
+ Clang's advice is "use feature detection", but they do not provide feature
+ detection support for specific SIMD functions.
+ We follow the approach from the SIMDe project and instead detect unrelated
+ features that should be available in the version we want (see
+ <https://github.com/simd-everywhere/simde/blob/master/simde/simde-detect-clang.h>).*/
+# if defined(__clang__)
+# if __has_warning("-Wextra-semi-stmt") || \
+ __has_builtin(__builtin_rotateleft32)
+# define OPUS_CLANG_8 (1)
+# endif
+# endif
+# if !defined(_MSC_VER) && !OPUS_GNUC_PREREQ(11,3) && !defined(OPUS_CLANG_8)
+# include <string.h>
+# include <emmintrin.h>
+
+# ifdef _mm_loadu_si32
+# undef _mm_loadu_si32
+# endif
+# define _mm_loadu_si32 WORKAROUND_mm_loadu_si32
+static inline __m128i WORKAROUND_mm_loadu_si32(void const* mem_addr) {
+ int val;
+ memcpy(&val, mem_addr, sizeof(val));
+ return _mm_cvtsi32_si128(val);
+}
+# elif defined(_MSC_VER)
+ /* MSVC needs this for _mm_loadu_si32 */
+# include <immintrin.h>
+# endif
+
+# define OP_CVTEPI8_EPI32_M32(x) \
+ (_mm_cvtepi8_epi32(_mm_loadu_si32(x)))
+
+# define OP_CVTEPI16_EPI32_M64(x) \
+ (_mm_cvtepi16_epi32(_mm_loadl_epi64((__m128i *)(void*)(x))))
+
+# endif
+
+#endif
--- /dev/null
+# PowerShell 清理脚本:清理所有编译产物和中间文件,仅保留源码\r
+# 使用方式: .\clean_all.ps1\r
+\r
+$ErrorActionPreference = "Stop"\r
+\r
+$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path\r
+\r
+Write-Host "=========================================="\r
+Write-Host "清理编译产物和中间文件"\r
+Write-Host "=========================================="\r
+Write-Host "工作目录: $ScriptDir"\r
+Write-Host ""\r
+\r
+$CleanedCount = 0\r
+\r
+function Clean-File {\r
+ param([string]$Path)\r
+ \r
+ if (Test-Path $Path) {\r
+ Remove-Item -Path $Path -Recurse -Force -ErrorAction SilentlyContinue\r
+ Write-Host " 删除: $Path"\r
+ $script:CleanedCount++\r
+ }\r
+}\r
+\r
+# 清理所有 .o 文件\r
+Write-Host "清理对象文件 (.o)..."\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.o" -File -ErrorAction SilentlyContinue | ForEach-Object {\r
+ Clean-File $_.FullName\r
+}\r
+\r
+# 清理生成的库文件\r
+Write-Host ""\r
+Write-Host "清理库文件..."\r
+Clean-File (Join-Path $ScriptDir "libopus_min.a")\r
+# 清理符号链接或普通文件\r
+$libopusPath = Join-Path $ScriptDir "libopus.a"\r
+if (Test-Path $libopusPath) {\r
+ $item = Get-Item $libopusPath -ErrorAction SilentlyContinue\r
+ if ($item.LinkType -eq "SymbolicLink") {\r
+ Remove-Item -Path $libopusPath -Force -ErrorAction SilentlyContinue\r
+ Write-Host " 删除: $libopusPath (符号链接)"\r
+ $CleanedCount++\r
+ } else {\r
+ Clean-File $libopusPath\r
+ }\r
+}\r
+\r
+# 清理可执行文件\r
+Write-Host ""\r
+Write-Host "清理可执行文件..."\r
+Clean-File (Join-Path $ScriptDir "opus_frame_to_pcm")\r
+Clean-File (Join-Path $ScriptDir "opus_frame_to_pcm.exe")\r
+\r
+# 清理测试输出文件\r
+Write-Host ""\r
+Write-Host "清理测试输出文件..."\r
+Clean-File (Join-Path $ScriptDir "test_output.pcm")\r
+Clean-File (Join-Path $ScriptDir "test_output_new.pcm")\r
+Clean-File (Join-Path $ScriptDir "test_frame.opus")\r
+\r
+# 清理 Makefile 生成的临时文件\r
+Write-Host ""\r
+Write-Host "清理 Makefile 临时文件..."\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.d" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter ".depend" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.su" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.gcda" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.gcno" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+\r
+# 清理可能的备份文件\r
+Write-Host ""\r
+Write-Host "清理备份文件..."\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*~" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.bak" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.swp" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+Get-ChildItem -Path $ScriptDir -Recurse -Filter "*.tmp" -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue\r
+\r
+# 清理空目录(除了源码目录结构)\r
+Write-Host ""\r
+Write-Host "清理空目录..."\r
+$EmptyDirs = Get-ChildItem -Path $ScriptDir -Recurse -Directory -ErrorAction SilentlyContinue | \r
+ Where-Object { (Get-ChildItem $_.FullName -Recurse -File -ErrorAction SilentlyContinue | Measure-Object).Count -eq 0 }\r
+$EmptyDirs | ForEach-Object {\r
+ # 只删除非源码目录的空目录\r
+ $relPath = $_.FullName.Replace($ScriptDir, "").TrimStart("\")\r
+ if ($relPath -notmatch "^src_lib" -and $relPath -notmatch "^celt" -and $relPath -notmatch "^silk" -and $relPath -notmatch "^include") {\r
+ try {\r
+ Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue\r
+ } catch {\r
+ # 忽略错误\r
+ }\r
+ }\r
+}\r
+\r
+Write-Host ""\r
+Write-Host "=========================================="\r
+if ($CleanedCount -gt 0) {\r
+ Write-Host "清理完成!共清理 $CleanedCount 个文件/目录"\r
+} else {\r
+ Write-Host "没有找到需要清理的文件"\r
+}\r
+Write-Host "=========================================="\r
+Write-Host ""\r
+Write-Host "保留的文件类型:"\r
+Write-Host " - 源码文件 (.c)"\r
+Write-Host " - 头文件 (.h)"\r
+Write-Host " - 配置文件 (config.h)"\r
+Write-Host " - 脚本文件 (.sh, .ps1, .bat)"\r
+Write-Host " - Makefile 文件"\r
+Write-Host " - 文档文件 (.md)"\r
+Write-Host ""\r
--- /dev/null
+#!/bin/bash
+# 清理脚本:清理所有编译产物和中间文件,仅保留源码
+# 使用方式: ./clean_all.sh
+
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+echo "=========================================="
+echo "清理编译产物和中间文件"
+echo "=========================================="
+echo "工作目录: $SCRIPT_DIR"
+echo ""
+
+# 计数器
+CLEANED_COUNT=0
+
+# 清理函数
+clean_file() {
+ if [ -f "$1" ] || [ -d "$1" ]; then
+ rm -rf "$1"
+ echo " 删除: $1"
+ CLEANED_COUNT=$((CLEANED_COUNT + 1))
+ fi
+}
+
+# 清理所有 .o 文件
+echo "清理对象文件 (.o)..."
+find "$SCRIPT_DIR" -type f -name "*.o" -print0 | while IFS= read -r -d '' file; do
+ clean_file "$file"
+done
+
+# 清理生成的库文件
+echo ""
+echo "清理库文件..."
+clean_file "$SCRIPT_DIR/libopus_min.a"
+# 清理符号链接或普通文件
+if [ -L "$SCRIPT_DIR/libopus.a" ]; then
+ rm -f "$SCRIPT_DIR/libopus.a"
+ echo " 删除: $SCRIPT_DIR/libopus.a (符号链接)"
+ CLEANED_COUNT=$((CLEANED_COUNT + 1))
+elif [ -f "$SCRIPT_DIR/libopus.a" ]; then
+ clean_file "$SCRIPT_DIR/libopus.a"
+fi
+
+# 清理可执行文件
+echo ""
+echo "清理可执行文件..."
+clean_file "$SCRIPT_DIR/opus_frame_to_pcm"
+clean_file "$SCRIPT_DIR/opus_frame_to_pcm.exe"
+
+# 清理测试输出文件
+echo ""
+echo "清理测试输出文件..."
+clean_file "$SCRIPT_DIR/test_output.pcm"
+clean_file "$SCRIPT_DIR/test_output_new.pcm"
+clean_file "$SCRIPT_DIR/test_frame.opus"
+
+# 清理 Makefile 生成的临时文件
+echo ""
+echo "清理 Makefile 临时文件..."
+find "$SCRIPT_DIR" -type f -name "*.d" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name ".depend" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name "*.su" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name "*.gcda" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name "*.gcno" -delete 2>/dev/null || true
+
+# 清理可能的备份文件
+echo ""
+echo "清理备份文件..."
+find "$SCRIPT_DIR" -type f -name "*~" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name "*.bak" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name "*.swp" -delete 2>/dev/null || true
+find "$SCRIPT_DIR" -type f -name "*.tmp" -delete 2>/dev/null || true
+
+# 清理空目录(除了源码目录)
+echo ""
+echo "清理空目录..."
+find "$SCRIPT_DIR/src_lib" -type d -empty -delete 2>/dev/null || true
+find "$SCRIPT_DIR/celt" -type d -empty -delete 2>/dev/null || true
+find "$SCRIPT_DIR/silk" -type d -empty -delete 2>/dev/null || true
+
+echo ""
+echo "=========================================="
+if [ $CLEANED_COUNT -gt 0 ]; then
+ echo "清理完成!共清理 $CLEANED_COUNT 个文件/目录"
+else
+ echo "没有找到需要清理的文件"
+fi
+echo "=========================================="
+echo ""
+echo "保留的文件类型:"
+echo " - 源码文件 (.c)"
+echo " - 头文件 (.h)"
+echo " - 配置文件 (config.h)"
+echo " - 脚本文件 (.sh, .ps1, .bat)"
+echo " - Makefile 文件"
+echo " - 文档文件 (.md)"
+echo ""
--- /dev/null
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Get CPU Info by asm method */
+#define CPU_INFO_BY_ASM 1
+
+/* Get CPU Info by c method */
+/* #undef CPU_INFO_BY_C */
+
+/* Custom modes */
+/* #undef CUSTOM_MODES */
+
+/* Disable DNN debug float */
+#define DISABLE_DEBUG_FLOAT 1
+
+/* Disable dot product instructions */
+/* #undef DISABLE_DOT_PROD */
+
+/* Do not build the float API */
+/* #undef DISABLE_FLOAT_API */
+
+/* Disable bitstream fixes from RFC 8251 */
+/* #undef DISABLE_UPDATE_DRAFT */
+
+/* Assertions */
+/* #undef ENABLE_ASSERTIONS */
+
+/* Deep PLC */
+/* #undef ENABLE_DEEP_PLC */
+
+/* DRED */
+/* #undef ENABLE_DRED */
+
+/* Hardening */
+#define ENABLE_HARDENING 1
+
+/* LOSSGEN */
+/* #undef ENABLE_LOSSGEN */
+
+/* Opus custom API */
+/* #undef ENABLE_OPUS_CUSTOM_API */
+
+/* Enable Opus Speech Coding Enhancement */
+/* #undef ENABLE_OSCE */
+
+/* Enable Opus Speech Coding Enhancement Blind BWE */
+/* #undef ENABLE_OSCE_BWE */
+
+/* Enable dumping of OSCE training data */
+/* #undef ENABLE_OSCE_TRAINING_DATA */
+
+/* Scalable quality extension */
+/* #undef ENABLE_QEXT */
+
+/* 24-bit internal resolution for fixed-point */
+#define ENABLE_RES24 1
+
+/* Debug fixed-point implementation */
+/* #undef FIXED_DEBUG */
+
+/* Compile as fixed-point (for machines without a fast enough FPU) */
+/* #undef FIXED_POINT */
+
+/* Float approximations */
+#define FLOAT_APPROX 1
+
+/* Fuzzing */
+/* #undef FUZZING */
+
+/* Define to 1 if you have the <alloca.h> header file. */
+/* #undef HAVE_ALLOCA_H */
+
+/* NE10 library is installed on host. Make sure it is on target! */
+/* #undef HAVE_ARM_NE10 */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `elf_aux_info' function. */
+/* #undef HAVE_ELF_AUX_INFO */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `lrint' function. */
+#define HAVE_LRINT 1
+
+/* Define to 1 if you have the `lrintf' function. */
+#define HAVE_LRINTF 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `__malloc_hook' function. */
+#define HAVE___MALLOC_HOOK 1
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#define LT_OBJDIR ".libs/"
+
+/* Make use of ARM asm optimization */
+/* #undef OPUS_ARM_ASM */
+
+/* Use generic ARMv4 inline asm optimizations */
+/* #undef OPUS_ARM_INLINE_ASM */
+
+/* Use ARMv5E inline asm optimizations */
+/* #undef OPUS_ARM_INLINE_EDSP */
+
+/* Use ARMv6 inline asm optimizations */
+/* #undef OPUS_ARM_INLINE_MEDIA */
+
+/* Use ARM NEON inline asm optimizations */
+/* #undef OPUS_ARM_INLINE_NEON */
+
+/* Compiler supports Aarch64 DOTPROD Intrinsics */
+/* #undef OPUS_ARM_MAY_HAVE_DOTPROD */
+
+/* Define if assembler supports EDSP instructions */
+/* #undef OPUS_ARM_MAY_HAVE_EDSP */
+
+/* Define if assembler supports ARMv6 media instructions */
+/* #undef OPUS_ARM_MAY_HAVE_MEDIA */
+
+/* Define if compiler supports NEON instructions */
+/* #undef OPUS_ARM_MAY_HAVE_NEON */
+
+/* Compiler supports ARMv7/Aarch64 Neon Intrinsics */
+/* #undef OPUS_ARM_MAY_HAVE_NEON_INTR */
+
+/* Define if binary requires Aarch64 Neon Intrinsics */
+/* #undef OPUS_ARM_PRESUME_AARCH64_NEON_INTR */
+
+/* Define if binary requires Aarch64 dotprod Intrinsics */
+/* #undef OPUS_ARM_PRESUME_DOTPROD */
+
+/* Define if binary requires EDSP instruction support */
+/* #undef OPUS_ARM_PRESUME_EDSP */
+
+/* Define if binary requires ARMv6 media instruction support */
+/* #undef OPUS_ARM_PRESUME_MEDIA */
+
+/* Define if binary requires NEON instruction support */
+/* #undef OPUS_ARM_PRESUME_NEON */
+
+/* Define if binary requires NEON intrinsics support */
+/* #undef OPUS_ARM_PRESUME_NEON_INTR */
+
+/* This is a build of OPUS */
+#define OPUS_BUILD /**/
+
+/* Run bit-exactness checks between optimized and C implementations */
+/* #undef OPUS_CHECK_ASM */
+
+/* Use run-time CPU capabilities detection */
+#define OPUS_HAVE_RTCD 1
+
+/* Compiler supports X86 AVX2 Intrinsics */
+#define OPUS_X86_MAY_HAVE_AVX2 1
+
+/* Compiler supports X86 SSE Intrinsics */
+#define OPUS_X86_MAY_HAVE_SSE 1
+
+/* Compiler supports X86 SSE2 Intrinsics */
+#define OPUS_X86_MAY_HAVE_SSE2 1
+
+/* Compiler supports X86 SSE4.1 Intrinsics */
+#define OPUS_X86_MAY_HAVE_SSE4_1 1
+
+/* Define if binary requires AVX2 intrinsics support */
+/* #undef OPUS_X86_PRESUME_AVX2 */
+
+/* Define if binary requires SSE intrinsics support */
+#define OPUS_X86_PRESUME_SSE 1
+
+/* Define if binary requires SSE2 intrinsics support */
+#define OPUS_X86_PRESUME_SSE2 1
+
+/* Define if binary requires SSE4.1 intrinsics support */
+/* #undef OPUS_X86_PRESUME_SSE4_1 */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "opus@xiph.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "opus"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "opus 1.6.1"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "opus"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.6.1"
+
+/* Define to 1 if all of the C90 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
+#define STDC_HEADERS 1
+
+/* Make use of alloca */
+/* #undef USE_ALLOCA */
+
+/* Use C99 variable-size arrays */
+#define VAR_ARRAYS 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to the equivalent of the C99 'restrict' keyword, or to
+ nothing if this is not supported. Do not define if restrict is
+ supported directly. */
+#define restrict __restrict
+/* Work around a bug in Sun C++: it does not support _Restrict or
+ __restrict__, even though the corresponding Sun C compiler ends up with
+ "#define restrict _Restrict" or "#define restrict __restrict__" in the
+ previous line. Perhaps some future version of Sun C++ will work with
+ restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
+#if defined __SUNPRO_CC && !defined __RESTRICT
+# define _Restrict
+# define __restrict__
+#endif
--- /dev/null
+#!/bin/bash
+# Script to copy necessary source files for building minimal decoder library
+
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
+
+echo "=========================================="
+echo "Copying Opus Decoder Source Files"
+echo "=========================================="
+echo "Project root: $PROJECT_ROOT"
+echo "Target directory: $SCRIPT_DIR"
+echo ""
+
+# Create directories
+mkdir -p "$SCRIPT_DIR/src_lib"
+mkdir -p "$SCRIPT_DIR/celt"
+mkdir -p "$SCRIPT_DIR/celt/x86"
+mkdir -p "$SCRIPT_DIR/silk"
+mkdir -p "$SCRIPT_DIR/silk/float"
+mkdir -p "$SCRIPT_DIR/silk/x86"
+mkdir -p "$SCRIPT_DIR/include"
+
+echo "Created directory structure"
+echo ""
+
+# Copy Opus API layer sources (decoder only)
+echo "Copying Opus API sources..."
+OPUS_SRC_FILES=(
+ "src/opus.c"
+ "src/opus_decoder.c"
+ "src/opus_multistream_decoder.c"
+ "src/opus_projection_decoder.c"
+ "src/extensions.c"
+ "src/repacketizer.c"
+ "src/mapping_matrix.c"
+)
+
+for file in "${OPUS_SRC_FILES[@]}"; do
+ if [ -f "$PROJECT_ROOT/$file" ]; then
+ cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/src_lib/"
+ echo " Copied: $file"
+ else
+ echo " Warning: $file not found"
+ fi
+done
+
+# Copy Opus private header
+if [ -f "$PROJECT_ROOT/src/opus_private.h" ]; then
+ cp "$PROJECT_ROOT/src/opus_private.h" "$SCRIPT_DIR/src_lib/"
+ echo " Copied: src/opus_private.h"
+fi
+
+echo ""
+
+# Copy CELT sources
+echo "Copying CELT sources..."
+CELT_SRC_FILES=(
+ "celt/bands.c"
+ "celt/celt.c"
+ "celt/celt_decoder.c"
+ "celt/cwrs.c"
+ "celt/entcode.c"
+ "celt/entdec.c"
+ "celt/entenc.c"
+ "celt/kiss_fft.c"
+ "celt/laplace.c"
+ "celt/mathops.c"
+ "celt/mdct.c"
+ "celt/modes.c"
+ "celt/pitch.c"
+ "celt/celt_lpc.c"
+ "celt/quant_bands.c"
+ "celt/rate.c"
+ "celt/vq.c"
+)
+
+for file in "${CELT_SRC_FILES[@]}"; do
+ if [ -f "$PROJECT_ROOT/$file" ]; then
+ cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/celt/"
+ echo " Copied: $file"
+ else
+ echo " Warning: $file not found"
+ fi
+done
+
+# Copy CELT x86 optimization
+echo "Copying CELT x86 optimization..."
+CELT_X86_FILES=(
+ "celt/x86/x86cpu.c"
+ "celt/x86/x86_celt_map.c"
+ "celt/x86/pitch_sse.c"
+ "celt/x86/pitch_sse2.c"
+ "celt/x86/vq_sse2.c"
+ "celt/x86/celt_lpc_sse4_1.c"
+ "celt/x86/pitch_sse4_1.c"
+ "celt/x86/pitch_avx.c"
+)
+
+for file in "${CELT_X86_FILES[@]}"; do
+ if [ -f "$PROJECT_ROOT/$file" ]; then
+ cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/celt/x86/"
+ echo " Copied: $file"
+ fi
+done
+
+# Copy CELT headers
+echo "Copying CELT headers..."
+if [ -d "$PROJECT_ROOT/celt" ]; then
+ find "$PROJECT_ROOT/celt" -maxdepth 1 -name "*.h" -exec cp {} "$SCRIPT_DIR/celt/" \;
+ echo " Copied CELT headers"
+fi
+
+echo ""
+
+# Copy SILK core decoder sources
+echo "Copying SILK decoder sources..."
+SILK_CORE_FILES=(
+ "silk/dec_API.c"
+ "silk/init_decoder.c"
+ "silk/decode_core.c"
+ "silk/decode_frame.c"
+ "silk/decode_parameters.c"
+ "silk/decode_indices.c"
+ "silk/decode_pulses.c"
+ "silk/decoder_set_fs.c"
+)
+
+for file in "${SILK_CORE_FILES[@]}"; do
+ if [ -f "$PROJECT_ROOT/$file" ]; then
+ cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/silk/"
+ echo " Copied: $file"
+ fi
+done
+
+# Copy SILK signal processing
+SILK_SIGNAL_FILES=(
+ "silk/CNG.c"
+ "silk/PLC.c"
+ "silk/resampler.c"
+ "silk/resampler_down2_3.c"
+ "silk/resampler_down2.c"
+ "silk/resampler_private_AR2.c"
+ "silk/resampler_private_down_FIR.c"
+ "silk/resampler_private_IIR_FIR.c"
+ "silk/resampler_private_up2_HQ.c"
+ "silk/resampler_rom.c"
+ "silk/biquad_alt.c"
+ "silk/bwexpander_32.c"
+ "silk/bwexpander.c"
+ "silk/LP_variable_cutoff.c"
+ "silk/HP_variable_cutoff.c"
+)
+
+for file in "${SILK_SIGNAL_FILES[@]}"; do
+ if [ -f "$PROJECT_ROOT/$file" ]; then
+ cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/silk/"
+ echo " Copied: $file"
+ fi
+done
+
+# Copy SILK NLSF processing
+SILK_NLSF_FILES=(
+ "silk/NLSF_decode.c"
+ "silk/NLSF_unpack.c"
+ "silk/NLSF2A.c"
+ "silk/NLSF_stabilize.c"
+ "silk/A2NLSF.c"
+ "silk/NLSF_VQ_weights_laroia.c"
+ "silk/table_LSF_cos.c"
+ "silk/LPC_inv_pred_gain.c"
+)
+
+for file in "${SILK_NLSF_FILES[@]}"; do
+ if [ -f "$PROJECT_ROOT/$file" ]; then
+ cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/silk/"
+ echo " Copied: $file"
+ fi
+done
+
+# Copy SILK stereo processing
+SILK_STEREO_FILES=(
+ "silk/stereo_MS_to_LR.c"
+ "silk/stereo_decode_pred.c"
+ "silk/stereo_find_predictor.c"
+)
+
+for file in "${SILK_STEREO_FILES[@]}"; do
+ if [ -f "$PROJECT_ROOT/$file" ]; then
+ cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/silk/"
+ echo " Copied: $file"
+ fi
+done
+
+# Copy SILK tables
+SILK_TABLE_FILES=(
+ "silk/tables_gain.c"
+ "silk/tables_LTP.c"
+ "silk/tables_NLSF_CB_NB_MB.c"
+ "silk/tables_NLSF_CB_WB.c"
+ "silk/tables_other.c"
+ "silk/tables_pitch_lag.c"
+ "silk/tables_pulses_per_block.c"
+ "silk/pitch_est_tables.c"
+)
+
+for file in "${SILK_TABLE_FILES[@]}"; do
+ if [ -f "$PROJECT_ROOT/$file" ]; then
+ cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/silk/"
+ echo " Copied: $file"
+ fi
+done
+
+# Copy SILK helper functions
+SILK_HELPER_FILES=(
+ "silk/code_signs.c"
+ "silk/interpolate.c"
+ "silk/shell_coder.c"
+ "silk/decode_pitch.c"
+ "silk/inner_prod_aligned.c"
+ "silk/lin2log.c"
+ "silk/log2lin.c"
+ "silk/LPC_analysis_filter.c"
+ "silk/LPC_fit.c"
+ "silk/sigm_Q15.c"
+ "silk/sort.c"
+ "silk/sum_sqr_shift.c"
+ "silk/gain_quant.c"
+)
+
+for file in "${SILK_HELPER_FILES[@]}"; do
+ if [ -f "$PROJECT_ROOT/$file" ]; then
+ cp "$PROJECT_ROOT/$file" "$SCRIPT_DIR/silk/"
+ echo " Copied: $file"
+ fi
+done
+
+# Copy SILK float implementation
+echo "Copying SILK float implementation..."
+if [ -d "$PROJECT_ROOT/silk/float" ]; then
+ find "$PROJECT_ROOT/silk/float" -name "*.c" -exec cp {} "$SCRIPT_DIR/silk/float/" \;
+ echo " Copied SILK float sources"
+fi
+
+# Copy SILK x86 optimization
+if [ -d "$PROJECT_ROOT/silk/x86" ]; then
+ if [ -f "$PROJECT_ROOT/silk/x86/x86_silk_map.c" ]; then
+ cp "$PROJECT_ROOT/silk/x86/x86_silk_map.c" "$SCRIPT_DIR/silk/x86/"
+ echo " Copied: silk/x86/x86_silk_map.c"
+ fi
+fi
+
+# Copy SILK headers
+echo "Copying SILK headers..."
+if [ -d "$PROJECT_ROOT/silk" ]; then
+ find "$PROJECT_ROOT/silk" -maxdepth 1 -name "*.h" -exec cp {} "$SCRIPT_DIR/silk/" \;
+ echo " Copied SILK headers"
+fi
+
+# Copy additional headers
+echo ""
+echo "Copying additional headers..."
+# Opus API headers
+if [ -f "$PROJECT_ROOT/include/opus_custom.h" ]; then
+ cp "$PROJECT_ROOT/include/opus_custom.h" "$SCRIPT_DIR/include/"
+ echo " Copied: include/opus_custom.h"
+fi
+if [ -f "$PROJECT_ROOT/include/opus_multistream.h" ]; then
+ cp "$PROJECT_ROOT/include/opus_multistream.h" "$SCRIPT_DIR/include/"
+ echo " Copied: include/opus_multistream.h"
+fi
+if [ -f "$PROJECT_ROOT/include/opus_projection.h" ]; then
+ cp "$PROJECT_ROOT/include/opus_projection.h" "$SCRIPT_DIR/include/"
+ echo " Copied: include/opus_projection.h"
+fi
+
+# Copy src headers
+if [ -d "$PROJECT_ROOT/src" ]; then
+ find "$PROJECT_ROOT/src" -maxdepth 1 -name "*.h" -exec cp {} "$SCRIPT_DIR/src_lib/" \;
+ echo " Copied src headers"
+fi
+
+# Copy x86 headers
+if [ -d "$PROJECT_ROOT/celt/x86" ]; then
+ find "$PROJECT_ROOT/celt/x86" -maxdepth 1 -name "*.h" -exec cp {} "$SCRIPT_DIR/celt/x86/" \;
+ echo " Copied CELT x86 headers"
+fi
+if [ -d "$PROJECT_ROOT/silk/x86" ]; then
+ find "$PROJECT_ROOT/silk/x86" -maxdepth 1 -name "*.h" -exec cp {} "$SCRIPT_DIR/silk/x86/" \;
+ echo " Copied SILK x86 headers"
+fi
+
+# Copy config.h from main project
+if [ -f "$PROJECT_ROOT/config.h" ]; then
+ cp "$PROJECT_ROOT/config.h" "$SCRIPT_DIR/config.h"
+ echo " Copied: config.h"
+fi
+
+echo ""
+echo "=========================================="
+echo "Source files copied successfully!"
+echo "=========================================="
+echo ""
+echo "Next steps:"
+echo " 1. Review copied files"
+echo " 2. Run: make -f Makefile.libopus"
+echo " 3. This will create libopus_min.a"
+echo ""
--- /dev/null
+/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
+ Written by Jean-Marc Valin and Koen Vos */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+/**
+ * @file opus.h
+ * @brief Opus reference implementation API
+ */
+
+#ifndef OPUS_H
+#define OPUS_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @mainpage Opus
+ *
+ * The Opus codec is designed for interactive speech and audio transmission over the Internet.
+ * It is designed by the IETF Codec Working Group and incorporates technology from
+ * Skype's SILK codec and Xiph.Org's CELT codec.
+ *
+ * The Opus codec is designed to handle a wide range of interactive audio applications,
+ * including Voice over IP, videoconferencing, in-game chat, and even remote live music
+ * performances. It can scale from low bit-rate narrowband speech to very high quality
+ * stereo music. Its main features are:
+
+ * @li Sampling rates from 8 to 48 kHz
+ * @li Bit-rates from 6 kb/s to 510 kb/s
+ * @li Support for both constant bit-rate (CBR) and variable bit-rate (VBR)
+ * @li Audio bandwidth from narrowband to full-band
+ * @li Support for speech and music
+ * @li Support for mono and stereo
+ * @li Support for multichannel (up to 255 channels)
+ * @li Frame sizes from 2.5 ms to 60 ms
+ * @li Good loss robustness and packet loss concealment (PLC)
+ * @li Floating point and fixed-point implementation
+ *
+ * Documentation sections:
+ * @li @ref opus_encoder
+ * @li @ref opus_decoder
+ * @li @ref opus_repacketizer
+ * @li @ref opus_multistream
+ * @li @ref opus_libinfo
+ * @li @ref opus_custom
+ */
+
+/** @defgroup opus_encoder Opus Encoder
+ * @{
+ *
+ * @brief This page describes the process and functions used to encode Opus.
+ *
+ * Since Opus is a stateful codec, the encoding process starts with creating an encoder
+ * state. This can be done with:
+ *
+ * @code
+ * int error;
+ * OpusEncoder *enc;
+ * enc = opus_encoder_create(Fs, channels, application, &error);
+ * @endcode
+ *
+ * From this point, @c enc can be used for encoding an audio stream. An encoder state
+ * @b must @b not be used for more than one stream at the same time. Similarly, the encoder
+ * state @b must @b not be re-initialized for each frame.
+ *
+ * While opus_encoder_create() allocates memory for the state, it's also possible
+ * to initialize pre-allocated memory:
+ *
+ * @code
+ * int size;
+ * int error;
+ * OpusEncoder *enc;
+ * size = opus_encoder_get_size(channels);
+ * enc = malloc(size);
+ * error = opus_encoder_init(enc, Fs, channels, application);
+ * @endcode
+ *
+ * where opus_encoder_get_size() returns the required size for the encoder state. Note that
+ * future versions of this code may change the size, so no assumptions should be made about it.
+ *
+ * The encoder state is always continuous in memory and only a shallow copy is sufficient
+ * to copy it (e.g. memcpy())
+ *
+ * It is possible to change some of the encoder's settings using the opus_encoder_ctl()
+ * interface. All these settings already default to the recommended value, so they should
+ * only be changed when necessary. The most common settings one may want to change are:
+ *
+ * @code
+ * opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate));
+ * opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
+ * opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal_type));
+ * @endcode
+ *
+ * where
+ *
+ * @arg bitrate is in bits per second (b/s)
+ * @arg complexity is a value from 1 to 10, where 1 is the lowest complexity and 10 is the highest
+ * @arg signal_type is either OPUS_AUTO (default), OPUS_SIGNAL_VOICE, or OPUS_SIGNAL_MUSIC
+ *
+ * See @ref opus_encoderctls and @ref opus_genericctls for a complete list of parameters that can be set or queried. Most parameters can be set or changed at any time during a stream.
+ *
+ * To encode a frame, opus_encode() or opus_encode_float() must be called with exactly one frame (2.5, 5, 10, 20, 40 or 60 ms) of audio data:
+ * @code
+ * len = opus_encode(enc, audio_frame, frame_size, packet, max_packet);
+ * @endcode
+ *
+ * where
+ * <ul>
+ * <li>audio_frame is the audio data in opus_int16 (or float for opus_encode_float())</li>
+ * <li>frame_size is the duration of the frame in samples (per channel)</li>
+ * <li>packet is the byte array to which the compressed data is written</li>
+ * <li>max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended).
+ * Do not use max_packet to control VBR target bitrate, instead use the #OPUS_SET_BITRATE CTL.</li>
+ * </ul>
+ *
+ * opus_encode() and opus_encode_float() return the number of bytes actually written to the packet.
+ * The return value <b>can be negative</b>, which indicates that an error has occurred. If the return value
+ * is 2 bytes or less, then the packet does not need to be transmitted (DTX).
+ *
+ * Once the encoder state if no longer needed, it can be destroyed with
+ *
+ * @code
+ * opus_encoder_destroy(enc);
+ * @endcode
+ *
+ * If the encoder was created with opus_encoder_init() rather than opus_encoder_create(),
+ * then no action is required aside from potentially freeing the memory that was manually
+ * allocated for it (calling free(enc) for the example above)
+ *
+ */
+
+/** Opus encoder state.
+ * This contains the complete state of an Opus encoder.
+ * It is position independent and can be freely copied.
+ * @see opus_encoder_create,opus_encoder_init
+ */
+typedef struct OpusEncoder OpusEncoder;
+
+/** Gets the size of an <code>OpusEncoder</code> structure.
+ * @param[in] channels <tt>int</tt>: Number of channels.
+ * This must be 1 or 2.
+ * @returns The size in bytes.
+ * @note Since this function does not take the application as input, it will overestimate
+ * the size required for OPUS_APPLICATION_RESTRICTED_SILK and OPUS_APPLICATION_RESTRICTED_CELT.
+ * That is generally not a problem, except when trying to know the size to use for a copy.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels);
+
+/**
+ */
+
+/** Allocates and initializes an encoder state.
+ * There are three coding modes:
+ *
+ * @ref OPUS_APPLICATION_VOIP gives best quality at a given bitrate for voice
+ * signals. It enhances the input signal by high-pass filtering and
+ * emphasizing formants and harmonics. Optionally it includes in-band
+ * forward error correction to protect against packet loss. Use this
+ * mode for typical VoIP applications. Because of the enhancement,
+ * even at high bitrates the output may sound different from the input.
+ *
+ * @ref OPUS_APPLICATION_AUDIO gives best quality at a given bitrate for most
+ * non-voice signals like music. Use this mode for music and mixed
+ * (music/voice) content, broadcast, and applications requiring less
+ * than 15 ms of coding delay.
+ *
+ * @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY configures low-delay mode that
+ * disables the speech-optimized mode in exchange for slightly reduced delay.
+ * This mode can only be set on an newly initialized or freshly reset encoder
+ * because it changes the codec delay.
+ *
+ * This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution).
+ * @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz)
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
+ * @param [in] application <tt>int</tt>: Coding mode (one of @ref OPUS_APPLICATION_VOIP, @ref OPUS_APPLICATION_AUDIO, or @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ * @param [out] error <tt>int*</tt>: @ref opus_errorcodes
+ * @note Regardless of the sampling rate and number channels selected, the Opus encoder
+ * can switch to a lower audio bandwidth or number of channels if the bitrate
+ * selected is too low. This also means that it is safe to always use 48 kHz stereo input
+ * and let the encoder optimize the encoding.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create(
+ opus_int32 Fs,
+ int channels,
+ int application,
+ int *error
+);
+
+/** Initializes a previously allocated encoder state
+ * The memory pointed to by st must be at least the size returned by opus_encoder_get_size().
+ * This is intended for applications which use their own allocator instead of malloc.
+ * @see opus_encoder_create(),opus_encoder_get_size()
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
+ * @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz)
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
+ * @param [in] application <tt>int</tt>: Coding mode (one of OPUS_APPLICATION_VOIP, OPUS_APPLICATION_AUDIO, or OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ * @retval #OPUS_OK Success or @ref opus_errorcodes
+ */
+OPUS_EXPORT int opus_encoder_init(
+ OpusEncoder *st,
+ opus_int32 Fs,
+ int channels,
+ int application
+) OPUS_ARG_NONNULL(1);
+
+/** Encodes an Opus frame.
+ * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
+ * @param [in] pcm <tt>opus_int16*</tt>: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16)
+ * @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
+ * input signal.
+ * This must be an Opus frame size for
+ * the encoder's sampling rate.
+ * For example, at 48 kHz the permitted
+ * values are 120, 240, 480, 960, 1920,
+ * and 2880.
+ * Passing in a duration of less than
+ * 10 ms (480 samples at 48 kHz) will
+ * prevent the encoder from using the LPC
+ * or hybrid modes.
+ * @param [out] data <tt>unsigned char*</tt>: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode(
+ OpusEncoder *st,
+ const opus_int16 *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes an Opus frame.
+ * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
+ * @param [in] pcm <tt>opus_int32*</tt>: Input signal (interleaved if 2 channels) representing (or slightly exceeding) 24-bit values. length is frame_size*channels*sizeof(opus_int32)
+ * @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
+ * input signal.
+ * This must be an Opus frame size for
+ * the encoder's sampling rate.
+ * For example, at 48 kHz the permitted
+ * values are 120, 240, 480, 960, 1920,
+ * and 2880.
+ * Passing in a duration of less than
+ * 10 ms (480 samples at 48 kHz) will
+ * prevent the encoder from using the LPC
+ * or hybrid modes.
+ * @param [out] data <tt>unsigned char*</tt>: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode24(
+ OpusEncoder *st,
+ const opus_int32 *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes an Opus frame from floating point input.
+ * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
+ * @param [in] pcm <tt>float*</tt>: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0.
+ * Samples with a range beyond +/-1.0 are supported but will
+ * be clipped by decoders using the integer API and should
+ * only be used if it is known that the far end supports
+ * extended dynamic range.
+ * length is frame_size*channels*sizeof(float)
+ * @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
+ * input signal.
+ * This must be an Opus frame size for
+ * the encoder's sampling rate.
+ * For example, at 48 kHz the permitted
+ * values are 120, 240, 480, 960, 1920,
+ * and 2880.
+ * Passing in a duration of less than
+ * 10 ms (480 samples at 48 kHz) will
+ * prevent the encoder from using the LPC
+ * or hybrid modes.
+ * @param [out] data <tt>unsigned char*</tt>: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float(
+ OpusEncoder *st,
+ const float *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Frees an <code>OpusEncoder</code> allocated by opus_encoder_create().
+ * @param[in] st <tt>OpusEncoder*</tt>: State to be freed.
+ */
+OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st);
+
+/** Perform a CTL function on an Opus encoder.
+ *
+ * Generally the request and subsequent arguments are generated
+ * by a convenience macro.
+ * @param st <tt>OpusEncoder*</tt>: Encoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls or
+ * @ref opus_encoderctls.
+ * @see opus_genericctls
+ * @see opus_encoderctls
+ */
+OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+/**@}*/
+
+/** @defgroup opus_decoder Opus Decoder
+ * @{
+ *
+ * @brief This page describes the process and functions used to decode Opus.
+ *
+ * The decoding process also starts with creating a decoder
+ * state. This can be done with:
+ * @code
+ * int error;
+ * OpusDecoder *dec;
+ * dec = opus_decoder_create(Fs, channels, &error);
+ * @endcode
+ * where
+ * @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000
+ * @li channels is the number of channels (1 or 2)
+ * @li error will hold the error code in case of failure (or #OPUS_OK on success)
+ * @li the return value is a newly created decoder state to be used for decoding
+ *
+ * While opus_decoder_create() allocates memory for the state, it's also possible
+ * to initialize pre-allocated memory:
+ * @code
+ * int size;
+ * int error;
+ * OpusDecoder *dec;
+ * size = opus_decoder_get_size(channels);
+ * dec = malloc(size);
+ * error = opus_decoder_init(dec, Fs, channels);
+ * @endcode
+ * where opus_decoder_get_size() returns the required size for the decoder state. Note that
+ * future versions of this code may change the size, so no assumptions should be made about it.
+ *
+ * The decoder state is always continuous in memory and only a shallow copy is sufficient
+ * to copy it (e.g. memcpy())
+ *
+ * To decode a frame, opus_decode() or opus_decode_float() must be called with a packet of compressed audio data:
+ * @code
+ * frame_size = opus_decode(dec, packet, len, decoded, max_size, 0);
+ * @endcode
+ * where
+ *
+ * @li packet is the byte array containing the compressed data
+ * @li len is the exact number of bytes contained in the packet
+ * @li decoded is the decoded audio data in opus_int16 (or float for opus_decode_float())
+ * @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array
+ *
+ * opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet.
+ * If that value is negative, then an error has occurred. This can occur if the packet is corrupted or if the audio
+ * buffer is too small to hold the decoded audio.
+ *
+ * Opus is a stateful codec with overlapping blocks and as a result Opus
+ * packets are not coded independently of each other. Packets must be
+ * passed into the decoder serially and in the correct order for a correct
+ * decode. Lost packets can be replaced with loss concealment by calling
+ * the decoder with a null pointer and zero length for the missing packet.
+ *
+ * A single codec state may only be accessed from a single thread at
+ * a time and any required locking must be performed by the caller. Separate
+ * streams must be decoded with separate decoder states and can be decoded
+ * in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK
+ * defined.
+ *
+ */
+
+/** Opus decoder state.
+ * This contains the complete state of an Opus decoder.
+ * It is position independent and can be freely copied.
+ * @see opus_decoder_create,opus_decoder_init
+ */
+typedef struct OpusDecoder OpusDecoder;
+
+/** Opus DRED decoder.
+ * This contains the complete state of an Opus DRED decoder.
+ * It is position independent and can be freely copied.
+ * @see opus_dred_decoder_create,opus_dred_decoder_init
+ */
+typedef struct OpusDREDDecoder OpusDREDDecoder;
+
+
+/** Opus DRED state.
+ * This contains the complete state of an Opus DRED packet.
+ * It is position independent and can be freely copied.
+ * @see opus_dred_create,opus_dred_init
+ */
+typedef struct OpusDRED OpusDRED;
+
+/** Gets the size of an <code>OpusDecoder</code> structure.
+ * @param [in] channels <tt>int</tt>: Number of channels.
+ * This must be 1 or 2.
+ * @returns The size in bytes.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels);
+
+/** Allocates and initializes a decoder state.
+ * @param [in] Fs <tt>opus_int32</tt>: Sample rate to decode at (Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode
+ * @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
+ *
+ * Internally Opus stores data at 48000 Hz, so that should be the default
+ * value for Fs. However, the decoder can efficiently decode to buffers
+ * at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use
+ * data at the full sample rate, or knows the compressed data doesn't
+ * use the full frequency range, it can request decoding at a reduced
+ * rate. Likewise, the decoder is capable of filling in either mono or
+ * interleaved stereo pcm buffers, at the caller's request.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create(
+ opus_int32 Fs,
+ int channels,
+ int *error
+);
+
+/** Initializes a previously allocated decoder state.
+ * The state must be at least the size returned by opus_decoder_get_size().
+ * This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @param [in] st <tt>OpusDecoder*</tt>: Decoder state.
+ * @param [in] Fs <tt>opus_int32</tt>: Sampling rate to decode to (Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode
+ * @retval #OPUS_OK Success or @ref opus_errorcodes
+ */
+OPUS_EXPORT int opus_decoder_init(
+ OpusDecoder *st,
+ opus_int32 Fs,
+ int channels
+) OPUS_ARG_NONNULL(1);
+
+/** Decode an Opus packet.
+ * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+ * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+ * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload*
+ * @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
+ * is frame_size*channels*sizeof(opus_int16)
+ * @param [in] frame_size Number of samples per channel of available space in \a pcm.
+ * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
+ * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
+ * then frame_size needs to be exactly the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
+ * FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
+ * @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
+ * decoded. If no such data is available, the frame is decoded as if it were lost.
+ * @returns Number of decoded samples per channel or @ref opus_errorcodes
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode(
+ OpusDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ opus_int16 *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode an Opus packet.
+ * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+ * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+ * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload*
+ * @param [out] pcm <tt>opus_int32*</tt>: Output signal (interleaved if 2 channels) representing (or slightly exceeding) 24-bit values. length
+ * is frame_size*channels*sizeof(opus_int32)
+ * @param [in] frame_size Number of samples per channel of available space in \a pcm.
+ * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
+ * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
+ * then frame_size needs to be exactly the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
+ * FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
+ * @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
+ * decoded. If no such data is available, the frame is decoded as if it were lost.
+ * @returns Number of decoded samples or @ref opus_errorcodes
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode24(
+ OpusDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ opus_int32 *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode an Opus packet with floating point output.
+ * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+ * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+ * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload
+ * @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
+ * is frame_size*channels*sizeof(float)
+ * @param [in] frame_size Number of samples per channel of available space in \a pcm.
+ * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
+ * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
+ * then frame_size needs to be exactly the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
+ * FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
+ * @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
+ * decoded. If no such data is available the frame is decoded as if it were lost.
+ * @returns Number of decoded samples per channel or @ref opus_errorcodes
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float(
+ OpusDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ float *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Perform a CTL function on an Opus decoder.
+ *
+ * Generally the request and subsequent arguments are generated
+ * by a convenience macro.
+ * @param st <tt>OpusDecoder*</tt>: Decoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls or
+ * @ref opus_decoderctls.
+ * @see opus_genericctls
+ * @see opus_decoderctls
+ */
+OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+/** Frees an <code>OpusDecoder</code> allocated by opus_decoder_create().
+ * @param[in] st <tt>OpusDecoder*</tt>: State to be freed.
+ */
+OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);
+
+/** Gets the size of an <code>OpusDREDDecoder</code> structure.
+ * @returns The size in bytes.
+ */
+OPUS_EXPORT int opus_dred_decoder_get_size(void);
+
+/** Allocates and initializes an OpusDREDDecoder state.
+ * @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
+ */
+OPUS_EXPORT OpusDREDDecoder *opus_dred_decoder_create(int *error);
+
+/** Initializes an <code>OpusDREDDecoder</code> state.
+ * @param[in] dec <tt>OpusDREDDecoder*</tt>: State to be initialized.
+ */
+OPUS_EXPORT int opus_dred_decoder_init(OpusDREDDecoder *dec);
+
+/** Frees an <code>OpusDREDDecoder</code> allocated by opus_dred_decoder_create().
+ * @param[in] dec <tt>OpusDREDDecoder*</tt>: State to be freed.
+ */
+OPUS_EXPORT void opus_dred_decoder_destroy(OpusDREDDecoder *dec);
+
+/** Perform a CTL function on an Opus DRED decoder.
+ *
+ * Generally the request and subsequent arguments are generated
+ * by a convenience macro.
+ * @param dred_dec <tt>OpusDREDDecoder*</tt>: DRED Decoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls or
+ * @ref opus_decoderctls.
+ * @see opus_genericctls
+ * @see opus_decoderctls
+ */
+OPUS_EXPORT int opus_dred_decoder_ctl(OpusDREDDecoder *dred_dec, int request, ...);
+
+/** Gets the size of an <code>OpusDRED</code> structure.
+ * @returns The size in bytes.
+ */
+OPUS_EXPORT int opus_dred_get_size(void);
+
+/** Allocates and initializes a DRED state.
+ * @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
+ */
+OPUS_EXPORT OpusDRED *opus_dred_alloc(int *error);
+
+/** Frees an <code>OpusDRED</code> allocated by opus_dred_create().
+ * @param[in] dec <tt>OpusDRED*</tt>: State to be freed.
+ */
+OPUS_EXPORT void opus_dred_free(OpusDRED *dec);
+
+/** Decode an Opus DRED packet.
+ * @param [in] dred_dec <tt>OpusDRED*</tt>: DRED Decoder state
+ * @param [in] dred <tt>OpusDRED*</tt>: DRED state
+ * @param [in] data <tt>char*</tt>: Input payload
+ * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload
+ * @param [in] max_dred_samples <tt>opus_int32</tt>: Maximum number of DRED samples that may be needed (if available in the packet).
+ * @param [in] sampling_rate <tt>opus_int32</tt>: Sampling rate used for max_dred_samples argument. Needs not match the actual sampling rate of the decoder.
+ * @param [out] dred_end <tt>opus_int32*</tt>: Number of non-encoded (silence) samples between the DRED timestamp and the last DRED sample.
+ * @param [in] defer_processing <tt>int</tt>: Flag (0 or 1). If set to one, the CPU-intensive part of the DRED decoding is deferred until opus_dred_process() is called.
+ * @returns Offset (positive) of the first decoded DRED samples, zero if no DRED is present, or @ref opus_errorcodes
+ */
+OPUS_EXPORT int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const unsigned char *data, opus_int32 len, opus_int32 max_dred_samples, opus_int32 sampling_rate, int *dred_end, int defer_processing) OPUS_ARG_NONNULL(1);
+
+/** Finish decoding an Opus DRED packet. The function only needs to be called if opus_dred_parse() was called with defer_processing=1.
+ * The source and destination will often be the same DRED state.
+ * @param [in] dred_dec <tt>OpusDRED*</tt>: DRED Decoder state
+ * @param [in] src <tt>OpusDRED*</tt>: Source DRED state to start the processing from.
+ * @param [out] dst <tt>OpusDRED*</tt>: Destination DRED state to store the updated state after processing.
+ * @returns @ref opus_errorcodes
+ */
+OPUS_EXPORT int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src, OpusDRED *dst);
+
+/** Decode audio from an Opus DRED packet with 16-bit output.
+ * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+ * @param [in] dred <tt>OpusDRED*</tt>: DRED state
+ * @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
+ * @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
+ * is frame_size*channels*sizeof(opus_int16)
+ * @param [in] frame_size Number of samples per channel to decode in \a pcm.
+ * frame_size <b>must</b> be a multiple of 2.5 ms.
+ * @returns Number of decoded samples or @ref opus_errorcodes
+ */
+OPUS_EXPORT int opus_decoder_dred_decode(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int16 *pcm, opus_int32 frame_size);
+
+/** Decode audio from an Opus DRED packet with 24-bit output.
+ * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+ * @param [in] dred <tt>OpusDRED*</tt>: DRED state
+ * @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
+ * @param [out] pcm <tt>opus_int32*</tt>: Output signal (interleaved if 2 channels). length
+ * is frame_size*channels*sizeof(opus_int16)
+ * @param [in] frame_size Number of samples per channel to decode in \a pcm.
+ * frame_size <b>must</b> be a multiple of 2.5 ms.
+ * @returns Number of decoded samples or @ref opus_errorcodes
+ */
+OPUS_EXPORT int opus_decoder_dred_decode24(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int32 *pcm, opus_int32 frame_size);
+
+/** Decode audio from an Opus DRED packet with floating point output.
+ * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+ * @param [in] dred <tt>OpusDRED*</tt>: DRED state
+ * @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
+ * @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
+ * is frame_size*channels*sizeof(float)
+ * @param [in] frame_size Number of samples per channel to decode in \a pcm.
+ * frame_size <b>must</b> be a multiple of 2.5 ms.
+ * @returns Number of decoded samples or @ref opus_errorcodes
+ */
+OPUS_EXPORT int opus_decoder_dred_decode_float(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, float *pcm, opus_int32 frame_size);
+
+
+/** Parse an opus packet into one or more frames.
+ * Opus_decode will perform this operation internally so most applications do
+ * not need to use this function.
+ * This function does not copy the frames, the returned pointers are pointers into
+ * the input packet.
+ * @param [in] data <tt>char*</tt>: Opus packet to be parsed
+ * @param [in] len <tt>opus_int32</tt>: size of data
+ * @param [out] out_toc <tt>char*</tt>: TOC pointer
+ * @param [out] frames <tt>char*[48]</tt> encapsulated frames
+ * @param [out] size <tt>opus_int16[48]</tt> sizes of the encapsulated frames
+ * @param [out] payload_offset <tt>int*</tt>: returns the position of the payload within the packet (in bytes)
+ * @returns number of frames
+ */
+OPUS_EXPORT int opus_packet_parse(
+ const unsigned char *data,
+ opus_int32 len,
+ unsigned char *out_toc,
+ const unsigned char *frames[48],
+ opus_int16 size[48],
+ int *payload_offset
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5);
+
+/** Gets the bandwidth of an Opus packet.
+ * @param [in] data <tt>char*</tt>: Opus packet
+ * @retval OPUS_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass)
+ * @retval OPUS_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass)
+ * @retval OPUS_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass)
+ * @retval OPUS_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass)
+ * @retval OPUS_BANDWIDTH_FULLBAND Fullband (20kHz bandpass)
+ * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of samples per frame from an Opus packet.
+ * @param [in] data <tt>char*</tt>: Opus packet.
+ * This must contain at least one byte of
+ * data.
+ * @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz.
+ * This must be a multiple of 400, or
+ * inaccurate results will be returned.
+ * @returns Number of samples per frame.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of channels from an Opus packet.
+ * @param [in] data <tt>char*</tt>: Opus packet
+ * @returns Number of channels
+ * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsigned char *data) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of frames in an Opus packet.
+ * @param [in] packet <tt>char*</tt>: Opus packet
+ * @param [in] len <tt>opus_int32</tt>: Length of packet
+ * @returns Number of frames
+ * @retval OPUS_BAD_ARG Insufficient data was passed to the function
+ * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1);
+
+/** Gets the number of samples of an Opus packet.
+ * @param [in] packet <tt>char*</tt>: Opus packet
+ * @param [in] len <tt>opus_int32</tt>: Length of packet
+ * @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz.
+ * This must be a multiple of 400, or
+ * inaccurate results will be returned.
+ * @returns Number of samples
+ * @retval OPUS_BAD_ARG Insufficient data was passed to the function
+ * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1);
+
+/** Checks whether an Opus packet has LBRR.
+ * @param [in] packet <tt>char*</tt>: Opus packet
+ * @param [in] len <tt>opus_int32</tt>: Length of packet
+ * @returns 1 is LBRR is present, 0 otherwise
+ * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_has_lbrr(const unsigned char packet[], opus_int32 len);
+
+/** Gets the number of samples of an Opus packet.
+ * @param [in] dec <tt>OpusDecoder*</tt>: Decoder state
+ * @param [in] packet <tt>char*</tt>: Opus packet
+ * @param [in] len <tt>opus_int32</tt>: Length of packet
+ * @returns Number of samples
+ * @retval OPUS_BAD_ARG Insufficient data was passed to the function
+ * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+
+/** Applies soft-clipping to bring a float signal within the [-1,1] range. If
+ * the signal is already in that range, nothing is done. If there are values
+ * outside of [-1,1], then the signal is clipped as smoothly as possible to
+ * both fit in the range and avoid creating excessive distortion in the
+ * process.
+ * @param [in,out] pcm <tt>float*</tt>: Input PCM and modified PCM
+ * @param [in] frame_size <tt>int</tt> Number of samples per channel to process
+ * @param [in] channels <tt>int</tt>: Number of channels
+ * @param [in,out] softclip_mem <tt>float*</tt>: State memory for the soft clipping process (one float per channel, initialized to zero)
+ */
+OPUS_EXPORT void opus_pcm_soft_clip(float *pcm, int frame_size, int channels, float *softclip_mem);
+
+
+/**@}*/
+
+/** @defgroup opus_repacketizer Repacketizer
+ * @{
+ *
+ * The repacketizer can be used to merge multiple Opus packets into a single
+ * packet or alternatively to split Opus packets that have previously been
+ * merged. Splitting valid Opus packets is always guaranteed to succeed,
+ * whereas merging valid packets only succeeds if all frames have the same
+ * mode, bandwidth, and frame size, and when the total duration of the merged
+ * packet is no more than 120 ms. The 120 ms limit comes from the
+ * specification and limits decoder memory requirements at a point where
+ * framing overhead becomes negligible.
+ *
+ * The repacketizer currently only operates on elementary Opus
+ * streams. It will not manipulate multistream packets successfully, except in
+ * the degenerate case where they consist of data from a single stream.
+ *
+ * The repacketizing process starts with creating a repacketizer state, either
+ * by calling opus_repacketizer_create() or by allocating the memory yourself,
+ * e.g.,
+ * @code
+ * OpusRepacketizer *rp;
+ * rp = (OpusRepacketizer*)malloc(opus_repacketizer_get_size());
+ * if (rp != NULL)
+ * opus_repacketizer_init(rp);
+ * @endcode
+ *
+ * Then the application should submit packets with opus_repacketizer_cat(),
+ * extract new packets with opus_repacketizer_out() or
+ * opus_repacketizer_out_range(), and then reset the state for the next set of
+ * input packets via opus_repacketizer_init().
+ *
+ * For example, to split a sequence of packets into individual frames:
+ * @code
+ * unsigned char *data;
+ * int len;
+ * while (get_next_packet(&data, &len))
+ * {
+ * unsigned char out[1276];
+ * opus_int32 out_len;
+ * int nb_frames;
+ * int err;
+ * int i;
+ * err = opus_repacketizer_cat(rp, data, len);
+ * if (err != OPUS_OK)
+ * {
+ * release_packet(data);
+ * return err;
+ * }
+ * nb_frames = opus_repacketizer_get_nb_frames(rp);
+ * for (i = 0; i < nb_frames; i++)
+ * {
+ * out_len = opus_repacketizer_out_range(rp, i, i+1, out, sizeof(out));
+ * if (out_len < 0)
+ * {
+ * release_packet(data);
+ * return (int)out_len;
+ * }
+ * output_next_packet(out, out_len);
+ * }
+ * opus_repacketizer_init(rp);
+ * release_packet(data);
+ * }
+ * @endcode
+ *
+ * Alternatively, to combine a sequence of frames into packets that each
+ * contain up to <code>TARGET_DURATION_MS</code> milliseconds of data:
+ * @code
+ * // The maximum number of packets with duration TARGET_DURATION_MS occurs
+ * // when the frame size is 2.5 ms, for a total of (TARGET_DURATION_MS*2/5)
+ * // packets.
+ * unsigned char *data[(TARGET_DURATION_MS*2/5)+1];
+ * opus_int32 len[(TARGET_DURATION_MS*2/5)+1];
+ * int nb_packets;
+ * unsigned char out[1277*(TARGET_DURATION_MS*2/2)];
+ * opus_int32 out_len;
+ * int prev_toc;
+ * nb_packets = 0;
+ * while (get_next_packet(data+nb_packets, len+nb_packets))
+ * {
+ * int nb_frames;
+ * int err;
+ * nb_frames = opus_packet_get_nb_frames(data[nb_packets], len[nb_packets]);
+ * if (nb_frames < 1)
+ * {
+ * release_packets(data, nb_packets+1);
+ * return nb_frames;
+ * }
+ * nb_frames += opus_repacketizer_get_nb_frames(rp);
+ * // If adding the next packet would exceed our target, or it has an
+ * // incompatible TOC sequence, output the packets we already have before
+ * // submitting it.
+ * // N.B., The nb_packets > 0 check ensures we've submitted at least one
+ * // packet since the last call to opus_repacketizer_init(). Otherwise a
+ * // single packet longer than TARGET_DURATION_MS would cause us to try to
+ * // output an (invalid) empty packet. It also ensures that prev_toc has
+ * // been set to a valid value. Additionally, len[nb_packets] > 0 is
+ * // guaranteed by the call to opus_packet_get_nb_frames() above, so the
+ * // reference to data[nb_packets][0] should be valid.
+ * if (nb_packets > 0 && (
+ * ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) ||
+ * opus_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames >
+ * TARGET_DURATION_MS*48))
+ * {
+ * out_len = opus_repacketizer_out(rp, out, sizeof(out));
+ * if (out_len < 0)
+ * {
+ * release_packets(data, nb_packets+1);
+ * return (int)out_len;
+ * }
+ * output_next_packet(out, out_len);
+ * opus_repacketizer_init(rp);
+ * release_packets(data, nb_packets);
+ * data[0] = data[nb_packets];
+ * len[0] = len[nb_packets];
+ * nb_packets = 0;
+ * }
+ * err = opus_repacketizer_cat(rp, data[nb_packets], len[nb_packets]);
+ * if (err != OPUS_OK)
+ * {
+ * release_packets(data, nb_packets+1);
+ * return err;
+ * }
+ * prev_toc = data[nb_packets][0];
+ * nb_packets++;
+ * }
+ * // Output the final, partial packet.
+ * if (nb_packets > 0)
+ * {
+ * out_len = opus_repacketizer_out(rp, out, sizeof(out));
+ * release_packets(data, nb_packets);
+ * if (out_len < 0)
+ * return (int)out_len;
+ * output_next_packet(out, out_len);
+ * }
+ * @endcode
+ *
+ * An alternate way of merging packets is to simply call opus_repacketizer_cat()
+ * unconditionally until it fails. At that point, the merged packet can be
+ * obtained with opus_repacketizer_out() and the input packet for which
+ * opus_repacketizer_cat() needs to be re-added to a newly reinitialized
+ * repacketizer state.
+ */
+
+typedef struct OpusRepacketizer OpusRepacketizer;
+
+/** Gets the size of an <code>OpusRepacketizer</code> structure.
+ * @returns The size in bytes.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void);
+
+/** (Re)initializes a previously allocated repacketizer state.
+ * The state must be at least the size returned by opus_repacketizer_get_size().
+ * This can be used for applications which use their own allocator instead of
+ * malloc().
+ * It must also be called to reset the queue of packets waiting to be
+ * repacketized, which is necessary if the maximum packet duration of 120 ms
+ * is reached or if you wish to submit packets with a different Opus
+ * configuration (coding mode, audio bandwidth, frame size, or channel count).
+ * Failure to do so will prevent a new packet from being added with
+ * opus_repacketizer_cat().
+ * @see opus_repacketizer_create
+ * @see opus_repacketizer_get_size
+ * @see opus_repacketizer_cat
+ * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state to
+ * (re)initialize.
+ * @returns A pointer to the same repacketizer state that was passed in.
+ */
+OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
+
+/** Allocates memory and initializes the new repacketizer with
+ * opus_repacketizer_init().
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void);
+
+/** Frees an <code>OpusRepacketizer</code> allocated by
+ * opus_repacketizer_create().
+ * @param[in] rp <tt>OpusRepacketizer*</tt>: State to be freed.
+ */
+OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp);
+
+/** Add a packet to the current repacketizer state.
+ * This packet must match the configuration of any packets already submitted
+ * for repacketization since the last call to opus_repacketizer_init().
+ * This means that it must have the same coding mode, audio bandwidth, frame
+ * size, and channel count.
+ * This can be checked in advance by examining the top 6 bits of the first
+ * byte of the packet, and ensuring they match the top 6 bits of the first
+ * byte of any previously submitted packet.
+ * The total duration of audio in the repacketizer state also must not exceed
+ * 120 ms, the maximum duration of a single packet, after adding this packet.
+ *
+ * The contents of the current repacketizer state can be extracted into new
+ * packets using opus_repacketizer_out() or opus_repacketizer_out_range().
+ *
+ * In order to add a packet with a different configuration or to add more
+ * audio beyond 120 ms, you must clear the repacketizer state by calling
+ * opus_repacketizer_init().
+ * If a packet is too large to add to the current repacketizer state, no part
+ * of it is added, even if it contains multiple frames, some of which might
+ * fit.
+ * If you wish to be able to add parts of such packets, you should first use
+ * another repacketizer to split the packet into pieces and add them
+ * individually.
+ * @see opus_repacketizer_out_range
+ * @see opus_repacketizer_out
+ * @see opus_repacketizer_init
+ * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state to which to
+ * add the packet.
+ * @param[in] data <tt>const unsigned char*</tt>: The packet data.
+ * The application must ensure
+ * this pointer remains valid
+ * until the next call to
+ * opus_repacketizer_init() or
+ * opus_repacketizer_destroy().
+ * @param len <tt>opus_int32</tt>: The number of bytes in the packet data.
+ * @returns An error code indicating whether or not the operation succeeded.
+ * @retval #OPUS_OK The packet's contents have been added to the repacketizer
+ * state.
+ * @retval #OPUS_INVALID_PACKET The packet did not have a valid TOC sequence,
+ * the packet's TOC sequence was not compatible
+ * with previously submitted packets (because
+ * the coding mode, audio bandwidth, frame size,
+ * or channel count did not match), or adding
+ * this packet would increase the total amount of
+ * audio stored in the repacketizer state to more
+ * than 120 ms.
+ */
+OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+
+
+/** Construct a new packet from data previously submitted to the repacketizer
+ * state via opus_repacketizer_cat().
+ * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state from which to
+ * construct the new packet.
+ * @param begin <tt>int</tt>: The index of the first frame in the current
+ * repacketizer state to include in the output.
+ * @param end <tt>int</tt>: One past the index of the last frame in the
+ * current repacketizer state to include in the
+ * output.
+ * @param[out] data <tt>const unsigned char*</tt>: The buffer in which to
+ * store the output packet.
+ * @param maxlen <tt>opus_int32</tt>: The maximum number of bytes to store in
+ * the output buffer. In order to guarantee
+ * success, this should be at least
+ * <code>1276</code> for a single frame,
+ * or for multiple frames,
+ * <code>1277*(end-begin)</code>.
+ * However, <code>1*(end-begin)</code> plus
+ * the size of all packet data submitted to
+ * the repacketizer since the last call to
+ * opus_repacketizer_init() or
+ * opus_repacketizer_create() is also
+ * sufficient, and possibly much smaller.
+ * @returns The total size of the output packet on success, or an error code
+ * on failure.
+ * @retval #OPUS_BAD_ARG <code>[begin,end)</code> was an invalid range of
+ * frames (begin < 0, begin >= end, or end >
+ * opus_repacketizer_get_nb_frames()).
+ * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
+ * complete output packet.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Return the total number of frames contained in packet data submitted to
+ * the repacketizer state so far via opus_repacketizer_cat() since the last
+ * call to opus_repacketizer_init() or opus_repacketizer_create().
+ * This defines the valid range of packets that can be extracted with
+ * opus_repacketizer_out_range() or opus_repacketizer_out().
+ * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state containing the
+ * frames.
+ * @returns The total number of frames contained in the packet data submitted
+ * to the repacketizer state.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
+
+/** Construct a new packet from data previously submitted to the repacketizer
+ * state via opus_repacketizer_cat().
+ * This is a convenience routine that returns all the data submitted so far
+ * in a single packet.
+ * It is equivalent to calling
+ * @code
+ * opus_repacketizer_out_range(rp, 0, opus_repacketizer_get_nb_frames(rp),
+ * data, maxlen)
+ * @endcode
+ * @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state from which to
+ * construct the new packet.
+ * @param[out] data <tt>const unsigned char*</tt>: The buffer in which to
+ * store the output packet.
+ * @param maxlen <tt>opus_int32</tt>: The maximum number of bytes to store in
+ * the output buffer. In order to guarantee
+ * success, this should be at least
+ * <code>1277*opus_repacketizer_get_nb_frames(rp)</code>.
+ * However,
+ * <code>1*opus_repacketizer_get_nb_frames(rp)</code>
+ * plus the size of all packet data
+ * submitted to the repacketizer since the
+ * last call to opus_repacketizer_init() or
+ * opus_repacketizer_create() is also
+ * sufficient, and possibly much smaller.
+ * @returns The total size of the output packet on success, or an error code
+ * on failure.
+ * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
+ * complete output packet.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1);
+
+/** Pads a given Opus packet to a larger size (possibly changing the TOC sequence).
+ * @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
+ * packet to pad.
+ * @param len <tt>opus_int32</tt>: The size of the packet.
+ * This must be at least 1.
+ * @param new_len <tt>opus_int32</tt>: The desired size of the packet after padding.
+ * This must be at least as large as len.
+ * @returns an error code
+ * @retval #OPUS_OK \a on success.
+ * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len.
+ * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
+ */
+OPUS_EXPORT int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len);
+
+/** Remove all padding from a given Opus packet and rewrite the TOC sequence to
+ * minimize space usage.
+ * @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
+ * packet to strip.
+ * @param len <tt>opus_int32</tt>: The size of the packet.
+ * This must be at least 1.
+ * @returns The new size of the output packet on success, or an error code
+ * on failure.
+ * @retval #OPUS_BAD_ARG \a len was less than 1.
+ * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len);
+
+/** Pads a given Opus multi-stream packet to a larger size (possibly changing the TOC sequence).
+ * @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
+ * packet to pad.
+ * @param len <tt>opus_int32</tt>: The size of the packet.
+ * This must be at least 1.
+ * @param new_len <tt>opus_int32</tt>: The desired size of the packet after padding.
+ * This must be at least 1.
+ * @param nb_streams <tt>opus_int32</tt>: The number of streams (not channels) in the packet.
+ * This must be at least as large as len.
+ * @returns an error code
+ * @retval #OPUS_OK \a on success.
+ * @retval #OPUS_BAD_ARG \a len was less than 1.
+ * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
+ */
+OPUS_EXPORT int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams);
+
+/** Remove all padding from a given Opus multi-stream packet and rewrite the TOC sequence to
+ * minimize space usage.
+ * @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
+ * packet to strip.
+ * @param len <tt>opus_int32</tt>: The size of the packet.
+ * This must be at least 1.
+ * @param nb_streams <tt>opus_int32</tt>: The number of streams (not channels) in the packet.
+ * This must be at least 1.
+ * @returns The new size of the output packet on success, or an error code
+ * on failure.
+ * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len.
+ * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_H */
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO
+ Copyright (c) 2007-2009 Xiph.Org Foundation
+ Copyright (c) 2008-2012 Gregory Maxwell
+ Written by Jean-Marc Valin and Gregory Maxwell */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+/**
+ @file opus_custom.h
+ @brief Opus-Custom reference implementation API
+ */
+
+#ifndef OPUS_CUSTOM_H
+#define OPUS_CUSTOM_H
+
+#include "opus_defines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+# define OPUS_CUSTOM_EXPORT OPUS_EXPORT
+# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT
+#else
+# define OPUS_CUSTOM_EXPORT
+# ifdef OPUS_BUILD
+# define OPUS_CUSTOM_EXPORT_STATIC static OPUS_INLINE
+# else
+# define OPUS_CUSTOM_EXPORT_STATIC
+# endif
+#endif
+
+/** @defgroup opus_custom Opus Custom
+ * @{
+ * Opus Custom is an optional part of the Opus specification and
+ * reference implementation which uses a distinct API from the regular
+ * API and supports frame sizes that are not normally supported.\ Use
+ * of Opus Custom is discouraged for all but very special applications
+ * for which a frame size different from 2.5, 5, 10, or 20 ms is needed
+ * (for either complexity or latency reasons) and where interoperability
+ * is less important.
+ *
+ * In addition to the interoperability limitations the use of Opus custom
+ * disables a substantial chunk of the codec and generally lowers the
+ * quality available at a given bitrate. Normally when an application needs
+ * a different frame size from the codec it should buffer to match the
+ * sizes but this adds a small amount of delay which may be important
+ * in some very low latency applications. Some transports (especially
+ * constant rate RF transports) may also work best with frames of
+ * particular durations.
+ *
+ * Libopus only supports custom modes if they are enabled at compile time.
+ *
+ * The Opus Custom API is similar to the regular API but the
+ * @ref opus_encoder_create and @ref opus_decoder_create calls take
+ * an additional mode parameter which is a structure produced by
+ * a call to @ref opus_custom_mode_create. Both the encoder and decoder
+ * must create a mode using the same sample rate (fs) and frame size
+ * (frame size) so these parameters must either be signaled out of band
+ * or fixed in a particular implementation.
+ *
+ * Similar to regular Opus the custom modes support on the fly frame size
+ * switching, but the sizes available depend on the particular frame size in
+ * use. For some initial frame sizes on a single on the fly size is available.
+ */
+
+/** Contains the state of an encoder. One encoder state is needed
+ for each stream. It is initialized once at the beginning of the
+ stream. Do *not* re-initialize the state for every frame.
+ @brief Encoder state
+ */
+typedef struct OpusCustomEncoder OpusCustomEncoder;
+
+/** State of the decoder. One decoder state is needed for each stream.
+ It is initialized once at the beginning of the stream. Do *not*
+ re-initialize the state for every frame.
+ @brief Decoder state
+ */
+typedef struct OpusCustomDecoder OpusCustomDecoder;
+
+/** The mode contains all the information necessary to create an
+ encoder. Both the encoder and decoder need to be initialized
+ with exactly the same mode, otherwise the output will be
+ corrupted. The mode MUST NOT BE DESTROYED until the encoders and
+ decoders that use it are destroyed as well.
+ @brief Mode configuration
+ */
+typedef struct OpusCustomMode OpusCustomMode;
+
+/** Creates a new mode struct. This will be passed to an encoder or
+ * decoder. The mode MUST NOT BE DESTROYED until the encoders and
+ * decoders that use it are destroyed as well.
+ * @param [in] Fs <tt>int</tt>: Sampling rate (8000 to 96000 Hz)
+ * @param [in] frame_size <tt>int</tt>: Number of samples (per channel) to encode in each
+ * packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes)
+ * @param [out] error <tt>int*</tt>: Returned error code (if NULL, no error will be returned)
+ * @return A newly created mode
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error);
+
+/** Destroys a mode struct. Only call this after all encoders and
+ * decoders using this mode are destroyed as well.
+ * @param [in] mode <tt>OpusCustomMode*</tt>: Mode to be freed.
+ */
+OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode);
+
+
+#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C)
+
+/* Encoder */
+/** Gets the size of an OpusCustomEncoder structure.
+ * @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
+ * @param [in] channels <tt>int</tt>: Number of channels
+ * @returns size
+ */
+OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size(
+ const OpusCustomMode *mode,
+ int channels
+) OPUS_ARG_NONNULL(1);
+
+#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
+/** Initializes a previously allocated encoder state
+ * The memory pointed to by st must be the size returned by opus_custom_encoder_get_size.
+ * This is intended for applications which use their own allocator instead of malloc.
+ * @see opus_custom_encoder_create(),opus_custom_encoder_get_size()
+ * To reset a previously initialized state use the OPUS_RESET_STATE CTL.
+ * @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
+ * @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
+ * the stream (must be the same characteristics as used for the
+ * decoder)
+ * @param [in] channels <tt>int</tt>: Number of channels
+ * @return OPUS_OK Success or @ref opus_errorcodes
+ */
+OPUS_CUSTOM_EXPORT int opus_custom_encoder_init(
+ OpusCustomEncoder *st,
+ const OpusCustomMode *mode,
+ int channels
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+# endif
+#endif
+
+
+/** Creates a new encoder state. Each stream needs its own encoder
+ * state (can't be shared across simultaneous streams).
+ * @param [in] mode <tt>OpusCustomMode*</tt>: Contains all the information about the characteristics of
+ * the stream (must be the same characteristics as used for the
+ * decoder)
+ * @param [in] channels <tt>int</tt>: Number of channels
+ * @param [out] error <tt>int*</tt>: Returns an error code
+ * @return Newly created encoder state.
+*/
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create(
+ const OpusCustomMode *mode,
+ int channels,
+ int *error
+) OPUS_ARG_NONNULL(1);
+
+
+/** Destroys an encoder state.
+ * @param[in] st <tt>OpusCustomEncoder*</tt>: State to be freed.
+ */
+OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st);
+
+/** Encodes a frame of audio.
+ * @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
+ * @param [in] pcm <tt>float*</tt>: PCM audio in float format, with a normal range of +/-1.0.
+ * Samples with a range beyond +/-1.0 are supported but will
+ * be clipped by decoders using the integer API and should
+ * only be used if it is known that the far end supports
+ * extended dynamic range. There must be exactly
+ * frame_size samples per channel.
+ * @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
+ * @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
+ * @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
+ * (can change from one frame to another)
+ * @return Number of bytes written to "compressed".
+ * If negative, an error has occurred (see error codes). It is IMPORTANT that
+ * the length returned be somehow transmitted to the decoder. Otherwise, no
+ * decoding is possible.
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float(
+ OpusCustomEncoder *st,
+ const float *pcm,
+ int frame_size,
+ unsigned char *compressed,
+ int maxCompressedBytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes a frame of audio.
+ * @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
+ * @param [in] pcm <tt>opus_int16*</tt>: PCM audio in signed 16-bit format (native endian).
+ * There must be exactly frame_size samples per channel.
+ * @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
+ * @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
+ * @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
+ * (can change from one frame to another)
+ * @return Number of bytes written to "compressed".
+ * If negative, an error has occurred (see error codes). It is IMPORTANT that
+ * the length returned be somehow transmitted to the decoder. Otherwise, no
+ * decoding is possible.
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode(
+ OpusCustomEncoder *st,
+ const opus_int16 *pcm,
+ int frame_size,
+ unsigned char *compressed,
+ int maxCompressedBytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes a frame of audio.
+ * @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
+ * @param [in] pcm <tt>opus_int32*</tt>: PCM audio in signed 32-bit format (native endian) representing (or slightly exceeding) 24-bit values.
+ * There must be exactly frame_size samples per channel.
+ * @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
+ * @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
+ * @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
+ * (can change from one frame to another)
+ * @return Number of bytes written to "compressed".
+ * If negative, an error has occurred (see error codes). It is IMPORTANT that
+ * the length returned be somehow transmitted to the decoder. Otherwise, no
+ * decoding is possible.
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode24(
+ OpusCustomEncoder *st,
+ const opus_int32 *pcm,
+ int frame_size,
+ unsigned char *compressed,
+ int maxCompressedBytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Perform a CTL function on an Opus custom encoder.
+ *
+ * Generally the request and subsequent arguments are generated
+ * by a convenience macro.
+ * @see opus_encoderctls
+ */
+OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
+
+
+#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C)
+/* Decoder */
+
+/** Gets the size of an OpusCustomDecoder structure.
+ * @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
+ * @param [in] channels <tt>int</tt>: Number of channels
+ * @returns size
+ */
+OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size(
+ const OpusCustomMode *mode,
+ int channels
+) OPUS_ARG_NONNULL(1);
+
+/** Initializes a previously allocated decoder state
+ * The memory pointed to by st must be the size returned by opus_custom_decoder_get_size.
+ * This is intended for applications which use their own allocator instead of malloc.
+ * @see opus_custom_decoder_create(),opus_custom_decoder_get_size()
+ * To reset a previously initialized state use the OPUS_RESET_STATE CTL.
+ * @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
+ * @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
+ * the stream (must be the same characteristics as used for the
+ * encoder)
+ * @param [in] channels <tt>int</tt>: Number of channels
+ * @return OPUS_OK Success or @ref opus_errorcodes
+ */
+OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init(
+ OpusCustomDecoder *st,
+ const OpusCustomMode *mode,
+ int channels
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
+
+#endif
+
+
+/** Creates a new decoder state. Each stream needs its own decoder state (can't
+ * be shared across simultaneous streams).
+ * @param [in] mode <tt>OpusCustomMode</tt>: Contains all the information about the characteristics of the
+ * stream (must be the same characteristics as used for the encoder)
+ * @param [in] channels <tt>int</tt>: Number of channels
+ * @param [out] error <tt>int*</tt>: Returns an error code
+ * @return Newly created decoder state.
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create(
+ const OpusCustomMode *mode,
+ int channels,
+ int *error
+) OPUS_ARG_NONNULL(1);
+
+/** Destroys a decoder state.
+ * @param[in] st <tt>OpusCustomDecoder*</tt>: State to be freed.
+ */
+OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st);
+
+/** Decode an opus custom frame with floating point output
+ * @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
+ * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+ * @param [in] len <tt>int</tt>: Number of bytes in payload
+ * @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
+ * is frame_size*channels*sizeof(float)
+ * @param [in] frame_size Number of samples per channel of available space in *pcm.
+ * @returns Number of decoded samples or @ref opus_errorcodes
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float(
+ OpusCustomDecoder *st,
+ const unsigned char *data,
+ int len,
+ float *pcm,
+ int frame_size
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode an opus custom frame
+ * @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
+ * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+ * @param [in] len <tt>int</tt>: Number of bytes in payload
+ * @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
+ * is frame_size*channels*sizeof(opus_int16)
+ * @param [in] frame_size Number of samples per channel of available space in *pcm.
+ * @returns Number of decoded samples or @ref opus_errorcodes
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode(
+ OpusCustomDecoder *st,
+ const unsigned char *data,
+ int len,
+ opus_int16 *pcm,
+ int frame_size
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode an opus custom frame
+ * @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
+ * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+ * @param [in] len <tt>int</tt>: Number of bytes in payload
+ * @param [out] pcm <tt>opus_int32*</tt>: Output signal (interleaved if 2 channels) representing (or slightly exceeding) 24-bit values. length
+ * is frame_size*channels*sizeof(opus_int32)
+ * @param [in] frame_size Number of samples per channel of available space in *pcm.
+ * @returns Number of decoded samples or @ref opus_errorcodes
+ */
+OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode24(
+ OpusCustomDecoder *st,
+ const unsigned char *data,
+ int len,
+ opus_int32 *pcm,
+ int frame_size
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Perform a CTL function on an Opus custom decoder.
+ *
+ * Generally the request and subsequent arguments are generated
+ * by a convenience macro.
+ * @see opus_genericctls
+ */
+OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_CUSTOM_H */
--- /dev/null
+/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
+ Written by Jean-Marc Valin and Koen Vos */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+/**
+ * @file opus_defines.h
+ * @brief Opus reference implementation constants
+ */
+
+#ifndef OPUS_DEFINES_H
+#define OPUS_DEFINES_H
+
+#include "opus_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup opus_errorcodes Error codes
+ * @{
+ */
+/** No error @hideinitializer*/
+#define OPUS_OK 0
+/** One or more invalid/out of range arguments @hideinitializer*/
+#define OPUS_BAD_ARG -1
+/** Not enough bytes allocated in the buffer @hideinitializer*/
+#define OPUS_BUFFER_TOO_SMALL -2
+/** An internal error was detected @hideinitializer*/
+#define OPUS_INTERNAL_ERROR -3
+/** The compressed data passed is corrupted @hideinitializer*/
+#define OPUS_INVALID_PACKET -4
+/** Invalid/unsupported request number @hideinitializer*/
+#define OPUS_UNIMPLEMENTED -5
+/** An encoder or decoder structure is invalid or already freed @hideinitializer*/
+#define OPUS_INVALID_STATE -6
+/** Memory allocation has failed @hideinitializer*/
+#define OPUS_ALLOC_FAIL -7
+/**@}*/
+
+/** @cond OPUS_INTERNAL_DOC */
+/**Export control for opus functions */
+
+#ifndef OPUS_EXPORT
+# if defined(_WIN32)
+# if defined(OPUS_BUILD) && defined(DLL_EXPORT)
+# define OPUS_EXPORT __declspec(dllexport)
+# else
+# define OPUS_EXPORT
+# endif
+# elif defined(__GNUC__) && defined(OPUS_BUILD)
+# define OPUS_EXPORT __attribute__ ((visibility ("default")))
+# else
+# define OPUS_EXPORT
+# endif
+#endif
+
+# if !defined(OPUS_GNUC_PREREQ)
+# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
+# define OPUS_GNUC_PREREQ(_maj,_min) \
+ ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
+# else
+# define OPUS_GNUC_PREREQ(_maj,_min) 0
+# endif
+# endif
+
+#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
+# if OPUS_GNUC_PREREQ(3,0)
+# define OPUS_RESTRICT __restrict__
+# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
+# define OPUS_RESTRICT __restrict
+# else
+# define OPUS_RESTRICT
+# endif
+#else
+# define OPUS_RESTRICT restrict
+#endif
+
+#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
+# if OPUS_GNUC_PREREQ(2,7)
+# define OPUS_INLINE __inline__
+# elif (defined(_MSC_VER))
+# define OPUS_INLINE __inline
+# else
+# define OPUS_INLINE
+# endif
+#else
+# define OPUS_INLINE inline
+#endif
+
+/**Warning attributes for opus functions
+ * NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out
+ * some paranoid null checks. */
+#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
+# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
+#else
+# define OPUS_WARN_UNUSED_RESULT
+#endif
+#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
+# define OPUS_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
+#else
+# define OPUS_ARG_NONNULL(_x)
+#endif
+
+/** These are the actual Encoder CTL ID numbers.
+ * They should not be used directly by applications.
+ * In general, SETs should be even and GETs should be odd.*/
+#define OPUS_SET_APPLICATION_REQUEST 4000
+#define OPUS_GET_APPLICATION_REQUEST 4001
+#define OPUS_SET_BITRATE_REQUEST 4002
+#define OPUS_GET_BITRATE_REQUEST 4003
+#define OPUS_SET_MAX_BANDWIDTH_REQUEST 4004
+#define OPUS_GET_MAX_BANDWIDTH_REQUEST 4005
+#define OPUS_SET_VBR_REQUEST 4006
+#define OPUS_GET_VBR_REQUEST 4007
+#define OPUS_SET_BANDWIDTH_REQUEST 4008
+#define OPUS_GET_BANDWIDTH_REQUEST 4009
+#define OPUS_SET_COMPLEXITY_REQUEST 4010
+#define OPUS_GET_COMPLEXITY_REQUEST 4011
+#define OPUS_SET_INBAND_FEC_REQUEST 4012
+#define OPUS_GET_INBAND_FEC_REQUEST 4013
+#define OPUS_SET_PACKET_LOSS_PERC_REQUEST 4014
+#define OPUS_GET_PACKET_LOSS_PERC_REQUEST 4015
+#define OPUS_SET_DTX_REQUEST 4016
+#define OPUS_GET_DTX_REQUEST 4017
+#define OPUS_SET_VBR_CONSTRAINT_REQUEST 4020
+#define OPUS_GET_VBR_CONSTRAINT_REQUEST 4021
+#define OPUS_SET_FORCE_CHANNELS_REQUEST 4022
+#define OPUS_GET_FORCE_CHANNELS_REQUEST 4023
+#define OPUS_SET_SIGNAL_REQUEST 4024
+#define OPUS_GET_SIGNAL_REQUEST 4025
+#define OPUS_GET_LOOKAHEAD_REQUEST 4027
+/* #define OPUS_RESET_STATE 4028 */
+#define OPUS_GET_SAMPLE_RATE_REQUEST 4029
+#define OPUS_GET_FINAL_RANGE_REQUEST 4031
+#define OPUS_GET_PITCH_REQUEST 4033
+#define OPUS_SET_GAIN_REQUEST 4034
+#define OPUS_GET_GAIN_REQUEST 4045 /* Should have been 4035 */
+#define OPUS_SET_LSB_DEPTH_REQUEST 4036
+#define OPUS_GET_LSB_DEPTH_REQUEST 4037
+#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039
+#define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040
+#define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041
+#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042
+#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043
+/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
+#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
+#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
+#define OPUS_GET_IN_DTX_REQUEST 4049
+#define OPUS_SET_DRED_DURATION_REQUEST 4050
+#define OPUS_GET_DRED_DURATION_REQUEST 4051
+#define OPUS_SET_DNN_BLOB_REQUEST 4052
+/*#define OPUS_GET_DNN_BLOB_REQUEST 4053 */
+#define OPUS_SET_OSCE_BWE_REQUEST 4054
+#define OPUS_GET_OSCE_BWE_REQUEST 4055
+#define OPUS_SET_QEXT_REQUEST 4056
+#define OPUS_GET_QEXT_REQUEST 4057
+#define OPUS_SET_IGNORE_EXTENSIONS_REQUEST 4058
+#define OPUS_GET_IGNORE_EXTENSIONS_REQUEST 4059
+
+/** Defines for the presence of extended APIs. */
+#define OPUS_HAVE_OPUS_PROJECTION_H
+
+/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
+#define opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
+
+#ifdef DISABLE_PTR_CHECK
+/* Disable checks to prevent ubsan from complaining about NULL checks
+ in test_opus_api. */
+#define opus_check_int_ptr(ptr) (ptr)
+#define opus_check_uint_ptr(ptr) (ptr)
+#define opus_check_uint8_ptr(ptr) (ptr)
+#define opus_check_val16_ptr(ptr) (ptr)
+#define opus_check_void_ptr(ptr) (ptr)
+#else
+#define opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
+#define opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
+#define opus_check_uint8_ptr(ptr) ((ptr) + ((ptr) - (opus_uint8*)(ptr)))
+#define opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr)))
+#define opus_check_void_ptr(x) ((void)((void *)0 == (x)), (x))
+#endif
+/** @endcond */
+
+/** @defgroup opus_ctlvalues Pre-defined values for CTL interface
+ * @see opus_genericctls, opus_encoderctls
+ * @{
+ */
+/* Values for the various encoder CTLs */
+#define OPUS_AUTO -1000 /**<Auto/default setting @hideinitializer*/
+#define OPUS_BITRATE_MAX -1 /**<Maximum bitrate @hideinitializer*/
+
+/** Best for most VoIP/videoconference applications where listening quality and intelligibility matter most
+ * @hideinitializer */
+#define OPUS_APPLICATION_VOIP 2048
+/** Best for broadcast/high-fidelity application where the decoded audio should be as close as possible to the input
+ * @hideinitializer */
+#define OPUS_APPLICATION_AUDIO 2049
+/** Only use when lowest-achievable latency is what matters most. Voice-optimized modes cannot be used.
+ * @hideinitializer */
+#define OPUS_APPLICATION_RESTRICTED_LOWDELAY 2051
+/** Experts only: forces SILK encoding; don't allocate CELT state at all. Disables OPUS_SET_APPLICATION. */
+#define OPUS_APPLICATION_RESTRICTED_SILK 2052
+/** Experts only: forces CELT encoding; don't allocate SILK state at all. Disables OPUS_SET_APPLICATION. */
+#define OPUS_APPLICATION_RESTRICTED_CELT 2053
+
+#define OPUS_SIGNAL_VOICE 3001 /**< Signal being encoded is voice */
+#define OPUS_SIGNAL_MUSIC 3002 /**< Signal being encoded is music */
+#define OPUS_BANDWIDTH_NARROWBAND 1101 /**< 4 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_MEDIUMBAND 1102 /**< 6 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_WIDEBAND 1103 /**< 8 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_SUPERWIDEBAND 1104 /**<12 kHz bandpass @hideinitializer*/
+#define OPUS_BANDWIDTH_FULLBAND 1105 /**<20 kHz bandpass @hideinitializer*/
+
+#define OPUS_FRAMESIZE_ARG 5000 /**< Select frame size from the argument (default) */
+#define OPUS_FRAMESIZE_2_5_MS 5001 /**< Use 2.5 ms frames */
+#define OPUS_FRAMESIZE_5_MS 5002 /**< Use 5 ms frames */
+#define OPUS_FRAMESIZE_10_MS 5003 /**< Use 10 ms frames */
+#define OPUS_FRAMESIZE_20_MS 5004 /**< Use 20 ms frames */
+#define OPUS_FRAMESIZE_40_MS 5005 /**< Use 40 ms frames */
+#define OPUS_FRAMESIZE_60_MS 5006 /**< Use 60 ms frames */
+#define OPUS_FRAMESIZE_80_MS 5007 /**< Use 80 ms frames */
+#define OPUS_FRAMESIZE_100_MS 5008 /**< Use 100 ms frames */
+#define OPUS_FRAMESIZE_120_MS 5009 /**< Use 120 ms frames */
+
+/**@}*/
+
+
+/** @defgroup opus_encoderctls Encoder related CTLs
+ *
+ * These are convenience macros for use with the \c opus_encode_ctl
+ * interface. They are used to generate the appropriate series of
+ * arguments for that call, passing the correct type, size and so
+ * on as expected for each particular request.
+ *
+ * Some usage examples:
+ *
+ * @code
+ * int ret;
+ * ret = opus_encoder_ctl(enc_ctx, OPUS_SET_BANDWIDTH(OPUS_AUTO));
+ * if (ret != OPUS_OK) return ret;
+ *
+ * opus_int32 rate;
+ * opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&rate));
+ *
+ * opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
+ * @endcode
+ *
+ * @see opus_genericctls, opus_encoder
+ * @{
+ */
+
+/** Configures the encoder's computational complexity.
+ * The supported range is 0-10 inclusive with 10 representing the highest complexity.
+ * @see OPUS_GET_COMPLEXITY
+ * @param[in] x <tt>opus_int32</tt>: Allowed values: 0-10, inclusive.
+ *
+ * @hideinitializer */
+#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, opus_check_int(x)
+/** Gets the encoder's complexity configuration.
+ * @see OPUS_SET_COMPLEXITY
+ * @param[out] x <tt>opus_int32 *</tt>: Returns a value in the range 0-10,
+ * inclusive.
+ * @hideinitializer */
+#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, opus_check_int_ptr(x)
+
+/** Configures the bitrate in the encoder.
+ * Rates from 500 to 512000 bits per second are meaningful, as well as the
+ * special values #OPUS_AUTO and #OPUS_BITRATE_MAX.
+ * The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much
+ * rate as it can, which is useful for controlling the rate by adjusting the
+ * output buffer size.
+ * @see OPUS_GET_BITRATE
+ * @param[in] x <tt>opus_int32</tt>: Bitrate in bits per second. The default
+ * is determined based on the number of
+ * channels and the input sampling rate.
+ * @hideinitializer */
+#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, opus_check_int(x)
+/** Gets the encoder's bitrate configuration.
+ * @see OPUS_SET_BITRATE
+ * @param[out] x <tt>opus_int32 *</tt>: Returns the bitrate in bits per second.
+ * The default is determined based on the
+ * number of channels and the input
+ * sampling rate.
+ * @hideinitializer */
+#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, opus_check_int_ptr(x)
+
+/** Enables or disables variable bitrate (VBR) in the encoder.
+ * The configured bitrate may not be met exactly because frames must
+ * be an integer number of bytes in length.
+ * @see OPUS_GET_VBR
+ * @see OPUS_SET_VBR_CONSTRAINT
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>0</dt><dd>Hard CBR. For LPC/hybrid modes at very low bit-rate, this can
+ * cause noticeable quality degradation.</dd>
+ * <dt>1</dt><dd>VBR (default). The exact type of VBR is controlled by
+ * #OPUS_SET_VBR_CONSTRAINT.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, opus_check_int(x)
+/** Determine if variable bitrate (VBR) is enabled in the encoder.
+ * @see OPUS_SET_VBR
+ * @see OPUS_GET_VBR_CONSTRAINT
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>0</dt><dd>Hard CBR.</dd>
+ * <dt>1</dt><dd>VBR (default). The exact type of VBR may be retrieved via
+ * #OPUS_GET_VBR_CONSTRAINT.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, opus_check_int_ptr(x)
+
+/** Enables or disables constrained VBR in the encoder.
+ * This setting is ignored when the encoder is in CBR mode.
+ * @warning Only the MDCT mode of Opus currently heeds the constraint.
+ * Speech mode ignores it completely, hybrid mode may fail to obey it
+ * if the LPC layer uses more bitrate than the constraint would have
+ * permitted.
+ * @see OPUS_GET_VBR_CONSTRAINT
+ * @see OPUS_SET_VBR
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>0</dt><dd>Unconstrained VBR.</dd>
+ * <dt>1</dt><dd>Constrained VBR (default). This creates a maximum of one
+ * frame of buffering delay assuming a transport with a
+ * serialization speed of the nominal bitrate.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, opus_check_int(x)
+/** Determine if constrained VBR is enabled in the encoder.
+ * @see OPUS_SET_VBR_CONSTRAINT
+ * @see OPUS_GET_VBR
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>0</dt><dd>Unconstrained VBR.</dd>
+ * <dt>1</dt><dd>Constrained VBR (default).</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, opus_check_int_ptr(x)
+
+/** Configures mono/stereo forcing in the encoder.
+ * This can force the encoder to produce packets encoded as either mono or
+ * stereo, regardless of the format of the input audio. This is useful when
+ * the caller knows that the input signal is currently a mono source embedded
+ * in a stereo stream.
+ * @see OPUS_GET_FORCE_CHANNELS
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
+ * <dt>1</dt> <dd>Forced mono</dd>
+ * <dt>2</dt> <dd>Forced stereo</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, opus_check_int(x)
+/** Gets the encoder's forced channel configuration.
+ * @see OPUS_SET_FORCE_CHANNELS
+ * @param[out] x <tt>opus_int32 *</tt>:
+ * <dl>
+ * <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
+ * <dt>1</dt> <dd>Forced mono</dd>
+ * <dt>2</dt> <dd>Forced stereo</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, opus_check_int_ptr(x)
+
+/** Configures the maximum bandpass that the encoder will select automatically.
+ * Applications should normally use this instead of #OPUS_SET_BANDWIDTH
+ * (leaving that set to the default, #OPUS_AUTO). This allows the
+ * application to set an upper bound based on the type of input it is
+ * providing, but still gives the encoder the freedom to reduce the bandpass
+ * when the bitrate becomes too low, for better overall quality.
+ * @see OPUS_GET_MAX_BANDWIDTH
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
+ * <dt>OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
+ * <dt>OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
+ * <dt>OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+ * <dt>OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband (default)</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, opus_check_int(x)
+
+/** Gets the encoder's configured maximum allowed bandpass.
+ * @see OPUS_SET_MAX_BANDWIDTH
+ * @param[out] x <tt>opus_int32 *</tt>: Allowed values:
+ * <dl>
+ * <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband (default)</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, opus_check_int_ptr(x)
+
+/** Sets the encoder's bandpass to a specific value.
+ * This prevents the encoder from automatically selecting the bandpass based
+ * on the available bitrate. If an application knows the bandpass of the input
+ * audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH
+ * instead, which still gives the encoder the freedom to reduce the bandpass
+ * when the bitrate becomes too low, for better overall quality.
+ * @see OPUS_GET_BANDWIDTH
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
+ * <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, opus_check_int(x)
+
+/** Configures the type of signal being encoded.
+ * This is a hint which helps the encoder's mode selection.
+ * @see OPUS_GET_SIGNAL
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
+ * <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
+ * <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured signal type.
+ * @see OPUS_SET_SIGNAL
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
+ * <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
+ * <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, opus_check_int_ptr(x)
+
+
+/** Configures the encoder's intended application.
+ * The initial value is a mandatory argument to the encoder_create function.
+ * @see OPUS_GET_APPLICATION
+ * @param[in] x <tt>opus_int32</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>#OPUS_APPLICATION_VOIP</dt>
+ * <dd>Process signal for improved speech intelligibility.</dd>
+ * <dt>#OPUS_APPLICATION_AUDIO</dt>
+ * <dd>Favor faithfulness to the original input.</dd>
+ * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+ * <dd>Configure the minimum possible coding delay by disabling certain modes
+ * of operation.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured application.
+ * @see OPUS_SET_APPLICATION
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>#OPUS_APPLICATION_VOIP</dt>
+ * <dd>Process signal for improved speech intelligibility.</dd>
+ * <dt>#OPUS_APPLICATION_AUDIO</dt>
+ * <dd>Favor faithfulness to the original input.</dd>
+ * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+ * <dd>Configure the minimum possible coding delay by disabling certain modes
+ * of operation.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, opus_check_int_ptr(x)
+
+/** Gets the total samples of delay added by the entire codec.
+ * This can be queried by the encoder and then the provided number of samples can be
+ * skipped on from the start of the decoder's output to provide time aligned input
+ * and output. From the perspective of a decoding application the real data begins this many
+ * samples late.
+ *
+ * The decoder contribution to this delay is identical for all decoders, but the
+ * encoder portion of the delay may vary from implementation to implementation,
+ * version to version, or even depend on the encoder's initial configuration.
+ * Applications needing delay compensation should call this CTL rather than
+ * hard-coding a value.
+ * @param[out] x <tt>opus_int32 *</tt>: Number of lookahead samples
+ * @hideinitializer */
+#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, opus_check_int_ptr(x)
+
+/** Configures the encoder's use of inband forward error correction (FEC).
+ * @note This is only applicable to the LPC layer
+ * @see OPUS_GET_INBAND_FEC
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>0</dt><dd>Disable inband FEC (default).</dd>
+ * <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd>
+ * <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, opus_check_int(x)
+/** Gets encoder's configured use of inband forward error correction.
+ * @see OPUS_SET_INBAND_FEC
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>0</dt><dd>Inband FEC disabled (default).</dd>
+ * <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd>
+ * <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, opus_check_int_ptr(x)
+
+/** Configures the encoder's expected packet loss percentage.
+ * Higher values trigger progressively more loss resistant behavior in the encoder
+ * at the expense of quality at a given bitrate in the absence of packet loss, but
+ * greater quality under loss.
+ * @see OPUS_GET_PACKET_LOSS_PERC
+ * @param[in] x <tt>opus_int32</tt>: Loss percentage in the range 0-100, inclusive (default: 0).
+ * @hideinitializer */
+#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured packet loss percentage.
+ * @see OPUS_SET_PACKET_LOSS_PERC
+ * @param[out] x <tt>opus_int32 *</tt>: Returns the configured loss percentage
+ * in the range 0-100, inclusive (default: 0).
+ * @hideinitializer */
+#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, opus_check_int_ptr(x)
+
+/** Configures the encoder's use of discontinuous transmission (DTX).
+ * @note This is only applicable to the LPC layer
+ * @see OPUS_GET_DTX
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>0</dt><dd>Disable DTX (default).</dd>
+ * <dt>1</dt><dd>Enabled DTX.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, opus_check_int(x)
+/** Gets encoder's configured use of discontinuous transmission.
+ * @see OPUS_SET_DTX
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>0</dt><dd>DTX disabled (default).</dd>
+ * <dt>1</dt><dd>DTX enabled.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, opus_check_int_ptr(x)
+/** Configures the depth of signal being encoded.
+ *
+ * This is a hint which helps the encoder identify silence and near-silence.
+ * It represents the number of significant bits of linear intensity below
+ * which the signal contains ignorable quantization or other noise.
+ *
+ * For example, OPUS_SET_LSB_DEPTH(14) would be an appropriate setting
+ * for G.711 u-law input. OPUS_SET_LSB_DEPTH(16) would be appropriate
+ * for 16-bit linear pcm input with opus_encode_float().
+ *
+ * When using opus_encode() instead of opus_encode_float(), or when libopus
+ * is compiled for fixed-point, the encoder uses the minimum of the value
+ * set here and the value 16.
+ *
+ * @see OPUS_GET_LSB_DEPTH
+ * @param[in] x <tt>opus_int32</tt>: Input precision in bits, between 8 and 24
+ * (default: 24).
+ * @hideinitializer */
+#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured signal depth.
+ * @see OPUS_SET_LSB_DEPTH
+ * @param[out] x <tt>opus_int32 *</tt>: Input precision in bits, between 8 and
+ * 24 (default: 24).
+ * @hideinitializer */
+#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, opus_check_int_ptr(x)
+
+/** Configures the encoder's use of variable duration frames.
+ * When variable duration is enabled, the encoder is free to use a shorter frame
+ * size than the one requested in the opus_encode*() call.
+ * It is then the user's responsibility
+ * to verify how much audio was encoded by checking the ToC byte of the encoded
+ * packet. The part of the audio that was not encoded needs to be resent to the
+ * encoder for the next call. Do not use this option unless you <b>really</b>
+ * know what you are doing.
+ * @see OPUS_GET_EXPERT_FRAME_DURATION
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
+ * <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured use of variable duration frames.
+ * @see OPUS_SET_EXPERT_FRAME_DURATION
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
+ * <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
+ * <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, opus_check_int_ptr(x)
+
+/** If set to 1, disables almost all use of prediction, making frames almost
+ * completely independent. This reduces quality.
+ * @see OPUS_GET_PREDICTION_DISABLED
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>0</dt><dd>Enable prediction (default).</dd>
+ * <dt>1</dt><dd>Disable prediction.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_SET_PREDICTION_DISABLED(x) OPUS_SET_PREDICTION_DISABLED_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured prediction status.
+ * @see OPUS_SET_PREDICTION_DISABLED
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>0</dt><dd>Prediction enabled (default).</dd>
+ * <dt>1</dt><dd>Prediction disabled.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, opus_check_int_ptr(x)
+
+/** If non-zero, enables Deep Redundancy (DRED) and use the specified maximum number of 10-ms redundant frames
+ * @hideinitializer */
+#define OPUS_SET_DRED_DURATION(x) OPUS_SET_DRED_DURATION_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured Deep Redundancy (DRED) maximum number of frames.
+ * @hideinitializer */
+#define OPUS_GET_DRED_DURATION(x) OPUS_GET_DRED_DURATION_REQUEST, opus_check_int_ptr(x)
+
+/** Provide external DNN weights from binary object (only when explicitly built without the weights)
+ * @hideinitializer */
+#define OPUS_SET_DNN_BLOB(data, len) OPUS_SET_DNN_BLOB_REQUEST, opus_check_void_ptr(data), opus_check_int(len)
+
+/** If set to 1, enables quality extension (QEXT), otherwise disables it (default). Warning: This will *hurt* audio quality unless operating at
+ a very high bitrate.
+ * @hideinitializer */
+#define OPUS_SET_QEXT(x) OPUS_SET_QEXT_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured quality extension (QEXT).
+ * @hideinitializer */
+#define OPUS_GET_QEXT(x) OPUS_GET_QEXT_REQUEST, opus_check_int_ptr(x)
+
+/**@}*/
+
+/** @defgroup opus_genericctls Generic CTLs
+ *
+ * These macros are used with the \c opus_decoder_ctl and
+ * \c opus_encoder_ctl calls to generate a particular
+ * request.
+ *
+ * When called on an \c OpusDecoder they apply to that
+ * particular decoder instance. When called on an
+ * \c OpusEncoder they apply to the corresponding setting
+ * on that encoder instance, if present.
+ *
+ * Some usage examples:
+ *
+ * @code
+ * int ret;
+ * opus_int32 pitch;
+ * ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch));
+ * if (ret == OPUS_OK) return ret;
+ *
+ * opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
+ * opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE);
+ *
+ * opus_int32 enc_bw, dec_bw;
+ * opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw));
+ * opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw));
+ * if (enc_bw != dec_bw) {
+ * printf("packet bandwidth mismatch!\n");
+ * }
+ * @endcode
+ *
+ * @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls
+ * @{
+ */
+
+/** Resets the codec state to be equivalent to a freshly initialized state.
+ * This should be called when switching streams in order to prevent
+ * the back to back decoding from giving different results from
+ * one at a time decoding.
+ * @hideinitializer */
+#define OPUS_RESET_STATE 4028
+
+/** Gets the final state of the codec's entropy coder.
+ * This is used for testing purposes,
+ * The encoder and decoder state should be identical after coding a payload
+ * (assuming no data corruption or software bugs)
+ *
+ * @param[out] x <tt>opus_uint32 *</tt>: Entropy coder state
+ *
+ * @hideinitializer */
+#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, opus_check_uint_ptr(x)
+
+/** Gets the encoder's configured bandpass or the decoder's last bandpass.
+ * @see OPUS_SET_BANDWIDTH
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
+ * <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
+ * <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, opus_check_int_ptr(x)
+
+/** Gets the sampling rate the encoder or decoder was initialized with.
+ * This simply returns the <code>Fs</code> value passed to opus_encoder_init()
+ * or opus_decoder_init().
+ * @param[out] x <tt>opus_int32 *</tt>: Sampling rate of encoder or decoder.
+ * @hideinitializer
+ */
+#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, opus_check_int_ptr(x)
+
+/** If set to 1, disables the use of phase inversion for intensity stereo,
+ * improving the quality of mono downmixes, but slightly reducing normal
+ * stereo quality. Disabling phase inversion in the decoder does not comply
+ * with RFC 6716, although it does not cause any interoperability issue and
+ * is expected to become part of the Opus standard once RFC 6716 is updated
+ * by draft-ietf-codec-opus-update.
+ * @see OPUS_GET_PHASE_INVERSION_DISABLED
+ * @param[in] x <tt>opus_int32</tt>: Allowed values:
+ * <dl>
+ * <dt>0</dt><dd>Enable phase inversion (default).</dd>
+ * <dt>1</dt><dd>Disable phase inversion.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_SET_PHASE_INVERSION_DISABLED(x) OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured phase inversion status.
+ * @see OPUS_SET_PHASE_INVERSION_DISABLED
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>0</dt><dd>Stereo phase inversion enabled (default).</dd>
+ * <dt>1</dt><dd>Stereo phase inversion disabled.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, opus_check_int_ptr(x)
+/** Gets the DTX state of the encoder.
+ * Returns whether the last encoded frame was either a comfort noise update
+ * during DTX or not encoded because of DTX.
+ * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+ * <dl>
+ * <dt>0</dt><dd>The encoder is not in DTX.</dd>
+ * <dt>1</dt><dd>The encoder is in DTX.</dd>
+ * </dl>
+ * @hideinitializer */
+#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_REQUEST, opus_check_int_ptr(x)
+
+/**@}*/
+
+/** @defgroup opus_decoderctls Decoder related CTLs
+ * @see opus_genericctls, opus_encoderctls, opus_decoder
+ * @{
+ */
+
+/** Configures decoder gain adjustment.
+ * Scales the decoded output by a factor specified in Q8 dB units.
+ * This has a maximum range of -32768 to 32767 inclusive, and returns
+ * OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment.
+ * This setting survives decoder reset.
+ *
+ * gain = pow(10, x/(20.0*256))
+ *
+ * @param[in] x <tt>opus_int32</tt>: Amount to scale PCM signal by in Q8 dB units.
+ * @hideinitializer */
+#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, opus_check_int(x)
+/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN
+ *
+ * @param[out] x <tt>opus_int32 *</tt>: Amount to scale PCM signal by in Q8 dB units.
+ * @hideinitializer */
+#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, opus_check_int_ptr(x)
+
+/** Gets the duration (in samples) of the last packet successfully decoded or concealed.
+ * @param[out] x <tt>opus_int32 *</tt>: Number of samples (at current sampling rate).
+ * @hideinitializer */
+#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, opus_check_int_ptr(x)
+
+/** Gets the pitch of the last decoded frame, if available.
+ * This can be used for any post-processing algorithm requiring the use of pitch,
+ * e.g. time stretching/shortening. If the last frame was not voiced, or if the
+ * pitch was not coded in the frame, then zero is returned.
+ *
+ * This CTL is only implemented for decoder instances.
+ *
+ * @param[out] x <tt>opus_int32 *</tt>: pitch period at 48 kHz (or 0 if not available)
+ *
+ * @hideinitializer */
+#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, opus_check_int_ptr(x)
+
+/** Enables blind bandwidth extension for wideband signals if decoding sampling rate is 48 kHz.
+ * @param[in] x <tt>opus_int32 </tt>: 1 enables bandwidth extension, 0 disables it.
+ * The default is 0.
+ *
+ * @hideinitializer */
+ #define OPUS_SET_OSCE_BWE(x) OPUS_SET_OSCE_BWE_REQUEST, opus_check_int(x)
+/** Gets blind bandwidth extension flag for wideband signals if decoding sampling rate is 48 kHz.
+ * @param[out] x <tt>opus_int32 *</tt>: 1 if bwe enabled, 0 if disabled.
+ *
+ * @hideinitializer */
+ #define OPUS_GET_OSCE_BWE(x) OPUS_GET_OSCE_BWE_REQUEST, opus_check_int_ptr(x)
+
+/** If set to 1, the decoder will ignore all extensions found in the padding area
+ * (does not affect DRED, which is decoded separately).
+ * @hideinitializer */
+#define OPUS_SET_IGNORE_EXTENSIONS(x) OPUS_SET_IGNORE_EXTENSIONS_REQUEST, opus_check_int(x)
+/** Gets whether the decoder is ignoring extensions.
+ * @hideinitializer */
+#define OPUS_GET_IGNORE_EXTENSIONS(x) OPUS_GET_IGNORE_EXTENSIONS_REQUEST, opus_check_int_ptr(x)
+
+/**@}*/
+
+/** @defgroup opus_libinfo Opus library information functions
+ * @{
+ */
+
+/** Converts an opus error code into a human readable string.
+ *
+ * @param[in] error <tt>int</tt>: Error number
+ * @returns Error string
+ */
+OPUS_EXPORT const char *opus_strerror(int error);
+
+/** Gets the libopus version string.
+ *
+ * Applications may look for the substring "-fixed" in the version string to
+ * determine whether they have a fixed-point or floating-point build at
+ * runtime.
+ *
+ * @returns Version string
+ */
+OPUS_EXPORT const char *opus_get_version_string(void);
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_DEFINES_H */
--- /dev/null
+#ifndef OPUS_FRAME_TO_PCM_H
+#define OPUS_FRAME_TO_PCM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Decode a single Opus packet (in-memory) into 16-bit PCM samples.
+ *
+ * @param packet_data Pointer to Opus packet bytes.
+ * @param packet_len Length of packet_data in bytes.
+ * @param sample_rate Sample rate in Hz (e.g. 16000/48000).
+ * @param channels Channel count. If <= 0, try to detect from packet; fallback 1.
+ * @param out_pcm Output buffer for interleaved opus_int16 PCM (little-endian in memory).
+ * @param out_pcm_capacity Capacity of out_pcm in samples (not bytes), i.e. max number of opus_int16 entries.
+ * @param out_pcm_samples [out] Number of samples written to out_pcm (in opus_int16 units, i.e. includes channels).
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int opus_frame_to_pcm_decode_packet(const unsigned char *packet_data, int packet_len,
+ int sample_rate, int channels,
+ short *out_pcm, int out_pcm_capacity,
+ int *out_pcm_samples);
+
+/**
+ * @brief Decode a single Opus packet/frame file into 16-bit little-endian PCM.
+ *
+ * @param input_file Input file path containing (single) Opus packet bytes.
+ * @param sample_rate Sample rate in Hz (e.g. 16000/48000).
+ * @param channels Channel count. If <= 0, try to detect from packet; fallback 1.
+ * @param output_file Output PCM file path. If NULL, write to stdout.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int opus_frame_to_pcm_decode_file(const char *input_file, int sample_rate, int channels,
+ const char *output_file);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_FRAME_TO_PCM_H */
+
--- /dev/null
+/* Copyright (c) 2011 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+/**
+ * @file opus_multistream.h
+ * @brief Opus reference implementation multistream API
+ */
+
+#ifndef OPUS_MULTISTREAM_H
+#define OPUS_MULTISTREAM_H
+
+#include "opus.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond OPUS_INTERNAL_DOC */
+
+/** Macros to trigger compilation errors when the wrong types are provided to a
+ * CTL. */
+/**@{*/
+#define opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr)))
+#define opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr)))
+/**@}*/
+
+/** These are the actual encoder and decoder CTL ID numbers.
+ * They should not be used directly by applications.
+ * In general, SETs should be even and GETs should be odd.*/
+/**@{*/
+#define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120
+#define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122
+/**@}*/
+
+/** @endcond */
+
+/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs
+ *
+ * These are convenience macros that are specific to the
+ * opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl()
+ * interface.
+ * The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and
+ * @ref opus_decoderctls may be applied to a multistream encoder or decoder as
+ * well.
+ * In addition, you may retrieve the encoder or decoder state for an specific
+ * stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or
+ * #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually.
+ */
+/**@{*/
+
+/** Gets the encoder state for an individual stream of a multistream encoder.
+ * @param[in] x <tt>opus_int32</tt>: The index of the stream whose encoder you
+ * wish to retrieve.
+ * This must be non-negative and less than
+ * the <code>streams</code> parameter used
+ * to initialize the encoder.
+ * @param[out] y <tt>OpusEncoder**</tt>: Returns a pointer to the given
+ * encoder state.
+ * @retval OPUS_BAD_ARG The index of the requested stream was out of range.
+ * @hideinitializer
+ */
+#define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, opus_check_int(x), opus_check_encstate_ptr(y)
+
+/** Gets the decoder state for an individual stream of a multistream decoder.
+ * @param[in] x <tt>opus_int32</tt>: The index of the stream whose decoder you
+ * wish to retrieve.
+ * This must be non-negative and less than
+ * the <code>streams</code> parameter used
+ * to initialize the decoder.
+ * @param[out] y <tt>OpusDecoder**</tt>: Returns a pointer to the given
+ * decoder state.
+ * @retval OPUS_BAD_ARG The index of the requested stream was out of range.
+ * @hideinitializer
+ */
+#define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, opus_check_int(x), opus_check_decstate_ptr(y)
+
+/**@}*/
+
+/** @defgroup opus_multistream Opus Multistream API
+ * @{
+ *
+ * The multistream API allows individual Opus streams to be combined into a
+ * single packet, enabling support for up to 255 channels. Unlike an
+ * elementary Opus stream, the encoder and decoder must negotiate the channel
+ * configuration before the decoder can successfully interpret the data in the
+ * packets produced by the encoder. Some basic information, such as packet
+ * duration, can be computed without any special negotiation.
+ *
+ * The format for multistream Opus packets is defined in
+ * <a href="https://tools.ietf.org/html/rfc7845">RFC 7845</a>
+ * and is based on the self-delimited Opus framing described in Appendix B of
+ * <a href="https://tools.ietf.org/html/rfc6716">RFC 6716</a>.
+ * Normal Opus packets are just a degenerate case of multistream Opus packets,
+ * and can be encoded or decoded with the multistream API by setting
+ * <code>streams</code> to <code>1</code> when initializing the encoder or
+ * decoder.
+ *
+ * Multistream Opus streams can contain up to 255 elementary Opus streams.
+ * These may be either "uncoupled" or "coupled", indicating that the decoder
+ * is configured to decode them to either 1 or 2 channels, respectively.
+ * The streams are ordered so that all coupled streams appear at the
+ * beginning.
+ *
+ * A <code>mapping</code> table defines which decoded channel <code>i</code>
+ * should be used for each input/output (I/O) channel <code>j</code>. This table is
+ * typically provided as an unsigned char array.
+ * Let <code>i = mapping[j]</code> be the index for I/O channel <code>j</code>.
+ * If <code>i < 2*coupled_streams</code>, then I/O channel <code>j</code> is
+ * encoded as the left channel of stream <code>(i/2)</code> if <code>i</code>
+ * is even, or as the right channel of stream <code>(i/2)</code> if
+ * <code>i</code> is odd. Otherwise, I/O channel <code>j</code> is encoded as
+ * mono in stream <code>(i - coupled_streams)</code>, unless it has the special
+ * value 255, in which case it is omitted from the encoding entirely (the
+ * decoder will reproduce it as silence). Each value <code>i</code> must either
+ * be the special value 255 or be less than <code>streams + coupled_streams</code>.
+ *
+ * The output channels specified by the encoder
+ * should use the
+ * <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis
+ * channel ordering</a>. A decoder may wish to apply an additional permutation
+ * to the mapping the encoder used to achieve a different output channel
+ * order (e.g. for outputting in WAV order).
+ *
+ * Each multistream packet contains an Opus packet for each stream, and all of
+ * the Opus packets in a single multistream packet must have the same
+ * duration. Therefore the duration of a multistream packet can be extracted
+ * from the TOC sequence of the first stream, which is located at the
+ * beginning of the packet, just like an elementary Opus stream:
+ *
+ * @code
+ * int nb_samples;
+ * int nb_frames;
+ * nb_frames = opus_packet_get_nb_frames(data, len);
+ * if (nb_frames < 1)
+ * return nb_frames;
+ * nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames;
+ * @endcode
+ *
+ * The general encoding and decoding process proceeds exactly the same as in
+ * the normal @ref opus_encoder and @ref opus_decoder APIs.
+ * See their documentation for an overview of how to use the corresponding
+ * multistream functions.
+ */
+
+/** Opus multistream encoder state.
+ * This contains the complete state of a multistream Opus encoder.
+ * It is position independent and can be freely copied.
+ * @see opus_multistream_encoder_create
+ * @see opus_multistream_encoder_init
+ */
+typedef struct OpusMSEncoder OpusMSEncoder;
+
+/** Opus multistream decoder state.
+ * This contains the complete state of a multistream Opus decoder.
+ * It is position independent and can be freely copied.
+ * @see opus_multistream_decoder_create
+ * @see opus_multistream_decoder_init
+ */
+typedef struct OpusMSDecoder OpusMSDecoder;
+
+/**\name Multistream encoder functions */
+/**@{*/
+
+/** Gets the size of an OpusMSEncoder structure.
+ * @param streams <tt>int</tt>: The total number of streams to encode from the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
+ * to encode.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * encoded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than 255.
+ * @returns The size in bytes on success, or a negative error code
+ * (see @ref opus_errorcodes) on error.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size(
+ int streams,
+ int coupled_streams
+);
+
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_surround_encoder_get_size(
+ int channels,
+ int mapping_family
+);
+
+
+/** Allocates and initializes a multistream encoder state.
+ * Call opus_multistream_encoder_destroy() to release
+ * this object when finished.
+ * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels <tt>int</tt>: Number of channels in the input signal.
+ * This must be at most 255.
+ * It may be greater than the number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>).
+ * @param streams <tt>int</tt>: The total number of streams to encode from the
+ * input.
+ * This must be no more than the number of channels.
+ * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
+ * to encode.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * encoded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than the number of input channels.
+ * @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
+ * encoded channels to input channels, as described in
+ * @ref opus_multistream. As an extra constraint, the
+ * multistream encoder does not allow encoding coupled
+ * streams for which one channel is unused since this
+ * is never a good idea.
+ * @param application <tt>int</tt>: The target encoder application.
+ * This must be one of the following:
+ * <dl>
+ * <dt>#OPUS_APPLICATION_VOIP</dt>
+ * <dd>Process signal for improved speech intelligibility.</dd>
+ * <dt>#OPUS_APPLICATION_AUDIO</dt>
+ * <dd>Favor faithfulness to the original input.</dd>
+ * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+ * <dd>Configure the minimum possible coding delay by disabling certain modes
+ * of operation.</dd>
+ * </dl>
+ * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
+ * code (see @ref opus_errorcodes) on
+ * failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create(
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ const unsigned char *mapping,
+ int application,
+ int *error
+) OPUS_ARG_NONNULL(5);
+
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_encoder_create(
+ opus_int32 Fs,
+ int channels,
+ int mapping_family,
+ int *streams,
+ int *coupled_streams,
+ unsigned char *mapping,
+ int application,
+ int *error
+) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
+
+/** Initialize a previously allocated multistream encoder state.
+ * The memory pointed to by \a st must be at least the size returned by
+ * opus_multistream_encoder_get_size().
+ * This is intended for applications which use their own allocator instead of
+ * malloc.
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @see opus_multistream_encoder_create
+ * @see opus_multistream_encoder_get_size
+ * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize.
+ * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels <tt>int</tt>: Number of channels in the input signal.
+ * This must be at most 255.
+ * It may be greater than the number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>).
+ * @param streams <tt>int</tt>: The total number of streams to encode from the
+ * input.
+ * This must be no more than the number of channels.
+ * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
+ * to encode.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * encoded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than the number of input channels.
+ * @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
+ * encoded channels to input channels, as described in
+ * @ref opus_multistream. As an extra constraint, the
+ * multistream encoder does not allow encoding coupled
+ * streams for which one channel is unused since this
+ * is never a good idea.
+ * @param application <tt>int</tt>: The target encoder application.
+ * This must be one of the following:
+ * <dl>
+ * <dt>#OPUS_APPLICATION_VOIP</dt>
+ * <dd>Process signal for improved speech intelligibility.</dd>
+ * <dt>#OPUS_APPLICATION_AUDIO</dt>
+ * <dd>Favor faithfulness to the original input.</dd>
+ * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+ * <dd>Configure the minimum possible coding delay by disabling certain modes
+ * of operation.</dd>
+ * </dl>
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+ * on failure.
+ */
+OPUS_EXPORT int opus_multistream_encoder_init(
+ OpusMSEncoder *st,
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ const unsigned char *mapping,
+ int application
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
+
+OPUS_EXPORT int opus_multistream_surround_encoder_init(
+ OpusMSEncoder *st,
+ opus_int32 Fs,
+ int channels,
+ int mapping_family,
+ int *streams,
+ int *coupled_streams,
+ unsigned char *mapping,
+ int application
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6) OPUS_ARG_NONNULL(7);
+
+/** Encodes a multistream Opus frame.
+ * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
+ * @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
+ * samples.
+ * This must contain
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+ * signal.
+ * This must be an Opus frame size for the
+ * encoder's sampling rate.
+ * For example, at 48 kHz the permitted values
+ * are 120, 240, 480, 960, 1920, and 2880.
+ * Passing in a duration of less than 10 ms
+ * (480 samples at 48 kHz) will prevent the
+ * encoder from using the LPC or hybrid modes.
+ * @param[out] data <tt>unsigned char*</tt>: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode(
+ OpusMSEncoder *st,
+ const opus_int16 *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes a multistream Opus frame.
+ * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
+ * @param[in] pcm <tt>const opus_int32*</tt>: The input signal as interleaved
+ * samples representing (or slightly exceeding) 24-bit values.
+ * This must contain
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+ * signal.
+ * This must be an Opus frame size for the
+ * encoder's sampling rate.
+ * For example, at 48 kHz the permitted values
+ * are 120, 240, 480, 960, 1920, and 2880.
+ * Passing in a duration of less than 10 ms
+ * (480 samples at 48 kHz) will prevent the
+ * encoder from using the LPC or hybrid modes.
+ * @param[out] data <tt>unsigned char*</tt>: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode24(
+ OpusMSEncoder *st,
+ const opus_int32 *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes a multistream Opus frame from floating point input.
+ * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
+ * @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
+ * samples with a normal range of
+ * +/-1.0.
+ * Samples with a range beyond +/-1.0
+ * are supported but will be clipped by
+ * decoders using the integer API and
+ * should only be used if it is known
+ * that the far end supports extended
+ * dynamic range.
+ * This must contain
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+ * signal.
+ * This must be an Opus frame size for the
+ * encoder's sampling rate.
+ * For example, at 48 kHz the permitted values
+ * are 120, 240, 480, 960, 1920, and 2880.
+ * Passing in a duration of less than 10 ms
+ * (480 samples at 48 kHz) will prevent the
+ * encoder from using the LPC or hybrid modes.
+ * @param[out] data <tt>unsigned char*</tt>: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float(
+ OpusMSEncoder *st,
+ const float *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Frees an <code>OpusMSEncoder</code> allocated by
+ * opus_multistream_encoder_create().
+ * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to be freed.
+ */
+OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st);
+
+/** Perform a CTL function on a multistream Opus encoder.
+ *
+ * Generally the request and subsequent arguments are generated by a
+ * convenience macro.
+ * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls,
+ * @ref opus_encoderctls, or @ref opus_multistream_ctls.
+ * @see opus_genericctls
+ * @see opus_encoderctls
+ * @see opus_multistream_ctls
+ */
+OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+/**@}*/
+
+/**\name Multistream decoder functions */
+/**@{*/
+
+/** Gets the size of an <code>OpusMSDecoder</code> structure.
+ * @param streams <tt>int</tt>: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams <tt>int</tt>: Number streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than 255.
+ * @returns The size in bytes on success, or a negative error code
+ * (see @ref opus_errorcodes) on error.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size(
+ int streams,
+ int coupled_streams
+);
+
+/** Allocates and initializes a multistream decoder state.
+ * Call opus_multistream_decoder_destroy() to release
+ * this object when finished.
+ * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels <tt>int</tt>: Number of channels to output.
+ * This must be at most 255.
+ * It may be different from the number of coded
+ * channels (<code>streams +
+ * coupled_streams</code>).
+ * @param streams <tt>int</tt>: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than 255.
+ * @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
+ * coded channels to output channels, as described in
+ * @ref opus_multistream.
+ * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
+ * code (see @ref opus_errorcodes) on
+ * failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create(
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ const unsigned char *mapping,
+ int *error
+) OPUS_ARG_NONNULL(5);
+
+/** Initialize a previously allocated decoder state object.
+ * The memory pointed to by \a st must be at least the size returned by
+ * opus_multistream_encoder_get_size().
+ * This is intended for applications which use their own allocator instead of
+ * malloc.
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @see opus_multistream_decoder_create
+ * @see opus_multistream_deocder_get_size
+ * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize.
+ * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels <tt>int</tt>: Number of channels to output.
+ * This must be at most 255.
+ * It may be different from the number of coded
+ * channels (<code>streams +
+ * coupled_streams</code>).
+ * @param streams <tt>int</tt>: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than 255.
+ * @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
+ * coded channels to output channels, as described in
+ * @ref opus_multistream.
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+ * on failure.
+ */
+OPUS_EXPORT int opus_multistream_decoder_init(
+ OpusMSDecoder *st,
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ const unsigned char *mapping
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
+
+/** Decode a multistream Opus packet.
+ * @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
+ * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+ * Use a <code>NULL</code>
+ * pointer to indicate packet
+ * loss.
+ * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+ * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
+ * samples.
+ * This must contain room for
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: The number of samples per channel of
+ * available space in \a pcm.
+ * If this is less than the maximum packet duration
+ * (120 ms; 5760 for 48kHz), this function will not be capable
+ * of decoding some packets. In the case of PLC (data==NULL)
+ * or FEC (decode_fec=1), then frame_size needs to be exactly
+ * the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the
+ * next incoming packet. For the PLC and FEC cases, frame_size
+ * <b>must</b> be a multiple of 2.5 ms.
+ * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+ * forward error correction data be decoded.
+ * If no such data is available, the frame is
+ * decoded as if it were lost.
+ * @returns Number of samples decoded on success or a negative error code
+ * (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode(
+ OpusMSDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ opus_int16 *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode a multistream Opus packet.
+ * @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
+ * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+ * Use a <code>NULL</code>
+ * pointer to indicate packet
+ * loss.
+ * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+ * @param[out] pcm <tt>opus_int32*</tt>: Output signal, with interleaved
+ * samples representing (or slightly exceeding) 24-bit values.
+ * This must contain room for
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: The number of samples per channel of
+ * available space in \a pcm.
+ * If this is less than the maximum packet duration
+ * (120 ms; 5760 for 48kHz), this function will not be capable
+ * of decoding some packets. In the case of PLC (data==NULL)
+ * or FEC (decode_fec=1), then frame_size needs to be exactly
+ * the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the
+ * next incoming packet. For the PLC and FEC cases, frame_size
+ * <b>must</b> be a multiple of 2.5 ms.
+ * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+ * forward error correction data be decoded.
+ * If no such data is available, the frame is
+ * decoded as if it were lost.
+ * @returns Number of samples decoded on success or a negative error code
+ * (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode24(
+ OpusMSDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ opus_int32 *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode a multistream Opus packet with floating point output.
+ * @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
+ * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+ * Use a <code>NULL</code>
+ * pointer to indicate packet
+ * loss.
+ * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+ * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
+ * samples.
+ * This must contain room for
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: The number of samples per channel of
+ * available space in \a pcm.
+ * If this is less than the maximum packet duration
+ * (120 ms; 5760 for 48kHz), this function will not be capable
+ * of decoding some packets. In the case of PLC (data==NULL)
+ * or FEC (decode_fec=1), then frame_size needs to be exactly
+ * the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the
+ * next incoming packet. For the PLC and FEC cases, frame_size
+ * <b>must</b> be a multiple of 2.5 ms.
+ * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+ * forward error correction data be decoded.
+ * If no such data is available, the frame is
+ * decoded as if it were lost.
+ * @returns Number of samples decoded on success or a negative error code
+ * (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float(
+ OpusMSDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ float *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Perform a CTL function on a multistream Opus decoder.
+ *
+ * Generally the request and subsequent arguments are generated by a
+ * convenience macro.
+ * @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls,
+ * @ref opus_decoderctls, or @ref opus_multistream_ctls.
+ * @see opus_genericctls
+ * @see opus_decoderctls
+ * @see opus_multistream_ctls
+ */
+OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+/** Frees an <code>OpusMSDecoder</code> allocated by
+ * opus_multistream_decoder_create().
+ * @param st <tt>OpusMSDecoder</tt>: Multistream decoder state to be freed.
+ */
+OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st);
+
+/**@}*/
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_MULTISTREAM_H */
--- /dev/null
+/* Copyright (c) 2017 Google Inc.
+ Written by Andrew Allen */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+/**
+ * @file opus_projection.h
+ * @brief Opus projection reference API
+ */
+
+#ifndef OPUS_PROJECTION_H
+#define OPUS_PROJECTION_H
+
+#include "opus_multistream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond OPUS_INTERNAL_DOC */
+
+/** These are the actual encoder and decoder CTL ID numbers.
+ * They should not be used directly by applications.c
+ * In general, SETs should be even and GETs should be odd.*/
+/**@{*/
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST 6001
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST 6003
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST 6005
+/**@}*/
+
+
+/** @endcond */
+
+/** @defgroup opus_projection_ctls Projection specific encoder and decoder CTLs
+ *
+ * These are convenience macros that are specific to the
+ * opus_projection_encoder_ctl() and opus_projection_decoder_ctl()
+ * interface.
+ * The CTLs from @ref opus_genericctls, @ref opus_encoderctls,
+ * @ref opus_decoderctls, and @ref opus_multistream_ctls may be applied to a
+ * projection encoder or decoder as well.
+ */
+/**@{*/
+
+/** Gets the gain (in dB. S7.8-format) of the demixing matrix from the encoder.
+ * @param[out] x <tt>opus_int32 *</tt>: Returns the gain (in dB. S7.8-format)
+ * of the demixing matrix.
+ * @hideinitializer
+ */
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST, opus_check_int_ptr(x)
+
+
+/** Gets the size in bytes of the demixing matrix from the encoder.
+ * @param[out] x <tt>opus_int32 *</tt>: Returns the size in bytes of the
+ * demixing matrix.
+ * @hideinitializer
+ */
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, opus_check_int_ptr(x)
+
+
+/** Copies the demixing matrix to the supplied pointer location.
+ * @param[out] x <tt>unsigned char *</tt>: Returns the demixing matrix to the
+ * supplied pointer location.
+ * @param y <tt>opus_int32</tt>: The size in bytes of the reserved memory at the
+ * pointer location.
+ * @hideinitializer
+ */
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX(x,y) OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, x, opus_check_int(y)
+
+
+/**@}*/
+
+/** Opus projection encoder state.
+ * This contains the complete state of a projection Opus encoder.
+ * It is position independent and can be freely copied.
+ * @see opus_projection_ambisonics_encoder_create
+ */
+typedef struct OpusProjectionEncoder OpusProjectionEncoder;
+
+
+/** Opus projection decoder state.
+ * This contains the complete state of a projection Opus decoder.
+ * It is position independent and can be freely copied.
+ * @see opus_projection_decoder_create
+ * @see opus_projection_decoder_init
+ */
+typedef struct OpusProjectionDecoder OpusProjectionDecoder;
+
+
+/**\name Projection encoder functions */
+/**@{*/
+
+/** Gets the size of an OpusProjectionEncoder structure.
+ * @param channels <tt>int</tt>: The total number of input channels to encode.
+ * This must be no more than 255.
+ * @param mapping_family <tt>int</tt>: The mapping family to use for selecting
+ * the appropriate projection.
+ * @returns The size in bytes on success, or a negative error code
+ * (see @ref opus_errorcodes) on error.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_ambisonics_encoder_get_size(
+ int channels,
+ int mapping_family
+);
+
+
+/** Allocates and initializes a projection encoder state.
+ * Call opus_projection_encoder_destroy() to release
+ * this object when finished.
+ * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels <tt>int</tt>: Number of channels in the input signal.
+ * This must be at most 255.
+ * It may be greater than the number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>).
+ * @param mapping_family <tt>int</tt>: The mapping family to use for selecting
+ * the appropriate projection.
+ * @param[out] streams <tt>int *</tt>: The total number of streams that will
+ * be encoded from the input.
+ * @param[out] coupled_streams <tt>int *</tt>: Number of coupled (2 channel)
+ * streams that will be encoded from the input.
+ * @param application <tt>int</tt>: The target encoder application.
+ * This must be one of the following:
+ * <dl>
+ * <dt>#OPUS_APPLICATION_VOIP</dt>
+ * <dd>Process signal for improved speech intelligibility.</dd>
+ * <dt>#OPUS_APPLICATION_AUDIO</dt>
+ * <dd>Favor faithfulness to the original input.</dd>
+ * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+ * <dd>Configure the minimum possible coding delay by disabling certain modes
+ * of operation.</dd>
+ * </dl>
+ * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
+ * code (see @ref opus_errorcodes) on
+ * failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionEncoder *opus_projection_ambisonics_encoder_create(
+ opus_int32 Fs,
+ int channels,
+ int mapping_family,
+ int *streams,
+ int *coupled_streams,
+ int application,
+ int *error
+) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5);
+
+
+/** Initialize a previously allocated projection encoder state.
+ * The memory pointed to by \a st must be at least the size returned by
+ * opus_projection_ambisonics_encoder_get_size().
+ * This is intended for applications which use their own allocator instead of
+ * malloc.
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @see opus_projection_ambisonics_encoder_create
+ * @see opus_projection_ambisonics_encoder_get_size
+ * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to initialize.
+ * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels <tt>int</tt>: Number of channels in the input signal.
+ * This must be at most 255.
+ * It may be greater than the number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>).
+ * @param streams <tt>int</tt>: The total number of streams to encode from the
+ * input.
+ * This must be no more than the number of channels.
+ * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
+ * to encode.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * encoded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than the number of input channels.
+ * @param application <tt>int</tt>: The target encoder application.
+ * This must be one of the following:
+ * <dl>
+ * <dt>#OPUS_APPLICATION_VOIP</dt>
+ * <dd>Process signal for improved speech intelligibility.</dd>
+ * <dt>#OPUS_APPLICATION_AUDIO</dt>
+ * <dd>Favor faithfulness to the original input.</dd>
+ * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+ * <dd>Configure the minimum possible coding delay by disabling certain modes
+ * of operation.</dd>
+ * </dl>
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+ * on failure.
+ */
+OPUS_EXPORT int opus_projection_ambisonics_encoder_init(
+ OpusProjectionEncoder *st,
+ opus_int32 Fs,
+ int channels,
+ int mapping_family,
+ int *streams,
+ int *coupled_streams,
+ int application
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
+
+
+/** Encodes a projection Opus frame.
+ * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
+ * @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
+ * samples.
+ * This must contain
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+ * signal.
+ * This must be an Opus frame size for the
+ * encoder's sampling rate.
+ * For example, at 48 kHz the permitted values
+ * are 120, 240, 480, 960, 1920, and 2880.
+ * Passing in a duration of less than 10 ms
+ * (480 samples at 48 kHz) will prevent the
+ * encoder from using the LPC or hybrid modes.
+ * @param[out] data <tt>unsigned char*</tt>: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode(
+ OpusProjectionEncoder *st,
+ const opus_int16 *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+/** Encodes a projection Opus frame.
+ * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
+ * @param[in] pcm <tt>const opus_int32*</tt>: The input signal as interleaved
+ * samples representing (or slightly exceeding) 24-bit values.
+ * This must contain
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+ * signal.
+ * This must be an Opus frame size for the
+ * encoder's sampling rate.
+ * For example, at 48 kHz the permitted values
+ * are 120, 240, 480, 960, 1920, and 2880.
+ * Passing in a duration of less than 10 ms
+ * (480 samples at 48 kHz) will prevent the
+ * encoder from using the LPC or hybrid modes.
+ * @param[out] data <tt>unsigned char*</tt>: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode24(
+ OpusProjectionEncoder *st,
+ const opus_int32 *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+
+/** Encodes a projection Opus frame from floating point input.
+ * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
+ * @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
+ * samples with a normal range of
+ * +/-1.0.
+ * Samples with a range beyond +/-1.0
+ * are supported but will be clipped by
+ * decoders using the integer API and
+ * should only be used if it is known
+ * that the far end supports extended
+ * dynamic range.
+ * This must contain
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+ * signal.
+ * This must be an Opus frame size for the
+ * encoder's sampling rate.
+ * For example, at 48 kHz the permitted values
+ * are 120, 240, 480, 960, 1920, and 2880.
+ * Passing in a duration of less than 10 ms
+ * (480 samples at 48 kHz) will prevent the
+ * encoder from using the LPC or hybrid modes.
+ * @param[out] data <tt>unsigned char*</tt>: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode_float(
+ OpusProjectionEncoder *st,
+ const float *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+
+/** Frees an <code>OpusProjectionEncoder</code> allocated by
+ * opus_projection_ambisonics_encoder_create().
+ * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to be freed.
+ */
+OPUS_EXPORT void opus_projection_encoder_destroy(OpusProjectionEncoder *st);
+
+
+/** Perform a CTL function on a projection Opus encoder.
+ *
+ * Generally the request and subsequent arguments are generated by a
+ * convenience macro.
+ * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls,
+ * @ref opus_encoderctls, @ref opus_multistream_ctls, or
+ * @ref opus_projection_ctls
+ * @see opus_genericctls
+ * @see opus_encoderctls
+ * @see opus_multistream_ctls
+ * @see opus_projection_ctls
+ */
+OPUS_EXPORT int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+
+/**@}*/
+
+/**\name Projection decoder functions */
+/**@{*/
+
+/** Gets the size of an <code>OpusProjectionDecoder</code> structure.
+ * @param channels <tt>int</tt>: The total number of output channels.
+ * This must be no more than 255.
+ * @param streams <tt>int</tt>: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams <tt>int</tt>: Number streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than 255.
+ * @returns The size in bytes on success, or a negative error code
+ * (see @ref opus_errorcodes) on error.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_decoder_get_size(
+ int channels,
+ int streams,
+ int coupled_streams
+);
+
+
+/** Allocates and initializes a projection decoder state.
+ * Call opus_projection_decoder_destroy() to release
+ * this object when finished.
+ * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels <tt>int</tt>: Number of channels to output.
+ * This must be at most 255.
+ * It may be different from the number of coded
+ * channels (<code>streams +
+ * coupled_streams</code>).
+ * @param streams <tt>int</tt>: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than 255.
+ * @param[in] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix
+ * that mapping from coded channels to output channels,
+ * as described in @ref opus_projection and
+ * @ref opus_projection_ctls.
+ * @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the
+ * demixing matrix, as
+ * described in @ref
+ * opus_projection_ctls.
+ * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
+ * code (see @ref opus_errorcodes) on
+ * failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionDecoder *opus_projection_decoder_create(
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ unsigned char *demixing_matrix,
+ opus_int32 demixing_matrix_size,
+ int *error
+) OPUS_ARG_NONNULL(5);
+
+
+/** Initialize a previously allocated projection decoder state object.
+ * The memory pointed to by \a st must be at least the size returned by
+ * opus_projection_decoder_get_size().
+ * This is intended for applications which use their own allocator instead of
+ * malloc.
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @see opus_projection_decoder_create
+ * @see opus_projection_deocder_get_size
+ * @param st <tt>OpusProjectionDecoder*</tt>: Projection encoder state to initialize.
+ * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels <tt>int</tt>: Number of channels to output.
+ * This must be at most 255.
+ * It may be different from the number of coded
+ * channels (<code>streams +
+ * coupled_streams</code>).
+ * @param streams <tt>int</tt>: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than 255.
+ * @param[in] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix
+ * that mapping from coded channels to output channels,
+ * as described in @ref opus_projection and
+ * @ref opus_projection_ctls.
+ * @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the
+ * demixing matrix, as
+ * described in @ref
+ * opus_projection_ctls.
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+ * on failure.
+ */
+OPUS_EXPORT int opus_projection_decoder_init(
+ OpusProjectionDecoder *st,
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ unsigned char *demixing_matrix,
+ opus_int32 demixing_matrix_size
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
+
+
+/** Decode a projection Opus packet.
+ * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
+ * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+ * Use a <code>NULL</code>
+ * pointer to indicate packet
+ * loss.
+ * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+ * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
+ * samples.
+ * This must contain room for
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: The number of samples per channel of
+ * available space in \a pcm.
+ * If this is less than the maximum packet duration
+ * (120 ms; 5760 for 48kHz), this function will not be capable
+ * of decoding some packets. In the case of PLC (data==NULL)
+ * or FEC (decode_fec=1), then frame_size needs to be exactly
+ * the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the
+ * next incoming packet. For the PLC and FEC cases, frame_size
+ * <b>must</b> be a multiple of 2.5 ms.
+ * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+ * forward error correction data be decoded.
+ * If no such data is available, the frame is
+ * decoded as if it were lost.
+ * @returns Number of samples decoded on success or a negative error code
+ * (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode(
+ OpusProjectionDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ opus_int16 *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode a projection Opus packet.
+ * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
+ * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+ * Use a <code>NULL</code>
+ * pointer to indicate packet
+ * loss.
+ * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+ * @param[out] pcm <tt>opus_int32*</tt>: Output signal, with interleaved
+ * samples representing (or slightly exceeding) 24-bit values.
+ * This must contain room for
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: The number of samples per channel of
+ * available space in \a pcm.
+ * If this is less than the maximum packet duration
+ * (120 ms; 5760 for 48kHz), this function will not be capable
+ * of decoding some packets. In the case of PLC (data==NULL)
+ * or FEC (decode_fec=1), then frame_size needs to be exactly
+ * the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the
+ * next incoming packet. For the PLC and FEC cases, frame_size
+ * <b>must</b> be a multiple of 2.5 ms.
+ * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+ * forward error correction data be decoded.
+ * If no such data is available, the frame is
+ * decoded as if it were lost.
+ * @returns Number of samples decoded on success or a negative error code
+ * (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode24(
+ OpusProjectionDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ opus_int32 *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+/** Decode a projection Opus packet with floating point output.
+ * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
+ * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+ * Use a <code>NULL</code>
+ * pointer to indicate packet
+ * loss.
+ * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+ * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
+ * samples.
+ * This must contain room for
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: The number of samples per channel of
+ * available space in \a pcm.
+ * If this is less than the maximum packet duration
+ * (120 ms; 5760 for 48kHz), this function will not be capable
+ * of decoding some packets. In the case of PLC (data==NULL)
+ * or FEC (decode_fec=1), then frame_size needs to be exactly
+ * the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the
+ * next incoming packet. For the PLC and FEC cases, frame_size
+ * <b>must</b> be a multiple of 2.5 ms.
+ * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+ * forward error correction data be decoded.
+ * If no such data is available, the frame is
+ * decoded as if it were lost.
+ * @returns Number of samples decoded on success or a negative error code
+ * (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode_float(
+ OpusProjectionDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ float *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+
+/** Perform a CTL function on a projection Opus decoder.
+ *
+ * Generally the request and subsequent arguments are generated by a
+ * convenience macro.
+ * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls,
+ * @ref opus_decoderctls, @ref opus_multistream_ctls, or
+ * @ref opus_projection_ctls.
+ * @see opus_genericctls
+ * @see opus_decoderctls
+ * @see opus_multistream_ctls
+ * @see opus_projection_ctls
+ */
+OPUS_EXPORT int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+
+/** Frees an <code>OpusProjectionDecoder</code> allocated by
+ * opus_projection_decoder_create().
+ * @param st <tt>OpusProjectionDecoder</tt>: Projection decoder state to be freed.
+ */
+OPUS_EXPORT void opus_projection_decoder_destroy(OpusProjectionDecoder *st);
+
+
+/**@}*/
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_PROJECTION_H */
--- /dev/null
+/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */
+/* Modified by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+/* opus_types.h based on ogg_types.h from libogg */
+
+/**
+ @file opus_types.h
+ @brief Opus reference implementation types
+*/
+#ifndef OPUS_TYPES_H
+#define OPUS_TYPES_H
+
+#define opus_int int /* used for counters etc; at least 16 bits */
+#define opus_int64 long long
+#define opus_int8 signed char
+
+#define opus_uint unsigned int /* used for counters etc; at least 16 bits */
+#define opus_uint64 unsigned long long
+#define opus_uint8 unsigned char
+
+/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
+#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
+#include <stdint.h>
+# undef opus_int64
+# undef opus_int8
+# undef opus_uint64
+# undef opus_uint8
+ typedef int8_t opus_int8;
+ typedef uint8_t opus_uint8;
+ typedef int16_t opus_int16;
+ typedef uint16_t opus_uint16;
+ typedef int32_t opus_int32;
+ typedef uint32_t opus_uint32;
+ typedef int64_t opus_int64;
+ typedef uint64_t opus_uint64;
+#elif defined(_WIN32)
+
+# if defined(__CYGWIN__)
+# include <_G_config.h>
+ typedef _G_int32_t opus_int32;
+ typedef _G_uint32_t opus_uint32;
+ typedef _G_int16 opus_int16;
+ typedef _G_uint16 opus_uint16;
+# elif defined(__MINGW32__)
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef int opus_int32;
+ typedef unsigned int opus_uint32;
+# elif defined(__MWERKS__)
+ typedef int opus_int32;
+ typedef unsigned int opus_uint32;
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+# else
+ /* MSVC/Borland */
+ typedef __int32 opus_int32;
+ typedef unsigned __int32 opus_uint32;
+ typedef __int16 opus_int16;
+ typedef unsigned __int16 opus_uint16;
+# endif
+
+#elif defined(__MACOS__)
+
+# include <sys/types.h>
+ typedef SInt16 opus_int16;
+ typedef UInt16 opus_uint16;
+ typedef SInt32 opus_int32;
+ typedef UInt32 opus_uint32;
+
+#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
+
+# include <sys/types.h>
+ typedef int16_t opus_int16;
+ typedef u_int16_t opus_uint16;
+ typedef int32_t opus_int32;
+ typedef u_int32_t opus_uint32;
+
+#elif defined(__BEOS__)
+
+ /* Be */
+# include <inttypes.h>
+ typedef int16 opus_int16;
+ typedef u_int16 opus_uint16;
+ typedef int32_t opus_int32;
+ typedef u_int32_t opus_uint32;
+
+#elif defined (__EMX__)
+
+ /* OS/2 GCC */
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef int opus_int32;
+ typedef unsigned int opus_uint32;
+
+#elif defined (DJGPP)
+
+ /* DJGPP */
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef int opus_int32;
+ typedef unsigned int opus_uint32;
+
+#elif defined(R5900)
+
+ /* PS2 EE */
+ typedef int opus_int32;
+ typedef unsigned opus_uint32;
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+
+#elif defined(__SYMBIAN32__)
+
+ /* Symbian GCC */
+ typedef signed short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef signed int opus_int32;
+ typedef unsigned int opus_uint32;
+
+#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
+
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef long opus_int32;
+ typedef unsigned long opus_uint32;
+
+#elif defined(CONFIG_TI_C6X)
+
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef int opus_int32;
+ typedef unsigned int opus_uint32;
+
+#else
+
+ /* Give up, take a reasonable guess */
+ typedef short opus_int16;
+ typedef unsigned short opus_uint16;
+ typedef int opus_int32;
+ typedef unsigned int opus_uint32;
+
+#endif
+
+#endif /* OPUS_TYPES_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+/* Conversion between prediction filter coefficients and NLSFs */
+/* Requires the order to be an even number */
+/* A piecewise linear approximation maps LSF <-> cos(LSF) */
+/* Therefore the result is not accurate NLSFs, but the two */
+/* functions are accurate inverses of each other */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "tables.h"
+
+/* Number of binary divisions, when not in low complexity mode */
+#define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
+#define MAX_ITERATIONS_A2NLSF_FIX 16
+
+/* Helper function for A2NLSF(..) */
+/* Transforms polynomials from cos(n*f) to cos(f)^n */
+static OPUS_INLINE void silk_A2NLSF_trans_poly(
+ opus_int32 *p, /* I/O Polynomial */
+ const opus_int dd /* I Polynomial order (= filter order / 2 ) */
+)
+{
+ opus_int k, n;
+
+ for( k = 2; k <= dd; k++ ) {
+ for( n = dd; n > k; n-- ) {
+ p[ n - 2 ] -= p[ n ];
+ }
+ p[ k - 2 ] -= silk_LSHIFT( p[ k ], 1 );
+ }
+}
+/* Helper function for A2NLSF(..) */
+/* Polynomial evaluation */
+static OPUS_INLINE opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in Q16 */
+ opus_int32 *p, /* I Polynomial, Q16 */
+ const opus_int32 x, /* I Evaluation point, Q12 */
+ const opus_int dd /* I Order */
+)
+{
+ opus_int n;
+ opus_int32 x_Q16, y32;
+
+ y32 = p[ dd ]; /* Q16 */
+ x_Q16 = silk_LSHIFT( x, 4 );
+
+ if ( opus_likely( 8 == dd ) )
+ {
+ y32 = silk_SMLAWW( p[ 7 ], y32, x_Q16 );
+ y32 = silk_SMLAWW( p[ 6 ], y32, x_Q16 );
+ y32 = silk_SMLAWW( p[ 5 ], y32, x_Q16 );
+ y32 = silk_SMLAWW( p[ 4 ], y32, x_Q16 );
+ y32 = silk_SMLAWW( p[ 3 ], y32, x_Q16 );
+ y32 = silk_SMLAWW( p[ 2 ], y32, x_Q16 );
+ y32 = silk_SMLAWW( p[ 1 ], y32, x_Q16 );
+ y32 = silk_SMLAWW( p[ 0 ], y32, x_Q16 );
+ }
+ else
+ {
+ for( n = dd - 1; n >= 0; n-- ) {
+ y32 = silk_SMLAWW( p[ n ], y32, x_Q16 ); /* Q16 */
+ }
+ }
+ return y32;
+}
+
+static OPUS_INLINE void silk_A2NLSF_init(
+ const opus_int32 *a_Q16,
+ opus_int32 *P,
+ opus_int32 *Q,
+ const opus_int dd
+)
+{
+ opus_int k;
+
+ /* Convert filter coefs to even and odd polynomials */
+ P[dd] = silk_LSHIFT( 1, 16 );
+ Q[dd] = silk_LSHIFT( 1, 16 );
+ for( k = 0; k < dd; k++ ) {
+ P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; /* Q16 */
+ Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; /* Q16 */
+ }
+
+ /* Divide out zeros as we have that for even filter orders, */
+ /* z = 1 is always a root in Q, and */
+ /* z = -1 is always a root in P */
+ for( k = dd; k > 0; k-- ) {
+ P[ k - 1 ] -= P[ k ];
+ Q[ k - 1 ] += Q[ k ];
+ }
+
+ /* Transform polynomials from cos(n*f) to cos(f)^n */
+ silk_A2NLSF_trans_poly( P, dd );
+ silk_A2NLSF_trans_poly( Q, dd );
+}
+
+/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */
+/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
+void silk_A2NLSF(
+ opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */
+ opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */
+ const opus_int d /* I Filter order (must be even) */
+)
+{
+ opus_int i, k, m, dd, root_ix, ffrac;
+ opus_int32 xlo, xhi, xmid;
+ opus_int32 ylo, yhi, ymid, thr;
+ opus_int32 nom, den;
+ opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ];
+ opus_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
+ opus_int32 *PQ[ 2 ];
+ opus_int32 *p;
+
+ /* Store pointers to array */
+ PQ[ 0 ] = P;
+ PQ[ 1 ] = Q;
+
+ dd = silk_RSHIFT( d, 1 );
+
+ silk_A2NLSF_init( a_Q16, P, Q, dd );
+
+ /* Find roots, alternating between P and Q */
+ p = P; /* Pointer to polynomial */
+
+ xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
+ ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
+
+ if( ylo < 0 ) {
+ /* Set the first NLSF to zero and move on to the next */
+ NLSF[ 0 ] = 0;
+ p = Q; /* Pointer to polynomial */
+ ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
+ root_ix = 1; /* Index of current root */
+ } else {
+ root_ix = 0; /* Index of current root */
+ }
+ k = 1; /* Loop counter */
+ i = 0; /* Counter for bandwidth expansions applied */
+ thr = 0;
+ while( 1 ) {
+ /* Evaluate polynomial */
+ xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */
+ yhi = silk_A2NLSF_eval_poly( p, xhi, dd );
+
+ /* Detect zero crossing */
+ if( ( ylo <= 0 && yhi >= thr ) || ( ylo >= 0 && yhi <= -thr ) ) {
+ if( yhi == 0 ) {
+ /* If the root lies exactly at the end of the current */
+ /* interval, look for the next root in the next interval */
+ thr = 1;
+ } else {
+ thr = 0;
+ }
+ /* Binary division */
+ ffrac = -256;
+ for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) {
+ /* Evaluate polynomial */
+ xmid = silk_RSHIFT_ROUND( xlo + xhi, 1 );
+ ymid = silk_A2NLSF_eval_poly( p, xmid, dd );
+
+ /* Detect zero crossing */
+ if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) {
+ /* Reduce frequency */
+ xhi = xmid;
+ yhi = ymid;
+ } else {
+ /* Increase frequency */
+ xlo = xmid;
+ ylo = ymid;
+ ffrac = silk_ADD_RSHIFT( ffrac, 128, m );
+ }
+ }
+
+ /* Interpolate */
+ if( silk_abs( ylo ) < 65536 ) {
+ /* Avoid dividing by zero */
+ den = ylo - yhi;
+ nom = silk_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + silk_RSHIFT( den, 1 );
+ if( den != 0 ) {
+ ffrac += silk_DIV32( nom, den );
+ }
+ } else {
+ /* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */
+ ffrac += silk_DIV32( ylo, silk_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) );
+ }
+ NLSF[ root_ix ] = (opus_int16)silk_min_32( silk_LSHIFT( (opus_int32)k, 8 ) + ffrac, silk_int16_MAX );
+
+ silk_assert( NLSF[ root_ix ] >= 0 );
+
+ root_ix++; /* Next root */
+ if( root_ix >= d ) {
+ /* Found all roots */
+ break;
+ }
+ /* Alternate pointer to polynomial */
+ p = PQ[ root_ix & 1 ];
+
+ /* Evaluate polynomial */
+ xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; /* Q12*/
+ ylo = silk_LSHIFT( 1 - ( root_ix & 2 ), 12 );
+ } else {
+ /* Increment loop counter */
+ k++;
+ xlo = xhi;
+ ylo = yhi;
+ thr = 0;
+
+ if( k > LSF_COS_TAB_SZ_FIX ) {
+ i++;
+ if( i > MAX_ITERATIONS_A2NLSF_FIX ) {
+ /* Set NLSFs to white spectrum and exit */
+ NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 );
+ for( k = 1; k < d; k++ ) {
+ NLSF[ k ] = (opus_int16)silk_ADD16( NLSF[ k-1 ], NLSF[ 0 ] );
+ }
+ return;
+ }
+
+ /* Error: Apply progressively more bandwidth expansion and run again */
+ silk_bwexpander_32( a_Q16, d, 65536 - silk_LSHIFT( 1, i ) );
+
+ silk_A2NLSF_init( a_Q16, P, Q, dd );
+ p = P; /* Pointer to polynomial */
+ xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
+ ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
+ if( ylo < 0 ) {
+ /* Set the first NLSF to zero and move on to the next */
+ NLSF[ 0 ] = 0;
+ p = Q; /* Pointer to polynomial */
+ ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
+ root_ix = 1; /* Index of current root */
+ } else {
+ root_ix = 0; /* Index of current root */
+ }
+ k = 1; /* Reset loop counter */
+ }
+ }
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_API_H
+#define SILK_API_H
+
+#include "control.h"
+#include "typedef.h"
+#include "errors.h"
+#include "entenc.h"
+#include "entdec.h"
+
+#ifdef ENABLE_DEEP_PLC
+#include "lpcnet_private.h"
+#endif
+
+#define SILK_MAX_FRAMES_PER_PACKET 3
+
+/* Struct for TOC (Table of Contents) */
+typedef struct {
+ opus_int VADFlag; /* Voice activity for packet */
+ opus_int VADFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* Voice activity for each frame in packet */
+ opus_int inbandFECFlag; /* Flag indicating if packet contains in-band FEC */
+} silk_TOC_struct;
+
+/****************************************/
+/* Encoder functions */
+/****************************************/
+
+/***********************************************/
+/* Get size in bytes of the Silk encoder state */
+/***********************************************/
+opus_int silk_Get_Encoder_Size( /* O Returns error code */
+ opus_int *encSizeBytes, /* O Number of bytes in SILK encoder state */
+ opus_int channels /* I Number of channels */
+);
+
+/*************************/
+/* Init or reset encoder */
+/*************************/
+opus_int silk_InitEncoder( /* O Returns error code */
+ void *encState, /* I/O State */
+ int channels, /* I Number of channels */
+ int arch, /* I Run-time architecture */
+ silk_EncControlStruct *encStatus /* O Encoder Status */
+);
+
+/**************************/
+/* Encode frame with Silk */
+/**************************/
+/* Note: if prefillFlag is set, the input must contain 10 ms of audio, irrespective of what */
+/* encControl->payloadSize_ms is set to */
+opus_int silk_Encode( /* O Returns error code */
+ void *encState, /* I/O State */
+ silk_EncControlStruct *encControl, /* I Control status */
+ const opus_res *samplesIn, /* I Speech sample input vector */
+ opus_int nSamplesIn, /* I Number of samples in input vector */
+ ec_enc *psRangeEnc, /* I/O Compressor data structure */
+ opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
+ const opus_int prefillFlag, /* I Flag to indicate prefilling buffers no coding */
+ int activity /* I Decision of Opus voice activity detector */
+);
+
+/****************************************/
+/* Decoder functions */
+/****************************************/
+
+
+/***********************************************/
+/* Load OSCE models from external data pointer */
+/***********************************************/
+opus_int silk_LoadOSCEModels(
+ void *decState, /* O I/O State */
+ const unsigned char *data, /* I pointer to binary blob */
+ int len /* I length of binary blob data */
+);
+
+/***********************************************/
+/* Get size in bytes of the Silk decoder state */
+/***********************************************/
+opus_int silk_Get_Decoder_Size( /* O Returns error code */
+ opus_int *decSizeBytes /* O Number of bytes in SILK decoder state */
+);
+
+/*************************/
+/* Init and Reset decoder */
+/*************************/
+opus_int silk_ResetDecoder( /* O Returns error code */
+ void *decState /* I/O State */
+);
+
+opus_int silk_InitDecoder( /* O Returns error code */
+ void *decState /* I/O State */
+);
+
+/******************/
+/* Decode a frame */
+/******************/
+opus_int silk_Decode( /* O Returns error code */
+ void* decState, /* I/O State */
+ silk_DecControlStruct* decControl, /* I/O Control Structure */
+ opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
+ opus_int newPacketFlag, /* I Indicates first decoder call for this packet */
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_res *samplesOut, /* O Decoded output speech vector */
+ opus_int32 *nSamplesOut, /* O Number of samples decoded */
+#ifdef ENABLE_DEEP_PLC
+ LPCNetPLCState *lpcnet,
+#endif
+ int arch /* I Run-time architecture */
+);
+
+#if 0
+/**************************************/
+/* Get table of contents for a packet */
+/**************************************/
+opus_int silk_get_TOC(
+ const opus_uint8 *payload, /* I Payload data */
+ const opus_int nBytesIn, /* I Number of input bytes */
+ const opus_int nFramesPerPayload, /* I Number of SILK frames per payload */
+ silk_TOC_struct *Silk_TOC /* O Type of content */
+);
+#endif
+
+
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "stack_alloc.h"
+
+/* Generates excitation for CNG LPC synthesis */
+static OPUS_INLINE void silk_CNG_exc(
+ opus_int32 exc_Q14[], /* O CNG excitation signal Q10 */
+ opus_int32 exc_buf_Q14[], /* I Random samples buffer Q10 */
+ opus_int length, /* I Length */
+ opus_int32 *rand_seed /* I/O Seed to random index generator */
+)
+{
+ opus_int32 seed;
+ opus_int i, idx, exc_mask;
+
+ exc_mask = CNG_BUF_MASK_MAX;
+ while( exc_mask > length ) {
+ exc_mask = silk_RSHIFT( exc_mask, 1 );
+ }
+
+ seed = *rand_seed;
+ for( i = 0; i < length; i++ ) {
+ seed = silk_RAND( seed );
+ idx = (opus_int)( silk_RSHIFT( seed, 24 ) & exc_mask );
+ silk_assert( idx >= 0 );
+ silk_assert( idx <= CNG_BUF_MASK_MAX );
+ exc_Q14[ i ] = exc_buf_Q14[ idx ];
+ }
+ *rand_seed = seed;
+}
+
+void silk_CNG_Reset(
+ silk_decoder_state *psDec /* I/O Decoder state */
+)
+{
+ opus_int i, NLSF_step_Q15, NLSF_acc_Q15;
+
+ NLSF_step_Q15 = silk_DIV32_16( silk_int16_MAX, psDec->LPC_order + 1 );
+ NLSF_acc_Q15 = 0;
+ for( i = 0; i < psDec->LPC_order; i++ ) {
+ NLSF_acc_Q15 += NLSF_step_Q15;
+ psDec->sCNG.CNG_smth_NLSF_Q15[ i ] = NLSF_acc_Q15;
+ }
+ psDec->sCNG.CNG_smth_Gain_Q16 = 0;
+ psDec->sCNG.rand_seed = 3176576;
+}
+
+/* Updates CNG estimate, and applies the CNG when packet was lost */
+void silk_CNG(
+ silk_decoder_state *psDec, /* I/O Decoder state */
+ silk_decoder_control *psDecCtrl, /* I/O Decoder control */
+ opus_int16 frame[], /* I/O Signal */
+ opus_int length /* I Length of residual */
+)
+{
+ opus_int i, subfr;
+ opus_int32 LPC_pred_Q10, max_Gain_Q16, gain_Q16, gain_Q10;
+ opus_int16 A_Q12[ MAX_LPC_ORDER ];
+ silk_CNG_struct *psCNG = &psDec->sCNG;
+ SAVE_STACK;
+
+ if( psDec->fs_kHz != psCNG->fs_kHz ) {
+ /* Reset state */
+ silk_CNG_Reset( psDec );
+
+ psCNG->fs_kHz = psDec->fs_kHz;
+ }
+ if( psDec->lossCnt == 0 && psDec->prevSignalType == TYPE_NO_VOICE_ACTIVITY ) {
+ /* Update CNG parameters */
+
+ /* Smoothing of LSF's */
+ for( i = 0; i < psDec->LPC_order; i++ ) {
+ psCNG->CNG_smth_NLSF_Q15[ i ] += silk_SMULWB( (opus_int32)psDec->prevNLSF_Q15[ i ] - (opus_int32)psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 );
+ }
+ /* Find the subframe with the highest gain */
+ max_Gain_Q16 = 0;
+ subfr = 0;
+ for( i = 0; i < psDec->nb_subfr; i++ ) {
+ if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) {
+ max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ];
+ subfr = i;
+ }
+ }
+ /* Update CNG excitation buffer with excitation from this subframe */
+ silk_memmove( &psCNG->CNG_exc_buf_Q14[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q14, ( psDec->nb_subfr - 1 ) * psDec->subfr_length * sizeof( opus_int32 ) );
+ silk_memcpy( psCNG->CNG_exc_buf_Q14, &psDec->exc_Q14[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( opus_int32 ) );
+
+ /* Smooth gains */
+ for( i = 0; i < psDec->nb_subfr; i++ ) {
+ psCNG->CNG_smth_Gain_Q16 += silk_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 );
+ /* If the smoothed gain is 3 dB greater than this subframe's gain, use this subframe's gain to adapt faster. */
+ if( silk_SMULWW( psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_THRESHOLD_Q16 ) > psDecCtrl->Gains_Q16[ i ] ) {
+ psCNG->CNG_smth_Gain_Q16 = psDecCtrl->Gains_Q16[ i ];
+ }
+ }
+ }
+
+ /* Add CNG when packet is lost or during DTX */
+ if( psDec->lossCnt ) {
+ VARDECL( opus_int32, CNG_sig_Q14 );
+ ALLOC( CNG_sig_Q14, length + MAX_LPC_ORDER, opus_int32 );
+
+ /* Generate CNG excitation */
+ gain_Q16 = silk_SMULWW( psDec->sPLC.randScale_Q14, psDec->sPLC.prevGain_Q16[1] );
+ if( gain_Q16 >= (1 << 21) || psCNG->CNG_smth_Gain_Q16 > (1 << 23) ) {
+ gain_Q16 = silk_SMULTT( gain_Q16, gain_Q16 );
+ gain_Q16 = silk_SUB_LSHIFT32(silk_SMULTT( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
+ gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 16 );
+ } else {
+ gain_Q16 = silk_SMULWW( gain_Q16, gain_Q16 );
+ gain_Q16 = silk_SUB_LSHIFT32(silk_SMULWW( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
+ gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 );
+ }
+ gain_Q10 = silk_RSHIFT( gain_Q16, 6 );
+
+ silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed );
+
+ /* Convert CNG NLSF to filter representation */
+ silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order, psDec->arch );
+
+ /* Generate CNG signal, by synthesis filtering */
+ silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
+ celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
+ for( i = 0; i < length; i++ ) {
+ /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+ LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
+ if( psDec->LPC_order == 16 ) {
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] );
+ }
+
+ /* Update states */
+ CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( CNG_sig_Q14[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
+
+ /* Scale with Gain and add to input signal */
+ frame[ i ] = (opus_int16)silk_ADD_SAT16( frame[ i ], silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( CNG_sig_Q14[ MAX_LPC_ORDER + i ], gain_Q10 ), 8 ) ) );
+
+ }
+ silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
+ } else {
+ silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( opus_int32 ) );
+ }
+ RESTORE_STACK;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef FIXED_POINT
+#include "main_FIX.h"
+#else
+#include "main_FLP.h"
+#endif
+#include "tuning_parameters.h"
+
+/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */
+void silk_HP_variable_cutoff(
+ silk_encoder_state_Fxx state_Fxx[] /* I/O Encoder states */
+)
+{
+ opus_int quality_Q15;
+ opus_int32 pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7;
+ silk_encoder_state *psEncC1 = &state_Fxx[ 0 ].sCmn;
+
+ /* Adaptive cutoff frequency: estimate low end of pitch frequency range */
+ if( psEncC1->prevSignalType == TYPE_VOICED ) {
+ /* difference, in log domain */
+ pitch_freq_Hz_Q16 = silk_DIV32_16( silk_LSHIFT( silk_MUL( psEncC1->fs_kHz, 1000 ), 16 ), psEncC1->prevLag );
+ pitch_freq_log_Q7 = silk_lin2log( pitch_freq_Hz_Q16 ) - ( 16 << 7 );
+
+ /* adjustment based on quality */
+ quality_Q15 = psEncC1->input_quality_bands_Q15[ 0 ];
+ pitch_freq_log_Q7 = silk_SMLAWB( pitch_freq_log_Q7, silk_SMULWB( silk_LSHIFT( -quality_Q15, 2 ), quality_Q15 ),
+ pitch_freq_log_Q7 - ( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ) ) );
+
+ /* delta_freq = pitch_freq_log - psEnc->variable_HP_smth1; */
+ delta_freq_Q7 = pitch_freq_log_Q7 - silk_RSHIFT( psEncC1->variable_HP_smth1_Q15, 8 );
+ if( delta_freq_Q7 < 0 ) {
+ /* less smoothing for decreasing pitch frequency, to track something close to the minimum */
+ delta_freq_Q7 = silk_MUL( delta_freq_Q7, 3 );
+ }
+
+ /* limit delta, to reduce impact of outliers in pitch estimation */
+ delta_freq_Q7 = silk_LIMIT_32( delta_freq_Q7, -SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ), SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ) );
+
+ /* update smoother */
+ psEncC1->variable_HP_smth1_Q15 = silk_SMLAWB( psEncC1->variable_HP_smth1_Q15,
+ silk_SMULBB( psEncC1->speech_activity_Q8, delta_freq_Q7 ), SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF1, 16 ) );
+
+ /* limit frequency range */
+ psEncC1->variable_HP_smth1_Q15 = silk_LIMIT_32( psEncC1->variable_HP_smth1_Q15,
+ silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ),
+ silk_LSHIFT( silk_lin2log( VARIABLE_HP_MAX_CUTOFF_HZ ), 8 ) );
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+/*! \file silk_Inlines.h
+ * \brief silk_Inlines.h defines OPUS_INLINE signal processing functions.
+ */
+
+#ifndef SILK_FIX_INLINES_H
+#define SILK_FIX_INLINES_H
+
+
+/* count leading zeros of opus_int64 */
+static OPUS_INLINE opus_int32 silk_CLZ64( opus_int64 in )
+{
+ opus_int32 in_upper;
+
+ in_upper = (opus_int32)silk_RSHIFT64(in, 32);
+ if (in_upper == 0) {
+ /* Search in the lower 32 bits */
+ return 32 + silk_CLZ32( (opus_int32) in );
+ } else {
+ /* Search in the upper 32 bits */
+ return silk_CLZ32( in_upper );
+ }
+}
+
+/* get number of leading zeros and fractional part (the bits right after the leading one */
+static OPUS_INLINE void silk_CLZ_FRAC(
+ opus_int32 in, /* I input */
+ opus_int32 *lz, /* O number of leading zeros */
+ opus_int32 *frac_Q7 /* O the 7 bits right after the leading one */
+)
+{
+ opus_int32 lzeros = silk_CLZ32(in);
+
+ * lz = lzeros;
+ * frac_Q7 = silk_ROR32(in, 24 - lzeros) & 0x7f;
+}
+
+/* Approximation of square root */
+/* Accuracy: < +/- 10% for output values > 15 */
+/* < +/- 2.5% for output values > 120 */
+static OPUS_INLINE opus_int32 silk_SQRT_APPROX( opus_int32 x )
+{
+ opus_int32 y, lz, frac_Q7;
+
+ if( x <= 0 ) {
+ return 0;
+ }
+
+ silk_CLZ_FRAC(x, &lz, &frac_Q7);
+
+ if( lz & 1 ) {
+ y = 32768;
+ } else {
+ y = 46214; /* 46214 = sqrt(2) * 32768 */
+ }
+
+ /* get scaling right */
+ y >>= silk_RSHIFT(lz, 1);
+
+ /* increment using fractional part of input */
+ y = silk_SMLAWB(y, y, silk_SMULBB(213, frac_Q7));
+
+ return y;
+}
+
+/* Divide two int32 values and return result as int32 in a given Q-domain */
+static OPUS_INLINE opus_int32 silk_DIV32_varQ( /* O returns a good approximation of "(a32 << Qres) / b32" */
+ const opus_int32 a32, /* I numerator (Q0) */
+ const opus_int32 b32, /* I denominator (Q0) */
+ const opus_int Qres /* I Q-domain of result (>= 0) */
+)
+{
+ opus_int a_headrm, b_headrm, lshift;
+ opus_int32 b32_inv, a32_nrm, b32_nrm, result;
+
+ silk_assert( b32 != 0 );
+ silk_assert( Qres >= 0 );
+
+ /* Compute number of bits head room and normalize inputs */
+ a_headrm = silk_CLZ32( silk_abs(a32) ) - 1;
+ a32_nrm = silk_LSHIFT(a32, a_headrm); /* Q: a_headrm */
+ b_headrm = silk_CLZ32( silk_abs(b32) ) - 1;
+ b32_nrm = silk_LSHIFT(b32, b_headrm); /* Q: b_headrm */
+
+ /* Inverse of b32, with 14 bits of precision */
+ b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */
+
+ /* First approximation */
+ result = silk_SMULWB(a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */
+
+ /* Compute residual by subtracting product of denominator and first approximation */
+ /* It's OK to overflow because the final value of a32_nrm should always be small */
+ a32_nrm = silk_SUB32_ovflw(a32_nrm, silk_LSHIFT_ovflw( silk_SMMUL(b32_nrm, result), 3 )); /* Q: a_headrm */
+
+ /* Refinement */
+ result = silk_SMLAWB(result, a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */
+
+ /* Convert to Qres domain */
+ lshift = 29 + a_headrm - b_headrm - Qres;
+ if( lshift < 0 ) {
+ return silk_LSHIFT_SAT32(result, -lshift);
+ } else {
+ if( lshift < 32){
+ return silk_RSHIFT(result, lshift);
+ } else {
+ /* Avoid undefined result */
+ return 0;
+ }
+ }
+}
+
+/* Invert int32 value and return result as int32 in a given Q-domain */
+static OPUS_INLINE opus_int32 silk_INVERSE32_varQ( /* O returns a good approximation of "(1 << Qres) / b32" */
+ const opus_int32 b32, /* I denominator (Q0) */
+ const opus_int Qres /* I Q-domain of result (> 0) */
+)
+{
+ opus_int b_headrm, lshift;
+ opus_int32 b32_inv, b32_nrm, err_Q32, result;
+
+ silk_assert( b32 != 0 );
+ silk_assert( Qres > 0 );
+
+ /* Compute number of bits head room and normalize input */
+ b_headrm = silk_CLZ32( silk_abs(b32) ) - 1;
+ b32_nrm = silk_LSHIFT(b32, b_headrm); /* Q: b_headrm */
+
+ /* Inverse of b32, with 14 bits of precision */
+ b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */
+
+ /* First approximation */
+ result = silk_LSHIFT(b32_inv, 16); /* Q: 61 - b_headrm */
+
+ /* Compute residual by subtracting product of denominator and first approximation from one */
+ err_Q32 = silk_LSHIFT( ((opus_int32)1<<29) - silk_SMULWB(b32_nrm, b32_inv), 3 ); /* Q32 */
+
+ /* Refinement */
+ result = silk_SMLAWW(result, err_Q32, b32_inv); /* Q: 61 - b_headrm */
+
+ /* Convert to Qres domain */
+ lshift = 61 - b_headrm - Qres;
+ if( lshift <= 0 ) {
+ return silk_LSHIFT_SAT32(result, -lshift);
+ } else {
+ if( lshift < 32){
+ return silk_RSHIFT(result, lshift);
+ }else{
+ /* Avoid undefined result */
+ return 0;
+ }
+ }
+}
+
+#endif /* SILK_FIX_INLINES_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "celt_lpc.h"
+
+/*******************************************/
+/* LPC analysis filter */
+/* NB! State is kept internally and the */
+/* filter always starts with zero state */
+/* first d output samples are set to zero */
+/*******************************************/
+
+/* OPT: Using celt_fir() for this function should be faster, but it may cause
+ integer overflows in intermediate values (not final results), which the
+ current implementation silences by casting to unsigned. Enabling
+ this should be safe in pretty much all cases, even though it is not technically
+ C89-compliant. */
+#define USE_CELT_FIR 0
+
+void silk_LPC_analysis_filter(
+ opus_int16 *out, /* O Output signal */
+ const opus_int16 *in, /* I Input signal */
+ const opus_int16 *B, /* I MA prediction coefficients, Q12 [order] */
+ const opus_int32 len, /* I Signal length */
+ const opus_int32 d, /* I Filter order */
+ int arch /* I Run-time architecture */
+)
+{
+ opus_int j;
+#if defined(FIXED_POINT) && USE_CELT_FIR
+ opus_int16 num[SILK_MAX_ORDER_LPC];
+#else
+ int ix;
+ opus_int32 out32_Q12, out32;
+ const opus_int16 *in_ptr;
+#endif
+
+ celt_assert( d >= 6 );
+ celt_assert( (d & 1) == 0 );
+ celt_assert( d <= len );
+
+#if defined(FIXED_POINT) && USE_CELT_FIR
+ celt_assert( d <= SILK_MAX_ORDER_LPC );
+ for ( j = 0; j < d; j++ ) {
+ num[ j ] = -B[ j ];
+ }
+ celt_fir( in + d, num, out + d, len - d, d, arch );
+ for ( j = 0; j < d; j++ ) {
+ out[ j ] = 0;
+ }
+#else
+ (void)arch;
+ for( ix = d; ix < len; ix++ ) {
+ in_ptr = &in[ ix - 1 ];
+
+ out32_Q12 = silk_SMULBB( in_ptr[ 0 ], B[ 0 ] );
+ /* Allowing wrap around so that two wraps can cancel each other. The rare
+ cases where the result wraps around can only be triggered by invalid streams*/
+ out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -1 ], B[ 1 ] );
+ out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -2 ], B[ 2 ] );
+ out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -3 ], B[ 3 ] );
+ out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -4 ], B[ 4 ] );
+ out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -5 ], B[ 5 ] );
+ for( j = 6; j < d; j += 2 ) {
+ out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j ], B[ j ] );
+ out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j - 1 ], B[ j + 1 ] );
+ }
+
+ /* Subtract prediction */
+ out32_Q12 = silk_SUB32_ovflw( silk_LSHIFT( (opus_int32)in_ptr[ 1 ], 12 ), out32_Q12 );
+
+ /* Scale to Q0 */
+ out32 = silk_RSHIFT_ROUND( out32_Q12, 12 );
+
+ /* Saturate output */
+ out[ ix ] = (opus_int16)silk_SAT16( out32 );
+ }
+
+ /* Set first d output samples to zero */
+ silk_memset( out, 0, d * sizeof( opus_int16 ) );
+#endif
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2013, Koen Vos. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around.
+ This logic is reused in _celt_lpc(). Any bug fixes should also be applied there. */
+void silk_LPC_fit(
+ opus_int16 *a_QOUT, /* O Output signal */
+ opus_int32 *a_QIN, /* I/O Input signal */
+ const opus_int QOUT, /* I Input Q domain */
+ const opus_int QIN, /* I Input Q domain */
+ const opus_int d /* I Filter order */
+)
+{
+ opus_int i, k, idx = 0;
+ opus_int32 maxabs, absval, chirp_Q16;
+
+ /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
+ for( i = 0; i < 10; i++ ) {
+ /* Find maximum absolute value and its index */
+ maxabs = 0;
+ for( k = 0; k < d; k++ ) {
+ absval = silk_abs( a_QIN[k] );
+ if( absval > maxabs ) {
+ maxabs = absval;
+ idx = k;
+ }
+ }
+ maxabs = silk_RSHIFT_ROUND( maxabs, QIN - QOUT );
+
+ if( maxabs > silk_int16_MAX ) {
+ /* Reduce magnitude of prediction coefficients */
+ maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
+ chirp_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
+ silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
+ silk_bwexpander_32( a_QIN, d, chirp_Q16 );
+ } else {
+ break;
+ }
+ }
+
+ if( i == 10 ) {
+ /* Reached the last iteration, clip the coefficients */
+ for( k = 0; k < d; k++ ) {
+ a_QOUT[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ) );
+ a_QIN[ k ] = silk_LSHIFT( (opus_int32)a_QOUT[ k ], QIN - QOUT );
+ }
+ } else {
+ for( k = 0; k < d; k++ ) {
+ a_QOUT[ k ] = (opus_int16)silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT );
+ }
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "define.h"
+
+#define QA 24
+#define A_LIMIT SILK_FIX_CONST( 0.99975, QA )
+
+#define MUL32_FRAC_Q(a32, b32, Q) ((opus_int32)(silk_RSHIFT_ROUND64(silk_SMULL(a32, b32), Q)))
+
+/* Compute inverse of LPC prediction gain, and */
+/* test if LPC coefficients are stable (all poles within unit circle) */
+static opus_int32 LPC_inverse_pred_gain_QA_c( /* O Returns inverse prediction gain in energy domain, Q30 */
+ opus_int32 A_QA[ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
+ const opus_int order /* I Prediction order */
+)
+{
+ opus_int k, n, mult2Q;
+ opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
+
+ invGain_Q30 = SILK_FIX_CONST( 1, 30 );
+ for( k = order - 1; k > 0; k-- ) {
+ /* Check for stability */
+ if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
+ return 0;
+ }
+
+ /* Set RC equal to negated AR coef */
+ rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
+
+ /* rc_mult1_Q30 range: [ 1 : 2^30 ] */
+ rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
+ silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */
+ silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) );
+
+ /* Update inverse gain */
+ /* invGain_Q30 range: [ 0 : 2^30 ] */
+ invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
+ silk_assert( invGain_Q30 >= 0 );
+ silk_assert( invGain_Q30 <= ( 1 << 30 ) );
+ if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+ return 0;
+ }
+
+ /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
+ mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
+ rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
+
+ /* Update AR coefficient */
+ for( n = 0; n < (k + 1) >> 1; n++ ) {
+ opus_int64 tmp64;
+ tmp1 = A_QA[ n ];
+ tmp2 = A_QA[ k - n - 1 ];
+ tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
+ MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
+ if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+ return 0;
+ }
+ A_QA[ n ] = ( opus_int32 )tmp64;
+ tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
+ MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
+ if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+ return 0;
+ }
+ A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
+ }
+ }
+
+ /* Check for stability */
+ if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
+ return 0;
+ }
+
+ /* Set RC equal to negated AR coef */
+ rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
+
+ /* Range: [ 1 : 2^30 ] */
+ rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
+
+ /* Update inverse gain */
+ /* Range: [ 0 : 2^30 ] */
+ invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
+ silk_assert( invGain_Q30 >= 0 );
+ silk_assert( invGain_Q30 <= ( 1 << 30 ) );
+ if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+ return 0;
+ }
+
+ return invGain_Q30;
+}
+
+/* For input in Q12 domain */
+opus_int32 silk_LPC_inverse_pred_gain_c( /* O Returns inverse prediction gain in energy domain, Q30 */
+ const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
+ const opus_int order /* I Prediction order */
+)
+{
+ opus_int k;
+ opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
+ opus_int32 DC_resp = 0;
+
+ /* Increase Q domain of the AR coefficients */
+ for( k = 0; k < order; k++ ) {
+ DC_resp += (opus_int32)A_Q12[ k ];
+ Atmp_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
+ }
+ /* If the DC is unstable, we don't even need to do the full calculations */
+ if( DC_resp >= 4096 ) {
+ return 0;
+ }
+ return LPC_inverse_pred_gain_QA_c( Atmp_QA, order );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_LPC_INV_PRED_GAIN_ARM_H
+# define SILK_LPC_INV_PRED_GAIN_ARM_H
+
+# include "celt/arm/armcpu.h"
+
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+opus_int32 silk_LPC_inverse_pred_gain_neon( /* O Returns inverse prediction gain in energy domain, Q30 */
+ const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
+ const opus_int order /* I Prediction order */
+);
+
+# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+# define OVERRIDE_silk_LPC_inverse_pred_gain (1)
+# define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), PRESUME_NEON(silk_LPC_inverse_pred_gain)(A_Q12, order))
+# endif
+# endif
+
+# if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
+/*Is run-time CPU detection enabled on this platform?*/
+# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern opus_int32 (*const SILK_LPC_INVERSE_PRED_GAIN_IMPL[OPUS_ARCHMASK+1])(const opus_int16 *A_Q12, const opus_int order);
+# define OVERRIDE_silk_LPC_inverse_pred_gain (1)
+# define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((*SILK_LPC_INVERSE_PRED_GAIN_IMPL[(arch)&OPUS_ARCHMASK])(A_Q12, order))
+# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+# define OVERRIDE_silk_LPC_inverse_pred_gain (1)
+# define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), silk_LPC_inverse_pred_gain_neon(A_Q12, order))
+# endif
+# endif
+
+#endif /* end SILK_LPC_INV_PRED_GAIN_ARM_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ Elliptic/Cauer filters designed with 0.1 dB passband ripple,
+ 80 dB minimum stopband attenuation, and
+ [0.95 : 0.15 : 0.35] normalized cut off frequencies.
+*/
+
+#include "main.h"
+
+/* Helper function, interpolates the filter taps */
+static OPUS_INLINE void silk_LP_interpolate_filter_taps(
+ opus_int32 B_Q28[ TRANSITION_NB ],
+ opus_int32 A_Q28[ TRANSITION_NA ],
+ const opus_int ind,
+ const opus_int32 fac_Q16
+)
+{
+ opus_int nb, na;
+
+ if( ind < TRANSITION_INT_NUM - 1 ) {
+ if( fac_Q16 > 0 ) {
+ if( fac_Q16 < 32768 ) { /* fac_Q16 is in range of a 16-bit int */
+ /* Piece-wise linear interpolation of B and A */
+ for( nb = 0; nb < TRANSITION_NB; nb++ ) {
+ B_Q28[ nb ] = silk_SMLAWB(
+ silk_Transition_LP_B_Q28[ ind ][ nb ],
+ silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
+ silk_Transition_LP_B_Q28[ ind ][ nb ],
+ fac_Q16 );
+ }
+ for( na = 0; na < TRANSITION_NA; na++ ) {
+ A_Q28[ na ] = silk_SMLAWB(
+ silk_Transition_LP_A_Q28[ ind ][ na ],
+ silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
+ silk_Transition_LP_A_Q28[ ind ][ na ],
+ fac_Q16 );
+ }
+ } else { /* ( fac_Q16 - ( 1 << 16 ) ) is in range of a 16-bit int */
+ silk_assert( fac_Q16 - ( 1 << 16 ) == silk_SAT16( fac_Q16 - ( 1 << 16 ) ) );
+ /* Piece-wise linear interpolation of B and A */
+ for( nb = 0; nb < TRANSITION_NB; nb++ ) {
+ B_Q28[ nb ] = silk_SMLAWB(
+ silk_Transition_LP_B_Q28[ ind + 1 ][ nb ],
+ silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
+ silk_Transition_LP_B_Q28[ ind ][ nb ],
+ fac_Q16 - ( (opus_int32)1 << 16 ) );
+ }
+ for( na = 0; na < TRANSITION_NA; na++ ) {
+ A_Q28[ na ] = silk_SMLAWB(
+ silk_Transition_LP_A_Q28[ ind + 1 ][ na ],
+ silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
+ silk_Transition_LP_A_Q28[ ind ][ na ],
+ fac_Q16 - ( (opus_int32)1 << 16 ) );
+ }
+ }
+ } else {
+ silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( opus_int32 ) );
+ silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( opus_int32 ) );
+ }
+ } else {
+ silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( opus_int32 ) );
+ silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( opus_int32 ) );
+ }
+}
+
+/* Low-pass filter with variable cutoff frequency based on */
+/* piece-wise linear interpolation between elliptic filters */
+/* Start by setting psEncC->mode <> 0; */
+/* Deactivate by setting psEncC->mode = 0; */
+void silk_LP_variable_cutoff(
+ silk_LP_state *psLP, /* I/O LP filter state */
+ opus_int16 *frame, /* I/O Low-pass filtered output signal */
+ const opus_int frame_length /* I Frame length */
+)
+{
+ opus_int32 B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0;
+ opus_int ind = 0;
+
+ silk_assert( psLP->transition_frame_no >= 0 && psLP->transition_frame_no <= TRANSITION_FRAMES );
+
+ /* Run filter if needed */
+ if( psLP->mode != 0 ) {
+ /* Calculate index and interpolation factor for interpolation */
+#if( TRANSITION_INT_STEPS == 64 )
+ fac_Q16 = silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 - 6 );
+#else
+ fac_Q16 = silk_DIV32_16( silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 ), TRANSITION_FRAMES );
+#endif
+ ind = silk_RSHIFT( fac_Q16, 16 );
+ fac_Q16 -= silk_LSHIFT( ind, 16 );
+
+ silk_assert( ind >= 0 );
+ silk_assert( ind < TRANSITION_INT_NUM );
+
+ /* Interpolate filter coefficients */
+ silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 );
+
+ /* Update transition frame number for next frame */
+ psLP->transition_frame_no = silk_LIMIT( psLP->transition_frame_no + psLP->mode, 0, TRANSITION_FRAMES );
+
+ /* ARMA low-pass filtering */
+ silk_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 );
+ silk_biquad_alt_stride1( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length);
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SIGPROCFIX_API_MACROCOUNT_H
+#define SIGPROCFIX_API_MACROCOUNT_H
+
+#ifdef silk_MACRO_COUNT
+#include <stdio.h>
+#define varDefine opus_int64 ops_count = 0;
+
+extern opus_int64 ops_count;
+
+static OPUS_INLINE opus_int64 silk_SaveCount(){
+ return(ops_count);
+}
+
+static OPUS_INLINE opus_int64 silk_SaveResetCount(){
+ opus_int64 ret;
+
+ ret = ops_count;
+ ops_count = 0;
+ return(ret);
+}
+
+static OPUS_INLINE silk_PrintCount(){
+ printf("ops_count = %d \n ", (opus_int32)ops_count);
+}
+
+#undef silk_MUL
+static OPUS_INLINE opus_int32 silk_MUL(opus_int32 a32, opus_int32 b32){
+ opus_int32 ret;
+ ops_count += 4;
+ ret = a32 * b32;
+ return ret;
+}
+
+#undef silk_MUL_uint
+static OPUS_INLINE opus_uint32 silk_MUL_uint(opus_uint32 a32, opus_uint32 b32){
+ opus_uint32 ret;
+ ops_count += 4;
+ ret = a32 * b32;
+ return ret;
+}
+#undef silk_MLA
+static OPUS_INLINE opus_int32 silk_MLA(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+ opus_int32 ret;
+ ops_count += 4;
+ ret = a32 + b32 * c32;
+ return ret;
+}
+
+#undef silk_MLA_uint
+static OPUS_INLINE opus_int32 silk_MLA_uint(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32){
+ opus_uint32 ret;
+ ops_count += 4;
+ ret = a32 + b32 * c32;
+ return ret;
+}
+
+#undef silk_SMULWB
+static OPUS_INLINE opus_int32 silk_SMULWB(opus_int32 a32, opus_int32 b32){
+ opus_int32 ret;
+ ops_count += 5;
+ ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16);
+ return ret;
+}
+#undef silk_SMLAWB
+static OPUS_INLINE opus_int32 silk_SMLAWB(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+ opus_int32 ret;
+ ops_count += 5;
+ ret = ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16)));
+ return ret;
+}
+
+#undef silk_SMULWT
+static OPUS_INLINE opus_int32 silk_SMULWT(opus_int32 a32, opus_int32 b32){
+ opus_int32 ret;
+ ops_count += 4;
+ ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16);
+ return ret;
+}
+#undef silk_SMLAWT
+static OPUS_INLINE opus_int32 silk_SMLAWT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+ opus_int32 ret;
+ ops_count += 4;
+ ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16));
+ return ret;
+}
+
+#undef silk_SMULBB
+static OPUS_INLINE opus_int32 silk_SMULBB(opus_int32 a32, opus_int32 b32){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = (opus_int32)((opus_int16)a32) * (opus_int32)((opus_int16)b32);
+ return ret;
+}
+#undef silk_SMLABB
+static OPUS_INLINE opus_int32 silk_SMLABB(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32);
+ return ret;
+}
+
+#undef silk_SMULBT
+static OPUS_INLINE opus_int32 silk_SMULBT(opus_int32 a32, opus_int32 b32 ){
+ opus_int32 ret;
+ ops_count += 4;
+ ret = ((opus_int32)((opus_int16)a32)) * (b32 >> 16);
+ return ret;
+}
+
+#undef silk_SMLABT
+static OPUS_INLINE opus_int32 silk_SMLABT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16);
+ return ret;
+}
+
+#undef silk_SMULTT
+static OPUS_INLINE opus_int32 silk_SMULTT(opus_int32 a32, opus_int32 b32){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = (a32 >> 16) * (b32 >> 16);
+ return ret;
+}
+
+#undef silk_SMLATT
+static OPUS_INLINE opus_int32 silk_SMLATT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = a32 + (b32 >> 16) * (c32 >> 16);
+ return ret;
+}
+
+
+/* multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode)*/
+#undef silk_MLA_ovflw
+#define silk_MLA_ovflw silk_MLA
+
+#undef silk_SMLABB_ovflw
+#define silk_SMLABB_ovflw silk_SMLABB
+
+#undef silk_SMLABT_ovflw
+#define silk_SMLABT_ovflw silk_SMLABT
+
+#undef silk_SMLATT_ovflw
+#define silk_SMLATT_ovflw silk_SMLATT
+
+#undef silk_SMLAWB_ovflw
+#define silk_SMLAWB_ovflw silk_SMLAWB
+
+#undef silk_SMLAWT_ovflw
+#define silk_SMLAWT_ovflw silk_SMLAWT
+
+#undef silk_SMULL
+static OPUS_INLINE opus_int64 silk_SMULL(opus_int32 a32, opus_int32 b32){
+ opus_int64 ret;
+ ops_count += 8;
+ ret = ((opus_int64)(a32) * /*(opus_int64)*/(b32));
+ return ret;
+}
+
+#undef silk_SMLAL
+static OPUS_INLINE opus_int64 silk_SMLAL(opus_int64 a64, opus_int32 b32, opus_int32 c32){
+ opus_int64 ret;
+ ops_count += 8;
+ ret = a64 + ((opus_int64)(b32) * /*(opus_int64)*/(c32));
+ return ret;
+}
+#undef silk_SMLALBB
+static OPUS_INLINE opus_int64 silk_SMLALBB(opus_int64 a64, opus_int16 b16, opus_int16 c16){
+ opus_int64 ret;
+ ops_count += 4;
+ ret = a64 + ((opus_int64)(b16) * /*(opus_int64)*/(c16));
+ return ret;
+}
+
+#undef SigProcFIX_CLZ16
+static OPUS_INLINE opus_int32 SigProcFIX_CLZ16(opus_int16 in16)
+{
+ opus_int32 out32 = 0;
+ ops_count += 10;
+ if( in16 == 0 ) {
+ return 16;
+ }
+ /* test nibbles */
+ if( in16 & 0xFF00 ) {
+ if( in16 & 0xF000 ) {
+ in16 >>= 12;
+ } else {
+ out32 += 4;
+ in16 >>= 8;
+ }
+ } else {
+ if( in16 & 0xFFF0 ) {
+ out32 += 8;
+ in16 >>= 4;
+ } else {
+ out32 += 12;
+ }
+ }
+ /* test bits and return */
+ if( in16 & 0xC ) {
+ if( in16 & 0x8 )
+ return out32 + 0;
+ else
+ return out32 + 1;
+ } else {
+ if( in16 & 0xE )
+ return out32 + 2;
+ else
+ return out32 + 3;
+ }
+}
+
+#undef SigProcFIX_CLZ32
+static OPUS_INLINE opus_int32 SigProcFIX_CLZ32(opus_int32 in32)
+{
+ /* test highest 16 bits and convert to opus_int16 */
+ ops_count += 2;
+ if( in32 & 0xFFFF0000 ) {
+ return SigProcFIX_CLZ16((opus_int16)(in32 >> 16));
+ } else {
+ return SigProcFIX_CLZ16((opus_int16)in32) + 16;
+ }
+}
+
+#undef silk_DIV32
+static OPUS_INLINE opus_int32 silk_DIV32(opus_int32 a32, opus_int32 b32){
+ ops_count += 64;
+ return a32 / b32;
+}
+
+#undef silk_DIV32_16
+static OPUS_INLINE opus_int32 silk_DIV32_16(opus_int32 a32, opus_int32 b32){
+ ops_count += 32;
+ return a32 / b32;
+}
+
+#undef silk_SAT8
+static OPUS_INLINE opus_int8 silk_SAT8(opus_int64 a){
+ opus_int8 tmp;
+ ops_count += 1;
+ tmp = (opus_int8)((a) > silk_int8_MAX ? silk_int8_MAX : \
+ ((a) < silk_int8_MIN ? silk_int8_MIN : (a)));
+ return(tmp);
+}
+
+#undef silk_SAT16
+static OPUS_INLINE opus_int16 silk_SAT16(opus_int64 a){
+ opus_int16 tmp;
+ ops_count += 1;
+ tmp = (opus_int16)((a) > silk_int16_MAX ? silk_int16_MAX : \
+ ((a) < silk_int16_MIN ? silk_int16_MIN : (a)));
+ return(tmp);
+}
+#undef silk_SAT32
+static OPUS_INLINE opus_int32 silk_SAT32(opus_int64 a){
+ opus_int32 tmp;
+ ops_count += 1;
+ tmp = (opus_int32)((a) > silk_int32_MAX ? silk_int32_MAX : \
+ ((a) < silk_int32_MIN ? silk_int32_MIN : (a)));
+ return(tmp);
+}
+#undef silk_POS_SAT32
+static OPUS_INLINE opus_int32 silk_POS_SAT32(opus_int64 a){
+ opus_int32 tmp;
+ ops_count += 1;
+ tmp = (opus_int32)((a) > silk_int32_MAX ? silk_int32_MAX : (a));
+ return(tmp);
+}
+
+#undef silk_ADD_POS_SAT8
+static OPUS_INLINE opus_int8 silk_ADD_POS_SAT8(opus_int64 a, opus_int64 b){
+ opus_int8 tmp;
+ ops_count += 1;
+ tmp = (opus_int8)((((a)+(b)) & 0x80) ? silk_int8_MAX : ((a)+(b)));
+ return(tmp);
+}
+#undef silk_ADD_POS_SAT16
+static OPUS_INLINE opus_int16 silk_ADD_POS_SAT16(opus_int64 a, opus_int64 b){
+ opus_int16 tmp;
+ ops_count += 1;
+ tmp = (opus_int16)((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b)));
+ return(tmp);
+}
+
+#undef silk_ADD_POS_SAT32
+static OPUS_INLINE opus_int32 silk_ADD_POS_SAT32(opus_int64 a, opus_int64 b){
+ opus_int32 tmp;
+ ops_count += 1;
+ tmp = (opus_int32)((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)));
+ return(tmp);
+}
+
+#undef silk_LSHIFT8
+static OPUS_INLINE opus_int8 silk_LSHIFT8(opus_int8 a, opus_int32 shift){
+ opus_int8 ret;
+ ops_count += 1;
+ ret = a << shift;
+ return ret;
+}
+#undef silk_LSHIFT16
+static OPUS_INLINE opus_int16 silk_LSHIFT16(opus_int16 a, opus_int32 shift){
+ opus_int16 ret;
+ ops_count += 1;
+ ret = a << shift;
+ return ret;
+}
+#undef silk_LSHIFT32
+static OPUS_INLINE opus_int32 silk_LSHIFT32(opus_int32 a, opus_int32 shift){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = a << shift;
+ return ret;
+}
+#undef silk_LSHIFT64
+static OPUS_INLINE opus_int64 silk_LSHIFT64(opus_int64 a, opus_int shift){
+ ops_count += 1;
+ return a << shift;
+}
+
+#undef silk_LSHIFT_ovflw
+static OPUS_INLINE opus_int32 silk_LSHIFT_ovflw(opus_int32 a, opus_int32 shift){
+ ops_count += 1;
+ return a << shift;
+}
+
+#undef silk_LSHIFT_uint
+static OPUS_INLINE opus_uint32 silk_LSHIFT_uint(opus_uint32 a, opus_int32 shift){
+ opus_uint32 ret;
+ ops_count += 1;
+ ret = a << shift;
+ return ret;
+}
+
+#undef silk_RSHIFT8
+static OPUS_INLINE opus_int8 silk_RSHIFT8(opus_int8 a, opus_int32 shift){
+ ops_count += 1;
+ return a >> shift;
+}
+#undef silk_RSHIFT16
+static OPUS_INLINE opus_int16 silk_RSHIFT16(opus_int16 a, opus_int32 shift){
+ ops_count += 1;
+ return a >> shift;
+}
+#undef silk_RSHIFT32
+static OPUS_INLINE opus_int32 silk_RSHIFT32(opus_int32 a, opus_int32 shift){
+ ops_count += 1;
+ return a >> shift;
+}
+#undef silk_RSHIFT64
+static OPUS_INLINE opus_int64 silk_RSHIFT64(opus_int64 a, opus_int64 shift){
+ ops_count += 1;
+ return a >> shift;
+}
+
+#undef silk_RSHIFT_uint
+static OPUS_INLINE opus_uint32 silk_RSHIFT_uint(opus_uint32 a, opus_int32 shift){
+ ops_count += 1;
+ return a >> shift;
+}
+
+#undef silk_ADD_LSHIFT
+static OPUS_INLINE opus_int32 silk_ADD_LSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = a + (b << shift);
+ return ret; /* shift >= 0*/
+}
+#undef silk_ADD_LSHIFT32
+static OPUS_INLINE opus_int32 silk_ADD_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = a + (b << shift);
+ return ret; /* shift >= 0*/
+}
+#undef silk_ADD_LSHIFT_uint
+static OPUS_INLINE opus_uint32 silk_ADD_LSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){
+ opus_uint32 ret;
+ ops_count += 1;
+ ret = a + (b << shift);
+ return ret; /* shift >= 0*/
+}
+#undef silk_ADD_RSHIFT
+static OPUS_INLINE opus_int32 silk_ADD_RSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = a + (b >> shift);
+ return ret; /* shift > 0*/
+}
+#undef silk_ADD_RSHIFT32
+static OPUS_INLINE opus_int32 silk_ADD_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = a + (b >> shift);
+ return ret; /* shift > 0*/
+}
+#undef silk_ADD_RSHIFT_uint
+static OPUS_INLINE opus_uint32 silk_ADD_RSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){
+ opus_uint32 ret;
+ ops_count += 1;
+ ret = a + (b >> shift);
+ return ret; /* shift > 0*/
+}
+#undef silk_SUB_LSHIFT32
+static OPUS_INLINE opus_int32 silk_SUB_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = a - (b << shift);
+ return ret; /* shift >= 0*/
+}
+#undef silk_SUB_RSHIFT32
+static OPUS_INLINE opus_int32 silk_SUB_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = a - (b >> shift);
+ return ret; /* shift > 0*/
+}
+
+#undef silk_RSHIFT_ROUND
+static OPUS_INLINE opus_int32 silk_RSHIFT_ROUND(opus_int32 a, opus_int32 shift){
+ opus_int32 ret;
+ ops_count += 3;
+ ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
+ return ret;
+}
+
+#undef silk_RSHIFT_ROUND64
+static OPUS_INLINE opus_int64 silk_RSHIFT_ROUND64(opus_int64 a, opus_int32 shift){
+ opus_int64 ret;
+ ops_count += 6;
+ ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
+ return ret;
+}
+
+#undef silk_abs_int64
+static OPUS_INLINE opus_int64 silk_abs_int64(opus_int64 a){
+ ops_count += 1;
+ return (((a) > 0) ? (a) : -(a)); /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN*/
+}
+
+#undef silk_abs_int32
+static OPUS_INLINE opus_int32 silk_abs_int32(opus_int32 a){
+ ops_count += 1;
+ return silk_abs(a);
+}
+
+
+#undef silk_min
+static silk_min(a, b){
+ ops_count += 1;
+ return (((a) < (b)) ? (a) : (b));
+}
+#undef silk_max
+static silk_max(a, b){
+ ops_count += 1;
+ return (((a) > (b)) ? (a) : (b));
+}
+#undef silk_sign
+static silk_sign(a){
+ ops_count += 1;
+ return ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ));
+}
+
+#undef silk_ADD16
+static OPUS_INLINE opus_int16 silk_ADD16(opus_int16 a, opus_int16 b){
+ opus_int16 ret;
+ ops_count += 1;
+ ret = a + b;
+ return ret;
+}
+
+#undef silk_ADD32
+static OPUS_INLINE opus_int32 silk_ADD32(opus_int32 a, opus_int32 b){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = a + b;
+ return ret;
+}
+
+#undef silk_ADD64
+static OPUS_INLINE opus_int64 silk_ADD64(opus_int64 a, opus_int64 b){
+ opus_int64 ret;
+ ops_count += 2;
+ ret = a + b;
+ return ret;
+}
+
+#undef silk_SUB16
+static OPUS_INLINE opus_int16 silk_SUB16(opus_int16 a, opus_int16 b){
+ opus_int16 ret;
+ ops_count += 1;
+ ret = a - b;
+ return ret;
+}
+
+#undef silk_SUB32
+static OPUS_INLINE opus_int32 silk_SUB32(opus_int32 a, opus_int32 b){
+ opus_int32 ret;
+ ops_count += 1;
+ ret = a - b;
+ return ret;
+}
+
+#undef silk_SUB64
+static OPUS_INLINE opus_int64 silk_SUB64(opus_int64 a, opus_int64 b){
+ opus_int64 ret;
+ ops_count += 2;
+ ret = a - b;
+ return ret;
+}
+
+#undef silk_ADD_SAT16
+static OPUS_INLINE opus_int16 silk_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) {
+ opus_int16 res;
+ /* Nb will be counted in AKP_add32 and silk_SAT16*/
+ res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) );
+ return res;
+}
+
+#undef silk_ADD_SAT32
+static OPUS_INLINE opus_int32 silk_ADD_SAT32(opus_int32 a32, opus_int32 b32){
+ opus_int32 res;
+ ops_count += 1;
+ res = ((((a32) + (b32)) & 0x80000000) == 0 ? \
+ ((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) : \
+ ((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) );
+ return res;
+}
+
+#undef silk_ADD_SAT64
+static OPUS_INLINE opus_int64 silk_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) {
+ opus_int64 res;
+ ops_count += 1;
+ res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \
+ ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) : \
+ ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) );
+ return res;
+}
+
+#undef silk_SUB_SAT16
+static OPUS_INLINE opus_int16 silk_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) {
+ opus_int16 res;
+ silk_assert(0);
+ /* Nb will be counted in sub-macros*/
+ res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) );
+ return res;
+}
+
+#undef silk_SUB_SAT32
+static OPUS_INLINE opus_int32 silk_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) {
+ opus_int32 res;
+ ops_count += 1;
+ res = ((((a32)-(b32)) & 0x80000000) == 0 ? \
+ (( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \
+ ((((a32)^0x80000000) & (b32) & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) );
+ return res;
+}
+
+#undef silk_SUB_SAT64
+static OPUS_INLINE opus_int64 silk_SUB_SAT64( opus_int64 a64, opus_int64 b64 ) {
+ opus_int64 res;
+ ops_count += 1;
+ res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \
+ (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) : \
+ ((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) );
+
+ return res;
+}
+
+#undef silk_SMULWW
+static OPUS_INLINE opus_int32 silk_SMULWW(opus_int32 a32, opus_int32 b32){
+ opus_int32 ret;
+ /* Nb will be counted in sub-macros*/
+ ret = silk_MLA(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16));
+ return ret;
+}
+
+#undef silk_SMLAWW
+static OPUS_INLINE opus_int32 silk_SMLAWW(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+ opus_int32 ret;
+ /* Nb will be counted in sub-macros*/
+ ret = silk_MLA(silk_SMLAWB((a32), (b32), (c32)), (b32), silk_RSHIFT_ROUND((c32), 16));
+ return ret;
+}
+
+#undef silk_min_int
+static OPUS_INLINE opus_int silk_min_int(opus_int a, opus_int b)
+{
+ ops_count += 1;
+ return (((a) < (b)) ? (a) : (b));
+}
+
+#undef silk_min_16
+static OPUS_INLINE opus_int16 silk_min_16(opus_int16 a, opus_int16 b)
+{
+ ops_count += 1;
+ return (((a) < (b)) ? (a) : (b));
+}
+#undef silk_min_32
+static OPUS_INLINE opus_int32 silk_min_32(opus_int32 a, opus_int32 b)
+{
+ ops_count += 1;
+ return (((a) < (b)) ? (a) : (b));
+}
+#undef silk_min_64
+static OPUS_INLINE opus_int64 silk_min_64(opus_int64 a, opus_int64 b)
+{
+ ops_count += 1;
+ return (((a) < (b)) ? (a) : (b));
+}
+
+/* silk_min() versions with typecast in the function call */
+#undef silk_max_int
+static OPUS_INLINE opus_int silk_max_int(opus_int a, opus_int b)
+{
+ ops_count += 1;
+ return (((a) > (b)) ? (a) : (b));
+}
+#undef silk_max_16
+static OPUS_INLINE opus_int16 silk_max_16(opus_int16 a, opus_int16 b)
+{
+ ops_count += 1;
+ return (((a) > (b)) ? (a) : (b));
+}
+#undef silk_max_32
+static OPUS_INLINE opus_int32 silk_max_32(opus_int32 a, opus_int32 b)
+{
+ ops_count += 1;
+ return (((a) > (b)) ? (a) : (b));
+}
+
+#undef silk_max_64
+static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
+{
+ ops_count += 1;
+ return (((a) > (b)) ? (a) : (b));
+}
+
+
+#undef silk_LIMIT_int
+static OPUS_INLINE opus_int silk_LIMIT_int(opus_int a, opus_int limit1, opus_int limit2)
+{
+ opus_int ret;
+ ops_count += 6;
+
+ ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
+ : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
+
+ return(ret);
+}
+
+#undef silk_LIMIT_16
+static OPUS_INLINE opus_int16 silk_LIMIT_16(opus_int16 a, opus_int16 limit1, opus_int16 limit2)
+{
+ opus_int16 ret;
+ ops_count += 6;
+
+ ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
+ : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
+
+return(ret);
+}
+
+
+#undef silk_LIMIT_32
+static OPUS_INLINE opus_int32 silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
+{
+ opus_int32 ret;
+ ops_count += 6;
+
+ ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
+ : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
+ return(ret);
+}
+
+#else
+#define varDefine
+#define silk_SaveCount()
+
+#endif
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Copyright (C) 2012 Xiph.Org Foundation
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 MACRO_DEBUG_H
+#define MACRO_DEBUG_H
+
+/* Redefine macro functions with extensive assertion in DEBUG mode.
+ As functions can't be undefined, this file can't work with SigProcFIX_MacroCount.h */
+
+#if ( defined (FIXED_DEBUG) || ( 0 && defined (_DEBUG) ) ) && !defined (silk_MACRO_COUNT)
+
+#undef silk_ADD16
+#define silk_ADD16(a,b) silk_ADD16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_ADD16_(opus_int16 a, opus_int16 b, char *file, int line){
+ opus_int16 ret;
+
+ ret = a + b;
+ if ( ret != silk_ADD_SAT16( a, b ) )
+ {
+ fprintf (stderr, "silk_ADD16(%d, %d) in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_ADD32
+#define silk_ADD32(a,b) silk_ADD32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_ADD32_(opus_int32 a, opus_int32 b, char *file, int line){
+ opus_int32 ret;
+
+ ret = (opus_int32)((opus_uint32)a + (opus_uint32)b);
+ if ( ret != silk_ADD_SAT32( a, b ) )
+ {
+ fprintf (stderr, "silk_ADD32(%d, %d) in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_ADD64
+#define silk_ADD64(a,b) silk_ADD64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_ADD64_(opus_int64 a, opus_int64 b, char *file, int line){
+ opus_int64 ret;
+
+ ret = a + b;
+ if ( ret != silk_ADD_SAT64( a, b ) )
+ {
+ fprintf (stderr, "silk_ADD64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_SUB16
+#define silk_SUB16(a,b) silk_SUB16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_SUB16_(opus_int16 a, opus_int16 b, char *file, int line){
+ opus_int16 ret;
+
+ ret = a - b;
+ if ( ret != silk_SUB_SAT16( a, b ) )
+ {
+ fprintf (stderr, "silk_SUB16(%d, %d) in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_SUB32
+#define silk_SUB32(a,b) silk_SUB32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SUB32_(opus_int32 a, opus_int32 b, char *file, int line){
+ opus_int64 ret;
+
+ ret = a - (opus_int64)b;
+ if ( ret != silk_SUB_SAT32( a, b ) )
+ {
+ fprintf (stderr, "silk_SUB32(%d, %d) in %s: line %d\n", a, b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_SUB64
+#define silk_SUB64(a,b) silk_SUB64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_SUB64_(opus_int64 a, opus_int64 b, char *file, int line){
+ opus_int64 ret;
+
+ ret = a - b;
+ if ( ret != silk_SUB_SAT64( a, b ) )
+ {
+ fprintf (stderr, "silk_SUB64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)b, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_ADD_SAT16
+#define silk_ADD_SAT16(a,b) silk_ADD_SAT16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_ADD_SAT16_( opus_int16 a16, opus_int16 b16, char *file, int line) {
+ opus_int16 res;
+ res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) );
+ if ( res != silk_SAT16( (opus_int32)a16 + (opus_int32)b16 ) )
+ {
+ fprintf (stderr, "silk_ADD_SAT16(%d, %d) in %s: line %d\n", a16, b16, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return res;
+}
+
+#undef silk_ADD_SAT32
+#define silk_ADD_SAT32(a,b) silk_ADD_SAT32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_ADD_SAT32_(opus_int32 a32, opus_int32 b32, char *file, int line){
+ opus_int32 res;
+ res = ((((opus_uint32)(a32) + (opus_uint32)(b32)) & 0x80000000) == 0 ? \
+ ((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) : \
+ ((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) );
+ if ( res != silk_SAT32( (opus_int64)a32 + (opus_int64)b32 ) )
+ {
+ fprintf (stderr, "silk_ADD_SAT32(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return res;
+}
+
+#undef silk_ADD_SAT64
+#define silk_ADD_SAT64(a,b) silk_ADD_SAT64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_ADD_SAT64_( opus_int64 a64, opus_int64 b64, char *file, int line) {
+ opus_int64 res;
+ int fail = 0;
+ res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \
+ ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) : \
+ ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) );
+ if( res != a64 + b64 ) {
+ /* Check that we saturated to the correct extreme value */
+ if ( !(( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) ||
+ ( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) ) )
+ {
+ fail = 1;
+ }
+ } else {
+ /* Saturation not necessary */
+ fail = res != a64 + b64;
+ }
+ if ( fail )
+ {
+ fprintf (stderr, "silk_ADD_SAT64(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return res;
+}
+
+#undef silk_SUB_SAT16
+#define silk_SUB_SAT16(a,b) silk_SUB_SAT16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_SUB_SAT16_( opus_int16 a16, opus_int16 b16, char *file, int line ) {
+ opus_int16 res;
+ res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) );
+ if ( res != silk_SAT16( (opus_int32)a16 - (opus_int32)b16 ) )
+ {
+ fprintf (stderr, "silk_SUB_SAT16(%d, %d) in %s: line %d\n", a16, b16, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return res;
+}
+
+#undef silk_SUB_SAT32
+#define silk_SUB_SAT32(a,b) silk_SUB_SAT32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SUB_SAT32_( opus_int32 a32, opus_int32 b32, char *file, int line ) {
+ opus_int32 res;
+ res = ((((opus_uint32)(a32)-(opus_uint32)(b32)) & 0x80000000) == 0 ? \
+ (( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \
+ ((((a32)^0x80000000) & (b32) & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) );
+ if ( res != silk_SAT32( (opus_int64)a32 - (opus_int64)b32 ) )
+ {
+ fprintf (stderr, "silk_SUB_SAT32(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return res;
+}
+
+#undef silk_SUB_SAT64
+#define silk_SUB_SAT64(a,b) silk_SUB_SAT64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_SUB_SAT64_( opus_int64 a64, opus_int64 b64, char *file, int line ) {
+ opus_int64 res;
+ int fail = 0;
+ res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \
+ (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) : \
+ ((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) );
+ if( res != a64 - b64 ) {
+ /* Check that we saturated to the correct extreme value */
+ if( !(( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) ||
+ ( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) ))
+ {
+ fail = 1;
+ }
+ } else {
+ /* Saturation not necessary */
+ fail = res != a64 - b64;
+ }
+ if ( fail )
+ {
+ fprintf (stderr, "silk_SUB_SAT64(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return res;
+}
+
+#undef silk_MUL
+#define silk_MUL(a,b) silk_MUL_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_MUL_(opus_int32 a32, opus_int32 b32, char *file, int line){
+ opus_int32 ret;
+ opus_int64 ret64;
+ ret = (opus_int32)((opus_uint32)a32 * (opus_uint32)b32);
+ ret64 = (opus_int64)a32 * (opus_int64)b32;
+ if ( (opus_int64)ret != ret64 )
+ {
+ fprintf (stderr, "silk_MUL(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_MUL_uint
+#define silk_MUL_uint(a,b) silk_MUL_uint_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_uint32 silk_MUL_uint_(opus_uint32 a32, opus_uint32 b32, char *file, int line){
+ opus_uint32 ret;
+ ret = a32 * b32;
+ if ( (opus_uint64)ret != (opus_uint64)a32 * (opus_uint64)b32 )
+ {
+ fprintf (stderr, "silk_MUL_uint(%u, %u) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_MLA
+#define silk_MLA(a,b,c) silk_MLA_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_MLA_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+ opus_int32 ret;
+ ret = a32 + b32 * c32;
+ if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32 )
+ {
+ fprintf (stderr, "silk_MLA(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_MLA_uint
+#define silk_MLA_uint(a,b,c) silk_MLA_uint_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_MLA_uint_(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32, char *file, int line){
+ opus_uint32 ret;
+ ret = a32 + b32 * c32;
+ if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32 )
+ {
+ fprintf (stderr, "silk_MLA_uint(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_SMULWB
+#define silk_SMULWB(a,b) silk_SMULWB_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMULWB_(opus_int32 a32, opus_int32 b32, char *file, int line){
+ opus_int32 ret;
+ ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16);
+ if ( (opus_int64)ret != ((opus_int64)a32 * (opus_int16)b32) >> 16 )
+ {
+ fprintf (stderr, "silk_SMULWB(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_SMLAWB
+#define silk_SMLAWB(a,b,c) silk_SMLAWB_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMLAWB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+ opus_int32 ret;
+ ret = silk_ADD32_ovflw( a32, silk_SMULWB( b32, c32 ) );
+ if ( ret != silk_ADD_SAT32( a32, silk_SMULWB( b32, c32 ) ) )
+ {
+ fprintf (stderr, "silk_SMLAWB(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_SMULWT
+#define silk_SMULWT(a,b) silk_SMULWT_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMULWT_(opus_int32 a32, opus_int32 b32, char *file, int line){
+ opus_int32 ret;
+ ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16);
+ if ( (opus_int64)ret != ((opus_int64)a32 * (b32 >> 16)) >> 16 )
+ {
+ fprintf (stderr, "silk_SMULWT(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_SMLAWT
+#define silk_SMLAWT(a,b,c) silk_SMLAWT_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMLAWT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+ opus_int32 ret;
+ ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16));
+ if ( (opus_int64)ret != (opus_int64)a32 + (((opus_int64)b32 * (c32 >> 16)) >> 16) )
+ {
+ fprintf (stderr, "silk_SMLAWT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_SMULL
+#define silk_SMULL(a,b) silk_SMULL_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_SMULL_(opus_int64 a64, opus_int64 b64, char *file, int line){
+ opus_int64 ret64;
+ int fail = 0;
+ ret64 = a64 * b64;
+ if( b64 != 0 ) {
+ fail = a64 != (ret64 / b64);
+ } else if( a64 != 0 ) {
+ fail = b64 != (ret64 / a64);
+ }
+ if ( fail )
+ {
+ fprintf (stderr, "silk_SMULL(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret64;
+}
+
+/* no checking needed for silk_SMULBB */
+#undef silk_SMLABB
+#define silk_SMLABB(a,b,c) silk_SMLABB_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMLABB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+ opus_int32 ret;
+ ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32);
+ if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int16)c32 )
+ {
+ fprintf (stderr, "silk_SMLABB(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+/* no checking needed for silk_SMULBT */
+#undef silk_SMLABT
+#define silk_SMLABT(a,b,c) silk_SMLABT_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMLABT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+ opus_int32 ret;
+ ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16);
+ if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (c32 >> 16) )
+ {
+ fprintf (stderr, "silk_SMLABT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+/* no checking needed for silk_SMULTT */
+#undef silk_SMLATT
+#define silk_SMLATT(a,b,c) silk_SMLATT_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMLATT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+ opus_int32 ret;
+ ret = a32 + (b32 >> 16) * (c32 >> 16);
+ if ( (opus_int64)ret != (opus_int64)a32 + (b32 >> 16) * (c32 >> 16) )
+ {
+ fprintf (stderr, "silk_SMLATT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_SMULWW
+#define silk_SMULWW(a,b) silk_SMULWW_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMULWW_(opus_int32 a32, opus_int32 b32, char *file, int line){
+ opus_int32 ret, tmp1, tmp2;
+ opus_int64 ret64;
+ int fail = 0;
+
+ ret = silk_SMULWB( a32, b32 );
+ tmp1 = silk_RSHIFT_ROUND( b32, 16 );
+ tmp2 = silk_MUL( a32, tmp1 );
+
+ fail |= (opus_int64)tmp2 != (opus_int64) a32 * (opus_int64) tmp1;
+
+ tmp1 = ret;
+ ret = silk_ADD32( tmp1, tmp2 );
+ fail |= silk_ADD32( tmp1, tmp2 ) != silk_ADD_SAT32( tmp1, tmp2 );
+
+ ret64 = silk_RSHIFT64( silk_SMULL( a32, b32 ), 16 );
+ fail |= (opus_int64)ret != ret64;
+
+ if ( fail )
+ {
+ fprintf (stderr, "silk_SMULWW(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+
+ return ret;
+}
+
+#undef silk_SMLAWW
+#define silk_SMLAWW(a,b,c) silk_SMLAWW_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SMLAWW_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
+ opus_int32 ret, tmp;
+
+ tmp = silk_SMULWW( b32, c32 );
+ ret = silk_ADD32( a32, tmp );
+ if ( ret != silk_ADD_SAT32( a32, tmp ) )
+ {
+ fprintf (stderr, "silk_SMLAWW(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+/* no checking needed for silk_SMULL
+ no checking needed for silk_SMLAL
+ no checking needed for silk_SMLALBB
+ no checking needed for SigProcFIX_CLZ16
+ no checking needed for SigProcFIX_CLZ32*/
+
+#undef silk_DIV32
+#define silk_DIV32(a,b) silk_DIV32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_DIV32_(opus_int32 a32, opus_int32 b32, char *file, int line){
+ if ( b32 == 0 )
+ {
+ fprintf (stderr, "silk_DIV32(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return a32 / b32;
+}
+
+#undef silk_DIV32_16
+#define silk_DIV32_16(a,b) silk_DIV32_16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_DIV32_16_(opus_int32 a32, opus_int32 b32, char *file, int line){
+ int fail = 0;
+ fail |= b32 == 0;
+ fail |= b32 > silk_int16_MAX;
+ fail |= b32 < silk_int16_MIN;
+ if ( fail )
+ {
+ fprintf (stderr, "silk_DIV32_16(%d, %d) in %s: line %d\n", a32, b32, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return a32 / b32;
+}
+
+/* no checking needed for silk_SAT8
+ no checking needed for silk_SAT16
+ no checking needed for silk_SAT32
+ no checking needed for silk_POS_SAT32
+ no checking needed for silk_ADD_POS_SAT8
+ no checking needed for silk_ADD_POS_SAT16
+ no checking needed for silk_ADD_POS_SAT32 */
+
+#undef silk_LSHIFT8
+#define silk_LSHIFT8(a,b) silk_LSHIFT8_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int8 silk_LSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){
+ opus_int8 ret;
+ int fail = 0;
+ ret = (opus_int8)((opus_uint8)a << shift);
+ fail |= shift < 0;
+ fail |= shift >= 8;
+ fail |= (opus_int64)ret != (opus_int64)(((opus_uint64)a) << shift);
+ if ( fail )
+ {
+ fprintf (stderr, "silk_LSHIFT8(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_LSHIFT16
+#define silk_LSHIFT16(a,b) silk_LSHIFT16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_LSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){
+ opus_int16 ret;
+ int fail = 0;
+ ret = (opus_int16)((opus_uint16)a << shift);
+ fail |= shift < 0;
+ fail |= shift >= 16;
+ fail |= (opus_int64)ret != (opus_int64)(((opus_uint64)a) << shift);
+ if ( fail )
+ {
+ fprintf (stderr, "silk_LSHIFT16(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_LSHIFT32
+#define silk_LSHIFT32(a,b) silk_LSHIFT32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_LSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){
+ opus_int32 ret;
+ int fail = 0;
+ ret = (opus_int32)((opus_uint32)a << shift);
+ fail |= shift < 0;
+ fail |= shift >= 32;
+ fail |= (opus_int64)ret != (opus_int64)(((opus_uint64)a) << shift);
+ if ( fail )
+ {
+ fprintf (stderr, "silk_LSHIFT32(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_LSHIFT64
+#define silk_LSHIFT64(a,b) silk_LSHIFT64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_LSHIFT64_(opus_int64 a, opus_int shift, char *file, int line){
+ opus_int64 ret;
+ int fail = 0;
+ ret = (opus_int64)((opus_uint64)a << shift);
+ fail |= shift < 0;
+ fail |= shift >= 64;
+ fail |= (ret>>shift) != ((opus_int64)a);
+ if ( fail )
+ {
+ fprintf (stderr, "silk_LSHIFT64(%lld, %d) in %s: line %d\n", (long long)a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_LSHIFT_ovflw
+#define silk_LSHIFT_ovflw(a,b) silk_LSHIFT_ovflw_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_LSHIFT_ovflw_(opus_int32 a, opus_int32 shift, char *file, int line){
+ if ( (shift < 0) || (shift >= 32) ) /* no check for overflow */
+ {
+ fprintf (stderr, "silk_LSHIFT_ovflw(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return a << shift;
+}
+
+#undef silk_LSHIFT_uint
+#define silk_LSHIFT_uint(a,b) silk_LSHIFT_uint_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_uint32 silk_LSHIFT_uint_(opus_uint32 a, opus_int32 shift, char *file, int line){
+ opus_uint32 ret;
+ ret = a << shift;
+ if ( (shift < 0) || ((opus_int64)ret != ((opus_int64)a) << shift))
+ {
+ fprintf (stderr, "silk_LSHIFT_uint(%u, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_RSHIFT8
+#define silk_RSHITF8(a,b) silk_RSHIFT8_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int8 silk_RSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){
+ if ( (shift < 0) || (shift>=8) )
+ {
+ fprintf (stderr, "silk_RSHITF8(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return a >> shift;
+}
+
+#undef silk_RSHIFT16
+#define silk_RSHITF16(a,b) silk_RSHIFT16_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_RSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){
+ if ( (shift < 0) || (shift>=16) )
+ {
+ fprintf (stderr, "silk_RSHITF16(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return a >> shift;
+}
+
+#undef silk_RSHIFT32
+#define silk_RSHIFT32(a,b) silk_RSHIFT32_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_RSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){
+ if ( (shift < 0) || (shift>=32) )
+ {
+ fprintf (stderr, "silk_RSHITF32(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return a >> shift;
+}
+
+#undef silk_RSHIFT64
+#define silk_RSHIFT64(a,b) silk_RSHIFT64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_RSHIFT64_(opus_int64 a, opus_int64 shift, char *file, int line){
+ if ( (shift < 0) || (shift>=64) )
+ {
+ fprintf (stderr, "silk_RSHITF64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return a >> shift;
+}
+
+#undef silk_RSHIFT_uint
+#define silk_RSHIFT_uint(a,b) silk_RSHIFT_uint_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_uint32 silk_RSHIFT_uint_(opus_uint32 a, opus_int32 shift, char *file, int line){
+ if ( (shift < 0) || (shift>32) )
+ {
+ fprintf (stderr, "silk_RSHIFT_uint(%u, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return a >> shift;
+}
+
+#undef silk_ADD_LSHIFT
+#define silk_ADD_LSHIFT(a,b,c) silk_ADD_LSHIFT_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE int silk_ADD_LSHIFT_(int a, int b, int shift, char *file, int line){
+ opus_int16 ret;
+ ret = a + (opus_int16)((opus_uint16)b << shift);
+ if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (opus_int64)(((opus_uint64)b) << shift)) )
+ {
+ fprintf (stderr, "silk_ADD_LSHIFT(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret; /* shift >= 0 */
+}
+
+#undef silk_ADD_LSHIFT32
+#define silk_ADD_LSHIFT32(a,b,c) silk_ADD_LSHIFT32_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_ADD_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
+ opus_int32 ret;
+ ret = silk_ADD32_ovflw(a, (opus_int32)((opus_uint32)b << shift));
+ if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (opus_int64)(((opus_uint64)b) << shift)) )
+ {
+ fprintf (stderr, "silk_ADD_LSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret; /* shift >= 0 */
+}
+
+#undef silk_ADD_LSHIFT_uint
+#define silk_ADD_LSHIFT_uint(a,b,c) silk_ADD_LSHIFT_uint_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_uint32 silk_ADD_LSHIFT_uint_(opus_uint32 a, opus_uint32 b, opus_int32 shift, char *file, int line){
+ opus_uint32 ret;
+ ret = a + (b << shift);
+ if ( (shift < 0) || (shift>32) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) )
+ {
+ fprintf (stderr, "silk_ADD_LSHIFT_uint(%u, %u, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret; /* shift >= 0 */
+}
+
+#undef silk_ADD_RSHIFT
+#define silk_ADD_RSHIFT(a,b,c) silk_ADD_RSHIFT_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE int silk_ADD_RSHIFT_(int a, int b, int shift, char *file, int line){
+ opus_int16 ret;
+ ret = a + (b >> shift);
+ if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
+ {
+ fprintf (stderr, "silk_ADD_RSHIFT(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret; /* shift > 0 */
+}
+
+#undef silk_ADD_RSHIFT32
+#define silk_ADD_RSHIFT32(a,b,c) silk_ADD_RSHIFT32_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_ADD_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
+ opus_int32 ret;
+ ret = silk_ADD32_ovflw(a, (b >> shift));
+ if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
+ {
+ fprintf (stderr, "silk_ADD_RSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret; /* shift > 0 */
+}
+
+#undef silk_ADD_RSHIFT_uint
+#define silk_ADD_RSHIFT_uint(a,b,c) silk_ADD_RSHIFT_uint_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_uint32 silk_ADD_RSHIFT_uint_(opus_uint32 a, opus_uint32 b, opus_int32 shift, char *file, int line){
+ opus_uint32 ret;
+ ret = a + (b >> shift);
+ if ( (shift < 0) || (shift>32) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
+ {
+ fprintf (stderr, "silk_ADD_RSHIFT_uint(%u, %u, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret; /* shift > 0 */
+}
+
+#undef silk_SUB_LSHIFT32
+#define silk_SUB_LSHIFT32(a,b,c) silk_SUB_LSHIFT32_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SUB_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
+ opus_int32 ret;
+ ret = silk_SUB32_ovflw(a, (opus_int32)((opus_uint32)b << shift));
+ if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (opus_int64)(((opus_uint64)b) << shift)) )
+ {
+ fprintf (stderr, "silk_SUB_LSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret; /* shift >= 0 */
+}
+
+#undef silk_SUB_RSHIFT32
+#define silk_SUB_RSHIFT32(a,b,c) silk_SUB_RSHIFT32_((a), (b), (c), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_SUB_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
+ opus_int32 ret;
+ ret = silk_SUB32_ovflw(a, (b >> shift));
+ if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (((opus_int64)b) >> shift)) )
+ {
+ fprintf (stderr, "silk_SUB_RSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret; /* shift > 0 */
+}
+
+#undef silk_RSHIFT_ROUND
+#define silk_RSHIFT_ROUND(a,b) silk_RSHIFT_ROUND_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_RSHIFT_ROUND_(opus_int32 a, opus_int32 shift, char *file, int line){
+ opus_int32 ret;
+ ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
+ /* the macro definition can't handle a shift of zero */
+ if ( (shift <= 0) || (shift>31) || ((opus_int64)ret != ((opus_int64)a + ((opus_int64)1 << (shift - 1))) >> shift) )
+ {
+ fprintf (stderr, "silk_RSHIFT_ROUND(%d, %d) in %s: line %d\n", a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return ret;
+}
+
+#undef silk_RSHIFT_ROUND64
+#define silk_RSHIFT_ROUND64(a,b) silk_RSHIFT_ROUND64_((a), (b), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_RSHIFT_ROUND64_(opus_int64 a, opus_int32 shift, char *file, int line){
+ opus_int64 ret;
+ /* the macro definition can't handle a shift of zero */
+ if ( (shift <= 0) || (shift>=64) )
+ {
+ fprintf (stderr, "silk_RSHIFT_ROUND64(%lld, %d) in %s: line %d\n", (long long)a, shift, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
+ return ret;
+}
+
+/* silk_abs is used on floats also, so doesn't work... */
+/*#undef silk_abs
+static OPUS_INLINE opus_int32 silk_abs(opus_int32 a){
+ silk_assert(a != 0x80000000);
+ return (((a) > 0) ? (a) : -(a)); // Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN
+}*/
+
+#undef silk_abs_int64
+#define silk_abs_int64(a) silk_abs_int64_((a), __FILE__, __LINE__)
+static OPUS_INLINE opus_int64 silk_abs_int64_(opus_int64 a, char *file, int line){
+ if ( a == silk_int64_MIN )
+ {
+ fprintf (stderr, "silk_abs_int64(%lld) in %s: line %d\n", (long long)a, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return (((a) > 0) ? (a) : -(a)); /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */
+}
+
+#undef silk_abs_int32
+#define silk_abs_int32(a) silk_abs_int32_((a), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_abs_int32_(opus_int32 a, char *file, int line){
+ if ( a == silk_int32_MIN )
+ {
+ fprintf (stderr, "silk_abs_int32(%d) in %s: line %d\n", a, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return silk_abs(a);
+}
+
+#undef silk_CHECK_FIT8
+#define silk_CHECK_FIT8(a) silk_CHECK_FIT8_((a), __FILE__, __LINE__)
+static OPUS_INLINE opus_int8 silk_CHECK_FIT8_( opus_int64 a, char *file, int line ){
+ opus_int8 ret;
+ ret = (opus_int8)a;
+ if ( (opus_int64)ret != a )
+ {
+ fprintf (stderr, "silk_CHECK_FIT8(%lld) in %s: line %d\n", (long long)a, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return( ret );
+}
+
+#undef silk_CHECK_FIT16
+#define silk_CHECK_FIT16(a) silk_CHECK_FIT16_((a), __FILE__, __LINE__)
+static OPUS_INLINE opus_int16 silk_CHECK_FIT16_( opus_int64 a, char *file, int line ){
+ opus_int16 ret;
+ ret = (opus_int16)a;
+ if ( (opus_int64)ret != a )
+ {
+ fprintf (stderr, "silk_CHECK_FIT16(%lld) in %s: line %d\n", (long long)a, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return( ret );
+}
+
+#undef silk_CHECK_FIT32
+#define silk_CHECK_FIT32(a) silk_CHECK_FIT32_((a), __FILE__, __LINE__)
+static OPUS_INLINE opus_int32 silk_CHECK_FIT32_( opus_int64 a, char *file, int line ){
+ opus_int32 ret;
+ ret = (opus_int32)a;
+ if ( (opus_int64)ret != a )
+ {
+ fprintf (stderr, "silk_CHECK_FIT32(%lld) in %s: line %d\n", (long long)a, file, line);
+#ifdef FIXED_DEBUG_ASSERT
+ silk_assert( 0 );
+#endif
+ }
+ return( ret );
+}
+
+/* no checking for silk_NSHIFT_MUL_32_32
+ no checking for silk_NSHIFT_MUL_16_16
+ no checking needed for silk_min
+ no checking needed for silk_max
+ no checking needed for silk_sign
+*/
+
+#endif
+#endif /* MACRO_DEBUG_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* conversion between prediction filter coefficients and LSFs */
+/* order should be even */
+/* a piecewise linear approximation maps LSF <-> cos(LSF) */
+/* therefore the result is not accurate LSFs, but the two */
+/* functions are accurate inverses of each other */
+
+#include "SigProc_FIX.h"
+#include "tables.h"
+
+#define QA 16
+
+/* helper function for NLSF2A(..) */
+static OPUS_INLINE void silk_NLSF2A_find_poly(
+ opus_int32 *out, /* O intermediate polynomial, QA [dd+1] */
+ const opus_int32 *cLSF, /* I vector of interleaved 2*cos(LSFs), QA [d] */
+ opus_int dd /* I polynomial order (= 1/2 * filter order) */
+)
+{
+ opus_int k, n;
+ opus_int32 ftmp;
+
+ out[0] = silk_LSHIFT( 1, QA );
+ out[1] = -cLSF[0];
+ for( k = 1; k < dd; k++ ) {
+ ftmp = cLSF[2*k]; /* QA*/
+ out[k+1] = silk_LSHIFT( out[k-1], 1 ) - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[k] ), QA );
+ for( n = k; n > 1; n-- ) {
+ out[n] += out[n-2] - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[n-1] ), QA );
+ }
+ out[1] -= ftmp;
+ }
+}
+
+/* compute whitening filter coefficients from normalized line spectral frequencies */
+void silk_NLSF2A(
+ opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */
+ const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */
+ const opus_int d, /* I filter order (should be even) */
+ int arch /* I Run-time architecture */
+)
+{
+ /* This ordering was found to maximize quality. It improves numerical accuracy of
+ silk_NLSF2A_find_poly() compared to "standard" ordering. */
+ static const unsigned char ordering16[16] = {
+ 0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1
+ };
+ static const unsigned char ordering10[10] = {
+ 0, 9, 6, 3, 4, 5, 8, 1, 2, 7
+ };
+ const unsigned char *ordering;
+ opus_int k, i, dd;
+ opus_int32 cos_LSF_QA[ SILK_MAX_ORDER_LPC ];
+ opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
+ opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
+ opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ];
+
+ silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
+ celt_assert( d==10 || d==16 );
+
+ /* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
+ ordering = d == 16 ? ordering16 : ordering10;
+ for( k = 0; k < d; k++ ) {
+ silk_assert( NLSF[k] >= 0 );
+
+ /* f_int on a scale 0-127 (rounded down) */
+ f_int = silk_RSHIFT( NLSF[k], 15 - 7 );
+
+ /* f_frac, range: 0..255 */
+ f_frac = NLSF[k] - silk_LSHIFT( f_int, 15 - 7 );
+
+ silk_assert(f_int >= 0);
+ silk_assert(f_int < LSF_COS_TAB_SZ_FIX );
+
+ /* Read start and end value from table */
+ cos_val = silk_LSFCosTab_FIX_Q12[ f_int ]; /* Q12 */
+ delta = silk_LSFCosTab_FIX_Q12[ f_int + 1 ] - cos_val; /* Q12, with a range of 0..200 */
+
+ /* Linear interpolation */
+ cos_LSF_QA[ordering[k]] = silk_RSHIFT_ROUND( silk_LSHIFT( cos_val, 8 ) + silk_MUL( delta, f_frac ), 20 - QA ); /* QA */
+ }
+
+ dd = silk_RSHIFT( d, 1 );
+
+ /* generate even and odd polynomials using convolution */
+ silk_NLSF2A_find_poly( P, &cos_LSF_QA[ 0 ], dd );
+ silk_NLSF2A_find_poly( Q, &cos_LSF_QA[ 1 ], dd );
+
+ /* convert even and odd polynomials to opus_int32 Q12 filter coefs */
+ for( k = 0; k < dd; k++ ) {
+ Ptmp = P[ k+1 ] + P[ k ];
+ Qtmp = Q[ k+1 ] - Q[ k ];
+
+ /* the Ptmp and Qtmp values at this stage need to fit in int32 */
+ a32_QA1[ k ] = -Qtmp - Ptmp; /* QA+1 */
+ a32_QA1[ d-k-1 ] = Qtmp - Ptmp; /* QA+1 */
+ }
+
+ /* Convert int32 coefficients to Q12 int16 coefs */
+ silk_LPC_fit( a_Q12, a32_QA1, 12, QA + 1, d );
+
+ for( i = 0; silk_LPC_inverse_pred_gain( a_Q12, d, arch ) == 0 && i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
+ /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */
+ /* on the unscaled coefficients, convert to Q12 and measure again */
+ silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
+ for( k = 0; k < d; k++ ) {
+ a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
+ }
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "define.h"
+#include "SigProc_FIX.h"
+
+/*
+R. Laroia, N. Phamdo and N. Farvardin, "Robust and Efficient Quantization of Speech LSP
+Parameters Using Structured Vector Quantization", Proc. IEEE Int. Conf. Acoust., Speech,
+Signal Processing, pp. 641-644, 1991.
+*/
+
+/* Laroia low complexity NLSF weights */
+void silk_NLSF_VQ_weights_laroia(
+ opus_int16 *pNLSFW_Q_OUT, /* O Pointer to input vector weights [D] */
+ const opus_int16 *pNLSF_Q15, /* I Pointer to input vector [D] */
+ const opus_int D /* I Input vector dimension (even) */
+)
+{
+ opus_int k;
+ opus_int32 tmp1_int, tmp2_int;
+
+ celt_assert( D > 0 );
+ celt_assert( ( D & 1 ) == 0 );
+
+ /* First value */
+ tmp1_int = silk_max_int( pNLSF_Q15[ 0 ], 1 );
+ tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int );
+ tmp2_int = silk_max_int( pNLSF_Q15[ 1 ] - pNLSF_Q15[ 0 ], 1 );
+ tmp2_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp2_int );
+ pNLSFW_Q_OUT[ 0 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
+ silk_assert( pNLSFW_Q_OUT[ 0 ] > 0 );
+
+ /* Main loop */
+ for( k = 1; k < D - 1; k += 2 ) {
+ tmp1_int = silk_max_int( pNLSF_Q15[ k + 1 ] - pNLSF_Q15[ k ], 1 );
+ tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int );
+ pNLSFW_Q_OUT[ k ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
+ silk_assert( pNLSFW_Q_OUT[ k ] > 0 );
+
+ tmp2_int = silk_max_int( pNLSF_Q15[ k + 2 ] - pNLSF_Q15[ k + 1 ], 1 );
+ tmp2_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp2_int );
+ pNLSFW_Q_OUT[ k + 1 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
+ silk_assert( pNLSFW_Q_OUT[ k + 1 ] > 0 );
+ }
+
+ /* Last value */
+ tmp1_int = silk_max_int( ( 1 << 15 ) - pNLSF_Q15[ D - 1 ], 1 );
+ tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int );
+ pNLSFW_Q_OUT[ D - 1 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
+ silk_assert( pNLSFW_Q_OUT[ D - 1 ] > 0 );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Predictive dequantizer for NLSF residuals */
+static OPUS_INLINE void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */
+ opus_int16 x_Q10[], /* O Output [ order ] */
+ const opus_int8 indices[], /* I Quantization indices [ order ] */
+ const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */
+ const opus_int quant_step_size_Q16, /* I Quantization step size */
+ const opus_int16 order /* I Number of input values */
+)
+{
+ opus_int i, out_Q10, pred_Q10;
+
+ out_Q10 = 0;
+ for( i = order-1; i >= 0; i-- ) {
+ pred_Q10 = silk_RSHIFT( silk_SMULBB( out_Q10, (opus_int16)pred_coef_Q8[ i ] ), 8 );
+ out_Q10 = silk_LSHIFT( indices[ i ], 10 );
+ if( out_Q10 > 0 ) {
+ out_Q10 = silk_SUB16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
+ } else if( out_Q10 < 0 ) {
+ out_Q10 = silk_ADD16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
+ }
+ out_Q10 = silk_SMLAWB( pred_Q10, (opus_int32)out_Q10, quant_step_size_Q16 );
+ x_Q10[ i ] = out_Q10;
+ }
+}
+
+
+/***********************/
+/* NLSF vector decoder */
+/***********************/
+void silk_NLSF_decode(
+ opus_int16 *pNLSF_Q15, /* O Quantized NLSF vector [ LPC_ORDER ] */
+ opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */
+ const silk_NLSF_CB_struct *psNLSF_CB /* I Codebook object */
+)
+{
+ opus_int i;
+ opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
+ opus_int16 ec_ix[ MAX_LPC_ORDER ];
+ opus_int16 res_Q10[ MAX_LPC_ORDER ];
+ opus_int32 NLSF_Q15_tmp;
+ const opus_uint8 *pCB_element;
+ const opus_int16 *pCB_Wght_Q9;
+
+ /* Unpack entropy table indices and predictor for current CB1 index */
+ silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] );
+
+ /* Predictive residual dequantizer */
+ silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order );
+
+ /* Apply inverse square-rooted weights to first stage and add to output */
+ pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
+ pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
+ for( i = 0; i < psNLSF_CB->order; i++ ) {
+ NLSF_Q15_tmp = silk_ADD_LSHIFT32( silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), pCB_Wght_Q9[ i ] ), (opus_int16)pCB_element[ i ], 7 );
+ pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 );
+ }
+
+ /* NLSF stabilization */
+ silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* NLSF stabilizer: */
+/* */
+/* - Moves NLSFs further apart if they are too close */
+/* - Moves NLSFs away from borders if they are too close */
+/* - High effort to achieve a modification with minimum */
+/* Euclidean distance to input vector */
+/* - Output are sorted NLSF coefficients */
+/* */
+
+#include "SigProc_FIX.h"
+
+/* Constant Definitions */
+#define MAX_LOOPS 20
+
+/* NLSF stabilizer, for a single input data vector */
+void silk_NLSF_stabilize(
+ opus_int16 *NLSF_Q15, /* I/O Unstable/stabilized normalized LSF vector in Q15 [L] */
+ const opus_int16 *NDeltaMin_Q15, /* I Min distance vector, NDeltaMin_Q15[L] must be >= 1 [L+1] */
+ const opus_int L /* I Number of NLSF parameters in the input vector */
+)
+{
+ opus_int i, I=0, k, loops;
+ opus_int16 center_freq_Q15;
+ opus_int32 diff_Q15, min_diff_Q15, min_center_Q15, max_center_Q15;
+
+ /* This is necessary to ensure an output within range of a opus_int16 */
+ silk_assert( NDeltaMin_Q15[L] >= 1 );
+
+ for( loops = 0; loops < MAX_LOOPS; loops++ ) {
+ /**************************/
+ /* Find smallest distance */
+ /**************************/
+ /* First element */
+ min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0];
+ I = 0;
+ /* Middle elements */
+ for( i = 1; i <= L-1; i++ ) {
+ diff_Q15 = NLSF_Q15[i] - ( NLSF_Q15[i-1] + NDeltaMin_Q15[i] );
+ if( diff_Q15 < min_diff_Q15 ) {
+ min_diff_Q15 = diff_Q15;
+ I = i;
+ }
+ }
+ /* Last element */
+ diff_Q15 = ( 1 << 15 ) - ( NLSF_Q15[L-1] + NDeltaMin_Q15[L] );
+ if( diff_Q15 < min_diff_Q15 ) {
+ min_diff_Q15 = diff_Q15;
+ I = L;
+ }
+
+ /***************************************************/
+ /* Now check if the smallest distance non-negative */
+ /***************************************************/
+ if( min_diff_Q15 >= 0 ) {
+ return;
+ }
+
+ if( I == 0 ) {
+ /* Move away from lower limit */
+ NLSF_Q15[0] = NDeltaMin_Q15[0];
+
+ } else if( I == L) {
+ /* Move away from higher limit */
+ NLSF_Q15[L-1] = ( 1 << 15 ) - NDeltaMin_Q15[L];
+
+ } else {
+ /* Find the lower extreme for the location of the current center frequency */
+ min_center_Q15 = 0;
+ for( k = 0; k < I; k++ ) {
+ min_center_Q15 += NDeltaMin_Q15[k];
+ }
+ min_center_Q15 += silk_RSHIFT( NDeltaMin_Q15[I], 1 );
+
+ /* Find the upper extreme for the location of the current center frequency */
+ max_center_Q15 = 1 << 15;
+ for( k = L; k > I; k-- ) {
+ max_center_Q15 -= NDeltaMin_Q15[k];
+ }
+ max_center_Q15 -= silk_RSHIFT( NDeltaMin_Q15[I], 1 );
+
+ /* Move apart, sorted by value, keeping the same center frequency */
+ center_freq_Q15 = (opus_int16)silk_LIMIT_32( silk_RSHIFT_ROUND( (opus_int32)NLSF_Q15[I-1] + (opus_int32)NLSF_Q15[I], 1 ),
+ min_center_Q15, max_center_Q15 );
+ NLSF_Q15[I-1] = center_freq_Q15 - silk_RSHIFT( NDeltaMin_Q15[I], 1 );
+ NLSF_Q15[I] = NLSF_Q15[I-1] + NDeltaMin_Q15[I];
+ }
+ }
+
+ /* Safe and simple fall back method, which is less ideal than the above */
+ if( loops == MAX_LOOPS )
+ {
+ /* Insertion sort (fast for already almost sorted arrays): */
+ /* Best case: O(n) for an already sorted array */
+ /* Worst case: O(n^2) for an inversely sorted array */
+ silk_insertion_sort_increasing_all_values_int16( &NLSF_Q15[0], L );
+
+ /* First NLSF should be no less than NDeltaMin[0] */
+ NLSF_Q15[0] = silk_max_int( NLSF_Q15[0], NDeltaMin_Q15[0] );
+
+ /* Keep delta_min distance between the NLSFs */
+ for( i = 1; i < L; i++ )
+ NLSF_Q15[i] = silk_max_int( NLSF_Q15[i], silk_ADD_SAT16( NLSF_Q15[i-1], NDeltaMin_Q15[i] ) );
+
+ /* Last NLSF should be no higher than 1 - NDeltaMin[L] */
+ NLSF_Q15[L-1] = silk_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] );
+
+ /* Keep NDeltaMin distance between the NLSFs */
+ for( i = L-2; i >= 0; i-- )
+ NLSF_Q15[i] = silk_min_int( NLSF_Q15[i], NLSF_Q15[i+1] - NDeltaMin_Q15[i+1] );
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Unpack predictor values and indices for entropy coding tables */
+void silk_NLSF_unpack(
+ opus_int16 ec_ix[], /* O Indices to entropy tables [ LPC_ORDER ] */
+ opus_uint8 pred_Q8[], /* O LSF predictor [ LPC_ORDER ] */
+ const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
+ const opus_int CB1_index /* I Index of vector in first LSF codebook */
+)
+{
+ opus_int i;
+ opus_uint8 entry;
+ const opus_uint8 *ec_sel_ptr;
+
+ ec_sel_ptr = &psNLSF_CB->ec_sel[ CB1_index * psNLSF_CB->order / 2 ];
+ for( i = 0; i < psNLSF_CB->order; i += 2 ) {
+ entry = *ec_sel_ptr++;
+ ec_ix [ i ] = silk_SMULBB( silk_RSHIFT( entry, 1 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 );
+ pred_Q8[ i ] = psNLSF_CB->pred_Q8[ i + ( entry & 1 ) * ( psNLSF_CB->order - 1 ) ];
+ ec_ix [ i + 1 ] = silk_SMULBB( silk_RSHIFT( entry, 5 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 );
+ pred_Q8[ i + 1 ] = psNLSF_CB->pred_Q8[ i + ( silk_RSHIFT( entry, 4 ) & 1 ) * ( psNLSF_CB->order - 1 ) + 1 ];
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2014 Vidyo.
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_NSQ_H
+#define SILK_NSQ_H
+
+#include "SigProc_FIX.h"
+
+#undef silk_short_prediction_create_arch_coef
+
+static OPUS_INLINE opus_int32 silk_noise_shape_quantizer_short_prediction_c(const opus_int32 *buf32, const opus_int16 *coef16, opus_int order)
+{
+ opus_int32 out;
+ silk_assert( order == 10 || order == 16 );
+
+ /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+ out = silk_RSHIFT( order, 1 );
+ out = silk_SMLAWB( out, buf32[ 0 ], coef16[ 0 ] );
+ out = silk_SMLAWB( out, buf32[ -1 ], coef16[ 1 ] );
+ out = silk_SMLAWB( out, buf32[ -2 ], coef16[ 2 ] );
+ out = silk_SMLAWB( out, buf32[ -3 ], coef16[ 3 ] );
+ out = silk_SMLAWB( out, buf32[ -4 ], coef16[ 4 ] );
+ out = silk_SMLAWB( out, buf32[ -5 ], coef16[ 5 ] );
+ out = silk_SMLAWB( out, buf32[ -6 ], coef16[ 6 ] );
+ out = silk_SMLAWB( out, buf32[ -7 ], coef16[ 7 ] );
+ out = silk_SMLAWB( out, buf32[ -8 ], coef16[ 8 ] );
+ out = silk_SMLAWB( out, buf32[ -9 ], coef16[ 9 ] );
+
+ if( order == 16 )
+ {
+ out = silk_SMLAWB( out, buf32[ -10 ], coef16[ 10 ] );
+ out = silk_SMLAWB( out, buf32[ -11 ], coef16[ 11 ] );
+ out = silk_SMLAWB( out, buf32[ -12 ], coef16[ 12 ] );
+ out = silk_SMLAWB( out, buf32[ -13 ], coef16[ 13 ] );
+ out = silk_SMLAWB( out, buf32[ -14 ], coef16[ 14 ] );
+ out = silk_SMLAWB( out, buf32[ -15 ], coef16[ 15 ] );
+ }
+ return out;
+}
+
+#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch) ((void)arch,silk_noise_shape_quantizer_short_prediction_c(in, coef, order))
+
+static OPUS_INLINE opus_int32 silk_NSQ_noise_shape_feedback_loop_c(const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef, opus_int order)
+{
+ opus_int32 out;
+ opus_int32 tmp1, tmp2;
+ opus_int j;
+
+ tmp2 = data0[0];
+ tmp1 = data1[0];
+ data1[0] = tmp2;
+
+ out = silk_RSHIFT(order, 1);
+ out = silk_SMLAWB(out, tmp2, coef[0]);
+
+ for (j = 2; j < order; j += 2) {
+ tmp2 = data1[j - 1];
+ data1[j - 1] = tmp1;
+ out = silk_SMLAWB(out, tmp1, coef[j - 1]);
+ tmp1 = data1[j + 0];
+ data1[j + 0] = tmp2;
+ out = silk_SMLAWB(out, tmp2, coef[j]);
+ }
+ data1[order - 1] = tmp1;
+ out = silk_SMLAWB(out, tmp1, coef[order - 1]);
+ /* Q11 -> Q12 */
+ out = silk_LSHIFT32( out, 1 );
+ return out;
+}
+
+#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch) ((void)arch,silk_NSQ_noise_shape_feedback_loop_c(data0, data1, coef, order))
+
+#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+#include "arm/NSQ_neon.h"
+#endif
+
+#if defined(__mips)
+#include "mips/NSQ_mips.h"
+#endif
+
+#endif /* SILK_NSQ_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_NSQ_DEL_DEC_ARM_H
+#define SILK_NSQ_DEL_DEC_ARM_H
+
+#include "celt/arm/armcpu.h"
+
+#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+void silk_NSQ_del_dec_neon(
+ const silk_encoder_state *psEncC, silk_nsq_state *NSQ,
+ SideInfoIndices *psIndices, const opus_int16 x16[], opus_int8 pulses[],
+ const opus_int16 *PredCoef_Q12,
+ const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],
+ const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER],
+ const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],
+ const opus_int Tilt_Q14[MAX_NB_SUBFR],
+ const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],
+ const opus_int32 Gains_Q16[MAX_NB_SUBFR],
+ const opus_int pitchL[MAX_NB_SUBFR], const opus_int Lambda_Q10,
+ const opus_int LTP_scale_Q14);
+
+#if !defined(OPUS_HAVE_RTCD)
+#define OVERRIDE_silk_NSQ_del_dec (1)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
+ LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
+ LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
+ LTP_scale_Q14, arch) \
+ ((void)(arch), \
+ PRESUME_NEON(silk_NSQ_del_dec)( \
+ psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, \
+ AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, \
+ Lambda_Q10, LTP_scale_Q14))
+#endif
+#endif
+
+#if !defined(OVERRIDE_silk_NSQ_del_dec)
+/*Is run-time CPU detection enabled on this platform?*/
+#if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && \
+ !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
+ const silk_encoder_state *psEncC, silk_nsq_state *NSQ,
+ SideInfoIndices *psIndices, const opus_int16 x16[], opus_int8 pulses[],
+ const opus_int16 *PredCoef_Q12,
+ const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],
+ const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER],
+ const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],
+ const opus_int Tilt_Q14[MAX_NB_SUBFR],
+ const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],
+ const opus_int32 Gains_Q16[MAX_NB_SUBFR],
+ const opus_int pitchL[MAX_NB_SUBFR], const opus_int Lambda_Q10,
+ const opus_int LTP_scale_Q14);
+#define OVERRIDE_silk_NSQ_del_dec (1)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
+ LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
+ LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
+ LTP_scale_Q14, arch) \
+ ((*SILK_NSQ_DEL_DEC_IMPL[(arch)&OPUS_ARCHMASK])( \
+ psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, \
+ AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, \
+ Lambda_Q10, LTP_scale_Q14))
+#elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#define OVERRIDE_silk_NSQ_del_dec (1)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
+ LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
+ LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
+ LTP_scale_Q14, arch) \
+ ((void)(arch), \
+ silk_NSQ_del_dec_neon(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
+ LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, \
+ LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, \
+ LTP_scale_Q14))
+#endif
+#endif
+
+#endif /* end SILK_NSQ_DEL_DEC_ARM_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 NSQ_MIPS_H__
+#define NSQ_MIPS_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "macros.h"
+
+#if defined (__mips_dsp) && __mips == 32
+
+#define MIPS_MULT __builtin_mips_mult
+#define MIPS_MADD __builtin_mips_madd
+#define MIPS_EXTR_R __builtin_mips_extr_r_w
+
+#define OVERRIDE_silk_noise_shape_quantizer_short_prediction
+/* suddenly performance is worse */
+#define dont_OVERRIDE_silk_NSQ_noise_shape_feedback_loop
+
+/* gets worst performance result */
+#elif defined(__mips_isa_rev) && __mips == 32
+
+static inline long long MIPS_MULT(int a, int b) {
+ return (long long)a * b;
+}
+
+static inline long long MIPS_MADD(long long acc, int a, int b) {
+ return acc + (long long)a * b;
+}
+
+static inline opus_val32 MIPS_EXTR_R(long long acc, int shift) {
+ return (opus_val32)((acc + (1 << shift) / 2) >> shift);
+}
+
+#define OVERRIDE_silk_noise_shape_quantizer_short_prediction
+#define OVERRIDE_silk_NSQ_noise_shape_feedback_loop
+
+#endif
+
+#if defined(OVERRIDE_silk_noise_shape_quantizer_short_prediction)
+
+static OPUS_INLINE opus_int32 silk_noise_shape_quantizer_short_prediction_mips(const opus_int32 *buf32, const opus_int16 *coef16, opus_int order)
+{
+ opus_int64 out;
+ silk_assert( order == 10 || order == 16 );
+
+ out = MIPS_MULT( buf32[ 0 ], coef16[ 0 ] );
+ out = MIPS_MADD( out, buf32[ -1 ], coef16[ 1 ] );
+ out = MIPS_MADD( out, buf32[ -2 ], coef16[ 2 ] );
+ out = MIPS_MADD( out, buf32[ -3 ], coef16[ 3 ] );
+ out = MIPS_MADD( out, buf32[ -4 ], coef16[ 4 ] );
+ out = MIPS_MADD( out, buf32[ -5 ], coef16[ 5 ] );
+ out = MIPS_MADD( out, buf32[ -6 ], coef16[ 6 ] );
+ out = MIPS_MADD( out, buf32[ -7 ], coef16[ 7 ] );
+ out = MIPS_MADD( out, buf32[ -8 ], coef16[ 8 ] );
+ out = MIPS_MADD( out, buf32[ -9 ], coef16[ 9 ] );
+
+ if( order == 16 )
+ {
+ out = MIPS_MADD( out, buf32[ -10 ], coef16[ 10 ] );
+ out = MIPS_MADD( out, buf32[ -11 ], coef16[ 11 ] );
+ out = MIPS_MADD( out, buf32[ -12 ], coef16[ 12 ] );
+ out = MIPS_MADD( out, buf32[ -13 ], coef16[ 13 ] );
+ out = MIPS_MADD( out, buf32[ -14 ], coef16[ 14 ] );
+ out = MIPS_MADD( out, buf32[ -15 ], coef16[ 15 ] );
+ }
+ return MIPS_EXTR_R(out, 16);
+}
+
+#undef silk_noise_shape_quantizer_short_prediction
+#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch) ((void)arch,silk_noise_shape_quantizer_short_prediction_mips(in, coef, order))
+
+#endif /* OVERRIDE_silk_noise_shape_quantizer_short_prediction */
+
+
+#if defined(OVERRIDE_silk_NSQ_noise_shape_feedback_loop)
+
+static OPUS_INLINE opus_int32 silk_NSQ_noise_shape_feedback_loop_mips(const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef, opus_int order)
+{
+ opus_int32 out;
+ opus_int32 tmp1, tmp2;
+ opus_int j;
+
+ tmp2 = data0[0];
+ tmp1 = data1[0];
+ data1[0] = tmp2;
+
+ out = MIPS_MULT(tmp2, coef[0]);
+
+ for (j = 2; j < order; j += 2) {
+ tmp2 = data1[j - 1];
+ data1[j - 1] = tmp1;
+ out = MIPS_MADD(out, tmp1, coef[j - 1]);
+ tmp1 = data1[j + 0];
+ data1[j + 0] = tmp2;
+ out = MIPS_MADD(out, tmp2, coef[j]);
+ }
+ data1[order - 1] = tmp1;
+ out = MIPS_MADD(out, tmp1, coef[order - 1]);
+ /* silk_SMLAWB: shift right by 16 && Q11 -> Q12: shift left by 1 */
+ return MIPS_EXTR_R( out, (16 - 1) );
+}
+
+#undef silk_NSQ_noise_shape_feedback_loop
+#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch) ((void)arch,silk_NSQ_noise_shape_feedback_loop_mips(data0, data1, coef, order))
+
+#endif /* OVERRIDE_silk_NSQ_noise_shape_feedback_loop */
+
+#endif /* NSQ_DEL_DEC_MIPSR1_H__ */
--- /dev/null
+/***********************************************************************
+Copyright (C) 2014 Vidyo
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_NSQ_NEON_H
+#define SILK_NSQ_NEON_H
+
+#include "cpu_support.h"
+#include "SigProc_FIX.h"
+
+#undef silk_short_prediction_create_arch_coef
+/* For vectorized calc, reverse a_Q12 coefs, convert to 32-bit, and shift for vqdmulhq_s32. */
+static OPUS_INLINE void silk_short_prediction_create_arch_coef_neon(opus_int32 *out, const opus_int16 *in, opus_int order)
+{
+ out[15] = silk_LSHIFT32(in[0], 15);
+ out[14] = silk_LSHIFT32(in[1], 15);
+ out[13] = silk_LSHIFT32(in[2], 15);
+ out[12] = silk_LSHIFT32(in[3], 15);
+ out[11] = silk_LSHIFT32(in[4], 15);
+ out[10] = silk_LSHIFT32(in[5], 15);
+ out[9] = silk_LSHIFT32(in[6], 15);
+ out[8] = silk_LSHIFT32(in[7], 15);
+ out[7] = silk_LSHIFT32(in[8], 15);
+ out[6] = silk_LSHIFT32(in[9], 15);
+
+ if (order == 16)
+ {
+ out[5] = silk_LSHIFT32(in[10], 15);
+ out[4] = silk_LSHIFT32(in[11], 15);
+ out[3] = silk_LSHIFT32(in[12], 15);
+ out[2] = silk_LSHIFT32(in[13], 15);
+ out[1] = silk_LSHIFT32(in[14], 15);
+ out[0] = silk_LSHIFT32(in[15], 15);
+ }
+ else
+ {
+ out[5] = 0;
+ out[4] = 0;
+ out[3] = 0;
+ out[2] = 0;
+ out[1] = 0;
+ out[0] = 0;
+ }
+}
+
+#if defined(OPUS_ARM_PRESUME_NEON_INTR)
+
+#define silk_short_prediction_create_arch_coef(out, in, order) \
+ (silk_short_prediction_create_arch_coef_neon(out, in, order))
+
+#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+
+#define silk_short_prediction_create_arch_coef(out, in, order) \
+ do { if (arch >= OPUS_ARCH_ARM_NEON) { silk_short_prediction_create_arch_coef_neon(out, in, order); } } while (0)
+
+#endif
+
+opus_int32 silk_noise_shape_quantizer_short_prediction_neon(const opus_int32 *buf32, const opus_int32 *coef32, opus_int order);
+
+opus_int32 silk_NSQ_noise_shape_feedback_loop_neon(const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef, opus_int order);
+
+#if defined(OPUS_ARM_PRESUME_NEON_INTR)
+#undef silk_noise_shape_quantizer_short_prediction
+#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch) \
+ ((void)arch,silk_noise_shape_quantizer_short_prediction_neon(in, coefRev, order))
+
+#undef silk_NSQ_noise_shape_feedback_loop
+#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch) ((void)arch,silk_NSQ_noise_shape_feedback_loop_neon(data0, data1, coef, order))
+
+#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+
+/* silk_noise_shape_quantizer_short_prediction implementations take different parameters based on arch
+ (coef vs. coefRev) so can't use the usual IMPL table implementation */
+#undef silk_noise_shape_quantizer_short_prediction
+#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch) \
+ (arch >= OPUS_ARCH_ARM_NEON ? \
+ silk_noise_shape_quantizer_short_prediction_neon(in, coefRev, order) : \
+ silk_noise_shape_quantizer_short_prediction_c(in, coef, order))
+
+extern opus_int32
+ (*const SILK_NSQ_NOISE_SHAPE_FEEDBACK_LOOP_IMPL[OPUS_ARCHMASK+1])(
+ const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef,
+ opus_int order);
+
+#undef silk_NSQ_noise_shape_feedback_loop
+#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch) \
+ (SILK_NSQ_NOISE_SHAPE_FEEDBACK_LOOP_IMPL[(arch)&OPUS_ARCHMASK](data0, data1, \
+ coef, order))
+
+#endif
+
+#endif /* SILK_NSQ_NEON_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "stack_alloc.h"
+#include "PLC.h"
+
+#ifdef ENABLE_DEEP_PLC
+#include "lpcnet.h"
+#endif
+
+#define NB_ATT 2
+static const opus_int16 HARM_ATT_Q15[NB_ATT] = { 32440, 31130 }; /* 0.99, 0.95 */
+static const opus_int16 PLC_RAND_ATTENUATE_V_Q15[NB_ATT] = { 31130, 26214 }; /* 0.95, 0.8 */
+static const opus_int16 PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = { 32440, 29491 }; /* 0.99, 0.9 */
+
+static OPUS_INLINE void silk_PLC_update(
+ silk_decoder_state *psDec, /* I/O Decoder state */
+ silk_decoder_control *psDecCtrl /* I/O Decoder control */
+);
+
+static OPUS_INLINE void silk_PLC_conceal(
+ silk_decoder_state *psDec, /* I/O Decoder state */
+ silk_decoder_control *psDecCtrl, /* I/O Decoder control */
+ opus_int16 frame[], /* O LPC residual signal */
+#ifdef ENABLE_DEEP_PLC
+ LPCNetPLCState *lpcnet,
+#endif
+ int arch /* I Run-time architecture */
+);
+
+
+void silk_PLC_Reset(
+ silk_decoder_state *psDec /* I/O Decoder state */
+)
+{
+ psDec->sPLC.pitchL_Q8 = silk_LSHIFT( psDec->frame_length, 8 - 1 );
+ psDec->sPLC.prevGain_Q16[ 0 ] = SILK_FIX_CONST( 1, 16 );
+ psDec->sPLC.prevGain_Q16[ 1 ] = SILK_FIX_CONST( 1, 16 );
+ psDec->sPLC.subfr_length = 20;
+ psDec->sPLC.nb_subfr = 2;
+}
+
+void silk_PLC(
+ silk_decoder_state *psDec, /* I/O Decoder state */
+ silk_decoder_control *psDecCtrl, /* I/O Decoder control */
+ opus_int16 frame[], /* I/O signal */
+ opus_int lost, /* I Loss flag */
+#ifdef ENABLE_DEEP_PLC
+ LPCNetPLCState *lpcnet,
+#endif
+ int arch /* I Run-time architecture */
+)
+{
+ /* PLC control function */
+ if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) {
+ silk_PLC_Reset( psDec );
+ psDec->sPLC.fs_kHz = psDec->fs_kHz;
+ }
+
+ if( lost ) {
+ /****************************/
+ /* Generate Signal */
+ /****************************/
+ silk_PLC_conceal( psDec, psDecCtrl, frame,
+#ifdef ENABLE_DEEP_PLC
+ lpcnet,
+#endif
+ arch );
+
+ psDec->lossCnt++;
+ } else {
+ /****************************/
+ /* Update state */
+ /****************************/
+ silk_PLC_update( psDec, psDecCtrl );
+#ifdef ENABLE_DEEP_PLC
+ if ( lpcnet != NULL && psDec->sPLC.fs_kHz == 16 ) {
+ int k;
+ for( k = 0; k < psDec->nb_subfr; k += 2 ) {
+ lpcnet_plc_update( lpcnet, frame + k * psDec->subfr_length );
+ }
+ }
+#endif
+ }
+}
+
+/**************************************************/
+/* Update state of PLC */
+/**************************************************/
+static OPUS_INLINE void silk_PLC_update(
+ silk_decoder_state *psDec, /* I/O Decoder state */
+ silk_decoder_control *psDecCtrl /* I/O Decoder control */
+)
+{
+ opus_int32 LTP_Gain_Q14, temp_LTP_Gain_Q14;
+ opus_int i, j;
+ silk_PLC_struct *psPLC;
+
+ psPLC = &psDec->sPLC;
+
+ /* Update parameters used in case of packet loss */
+ psDec->prevSignalType = psDec->indices.signalType;
+ LTP_Gain_Q14 = 0;
+ if( psDec->indices.signalType == TYPE_VOICED ) {
+ /* Find the parameters for the last subframe which contains a pitch pulse */
+ for( j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; j++ ) {
+ if( j == psDec->nb_subfr ) {
+ break;
+ }
+ temp_LTP_Gain_Q14 = 0;
+ for( i = 0; i < LTP_ORDER; i++ ) {
+ temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[ ( psDec->nb_subfr - 1 - j ) * LTP_ORDER + i ];
+ }
+ if( temp_LTP_Gain_Q14 > LTP_Gain_Q14 ) {
+ LTP_Gain_Q14 = temp_LTP_Gain_Q14;
+ silk_memcpy( psPLC->LTPCoef_Q14,
+ &psDecCtrl->LTPCoef_Q14[ silk_SMULBB( psDec->nb_subfr - 1 - j, LTP_ORDER ) ],
+ LTP_ORDER * sizeof( opus_int16 ) );
+
+ psPLC->pitchL_Q8 = silk_LSHIFT( psDecCtrl->pitchL[ psDec->nb_subfr - 1 - j ], 8 );
+ }
+ }
+
+ silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
+ psPLC->LTPCoef_Q14[ LTP_ORDER / 2 ] = LTP_Gain_Q14;
+
+ /* Limit LT coefs */
+ if( LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14 ) {
+ opus_int scale_Q10;
+ opus_int32 tmp;
+
+ tmp = silk_LSHIFT( V_PITCH_GAIN_START_MIN_Q14, 10 );
+ scale_Q10 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
+ for( i = 0; i < LTP_ORDER; i++ ) {
+ psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q10 ), 10 );
+ }
+ } else if( LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14 ) {
+ opus_int scale_Q14;
+ opus_int32 tmp;
+
+ tmp = silk_LSHIFT( V_PITCH_GAIN_START_MAX_Q14, 14 );
+ scale_Q14 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
+ for( i = 0; i < LTP_ORDER; i++ ) {
+ psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q14 ), 14 );
+ }
+ }
+ } else {
+ psPLC->pitchL_Q8 = silk_LSHIFT( silk_SMULBB( psDec->fs_kHz, 18 ), 8 );
+ silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ));
+ }
+
+ /* Save LPC coefficients */
+ silk_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
+ psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14;
+
+ /* Save last two gains */
+ silk_memcpy( psPLC->prevGain_Q16, &psDecCtrl->Gains_Q16[ psDec->nb_subfr - 2 ], 2 * sizeof( opus_int32 ) );
+
+ psPLC->subfr_length = psDec->subfr_length;
+ psPLC->nb_subfr = psDec->nb_subfr;
+}
+
+static OPUS_INLINE void silk_PLC_energy(opus_int32 *energy1, opus_int *shift1, opus_int32 *energy2, opus_int *shift2,
+ const opus_int32 *exc_Q14, const opus_int32 *prevGain_Q10, int subfr_length, int nb_subfr)
+{
+ int i, k;
+ VARDECL( opus_int16, exc_buf );
+ opus_int16 *exc_buf_ptr;
+ SAVE_STACK;
+ ALLOC( exc_buf, 2*subfr_length, opus_int16 );
+ /* Find random noise component */
+ /* Scale previous excitation signal */
+ exc_buf_ptr = exc_buf;
+ for( k = 0; k < 2; k++ ) {
+ for( i = 0; i < subfr_length; i++ ) {
+ exc_buf_ptr[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT(
+ silk_SMULWW( exc_Q14[ i + ( k + nb_subfr - 2 ) * subfr_length ], prevGain_Q10[ k ] ), 8 ) );
+ }
+ exc_buf_ptr += subfr_length;
+ }
+ /* Find the subframe with lowest energy of the last two and use that as random noise generator */
+ silk_sum_sqr_shift( energy1, shift1, exc_buf, subfr_length );
+ silk_sum_sqr_shift( energy2, shift2, &exc_buf[ subfr_length ], subfr_length );
+ RESTORE_STACK;
+}
+
+static OPUS_INLINE void silk_PLC_conceal(
+ silk_decoder_state *psDec, /* I/O Decoder state */
+ silk_decoder_control *psDecCtrl, /* I/O Decoder control */
+ opus_int16 frame[], /* O LPC residual signal */
+#ifdef ENABLE_DEEP_PLC
+ LPCNetPLCState *lpcnet,
+#endif
+ int arch /* I Run-time architecture */
+)
+{
+ opus_int i, j, k;
+ opus_int lag, idx, sLTP_buf_idx, shift1, shift2;
+ opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q30;
+ opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr;
+ opus_int32 LPC_pred_Q10, LTP_pred_Q12;
+ opus_int16 rand_scale_Q14;
+ opus_int16 *B_Q14;
+ opus_int32 *sLPC_Q14_ptr;
+ opus_int16 A_Q12[ MAX_LPC_ORDER ];
+#ifdef SMALL_FOOTPRINT
+ opus_int16 *sLTP;
+#else
+ VARDECL( opus_int16, sLTP );
+#endif
+ VARDECL( opus_int32, sLTP_Q14 );
+ silk_PLC_struct *psPLC = &psDec->sPLC;
+ opus_int32 prevGain_Q10[2];
+ SAVE_STACK;
+
+ ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 );
+#ifdef SMALL_FOOTPRINT
+ /* Ugly hack that breaks aliasing rules to save stack: put sLTP at the very end of sLTP_Q14. */
+ sLTP = ((opus_int16*)&sLTP_Q14[psDec->ltp_mem_length + psDec->frame_length])-psDec->ltp_mem_length;
+#else
+ ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
+#endif
+
+ prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6);
+ prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6);
+
+ if( psDec->first_frame_after_reset ) {
+ silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) );
+ }
+
+ silk_PLC_energy(&energy1, &shift1, &energy2, &shift2, psDec->exc_Q14, prevGain_Q10, psDec->subfr_length, psDec->nb_subfr);
+
+ if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) {
+ /* First sub-frame has lowest energy */
+ rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ];
+ } else {
+ /* Second sub-frame has lowest energy */
+ rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ];
+ }
+
+ /* Set up Gain to random noise component */
+ B_Q14 = psPLC->LTPCoef_Q14;
+ rand_scale_Q14 = psPLC->randScale_Q14;
+
+ /* Set up attenuation gains */
+ harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
+ if( psDec->prevSignalType == TYPE_VOICED ) {
+ rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
+ } else {
+ rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
+ }
+
+ /* LPC concealment. Apply BWE to previous LPC */
+ silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) );
+
+ /* Preload LPC coefficients to array on stack. Gives small performance gain */
+ silk_memcpy( A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
+
+ /* First Lost frame */
+ if( psDec->lossCnt == 0 ) {
+ rand_scale_Q14 = 1 << 14;
+
+ /* Reduce random noise Gain for voiced frames */
+ if( psDec->prevSignalType == TYPE_VOICED ) {
+ for( i = 0; i < LTP_ORDER; i++ ) {
+ rand_scale_Q14 -= B_Q14[ i ];
+ }
+ rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */
+ rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 );
+ } else {
+ /* Reduce random noise for unvoiced frames with high LPC gain */
+ opus_int32 invGain_Q30, down_scale_Q30;
+
+ invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order, arch );
+
+ down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
+ down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
+ down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES );
+
+ rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 );
+ }
+ }
+
+ rand_seed = psPLC->rand_seed;
+ lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
+ sLTP_buf_idx = psDec->ltp_mem_length;
+
+ /* Rewhiten LTP state */
+ idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
+ celt_assert( idx > 0 );
+ silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch );
+ /* Scale LTP state */
+ inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 );
+ inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 );
+ for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) {
+ sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] );
+ }
+
+ /***************************/
+ /* LTP synthesis filtering */
+ /***************************/
+ for( k = 0; k < psDec->nb_subfr; k++ ) {
+ /* Set up pointer */
+ pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
+ for( i = 0; i < psDec->subfr_length; i++ ) {
+ /* Unrolled loop */
+ /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+ LTP_pred_Q12 = 2;
+ LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ 0 ], B_Q14[ 0 ] );
+ LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
+ LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
+ LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
+ LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
+ pred_lag_ptr++;
+
+ /* Generate LPC excitation */
+ rand_seed = silk_RAND( rand_seed );
+ idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK;
+ sLTP_Q14[ sLTP_buf_idx ] = silk_LSHIFT32( silk_SMLAWB( LTP_pred_Q12, rand_ptr[ idx ], rand_scale_Q14 ), 2 );
+ sLTP_buf_idx++;
+ }
+
+ /* Gradually reduce LTP gain */
+ for( j = 0; j < LTP_ORDER; j++ ) {
+ B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 );
+ }
+ /* Gradually reduce excitation gain */
+ rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 );
+
+ /* Slowly increase pitch lag */
+ psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 );
+ psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) );
+ lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
+ }
+
+ /***************************/
+ /* LPC synthesis filtering */
+ /***************************/
+ sLPC_Q14_ptr = &sLTP_Q14[ psDec->ltp_mem_length - MAX_LPC_ORDER ];
+
+ /* Copy LPC state */
+ silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
+
+ celt_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
+ for( i = 0; i < psDec->frame_length; i++ ) {
+ /* partly unrolled */
+ /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+ LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
+ for( j = 10; j < psDec->LPC_order; j++ ) {
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] );
+ }
+
+ /* Add prediction to LPC excitation */
+ sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ],
+ silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ));
+
+ /* Scale with Gain */
+ frame[ i ] = (opus_int16)silk_SAT16( silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], prevGain_Q10[ 1 ] ), 8 ) ) );
+ }
+#ifdef ENABLE_DEEP_PLC
+ if ( lpcnet != NULL && lpcnet->loaded && psDec->sPLC.fs_kHz == 16 ) {
+ int run_deep_plc = psDec->sPLC.enable_deep_plc || lpcnet->fec_fill_pos != 0;
+ if( run_deep_plc ) {
+ for( k = 0; k < psDec->nb_subfr; k += 2 ) {
+ lpcnet_plc_conceal( lpcnet, frame + k * psDec->subfr_length );
+ }
+ /* We *should* be able to copy only from psDec->frame_length-MAX_LPC_ORDER, i.e. the last MAX_LPC_ORDER samples. */
+ for( i = 0; i < psDec->frame_length; i++ ) {
+ sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = (int)floor(.5 + frame[ i ] * (float)(1 << 24) / prevGain_Q10[ 1 ] );
+ }
+ } else {
+ for( k = 0; k < psDec->nb_subfr; k += 2 ) {
+ lpcnet_plc_update( lpcnet, frame + k * psDec->subfr_length );
+ }
+ }
+ }
+#endif
+
+ /* Save LPC state */
+ silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
+
+ /**************************************/
+ /* Update states */
+ /**************************************/
+ psPLC->rand_seed = rand_seed;
+ psPLC->randScale_Q14 = rand_scale_Q14;
+ for( i = 0; i < MAX_NB_SUBFR; i++ ) {
+ psDecCtrl->pitchL[ i ] = lag;
+ }
+ RESTORE_STACK;
+}
+
+/* Glues concealed frames with new good received frames */
+void silk_PLC_glue_frames(
+ silk_decoder_state *psDec, /* I/O decoder state */
+ opus_int16 frame[], /* I/O signal */
+ opus_int length /* I length of signal */
+)
+{
+ opus_int i, energy_shift;
+ opus_int32 energy;
+ silk_PLC_struct *psPLC;
+ psPLC = &psDec->sPLC;
+
+ if( psDec->lossCnt ) {
+ /* Calculate energy in concealed residual */
+ silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, frame, length );
+
+ psPLC->last_frame_lost = 1;
+ } else {
+ if( psDec->sPLC.last_frame_lost ) {
+ /* Calculate residual in decoded signal if last frame was lost */
+ silk_sum_sqr_shift( &energy, &energy_shift, frame, length );
+
+ /* Normalize energies */
+ if( energy_shift > psPLC->conc_energy_shift ) {
+ psPLC->conc_energy = silk_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift );
+ } else if( energy_shift < psPLC->conc_energy_shift ) {
+ energy = silk_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift );
+ }
+
+ /* Fade in the energy difference */
+ if( energy > psPLC->conc_energy ) {
+ opus_int32 frac_Q24, LZ;
+ opus_int32 gain_Q16, slope_Q16;
+
+ LZ = silk_CLZ32( psPLC->conc_energy );
+ LZ = LZ - 1;
+ psPLC->conc_energy = silk_LSHIFT( psPLC->conc_energy, LZ );
+ energy = silk_RSHIFT( energy, silk_max_32( 24 - LZ, 0 ) );
+
+ frac_Q24 = silk_DIV32( psPLC->conc_energy, silk_max( energy, 1 ) );
+
+ gain_Q16 = silk_LSHIFT( silk_SQRT_APPROX( frac_Q24 ), 4 );
+ slope_Q16 = silk_DIV32_16( ( (opus_int32)1 << 16 ) - gain_Q16, length );
+ /* Make slope 4x steeper to avoid missing onsets after DTX */
+ slope_Q16 = silk_LSHIFT( slope_Q16, 2 );
+#ifdef ENABLE_DEEP_PLC
+ if ( psDec->sPLC.fs_kHz != 16 )
+#endif
+ {
+ for( i = 0; i < length; i++ ) {
+ frame[ i ] = silk_SMULWB( gain_Q16, frame[ i ] );
+ gain_Q16 += slope_Q16;
+ if( gain_Q16 > (opus_int32)1 << 16 ) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ psPLC->last_frame_lost = 0;
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_PLC_H
+#define SILK_PLC_H
+
+#include "main.h"
+
+#define BWE_COEF 0.99
+#define V_PITCH_GAIN_START_MIN_Q14 11469 /* 0.7 in Q14 */
+#define V_PITCH_GAIN_START_MAX_Q14 15565 /* 0.95 in Q14 */
+#define MAX_PITCH_LAG_MS 18
+#define RAND_BUF_SIZE 128
+#define RAND_BUF_MASK ( RAND_BUF_SIZE - 1 )
+#define LOG2_INV_LPC_GAIN_HIGH_THRES 3 /* 2^3 = 8 dB LPC gain */
+#define LOG2_INV_LPC_GAIN_LOW_THRES 8 /* 2^8 = 24 dB LPC gain */
+#define PITCH_DRIFT_FAC_Q16 655 /* 0.01 in Q16 */
+
+void silk_PLC_Reset(
+ silk_decoder_state *psDec /* I/O Decoder state */
+);
+
+void silk_PLC(
+ silk_decoder_state *psDec, /* I/O Decoder state */
+ silk_decoder_control *psDecCtrl, /* I/O Decoder control */
+ opus_int16 frame[], /* I/O signal */
+ opus_int lost, /* I Loss flag */
+#ifdef ENABLE_DEEP_PLC
+ LPCNetPLCState *lpcnet,
+#endif
+ int arch /* I Run-time architecture */
+);
+
+void silk_PLC_glue_frames(
+ silk_decoder_state *psDec, /* I/O decoder state */
+ opus_int16 frame[], /* I/O signal */
+ opus_int length /* I length of signal */
+);
+
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_SIGPROC_FIX_H
+#define SILK_SIGPROC_FIX_H
+
+
+/*#define silk_MACRO_COUNT */ /* Used to enable WMOPS counting */
+
+#define SILK_MAX_ORDER_LPC 24 /* max order of the LPC analysis in schur() and k2a() */
+
+#include <string.h> /* for memset(), memcpy(), memmove() */
+#include "typedef.h"
+#include "resampler_structs.h"
+#include "macros.h"
+#include "cpu_support.h"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+#include "x86/SigProc_FIX_sse.h"
+#endif
+
+#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "arm/biquad_alt_arm.h"
+#include "arm/LPC_inv_pred_gain_arm.h"
+#endif
+
+/********************************************************************/
+/* SIGNAL PROCESSING FUNCTIONS */
+/********************************************************************/
+
+/*!
+ * Initialize/reset the resampler state for a given pair of input/output sampling rates
+*/
+opus_int silk_resampler_init(
+ silk_resampler_state_struct *S, /* I/O Resampler state */
+ opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */
+ opus_int32 Fs_Hz_out, /* I Output sampling rate (Hz) */
+ opus_int forEnc /* I If 1: encoder; if 0: decoder */
+);
+
+/*!
+ * Resampler: convert from one sampling rate to another
+ */
+opus_int silk_resampler(
+ silk_resampler_state_struct *S, /* I/O Resampler state */
+ opus_int16 out[], /* O Output signal */
+ const opus_int16 in[], /* I Input signal */
+ opus_int32 inLen /* I Number of input samples */
+);
+
+/*!
+* Downsample 2x, mediocre quality
+*/
+void silk_resampler_down2(
+ opus_int32 *S, /* I/O State vector [ 2 ] */
+ opus_int16 *out, /* O Output signal [ len ] */
+ const opus_int16 *in, /* I Input signal [ floor(len/2) ] */
+ opus_int32 inLen /* I Number of input samples */
+);
+
+/*!
+ * Downsample by a factor 2/3, low quality
+*/
+void silk_resampler_down2_3(
+ opus_int32 *S, /* I/O State vector [ 6 ] */
+ opus_int16 *out, /* O Output signal [ floor(2*inLen/3) ] */
+ const opus_int16 *in, /* I Input signal [ inLen ] */
+ opus_int32 inLen /* I Number of input samples */
+);
+
+/*!
+ * second order ARMA filter;
+ * slower than biquad() but uses more precise coefficients
+ * can handle (slowly) varying coefficients
+ */
+void silk_biquad_alt_stride1(
+ const opus_int16 *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [2] */
+ opus_int16 *out, /* O output signal */
+ const opus_int32 len /* I signal length (must be even) */
+);
+
+void silk_biquad_alt_stride2_c(
+ const opus_int16 *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [4] */
+ opus_int16 *out, /* O output signal */
+ const opus_int32 len /* I signal length (must be even) */
+);
+
+/* Variable order MA prediction error filter. */
+void silk_LPC_analysis_filter(
+ opus_int16 *out, /* O Output signal */
+ const opus_int16 *in, /* I Input signal */
+ const opus_int16 *B, /* I MA prediction coefficients, Q12 [order] */
+ const opus_int32 len, /* I Signal length */
+ const opus_int32 d, /* I Filter order */
+ int arch /* I Run-time architecture */
+);
+
+/* Chirp (bandwidth expand) LP AR filter */
+void silk_bwexpander(
+ opus_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */
+ const opus_int d, /* I Length of ar */
+ opus_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */
+);
+
+/* Chirp (bandwidth expand) LP AR filter */
+void silk_bwexpander_32(
+ opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */
+ const opus_int d, /* I Length of ar */
+ opus_int32 chirp_Q16 /* I Chirp factor in Q16 */
+);
+
+/* Compute inverse of LPC prediction gain, and */
+/* test if LPC coefficients are stable (all poles within unit circle) */
+opus_int32 silk_LPC_inverse_pred_gain_c( /* O Returns inverse prediction gain in energy domain, Q30 */
+ const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
+ const opus_int order /* I Prediction order */
+);
+
+/* Split signal in two decimated bands using first-order allpass filters */
+void silk_ana_filt_bank_1(
+ const opus_int16 *in, /* I Input signal [N] */
+ opus_int32 *S, /* I/O State vector [2] */
+ opus_int16 *outL, /* O Low band [N/2] */
+ opus_int16 *outH, /* O High band [N/2] */
+ const opus_int32 N /* I Number of input samples */
+);
+
+#if !defined(OVERRIDE_silk_biquad_alt_stride2)
+#define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_c(in, B_Q28, A_Q28, S, out, len))
+#endif
+
+#if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
+#define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), silk_LPC_inverse_pred_gain_c(A_Q12, order))
+#endif
+
+/********************************************************************/
+/* SCALAR FUNCTIONS */
+/********************************************************************/
+
+/* Approximation of 128 * log2() (exact inverse of approx 2^() below) */
+/* Convert input to a log scale */
+opus_int32 silk_lin2log(
+ const opus_int32 inLin /* I input in linear scale */
+);
+
+/* Approximation of a sigmoid function */
+opus_int silk_sigm_Q15(
+ opus_int in_Q5 /* I */
+);
+
+/* Approximation of 2^() (exact inverse of approx log2() above) */
+/* Convert input to a linear scale */
+opus_int32 silk_log2lin(
+ const opus_int32 inLog_Q7 /* I input on log scale */
+);
+
+/* Compute number of bits to right shift the sum of squares of a vector */
+/* of int16s to make it fit in an int32 */
+void silk_sum_sqr_shift(
+ opus_int32 *energy, /* O Energy of x, after shifting to the right */
+ opus_int *shift, /* O Number of bits right shift applied to energy */
+ const opus_int16 *x, /* I Input vector */
+ opus_int len /* I Length of input vector */
+);
+
+/* Calculates the reflection coefficients from the correlation sequence */
+/* Faster than schur64(), but much less accurate. */
+/* uses SMLAWB(), requiring armv5E and higher. */
+opus_int32 silk_schur( /* O Returns residual energy */
+ opus_int16 *rc_Q15, /* O reflection coefficients [order] Q15 */
+ const opus_int32 *c, /* I correlations [order+1] */
+ const opus_int32 order /* I prediction order */
+);
+
+/* Calculates the reflection coefficients from the correlation sequence */
+/* Slower than schur(), but more accurate. */
+/* Uses SMULL(), available on armv4 */
+opus_int32 silk_schur64( /* O returns residual energy */
+ opus_int32 rc_Q16[], /* O Reflection coefficients [order] Q16 */
+ const opus_int32 c[], /* I Correlations [order+1] */
+ opus_int32 order /* I Prediction order */
+);
+
+/* Step up function, converts reflection coefficients to prediction coefficients */
+void silk_k2a(
+ opus_int32 *A_Q24, /* O Prediction coefficients [order] Q24 */
+ const opus_int16 *rc_Q15, /* I Reflection coefficients [order] Q15 */
+ const opus_int32 order /* I Prediction order */
+);
+
+/* Step up function, converts reflection coefficients to prediction coefficients */
+void silk_k2a_Q16(
+ opus_int32 *A_Q24, /* O Prediction coefficients [order] Q24 */
+ const opus_int32 *rc_Q16, /* I Reflection coefficients [order] Q16 */
+ const opus_int32 order /* I Prediction order */
+);
+
+/* Apply sine window to signal vector. */
+/* Window types: */
+/* 1 -> sine window from 0 to pi/2 */
+/* 2 -> sine window from pi/2 to pi */
+/* every other sample of window is linearly interpolated, for speed */
+void silk_apply_sine_window(
+ opus_int16 px_win[], /* O Pointer to windowed signal */
+ const opus_int16 px[], /* I Pointer to input signal */
+ const opus_int win_type, /* I Selects a window type */
+ const opus_int length /* I Window length, multiple of 4 */
+);
+
+/* Compute autocorrelation */
+void silk_autocorr(
+ opus_int32 *results, /* O Result (length correlationCount) */
+ opus_int *scale, /* O Scaling of the correlation vector */
+ const opus_int16 *inputData, /* I Input data to correlate */
+ const opus_int inputDataSize, /* I Length of input */
+ const opus_int correlationCount, /* I Number of correlation taps to compute */
+ int arch /* I Run-time architecture */
+);
+
+void silk_decode_pitch(
+ opus_int16 lagIndex, /* I */
+ opus_int8 contourIndex, /* O */
+ opus_int pitch_lags[], /* O 4 pitch values */
+ const opus_int Fs_kHz, /* I sampling frequency (kHz) */
+ const opus_int nb_subfr /* I number of sub frames */
+);
+
+opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */
+ const opus_int16 *frame, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */
+ opus_int *pitch_out, /* O 4 pitch lag values */
+ opus_int16 *lagIndex, /* O Lag Index */
+ opus_int8 *contourIndex, /* O Pitch contour Index */
+ opus_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */
+ opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */
+ const opus_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */
+ const opus_int search_thres2_Q13, /* I Final threshold for lag candidates 0 - 1 */
+ const opus_int Fs_kHz, /* I Sample frequency (kHz) */
+ const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */
+ const opus_int nb_subfr, /* I number of 5 ms subframes */
+ int arch /* I Run-time architecture */
+);
+
+/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */
+/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
+void silk_A2NLSF(
+ opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */
+ opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */
+ const opus_int d /* I Filter order (must be even) */
+);
+
+/* compute whitening filter coefficients from normalized line spectral frequencies */
+void silk_NLSF2A(
+ opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */
+ const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */
+ const opus_int d, /* I filter order (should be even) */
+ int arch /* I Run-time architecture */
+);
+
+/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
+void silk_LPC_fit(
+ opus_int16 *a_QOUT, /* O Output signal */
+ opus_int32 *a_QIN, /* I/O Input signal */
+ const opus_int QOUT, /* I Input Q domain */
+ const opus_int QIN, /* I Input Q domain */
+ const opus_int d /* I Filter order */
+);
+
+void silk_insertion_sort_increasing(
+ opus_int32 *a, /* I/O Unsorted / Sorted vector */
+ opus_int *idx, /* O Index vector for the sorted elements */
+ const opus_int L, /* I Vector length */
+ const opus_int K /* I Number of correctly sorted positions */
+);
+
+void silk_insertion_sort_decreasing_int16(
+ opus_int16 *a, /* I/O Unsorted / Sorted vector */
+ opus_int *idx, /* O Index vector for the sorted elements */
+ const opus_int L, /* I Vector length */
+ const opus_int K /* I Number of correctly sorted positions */
+);
+
+void silk_insertion_sort_increasing_all_values_int16(
+ opus_int16 *a, /* I/O Unsorted / Sorted vector */
+ const opus_int L /* I Vector length */
+);
+
+/* NLSF stabilizer, for a single input data vector */
+void silk_NLSF_stabilize(
+ opus_int16 *NLSF_Q15, /* I/O Unstable/stabilized normalized LSF vector in Q15 [L] */
+ const opus_int16 *NDeltaMin_Q15, /* I Min distance vector, NDeltaMin_Q15[L] must be >= 1 [L+1] */
+ const opus_int L /* I Number of NLSF parameters in the input vector */
+);
+
+/* Laroia low complexity NLSF weights */
+void silk_NLSF_VQ_weights_laroia(
+ opus_int16 *pNLSFW_Q_OUT, /* O Pointer to input vector weights [D] */
+ const opus_int16 *pNLSF_Q15, /* I Pointer to input vector [D] */
+ const opus_int D /* I Input vector dimension (even) */
+);
+
+/* Compute reflection coefficients from input signal */
+void silk_burg_modified_c(
+ opus_int32 *res_nrg, /* O Residual energy */
+ opus_int *res_nrg_Q, /* O Residual energy Q value */
+ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
+ const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */
+ const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */
+ const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */
+ const opus_int nb_subfr, /* I Number of subframes stacked in x */
+ const opus_int D, /* I Order */
+ int arch /* I Run-time architecture */
+);
+
+/* Copy and multiply a vector by a constant */
+void silk_scale_copy_vector16(
+ opus_int16 *data_out,
+ const opus_int16 *data_in,
+ opus_int32 gain_Q16, /* I Gain in Q16 */
+ const opus_int dataSize /* I Length */
+);
+
+/* Some for the LTP related function requires Q26 to work.*/
+void silk_scale_vector32_Q26_lshift_18(
+ opus_int32 *data1, /* I/O Q0/Q18 */
+ opus_int32 gain_Q26, /* I Q26 */
+ opus_int dataSize /* I length */
+);
+
+/********************************************************************/
+/* INLINE ARM MATH */
+/********************************************************************/
+
+/* return sum( inVec1[i] * inVec2[i] ) */
+
+opus_int32 silk_inner_prod_aligned(
+ const opus_int16 *const inVec1, /* I input vector 1 */
+ const opus_int16 *const inVec2, /* I input vector 2 */
+ const opus_int len, /* I vector lengths */
+ int arch /* I Run-time architecture */
+);
+
+
+opus_int32 silk_inner_prod_aligned_scale(
+ const opus_int16 *const inVec1, /* I input vector 1 */
+ const opus_int16 *const inVec2, /* I input vector 2 */
+ const opus_int scale, /* I number of bits to shift */
+ const opus_int len /* I vector lengths */
+);
+
+opus_int64 silk_inner_prod16_c(
+ const opus_int16 *inVec1, /* I input vector 1 */
+ const opus_int16 *inVec2, /* I input vector 2 */
+ const opus_int len /* I vector lengths */
+);
+
+/********************************************************************/
+/* MACROS */
+/********************************************************************/
+
+/* Rotate a32 right by 'rot' bits. Negative rot values result in rotating
+ left. Output is 32bit int.
+ Note: contemporary compilers recognize the C expression below and
+ compile it into a 'ror' instruction if available. No need for OPUS_INLINE ASM! */
+static OPUS_INLINE opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
+{
+ opus_uint32 x = (opus_uint32) a32;
+ opus_uint32 r = (opus_uint32) rot;
+ opus_uint32 m = (opus_uint32) -rot;
+ if( rot == 0 ) {
+ return a32;
+ } else if( rot < 0 ) {
+ return (opus_int32) ((x << m) | (x >> (32 - m)));
+ } else {
+ return (opus_int32) ((x << (32 - r)) | (x >> r));
+ }
+}
+
+/* Allocate opus_int16 aligned to 4-byte memory address */
+#if EMBEDDED_ARM
+#define silk_DWORD_ALIGN __attribute__((aligned(4)))
+#else
+#define silk_DWORD_ALIGN
+#endif
+
+/* Useful Macros that can be adjusted to other platforms */
+#define silk_memcpy(dest, src, size) memcpy((dest), (src), (size))
+#define silk_memset(dest, src, size) memset((dest), (src), (size))
+#define silk_memmove(dest, src, size) memmove((dest), (src), (size))
+
+/* Fixed point macros */
+
+/* (a32 * b32) output have to be 32bit int */
+#define silk_MUL(a32, b32) ((a32) * (b32))
+
+/* (a32 * b32) output have to be 32bit uint */
+#define silk_MUL_uint(a32, b32) silk_MUL(a32, b32)
+
+/* a32 + (b32 * c32) output have to be 32bit int */
+#define silk_MLA(a32, b32, c32) silk_ADD32((a32),((b32) * (c32)))
+
+/* a32 + (b32 * c32) output have to be 32bit uint */
+#define silk_MLA_uint(a32, b32, c32) silk_MLA(a32, b32, c32)
+
+/* ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int */
+#define silk_SMULTT(a32, b32) (((a32) >> 16) * ((b32) >> 16))
+
+/* a32 + ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int */
+#define silk_SMLATT(a32, b32, c32) silk_ADD32((a32),((b32) >> 16) * ((c32) >> 16))
+
+#define silk_SMLALBB(a64, b16, c16) silk_ADD64((a64),(opus_int64)((opus_int32)(b16) * (opus_int32)(c16)))
+
+/* (a32 * b32) */
+#define silk_SMULL(a32, b32) ((opus_int64)(a32) * /*(opus_int64)*/(b32))
+
+/* Adds two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
+ (just standard two's complement implementation-specific behaviour) */
+#define silk_ADD32_ovflw(a, b) ((opus_int32)((opus_uint32)(a) + (opus_uint32)(b)))
+/* Subtractss two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
+ (just standard two's complement implementation-specific behaviour) */
+#define silk_SUB32_ovflw(a, b) ((opus_int32)((opus_uint32)(a) - (opus_uint32)(b)))
+
+/* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) */
+#define silk_MLA_ovflw(a32, b32, c32) silk_ADD32_ovflw((a32), (opus_uint32)(b32) * (opus_uint32)(c32))
+#define silk_SMLABB_ovflw(a32, b32, c32) (silk_ADD32_ovflw((a32) , ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32))))
+
+#define silk_DIV32_16(a32, b16) ((opus_int32)((a32) / (b16)))
+#define silk_DIV32(a32, b32) ((opus_int32)((a32) / (b32)))
+
+/* These macros enables checking for overflow in silk_API_Debug.h*/
+#define silk_ADD16(a, b) ((a) + (b))
+#define silk_ADD32(a, b) ((a) + (b))
+#define silk_ADD64(a, b) ((a) + (b))
+
+#define silk_SUB16(a, b) ((a) - (b))
+#define silk_SUB32(a, b) ((a) - (b))
+#define silk_SUB64(a, b) ((a) - (b))
+
+#define silk_SAT8(a) ((a) > silk_int8_MAX ? silk_int8_MAX : \
+ ((a) < silk_int8_MIN ? silk_int8_MIN : (a)))
+#define silk_SAT16(a) ((a) > silk_int16_MAX ? silk_int16_MAX : \
+ ((a) < silk_int16_MIN ? silk_int16_MIN : (a)))
+#define silk_SAT32(a) ((a) > silk_int32_MAX ? silk_int32_MAX : \
+ ((a) < silk_int32_MIN ? silk_int32_MIN : (a)))
+
+#define silk_CHECK_FIT8(a) (a)
+#define silk_CHECK_FIT16(a) (a)
+#define silk_CHECK_FIT32(a) (a)
+
+#define silk_ADD_SAT16(a, b) (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a), (b) ) )
+#define silk_ADD_SAT64(a, b) ((((a) + (b)) & 0x8000000000000000LL) == 0 ? \
+ ((((a) & (b)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a)+(b)) : \
+ ((((a) | (b)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a)+(b)) )
+
+#define silk_SUB_SAT16(a, b) (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a), (b) ) )
+#define silk_SUB_SAT64(a, b) ((((a)-(b)) & 0x8000000000000000LL) == 0 ? \
+ (( (a) & ((b)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a)-(b)) : \
+ ((((a)^0x8000000000000000LL) & (b) & 0x8000000000000000LL) ? silk_int64_MAX : (a)-(b)) )
+
+/* Saturation for positive input values */
+#define silk_POS_SAT32(a) ((a) > silk_int32_MAX ? silk_int32_MAX : (a))
+
+/* Add with saturation for positive input values */
+#define silk_ADD_POS_SAT8(a, b) ((((a)+(b)) & 0x80) ? silk_int8_MAX : ((a)+(b)))
+#define silk_ADD_POS_SAT16(a, b) ((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b)))
+#define silk_ADD_POS_SAT32(a, b) ((((opus_uint32)(a)+(opus_uint32)(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)))
+
+#define silk_LSHIFT8(a, shift) ((opus_int8)((opus_uint8)(a)<<(shift))) /* shift >= 0, shift < 8 */
+#define silk_LSHIFT16(a, shift) ((opus_int16)((opus_uint16)(a)<<(shift))) /* shift >= 0, shift < 16 */
+#define silk_LSHIFT32(a, shift) ((opus_int32)((opus_uint32)(a)<<(shift))) /* shift >= 0, shift < 32 */
+#define silk_LSHIFT64(a, shift) ((opus_int64)((opus_uint64)(a)<<(shift))) /* shift >= 0, shift < 64 */
+#define silk_LSHIFT(a, shift) silk_LSHIFT32(a, shift) /* shift >= 0, shift < 32 */
+
+#define silk_RSHIFT8(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 8 */
+#define silk_RSHIFT16(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 16 */
+#define silk_RSHIFT32(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 32 */
+#define silk_RSHIFT64(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 64 */
+#define silk_RSHIFT(a, shift) silk_RSHIFT32(a, shift) /* shift >= 0, shift < 32 */
+
+/* saturates before shifting */
+#define silk_LSHIFT_SAT32(a, shift) (silk_LSHIFT32( silk_LIMIT( (a), silk_RSHIFT32( silk_int32_MIN, (shift) ), \
+ silk_RSHIFT32( silk_int32_MAX, (shift) ) ), (shift) ))
+
+#define silk_LSHIFT_ovflw(a, shift) ((opus_int32)((opus_uint32)(a) << (shift))) /* shift >= 0, allowed to overflow */
+#define silk_LSHIFT_uint(a, shift) ((a) << (shift)) /* shift >= 0 */
+#define silk_RSHIFT_uint(a, shift) ((a) >> (shift)) /* shift >= 0 */
+
+#define silk_ADD_LSHIFT(a, b, shift) ((a) + silk_LSHIFT((b), (shift))) /* shift >= 0 */
+#define silk_ADD_LSHIFT32(a, b, shift) silk_ADD32((a), silk_LSHIFT32((b), (shift))) /* shift >= 0 */
+#define silk_ADD_LSHIFT_uint(a, b, shift) ((a) + silk_LSHIFT_uint((b), (shift))) /* shift >= 0 */
+#define silk_ADD_RSHIFT(a, b, shift) ((a) + silk_RSHIFT((b), (shift))) /* shift >= 0 */
+#define silk_ADD_RSHIFT32(a, b, shift) silk_ADD32((a), silk_RSHIFT32((b), (shift))) /* shift >= 0 */
+#define silk_ADD_RSHIFT_uint(a, b, shift) ((a) + silk_RSHIFT_uint((b), (shift))) /* shift >= 0 */
+#define silk_SUB_LSHIFT32(a, b, shift) silk_SUB32((a), silk_LSHIFT32((b), (shift))) /* shift >= 0 */
+#define silk_SUB_RSHIFT32(a, b, shift) silk_SUB32((a), silk_RSHIFT32((b), (shift))) /* shift >= 0 */
+
+/* Requires that shift > 0 */
+#define silk_RSHIFT_ROUND(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1)
+#define silk_RSHIFT_ROUND64(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1)
+
+/* Number of rightshift required to fit the multiplication */
+#define silk_NSHIFT_MUL_32_32(a, b) ( -(31- (32-silk_CLZ32(silk_abs(a)) + (32-silk_CLZ32(silk_abs(b))))) )
+#define silk_NSHIFT_MUL_16_16(a, b) ( -(15- (16-silk_CLZ16(silk_abs(a)) + (16-silk_CLZ16(silk_abs(b))))) )
+
+
+#define silk_min(a, b) (((a) < (b)) ? (a) : (b))
+#define silk_max(a, b) (((a) > (b)) ? (a) : (b))
+
+/* Macro to convert floating-point constants to fixed-point */
+#define SILK_FIX_CONST( C, Q ) ((opus_int32)((C) * ((opus_int64)1 << (Q)) + 0.5))
+
+/* silk_min() versions with typecast in the function call */
+static OPUS_INLINE opus_int silk_min_int(opus_int a, opus_int b)
+{
+ return (((a) < (b)) ? (a) : (b));
+}
+static OPUS_INLINE opus_int16 silk_min_16(opus_int16 a, opus_int16 b)
+{
+ return (((a) < (b)) ? (a) : (b));
+}
+static OPUS_INLINE opus_int32 silk_min_32(opus_int32 a, opus_int32 b)
+{
+ return (((a) < (b)) ? (a) : (b));
+}
+static OPUS_INLINE opus_int64 silk_min_64(opus_int64 a, opus_int64 b)
+{
+ return (((a) < (b)) ? (a) : (b));
+}
+
+/* silk_min() versions with typecast in the function call */
+static OPUS_INLINE opus_int silk_max_int(opus_int a, opus_int b)
+{
+ return (((a) > (b)) ? (a) : (b));
+}
+static OPUS_INLINE opus_int16 silk_max_16(opus_int16 a, opus_int16 b)
+{
+ return (((a) > (b)) ? (a) : (b));
+}
+static OPUS_INLINE opus_int32 silk_max_32(opus_int32 a, opus_int32 b)
+{
+ return (((a) > (b)) ? (a) : (b));
+}
+static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
+{
+ return (((a) > (b)) ? (a) : (b));
+}
+
+#define silk_LIMIT( a, limit1, limit2) ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
+ : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))))
+
+#define silk_LIMIT_int silk_LIMIT
+#define silk_LIMIT_16 silk_LIMIT
+#define silk_LIMIT_32 silk_LIMIT
+
+#define silk_abs(a) (((a) > 0) ? (a) : -(a)) /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */
+#define silk_abs_int(a) (((a) ^ ((a) >> (8 * sizeof(a) - 1))) - ((a) >> (8 * sizeof(a) - 1)))
+#define silk_abs_int32(a) (((a) ^ ((a) >> 31)) - ((a) >> 31))
+#define silk_abs_int64(a) (((a) > 0) ? (a) : -(a))
+
+#define silk_sign(a) ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ))
+
+/* PSEUDO-RANDOM GENERATOR */
+/* Make sure to store the result as the seed for the next call (also in between */
+/* frames), otherwise result won't be random at all. When only using some of the */
+/* bits, take the most significant bits by right-shifting. */
+#define RAND_MULTIPLIER 196314165
+#define RAND_INCREMENT 907633515
+#define silk_RAND(seed) (silk_MLA_ovflw((RAND_INCREMENT), (seed), (RAND_MULTIPLIER)))
+
+/* Add some multiplication functions that can be easily mapped to ARM/MIPS32. */
+
+/* silk_SMMUL: Signed top word multiply.
+ ARMv6 2 instruction cycles.
+ ARMv3M+ 3 instruction cycles. use SMULL and ignore LSB registers.(except xM)
+ MIPS32 2 instructions mul+mfhi
+ MIPS32r6 1 instruction muh */
+/*#define silk_SMMUL(a32, b32) (opus_int32)silk_RSHIFT(silk_SMLAL(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16)), 16)*/
+/* the following seems faster on x86 */
+#define silk_SMMUL(a32, b32) (opus_int32)silk_RSHIFT64(silk_SMULL((a32), (b32)), 32)
+
+#if !defined(OVERRIDE_silk_burg_modified)
+#define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
+ ((void)(arch), silk_burg_modified_c(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
+#endif
+
+#if !defined(OVERRIDE_silk_inner_prod16)
+#define silk_inner_prod16(inVec1, inVec2, len, arch) \
+ ((void)(arch),silk_inner_prod16_c(inVec1, inVec2, len))
+#endif
+
+#include "Inlines.h"
+#include "MacroCount.h"
+#include "MacroDebug.h"
+
+#ifdef OPUS_ARM_INLINE_ASM
+#include "arm/SigProc_FIX_armv4.h"
+#endif
+
+#ifdef OPUS_ARM_INLINE_EDSP
+#include "arm/SigProc_FIX_armv5e.h"
+#endif
+
+#if defined(FIXED_POINT) && defined(__mips_dsp) && __mips == 32
+#include "mips/sigproc_fix_mipsr1.h"
+#endif
+
+#ifdef OPUS_XTENSA_LX7
+#include "xtensa/SigProc_FIX_lx7.h"
+#endif
+
+
+#endif /* SILK_SIGPROC_FIX_H */
--- /dev/null
+/***********************************************************************
+Copyright (C) 2013 Xiph.Org Foundation and contributors
+Copyright (c) 2013 Parrot
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_SIGPROC_FIX_ARMv4_H
+#define SILK_SIGPROC_FIX_ARMv4_H
+
+#undef silk_MLA
+static OPUS_INLINE opus_int32 silk_MLA_armv4(opus_int32 a, opus_int32 b,
+ opus_int32 c)
+{
+ opus_int32 res;
+ __asm__(
+ "#silk_MLA\n\t"
+ "mla %0, %1, %2, %3\n\t"
+ : "=&r"(res)
+ : "r"(b), "r"(c), "r"(a)
+ );
+ return res;
+}
+#define silk_MLA(a, b, c) (silk_MLA_armv4(a, b, c))
+
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Copyright (c) 2013 Parrot
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_SIGPROC_FIX_ARMv5E_H
+#define SILK_SIGPROC_FIX_ARMv5E_H
+
+#undef silk_SMULTT
+static OPUS_INLINE opus_int32 silk_SMULTT_armv5e(opus_int32 a, opus_int32 b)
+{
+ opus_int32 res;
+ __asm__(
+ "#silk_SMULTT\n\t"
+ "smultt %0, %1, %2\n\t"
+ : "=r"(res)
+ : "%r"(a), "r"(b)
+ );
+ return res;
+}
+#define silk_SMULTT(a, b) (silk_SMULTT_armv5e(a, b))
+
+#undef silk_SMLATT
+static OPUS_INLINE opus_int32 silk_SMLATT_armv5e(opus_int32 a, opus_int32 b,
+ opus_int32 c)
+{
+ opus_int32 res;
+ __asm__(
+ "#silk_SMLATT\n\t"
+ "smlatt %0, %1, %2, %3\n\t"
+ : "=r"(res)
+ : "%r"(b), "r"(c), "r"(a)
+ );
+ return res;
+}
+#define silk_SMLATT(a, b, c) (silk_SMLATT_armv5e(a, b, c))
+
+#endif
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SIGPROC_FIX_SSE_H
+# define SIGPROC_FIX_SSE_H
+
+# ifdef HAVE_CONFIG_H
+# include "config.h"
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+void silk_burg_modified_sse4_1(
+ opus_int32 *res_nrg, /* O Residual energy */
+ opus_int *res_nrg_Q, /* O Residual energy Q value */
+ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
+ const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */
+ const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */
+ const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */
+ const opus_int nb_subfr, /* I Number of subframes stacked in x */
+ const opus_int D, /* I Order */
+ int arch /* I Run-time architecture */
+);
+
+# if defined(OPUS_X86_PRESUME_SSE4_1)
+
+# define OVERRIDE_silk_burg_modified
+# define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
+ ((void)(arch), silk_burg_modified_sse4_1(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
+
+# elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_BURG_MODIFIED_IMPL[OPUS_ARCHMASK + 1])(
+ opus_int32 *res_nrg, /* O Residual energy */
+ opus_int *res_nrg_Q, /* O Residual energy Q value */
+ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
+ const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */
+ const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */
+ const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */
+ const opus_int nb_subfr, /* I Number of subframes stacked in x */
+ const opus_int D, /* I Order */
+ int arch /* I Run-time architecture */);
+
+# define OVERRIDE_silk_burg_modified
+# define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
+ ((*SILK_BURG_MODIFIED_IMPL[(arch) & OPUS_ARCHMASK])(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
+
+# endif
+
+opus_int64 silk_inner_prod16_sse4_1(
+ const opus_int16 *inVec1,
+ const opus_int16 *inVec2,
+ const opus_int len
+);
+
+
+# if defined(OPUS_X86_PRESUME_SSE4_1)
+
+# define OVERRIDE_silk_inner_prod16
+# define silk_inner_prod16(inVec1, inVec2, len, arch) \
+ ((void)(arch),silk_inner_prod16_sse4_1(inVec1, inVec2, len))
+
+# elif defined(OPUS_HAVE_RTCD)
+
+extern opus_int64 (*const SILK_INNER_PROD16_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_int16 *inVec1,
+ const opus_int16 *inVec2,
+ const opus_int len);
+
+# define OVERRIDE_silk_inner_prod16
+# define silk_inner_prod16(inVec1, inVec2, len, arch) \
+ ((*SILK_INNER_PROD16_IMPL[(arch) & OPUS_ARCHMASK])(inVec1, inVec2, len))
+
+# endif
+# endif
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_SIGPROC_FLP_H
+#define SILK_SIGPROC_FLP_H
+
+#include "SigProc_FIX.h"
+#include "float_cast.h"
+#include "main.h"
+#include <math.h>
+
+
+/********************************************************************/
+/* SIGNAL PROCESSING FUNCTIONS */
+/********************************************************************/
+
+/* Chirp (bw expand) LP AR filter */
+void silk_bwexpander_FLP(
+ silk_float *ar, /* I/O AR filter to be expanded (without leading 1) */
+ const opus_int d, /* I length of ar */
+ const silk_float chirp /* I chirp factor (typically in range (0..1) ) */
+);
+
+/* compute inverse of LPC prediction gain, and */
+/* test if LPC coefficients are stable (all poles within unit circle) */
+/* this code is based on silk_FLP_a2k() */
+silk_float silk_LPC_inverse_pred_gain_FLP( /* O return inverse prediction gain, energy domain */
+ const silk_float *A, /* I prediction coefficients [order] */
+ opus_int32 order /* I prediction order */
+);
+
+silk_float silk_schur_FLP( /* O returns residual energy */
+ silk_float refl_coef[], /* O reflection coefficients (length order) */
+ const silk_float auto_corr[], /* I autocorrelation sequence (length order+1) */
+ opus_int order /* I order */
+);
+
+void silk_k2a_FLP(
+ silk_float *A, /* O prediction coefficients [order] */
+ const silk_float *rc, /* I reflection coefficients [order] */
+ opus_int32 order /* I prediction order */
+);
+
+/* compute autocorrelation */
+void silk_autocorrelation_FLP(
+ silk_float *results, /* O result (length correlationCount) */
+ const silk_float *inputData, /* I input data to correlate */
+ opus_int inputDataSize, /* I length of input */
+ opus_int correlationCount, /* I number of correlation taps to compute */
+ int arch
+);
+
+opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced, 1 unvoiced */
+ const silk_float *frame, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */
+ opus_int *pitch_out, /* O Pitch lag values [nb_subfr] */
+ opus_int16 *lagIndex, /* O Lag Index */
+ opus_int8 *contourIndex, /* O Pitch contour Index */
+ silk_float *LTPCorr, /* I/O Normalized correlation; input: value from previous frame */
+ opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */
+ const silk_float search_thres1, /* I First stage threshold for lag candidates 0 - 1 */
+ const silk_float search_thres2, /* I Final threshold for lag candidates 0 - 1 */
+ const opus_int Fs_kHz, /* I sample frequency (kHz) */
+ const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */
+ const opus_int nb_subfr, /* I Number of 5 ms subframes */
+ int arch /* I Run-time architecture */
+);
+
+void silk_insertion_sort_decreasing_FLP(
+ silk_float *a, /* I/O Unsorted / Sorted vector */
+ opus_int *idx, /* O Index vector for the sorted elements */
+ const opus_int L, /* I Vector length */
+ const opus_int K /* I Number of correctly sorted positions */
+);
+
+/* Compute reflection coefficients from input signal */
+silk_float silk_burg_modified_FLP( /* O returns residual energy */
+ silk_float A[], /* O prediction coefficients (length order) */
+ const silk_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */
+ const silk_float minInvGain, /* I minimum inverse prediction gain */
+ const opus_int subfr_length, /* I input signal subframe length (incl. D preceding samples) */
+ const opus_int nb_subfr, /* I number of subframes stacked in x */
+ const opus_int D, /* I order */
+ int arch
+);
+
+/* multiply a vector by a constant */
+void silk_scale_vector_FLP(
+ silk_float *data1,
+ silk_float gain,
+ opus_int dataSize
+);
+
+/* copy and multiply a vector by a constant */
+void silk_scale_copy_vector_FLP(
+ silk_float *data_out,
+ const silk_float *data_in,
+ silk_float gain,
+ opus_int dataSize
+);
+
+/* inner product of two silk_float arrays, with result as double */
+double silk_inner_product_FLP_c(
+ const silk_float *data1,
+ const silk_float *data2,
+ opus_int dataSize
+);
+
+#ifndef OVERRIDE_inner_product_FLP
+#define silk_inner_product_FLP(data1, data2, dataSize, arch) ((void)arch,silk_inner_product_FLP_c(data1, data2, dataSize))
+#endif
+
+
+/* sum of squares of a silk_float array, with result as double */
+double silk_energy_FLP(
+ const silk_float *data,
+ opus_int dataSize
+);
+
+/********************************************************************/
+/* MACROS */
+/********************************************************************/
+
+#define PI (3.1415926536f)
+
+#define silk_min_float( a, b ) (((a) < (b)) ? (a) : (b))
+#define silk_max_float( a, b ) (((a) > (b)) ? (a) : (b))
+#define silk_abs_float( a ) ((silk_float)fabs(a))
+
+/* sigmoid function */
+static OPUS_INLINE silk_float silk_sigmoid( silk_float x )
+{
+ return (silk_float)(1.0 / (1.0 + exp(-x)));
+}
+
+/* floating-point to integer conversion (rounding) */
+static OPUS_INLINE opus_int32 silk_float2int( silk_float x )
+{
+ return (opus_int32)float2int( x );
+}
+
+/* floating-point to integer conversion (rounding) */
+static OPUS_INLINE void silk_float2short_array(
+ opus_int16 *out,
+ const silk_float *in,
+ opus_int32 length
+)
+{
+ opus_int32 k;
+ for( k = length - 1; k >= 0; k-- ) {
+ out[k] = silk_SAT16( (opus_int32)float2int( in[k] ) );
+ }
+}
+
+/* integer to floating-point conversion */
+static OPUS_INLINE void silk_short2float_array(
+ silk_float *out,
+ const opus_int16 *in,
+ opus_int32 length
+)
+{
+ opus_int32 k;
+ for( k = length - 1; k >= 0; k-- ) {
+ out[k] = (silk_float)in[k];
+ }
+}
+
+/* using log2() helps the fixed-point conversion */
+static OPUS_INLINE silk_float silk_log2( double x )
+{
+ return ( silk_float )( 3.32192809488736 * log10( x ) );
+}
+
+#endif /* SILK_SIGPROC_FLP_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+/* *
+ * silk_biquad_alt.c *
+ * *
+ * Second order ARMA filter *
+ * Can handle slowly varying filter coefficients *
+ * */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Second order ARMA filter, alternative implementation */
+void silk_biquad_alt_stride1(
+ const opus_int16 *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [2] */
+ opus_int16 *out, /* O output signal */
+ const opus_int32 len /* I signal length (must be even) */
+)
+{
+ /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
+ opus_int k;
+ opus_int32 inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14;
+
+ /* Negate A_Q28 values and split in two parts */
+ A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */
+ A0_U_Q28 = silk_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */
+ A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */
+ A1_U_Q28 = silk_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */
+
+ for( k = 0; k < len; k++ ) {
+ /* S[ 0 ], S[ 1 ]: Q12 */
+ inval = in[ k ];
+ out32_Q14 = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 );
+
+ S[ 0 ] = S[1] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A0_L_Q28 ), 14 );
+ S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14, A0_U_Q28 );
+ S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], inval);
+
+ S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A1_L_Q28 ), 14 );
+ S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14, A1_U_Q28 );
+ S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval );
+
+ /* Scale back to Q0 and saturate */
+ out[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
+ }
+}
+
+void silk_biquad_alt_stride2_c(
+ const opus_int16 *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [4] */
+ opus_int16 *out, /* O output signal */
+ const opus_int32 len /* I signal length (must be even) */
+)
+{
+ /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
+ opus_int k;
+ opus_int32 A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14[ 2 ];
+
+ /* Negate A_Q28 values and split in two parts */
+ A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */
+ A0_U_Q28 = silk_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */
+ A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */
+ A1_U_Q28 = silk_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */
+
+ for( k = 0; k < len; k++ ) {
+ /* S[ 0 ], S[ 1 ], S[ 2 ], S[ 3 ]: Q12 */
+ out32_Q14[ 0 ] = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], in[ 2 * k + 0 ] ), 2 );
+ out32_Q14[ 1 ] = silk_LSHIFT( silk_SMLAWB( S[ 2 ], B_Q28[ 0 ], in[ 2 * k + 1 ] ), 2 );
+
+ S[ 0 ] = S[ 1 ] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 0 ], A0_L_Q28 ), 14 );
+ S[ 2 ] = S[ 3 ] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 1 ], A0_L_Q28 ), 14 );
+ S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14[ 0 ], A0_U_Q28 );
+ S[ 2 ] = silk_SMLAWB( S[ 2 ], out32_Q14[ 1 ], A0_U_Q28 );
+ S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], in[ 2 * k + 0 ] );
+ S[ 2 ] = silk_SMLAWB( S[ 2 ], B_Q28[ 1 ], in[ 2 * k + 1 ] );
+
+ S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 0 ], A1_L_Q28 ), 14 );
+ S[ 3 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 1 ], A1_L_Q28 ), 14 );
+ S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14[ 0 ], A1_U_Q28 );
+ S[ 3 ] = silk_SMLAWB( S[ 3 ], out32_Q14[ 1 ], A1_U_Q28 );
+ S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], in[ 2 * k + 0 ] );
+ S[ 3 ] = silk_SMLAWB( S[ 3 ], B_Q28[ 2 ], in[ 2 * k + 1 ] );
+
+ /* Scale back to Q0 and saturate */
+ out[ 2 * k + 0 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14[ 0 ] + (1<<14) - 1, 14 ) );
+ out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14[ 1 ] + (1<<14) - 1, 14 ) );
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_BIQUAD_ALT_ARM_H
+# define SILK_BIQUAD_ALT_ARM_H
+
+# include "celt/arm/armcpu.h"
+
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+void silk_biquad_alt_stride2_neon(
+ const opus_int16 *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [4] */
+ opus_int16 *out, /* O output signal */
+ const opus_int32 len /* I signal length (must be even) */
+);
+
+# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+# define OVERRIDE_silk_biquad_alt_stride2 (1)
+# define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), PRESUME_NEON(silk_biquad_alt_stride2)(in, B_Q28, A_Q28, S, out, len))
+# endif
+# endif
+
+# if !defined(OVERRIDE_silk_biquad_alt_stride2)
+/*Is run-time CPU detection enabled on this platform?*/
+# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const SILK_BIQUAD_ALT_STRIDE2_IMPL[OPUS_ARCHMASK+1])(
+ const opus_int16 *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [4] */
+ opus_int16 *out, /* O output signal */
+ const opus_int32 len /* I signal length (must be even) */
+ );
+# define OVERRIDE_silk_biquad_alt_stride2 (1)
+# define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((*SILK_BIQUAD_ALT_STRIDE2_IMPL[(arch)&OPUS_ARCHMASK])(in, B_Q28, A_Q28, S, out, len))
+# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+# define OVERRIDE_silk_biquad_alt_stride2 (1)
+# define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_neon(in, B_Q28, A_Q28, S, out, len))
+# endif
+# endif
+
+#endif /* end SILK_BIQUAD_ALT_ARM_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Chirp (bandwidth expand) LP AR filter */
+void silk_bwexpander(
+ opus_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */
+ const opus_int d, /* I Length of ar */
+ opus_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */
+)
+{
+ opus_int i;
+ opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536;
+
+ /* NB: Dont use silk_SMULWB, instead of silk_RSHIFT_ROUND( silk_MUL(), 16 ), below. */
+ /* Bias in silk_SMULWB can lead to unstable filters */
+ for( i = 0; i < d - 1; i++ ) {
+ ar[ i ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ i ] ), 16 );
+ chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
+ }
+ ar[ d - 1 ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ d - 1 ] ), 16 );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Chirp (bandwidth expand) LP AR filter.
+ This logic is reused in _celt_lpc(). Any bug fixes should also be applied there. */
+void silk_bwexpander_32(
+ opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */
+ const opus_int d, /* I Length of ar */
+ opus_int32 chirp_Q16 /* I Chirp factor in Q16 */
+)
+{
+ opus_int i;
+ opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536;
+
+ for( i = 0; i < d - 1; i++ ) {
+ ar[ i ] = silk_SMULWW( chirp_Q16, ar[ i ] );
+ chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
+ }
+ ar[ d - 1 ] = silk_SMULWW( chirp_Q16, ar[ d - 1 ] );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/*#define silk_enc_map(a) ((a) > 0 ? 1 : 0)*/
+/*#define silk_dec_map(a) ((a) > 0 ? 1 : -1)*/
+/* shifting avoids if-statement */
+#define silk_enc_map(a) ( silk_RSHIFT( (a), 15 ) + 1 )
+#define silk_dec_map(a) ( silk_LSHIFT( (a), 1 ) - 1 )
+
+/* Encodes signs of excitation */
+void silk_encode_signs(
+ ec_enc *psRangeEnc, /* I/O Compressor data structure */
+ const opus_int8 pulses[], /* I pulse signal */
+ opus_int length, /* I length of input */
+ const opus_int signalType, /* I Signal type */
+ const opus_int quantOffsetType, /* I Quantization offset type */
+ const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
+)
+{
+ opus_int i, j, p;
+ opus_uint8 icdf[ 2 ];
+ const opus_int8 *q_ptr;
+ const opus_uint8 *icdf_ptr;
+
+ icdf[ 1 ] = 0;
+ q_ptr = pulses;
+ i = silk_SMULBB( 7, silk_ADD_LSHIFT( quantOffsetType, signalType, 1 ) );
+ icdf_ptr = &silk_sign_iCDF[ i ];
+ length = silk_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH );
+ for( i = 0; i < length; i++ ) {
+ p = sum_pulses[ i ];
+ if( p > 0 ) {
+ icdf[ 0 ] = icdf_ptr[ silk_min( p & 0x1F, 6 ) ];
+ for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) {
+ if( q_ptr[ j ] != 0 ) {
+ ec_enc_icdf( psRangeEnc, silk_enc_map( q_ptr[ j ]), icdf, 8 );
+ }
+ }
+ }
+ q_ptr += SHELL_CODEC_FRAME_LENGTH;
+ }
+}
+
+/* Decodes signs of excitation */
+void silk_decode_signs(
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int16 pulses[], /* I/O pulse signal */
+ opus_int length, /* I length of input */
+ const opus_int signalType, /* I Signal type */
+ const opus_int quantOffsetType, /* I Quantization offset type */
+ const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
+)
+{
+ opus_int i, j, p;
+ opus_uint8 icdf[ 2 ];
+ opus_int16 *q_ptr;
+ const opus_uint8 *icdf_ptr;
+
+ icdf[ 1 ] = 0;
+ q_ptr = pulses;
+ i = silk_SMULBB( 7, silk_ADD_LSHIFT( quantOffsetType, signalType, 1 ) );
+ icdf_ptr = &silk_sign_iCDF[ i ];
+ length = silk_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH );
+ for( i = 0; i < length; i++ ) {
+ p = sum_pulses[ i ];
+ if( p > 0 ) {
+ icdf[ 0 ] = icdf_ptr[ silk_min( p & 0x1F, 6 ) ];
+ for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) {
+ if( q_ptr[ j ] > 0 ) {
+ /* attach sign */
+#if 0
+ /* conditional implementation */
+ if( ec_dec_icdf( psRangeDec, icdf, 8 ) == 0 ) {
+ q_ptr[ j ] = -q_ptr[ j ];
+ }
+#else
+ /* implementation with shift, subtraction, multiplication */
+ q_ptr[ j ] *= silk_dec_map( ec_dec_icdf( psRangeDec, icdf, 8 ) );
+#endif
+ }
+ }
+ }
+ q_ptr += SHELL_CODEC_FRAME_LENGTH;
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_CONTROL_H
+#define SILK_CONTROL_H
+
+#include "typedef.h"
+
+
+/* Decoder API flags */
+#define FLAG_DECODE_NORMAL 0
+#define FLAG_PACKET_LOST 1
+#define FLAG_DECODE_LBRR 2
+
+/***********************************************/
+/* Structure for controlling encoder operation */
+/***********************************************/
+typedef struct {
+ /* I: Number of channels; 1/2 */
+ opus_int32 nChannelsAPI;
+
+ /* I: Number of channels; 1/2 */
+ opus_int32 nChannelsInternal;
+
+ /* I: Input signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000 */
+ opus_int32 API_sampleRate;
+
+ /* I: Maximum internal sampling rate in Hertz; 8000/12000/16000 */
+ opus_int32 maxInternalSampleRate;
+
+ /* I: Minimum internal sampling rate in Hertz; 8000/12000/16000 */
+ opus_int32 minInternalSampleRate;
+
+ /* I: Soft request for internal sampling rate in Hertz; 8000/12000/16000 */
+ opus_int32 desiredInternalSampleRate;
+
+ /* I: Number of samples per packet in milliseconds; 10/20/40/60 */
+ opus_int payloadSize_ms;
+
+ /* I: Bitrate during active speech in bits/second; internally limited */
+ opus_int32 bitRate;
+
+ /* I: Uplink packet loss in percent (0-100) */
+ opus_int packetLossPercentage;
+
+ /* I: Complexity mode; 0 is lowest, 10 is highest complexity */
+ opus_int complexity;
+
+ /* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */
+ opus_int useInBandFEC;
+
+ /* I: Flag to enable in-band Deep REDundancy (DRED); 0/1 */
+ opus_int useDRED;
+
+ /* I: Flag to actually code in-band Forward Error Correction (FEC) in the current packet; 0/1 */
+ opus_int LBRR_coded;
+
+ /* I: Flag to enable discontinuous transmission (DTX); 0/1 */
+ opus_int useDTX;
+
+ /* I: Flag to use constant bitrate */
+ opus_int useCBR;
+
+ /* I: Maximum number of bits allowed for the frame */
+ opus_int maxBits;
+
+ /* I: Causes a smooth downmix to mono */
+ opus_int toMono;
+
+ /* I: Opus encoder is allowing us to switch bandwidth */
+ opus_int opusCanSwitch;
+
+ /* I: Make frames as independent as possible (but still use LPC) */
+ opus_int reducedDependency;
+
+ /* O: Internal sampling rate used, in Hertz; 8000/12000/16000 */
+ opus_int32 internalSampleRate;
+
+ /* O: Flag that bandwidth switching is allowed (because low voice activity) */
+ opus_int allowBandwidthSwitch;
+
+ /* O: Flag that SILK runs in WB mode without variable LP filter (use for switching between WB/SWB/FB) */
+ opus_int inWBmodeWithoutVariableLP;
+
+ /* O: Stereo width */
+ opus_int stereoWidth_Q14;
+
+ /* O: Tells the Opus encoder we're ready to switch */
+ opus_int switchReady;
+
+ /* O: SILK Signal type */
+ opus_int signalType;
+
+ /* O: SILK offset (dithering) */
+ opus_int offset;
+} silk_EncControlStruct;
+
+/**************************************************************************/
+/* Structure for controlling decoder operation and reading decoder status */
+/**************************************************************************/
+typedef struct {
+ /* I: Number of channels; 1/2 */
+ opus_int32 nChannelsAPI;
+
+ /* I: Number of channels; 1/2 */
+ opus_int32 nChannelsInternal;
+
+ /* I: Output signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000 */
+ opus_int32 API_sampleRate;
+
+ /* I: Internal sampling rate used, in Hertz; 8000/12000/16000 */
+ opus_int32 internalSampleRate;
+
+ /* I: Number of samples per packet in milliseconds; 10/20/40/60 */
+ opus_int payloadSize_ms;
+
+ /* O: Pitch lag of previous frame (0 if unvoiced), measured in samples at 48 kHz */
+ opus_int prevPitchLag;
+
+ /* I: Enable Deep PLC */
+ opus_int enable_deep_plc;
+
+#ifdef ENABLE_OSCE
+ /* I: OSCE method */
+ opus_int osce_method;
+
+#ifdef ENABLE_OSCE_BWE
+ /* I: OSCE bandwidth extension method */
+ opus_int enable_osce_bwe;
+
+ /* I: extended mode */
+ opus_int osce_extended_mode;
+
+ /* O: previous extended mode */
+ opus_int prev_osce_extended_mode;
+#endif
+#endif
+} silk_DecControlStruct;
+
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_DEBUG_H
+#define SILK_DEBUG_H
+
+/* Set to 1 to enable DEBUG_STORE_DATA() macros for dumping
+ * intermediate signals from the codec.
+ */
+#define SILK_DEBUG 0
+
+/* Flag for using timers */
+#define SILK_TIC_TOC 0
+
+#if SILK_DEBUG || SILK_TIC_TOC
+#include "typedef.h"
+#include <string.h> /* strcpy, strcmp */
+#include <stdio.h> /* file writing */
+#endif
+
+
+#if SILK_TIC_TOC
+
+unsigned long GetHighResolutionTime(void); /* O time in usec*/
+
+#if (defined(_WIN32) || defined(_WINCE))
+#include <windows.h> /* timer */
+#else /* Linux or Mac*/
+#include <sys/time.h>
+#endif
+
+/*********************************/
+/* timer functions for profiling */
+/*********************************/
+/* example: */
+/* */
+/* TIC(LPC) */
+/* do_LPC(in_vec, order, acoef); // do LPC analysis */
+/* TOC(LPC) */
+/* */
+/* and call the following just before exiting (from main) */
+/* */
+/* silk_TimerSave("silk_TimingData.txt"); */
+/* */
+/* results are now in silk_TimingData.txt */
+
+void silk_TimerSave(char *file_name);
+
+/* max number of timers (in different locations) */
+#define silk_NUM_TIMERS_MAX 50
+/* max length of name tags in TIC(..), TOC(..) */
+#define silk_NUM_TIMERS_MAX_TAG_LEN 30
+
+extern int silk_Timer_nTimers;
+extern int silk_Timer_depth_ctr;
+extern char silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN];
+#ifdef _WIN32
+extern LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX];
+#else
+extern unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX];
+#endif
+extern unsigned int silk_Timer_cnt[silk_NUM_TIMERS_MAX];
+extern opus_int64 silk_Timer_sum[silk_NUM_TIMERS_MAX];
+extern opus_int64 silk_Timer_max[silk_NUM_TIMERS_MAX];
+extern opus_int64 silk_Timer_min[silk_NUM_TIMERS_MAX];
+extern opus_int64 silk_Timer_depth[silk_NUM_TIMERS_MAX];
+
+/* WARNING: TIC()/TOC can measure only up to 0.1 seconds at a time */
+#ifdef _WIN32
+#define TIC(TAG_NAME) { \
+ static int init = 0; \
+ static int ID = -1; \
+ if( init == 0 ) \
+ { \
+ int k; \
+ init = 1; \
+ for( k = 0; k < silk_Timer_nTimers; k++ ) { \
+ if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \
+ ID = k; \
+ break; \
+ } \
+ } \
+ if (ID == -1) { \
+ ID = silk_Timer_nTimers; \
+ silk_Timer_nTimers++; \
+ silk_Timer_depth[ID] = silk_Timer_depth_ctr; \
+ strcpy(silk_Timer_tags[ID], #TAG_NAME); \
+ silk_Timer_cnt[ID] = 0; \
+ silk_Timer_sum[ID] = 0; \
+ silk_Timer_min[ID] = 0xFFFFFFFF; \
+ silk_Timer_max[ID] = 0; \
+ } \
+ } \
+ silk_Timer_depth_ctr++; \
+ QueryPerformanceCounter(&silk_Timer_start[ID]); \
+}
+#else
+#define TIC(TAG_NAME) { \
+ static int init = 0; \
+ static int ID = -1; \
+ if( init == 0 ) \
+ { \
+ int k; \
+ init = 1; \
+ for( k = 0; k < silk_Timer_nTimers; k++ ) { \
+ if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \
+ ID = k; \
+ break; \
+ } \
+ } \
+ if (ID == -1) { \
+ ID = silk_Timer_nTimers; \
+ silk_Timer_nTimers++; \
+ silk_Timer_depth[ID] = silk_Timer_depth_ctr; \
+ strcpy(silk_Timer_tags[ID], #TAG_NAME); \
+ silk_Timer_cnt[ID] = 0; \
+ silk_Timer_sum[ID] = 0; \
+ silk_Timer_min[ID] = 0xFFFFFFFF; \
+ silk_Timer_max[ID] = 0; \
+ } \
+ } \
+ silk_Timer_depth_ctr++; \
+ silk_Timer_start[ID] = GetHighResolutionTime(); \
+}
+#endif
+
+#ifdef _WIN32
+#define TOC(TAG_NAME) { \
+ LARGE_INTEGER lpPerformanceCount; \
+ static int init = 0; \
+ static int ID = 0; \
+ if( init == 0 ) \
+ { \
+ int k; \
+ init = 1; \
+ for( k = 0; k < silk_Timer_nTimers; k++ ) { \
+ if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \
+ ID = k; \
+ break; \
+ } \
+ } \
+ } \
+ QueryPerformanceCounter(&lpPerformanceCount); \
+ lpPerformanceCount.QuadPart -= silk_Timer_start[ID].QuadPart; \
+ if((lpPerformanceCount.QuadPart < 100000000) && \
+ (lpPerformanceCount.QuadPart >= 0)) { \
+ silk_Timer_cnt[ID]++; \
+ silk_Timer_sum[ID] += lpPerformanceCount.QuadPart; \
+ if( lpPerformanceCount.QuadPart > silk_Timer_max[ID] ) \
+ silk_Timer_max[ID] = lpPerformanceCount.QuadPart; \
+ if( lpPerformanceCount.QuadPart < silk_Timer_min[ID] ) \
+ silk_Timer_min[ID] = lpPerformanceCount.QuadPart; \
+ } \
+ silk_Timer_depth_ctr--; \
+}
+#else
+#define TOC(TAG_NAME) { \
+ unsigned long endTime; \
+ static int init = 0; \
+ static int ID = 0; \
+ if( init == 0 ) \
+ { \
+ int k; \
+ init = 1; \
+ for( k = 0; k < silk_Timer_nTimers; k++ ) { \
+ if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \
+ ID = k; \
+ break; \
+ } \
+ } \
+ } \
+ endTime = GetHighResolutionTime(); \
+ endTime -= silk_Timer_start[ID]; \
+ if((endTime < 100000000) && \
+ (endTime >= 0)) { \
+ silk_Timer_cnt[ID]++; \
+ silk_Timer_sum[ID] += endTime; \
+ if( endTime > silk_Timer_max[ID] ) \
+ silk_Timer_max[ID] = endTime; \
+ if( endTime < silk_Timer_min[ID] ) \
+ silk_Timer_min[ID] = endTime; \
+ } \
+ silk_Timer_depth_ctr--; \
+}
+#endif
+
+#else /* SILK_TIC_TOC */
+
+/* define macros as empty strings */
+#define TIC(TAG_NAME)
+#define TOC(TAG_NAME)
+#define silk_TimerSave(FILE_NAME)
+
+#endif /* SILK_TIC_TOC */
+
+
+#if SILK_DEBUG
+/************************************/
+/* write data to file for debugging */
+/************************************/
+/* Example: DEBUG_STORE_DATA(testfile.pcm, &RIN[0], 160*sizeof(opus_int16)); */
+
+#define silk_NUM_STORES_MAX 100
+extern FILE *silk_debug_store_fp[ silk_NUM_STORES_MAX ];
+extern int silk_debug_store_count;
+
+/* Faster way of storing the data */
+#define DEBUG_STORE_DATA( FILE_NAME, DATA_PTR, N_BYTES ) { \
+ static opus_int init = 0, cnt = 0; \
+ static FILE **fp; \
+ if (init == 0) { \
+ init = 1; \
+ cnt = silk_debug_store_count++; \
+ silk_debug_store_fp[ cnt ] = fopen(#FILE_NAME, "wb"); \
+ } \
+ fwrite((DATA_PTR), (N_BYTES), 1, silk_debug_store_fp[ cnt ]); \
+}
+
+/* Call this at the end of main() */
+#define SILK_DEBUG_STORE_CLOSE_FILES { \
+ opus_int i; \
+ for( i = 0; i < silk_debug_store_count; i++ ) { \
+ fclose( silk_debug_store_fp[ i ] ); \
+ } \
+}
+
+#else /* SILK_DEBUG */
+
+/* define macros as empty strings */
+#define DEBUG_STORE_DATA(FILE_NAME, DATA_PTR, N_BYTES)
+#define SILK_DEBUG_STORE_CLOSE_FILES
+
+#endif /* SILK_DEBUG */
+
+#endif /* SILK_DEBUG_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "API.h"
+#include "main.h"
+#include "stack_alloc.h"
+#include "os_support.h"
+
+#ifdef ENABLE_OSCE
+#include "osce.h"
+#include "osce_structs.h"
+#ifdef ENABLE_OSCE_BWE
+#include "osce_features.h"
+#endif
+#endif
+
+/************************/
+/* Decoder Super Struct */
+/************************/
+typedef struct {
+ silk_decoder_state channel_state[ DECODER_NUM_CHANNELS ];
+ stereo_dec_state sStereo;
+ opus_int nChannelsAPI;
+ opus_int nChannelsInternal;
+ opus_int prev_decode_only_middle;
+#ifdef ENABLE_OSCE
+ OSCEModel osce_model;
+#endif
+} silk_decoder;
+
+/*********************/
+/* Decoder functions */
+/*********************/
+
+
+
+opus_int silk_LoadOSCEModels(void *decState, const unsigned char *data, int len)
+{
+#ifdef ENABLE_OSCE
+ opus_int ret = SILK_NO_ERROR;
+
+ ret = osce_load_models(&((silk_decoder *)decState)->osce_model, data, len);
+ ((silk_decoder *)decState)->osce_model.loaded = (ret == 0);
+ return ret;
+#else
+ (void) decState;
+ (void) data;
+ (void) len;
+ return SILK_NO_ERROR;
+#endif
+}
+
+opus_int silk_Get_Decoder_Size( /* O Returns error code */
+ opus_int *decSizeBytes /* O Number of bytes in SILK decoder state */
+)
+{
+ opus_int ret = SILK_NO_ERROR;
+
+ *decSizeBytes = sizeof( silk_decoder );
+
+ return ret;
+}
+
+/* Reset decoder state */
+opus_int silk_ResetDecoder( /* O Returns error code */
+ void *decState /* I/O State */
+)
+{
+ opus_int n, ret = SILK_NO_ERROR;
+ silk_decoder_state *channel_state = ((silk_decoder *)decState)->channel_state;
+
+ for( n = 0; n < DECODER_NUM_CHANNELS; n++ ) {
+ ret = silk_reset_decoder( &channel_state[ n ] );
+ }
+ silk_memset(&((silk_decoder *)decState)->sStereo, 0, sizeof(((silk_decoder *)decState)->sStereo));
+ /* Not strictly needed, but it's cleaner that way */
+ ((silk_decoder *)decState)->prev_decode_only_middle = 0;
+
+ return ret;
+}
+
+
+opus_int silk_InitDecoder( /* O Returns error code */
+ void *decState /* I/O State */
+)
+{
+ opus_int n, ret = SILK_NO_ERROR;
+ silk_decoder_state *channel_state = ((silk_decoder *)decState)->channel_state;
+#ifdef ENABLE_OSCE
+ ((silk_decoder *)decState)->osce_model.loaded = 0;
+#endif
+#ifndef USE_WEIGHTS_FILE
+ /* load osce models */
+ silk_LoadOSCEModels(decState, NULL, 0);
+#endif
+
+ for( n = 0; n < DECODER_NUM_CHANNELS; n++ ) {
+ ret = silk_init_decoder( &channel_state[ n ] );
+ }
+ silk_memset(&((silk_decoder *)decState)->sStereo, 0, sizeof(((silk_decoder *)decState)->sStereo));
+ /* Not strictly needed, but it's cleaner that way */
+ ((silk_decoder *)decState)->prev_decode_only_middle = 0;
+
+ return ret;
+}
+
+/* Decode a frame */
+opus_int silk_Decode( /* O Returns error code */
+ void* decState, /* I/O State */
+ silk_DecControlStruct* decControl, /* I/O Control Structure */
+ opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
+ opus_int newPacketFlag, /* I Indicates first decoder call for this packet */
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_res *samplesOut, /* O Decoded output speech vector */
+ opus_int32 *nSamplesOut, /* O Number of samples decoded */
+#ifdef ENABLE_DEEP_PLC
+ LPCNetPLCState *lpcnet,
+#endif
+ int arch /* I Run-time architecture */
+)
+{
+ opus_int i, n, decode_only_middle = 0, ret = SILK_NO_ERROR;
+ opus_int32 nSamplesOutDec, LBRR_symbol;
+ opus_int16 *samplesOut1_tmp[ 2 ];
+ VARDECL( opus_int16, samplesOut1_tmp_storage1 );
+ VARDECL( opus_int16, samplesOut2_tmp );
+ opus_int32 MS_pred_Q13[ 2 ] = { 0 };
+ opus_int16 *resample_out_ptr;
+ silk_decoder *psDec = ( silk_decoder * )decState;
+ silk_decoder_state *channel_state = psDec->channel_state;
+ opus_int has_side;
+ opus_int stereo_to_mono;
+#ifdef ENABLE_OSCE_BWE
+ VARDECL( opus_int16, resamp_buffer );
+#endif
+ SAVE_STACK;
+
+ celt_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 );
+
+ /**********************************/
+ /* Test if first frame in payload */
+ /**********************************/
+ if( newPacketFlag ) {
+ for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+ channel_state[ n ].nFramesDecoded = 0; /* Used to count frames in packet */
+ }
+ }
+
+ /* If Mono -> Stereo transition in bitstream: init state of second channel */
+ if( decControl->nChannelsInternal > psDec->nChannelsInternal ) {
+ ret += silk_init_decoder( &channel_state[ 1 ] );
+ }
+
+ stereo_to_mono = decControl->nChannelsInternal == 1 && psDec->nChannelsInternal == 2 &&
+ ( decControl->internalSampleRate == 1000*channel_state[ 0 ].fs_kHz );
+
+ if( channel_state[ 0 ].nFramesDecoded == 0 ) {
+ for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+ opus_int fs_kHz_dec;
+ if( decControl->payloadSize_ms == 0 ) {
+ /* Assuming packet loss, use 10 ms */
+ channel_state[ n ].nFramesPerPacket = 1;
+ channel_state[ n ].nb_subfr = 2;
+ } else if( decControl->payloadSize_ms == 10 ) {
+ channel_state[ n ].nFramesPerPacket = 1;
+ channel_state[ n ].nb_subfr = 2;
+ } else if( decControl->payloadSize_ms == 20 ) {
+ channel_state[ n ].nFramesPerPacket = 1;
+ channel_state[ n ].nb_subfr = 4;
+ } else if( decControl->payloadSize_ms == 40 ) {
+ channel_state[ n ].nFramesPerPacket = 2;
+ channel_state[ n ].nb_subfr = 4;
+ } else if( decControl->payloadSize_ms == 60 ) {
+ channel_state[ n ].nFramesPerPacket = 3;
+ channel_state[ n ].nb_subfr = 4;
+ } else {
+ celt_assert( 0 );
+ RESTORE_STACK;
+ return SILK_DEC_INVALID_FRAME_SIZE;
+ }
+ fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1;
+ if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) {
+ celt_assert( 0 );
+ RESTORE_STACK;
+ return SILK_DEC_INVALID_SAMPLING_FREQUENCY;
+ }
+ ret += silk_decoder_set_fs( &channel_state[ n ], fs_kHz_dec, decControl->API_sampleRate );
+ }
+ }
+
+ if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 && ( psDec->nChannelsAPI == 1 || psDec->nChannelsInternal == 1 ) ) {
+ silk_memset( psDec->sStereo.pred_prev_Q13, 0, sizeof( psDec->sStereo.pred_prev_Q13 ) );
+ silk_memset( psDec->sStereo.sSide, 0, sizeof( psDec->sStereo.sSide ) );
+ silk_memcpy( &channel_state[ 1 ].resampler_state, &channel_state[ 0 ].resampler_state, sizeof( silk_resampler_state_struct ) );
+ }
+ psDec->nChannelsAPI = decControl->nChannelsAPI;
+ psDec->nChannelsInternal = decControl->nChannelsInternal;
+
+ if( decControl->API_sampleRate > (opus_int32)MAX_API_FS_KHZ * 1000 || decControl->API_sampleRate < 8000 ) {
+ ret = SILK_DEC_INVALID_SAMPLING_FREQUENCY;
+ RESTORE_STACK;
+ return( ret );
+ }
+
+ if( lostFlag != FLAG_PACKET_LOST && channel_state[ 0 ].nFramesDecoded == 0 ) {
+ /* First decoder call for this payload */
+ /* Decode VAD flags and LBRR flag */
+ for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+ for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) {
+ channel_state[ n ].VAD_flags[ i ] = ec_dec_bit_logp(psRangeDec, 1);
+ }
+ channel_state[ n ].LBRR_flag = ec_dec_bit_logp(psRangeDec, 1);
+ }
+ /* Decode LBRR flags */
+ for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+ silk_memset( channel_state[ n ].LBRR_flags, 0, sizeof( channel_state[ n ].LBRR_flags ) );
+ if( channel_state[ n ].LBRR_flag ) {
+ if( channel_state[ n ].nFramesPerPacket == 1 ) {
+ channel_state[ n ].LBRR_flags[ 0 ] = 1;
+ } else {
+ LBRR_symbol = ec_dec_icdf( psRangeDec, silk_LBRR_flags_iCDF_ptr[ channel_state[ n ].nFramesPerPacket - 2 ], 8 ) + 1;
+ for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) {
+ channel_state[ n ].LBRR_flags[ i ] = silk_RSHIFT( LBRR_symbol, i ) & 1;
+ }
+ }
+ }
+ }
+
+ if( lostFlag == FLAG_DECODE_NORMAL ) {
+ /* Regular decoding: skip all LBRR data */
+ for( i = 0; i < channel_state[ 0 ].nFramesPerPacket; i++ ) {
+ for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+ if( channel_state[ n ].LBRR_flags[ i ] ) {
+ opus_int16 pulses[ MAX_FRAME_LENGTH ];
+ opus_int condCoding;
+
+ if( decControl->nChannelsInternal == 2 && n == 0 ) {
+ silk_stereo_decode_pred( psRangeDec, MS_pred_Q13 );
+ if( channel_state[ 1 ].LBRR_flags[ i ] == 0 ) {
+ silk_stereo_decode_mid_only( psRangeDec, &decode_only_middle );
+ }
+ }
+ /* Use conditional coding if previous frame available */
+ if( i > 0 && channel_state[ n ].LBRR_flags[ i - 1 ] ) {
+ condCoding = CODE_CONDITIONALLY;
+ } else {
+ condCoding = CODE_INDEPENDENTLY;
+ }
+ silk_decode_indices( &channel_state[ n ], psRangeDec, i, 1, condCoding );
+ silk_decode_pulses( psRangeDec, pulses, channel_state[ n ].indices.signalType,
+ channel_state[ n ].indices.quantOffsetType, channel_state[ n ].frame_length );
+ }
+ }
+ }
+ }
+ }
+
+ /* Get MS predictor index */
+ if( decControl->nChannelsInternal == 2 ) {
+ if( lostFlag == FLAG_DECODE_NORMAL ||
+ ( lostFlag == FLAG_DECODE_LBRR && channel_state[ 0 ].LBRR_flags[ channel_state[ 0 ].nFramesDecoded ] == 1 ) )
+ {
+ silk_stereo_decode_pred( psRangeDec, MS_pred_Q13 );
+ /* For LBRR data, decode mid-only flag only if side-channel's LBRR flag is false */
+ if( ( lostFlag == FLAG_DECODE_NORMAL && channel_state[ 1 ].VAD_flags[ channel_state[ 0 ].nFramesDecoded ] == 0 ) ||
+ ( lostFlag == FLAG_DECODE_LBRR && channel_state[ 1 ].LBRR_flags[ channel_state[ 0 ].nFramesDecoded ] == 0 ) )
+ {
+ silk_stereo_decode_mid_only( psRangeDec, &decode_only_middle );
+ } else {
+ decode_only_middle = 0;
+ }
+ } else {
+ for( n = 0; n < 2; n++ ) {
+ MS_pred_Q13[ n ] = psDec->sStereo.pred_prev_Q13[ n ];
+ }
+ }
+ }
+
+ /* Reset side channel decoder prediction memory for first frame with side coding */
+ if( decControl->nChannelsInternal == 2 && decode_only_middle == 0 && psDec->prev_decode_only_middle == 1 ) {
+ silk_memset( psDec->channel_state[ 1 ].outBuf, 0, sizeof(psDec->channel_state[ 1 ].outBuf) );
+ silk_memset( psDec->channel_state[ 1 ].sLPC_Q14_buf, 0, sizeof(psDec->channel_state[ 1 ].sLPC_Q14_buf) );
+ psDec->channel_state[ 1 ].lagPrev = 100;
+ psDec->channel_state[ 1 ].LastGainIndex = 10;
+ psDec->channel_state[ 1 ].prevSignalType = TYPE_NO_VOICE_ACTIVITY;
+ psDec->channel_state[ 1 ].first_frame_after_reset = 1;
+ }
+
+ /* Check if the temp buffer fits into the output PCM buffer. If it fits,
+ we can delay allocating the temp buffer until after the SILK peak stack
+ usage. We need to use a < and not a <= because of the two extra samples. */
+ ALLOC( samplesOut1_tmp_storage1, decControl->nChannelsInternal*(channel_state[ 0 ].frame_length + 2 ),
+ opus_int16 );
+ samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage1;
+ samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage1 + channel_state[ 0 ].frame_length + 2;
+
+ if( lostFlag == FLAG_DECODE_NORMAL ) {
+ has_side = !decode_only_middle;
+ } else {
+ has_side = !psDec->prev_decode_only_middle
+ || (decControl->nChannelsInternal == 2 && lostFlag == FLAG_DECODE_LBRR && channel_state[1].LBRR_flags[ channel_state[1].nFramesDecoded ] == 1 );
+ }
+ channel_state[ 0 ].sPLC.enable_deep_plc = decControl->enable_deep_plc;
+ /* Call decoder for one frame */
+ for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+ if( n == 0 || has_side ) {
+ opus_int FrameIndex;
+ opus_int condCoding;
+
+ FrameIndex = channel_state[ 0 ].nFramesDecoded - n;
+ /* Use independent coding if no previous frame available */
+ if( FrameIndex <= 0 ) {
+ condCoding = CODE_INDEPENDENTLY;
+ } else if( lostFlag == FLAG_DECODE_LBRR ) {
+ condCoding = channel_state[ n ].LBRR_flags[ FrameIndex - 1 ] ? CODE_CONDITIONALLY : CODE_INDEPENDENTLY;
+ } else if( n > 0 && psDec->prev_decode_only_middle ) {
+ /* If we skipped a side frame in this packet, we don't
+ need LTP scaling; the LTP state is well-defined. */
+ condCoding = CODE_INDEPENDENTLY_NO_LTP_SCALING;
+ } else {
+ condCoding = CODE_CONDITIONALLY;
+ }
+#ifdef ENABLE_OSCE
+ if ( channel_state[n].osce.method != decControl->osce_method ) {
+ osce_reset( &channel_state[n].osce, decControl->osce_method );
+ }
+#endif
+ ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag, condCoding,
+#ifdef ENABLE_DEEP_PLC
+ n == 0 ? lpcnet : NULL,
+#endif
+#ifdef ENABLE_OSCE
+ &psDec->osce_model,
+#endif
+ arch);
+ } else {
+ silk_memset( &samplesOut1_tmp[ n ][ 2 ], 0, nSamplesOutDec * sizeof( opus_int16 ) );
+ }
+ channel_state[ n ].nFramesDecoded++;
+ }
+
+ if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) {
+ /* Convert Mid/Side to Left/Right */
+ silk_stereo_MS_to_LR( &psDec->sStereo, samplesOut1_tmp[ 0 ], samplesOut1_tmp[ 1 ], MS_pred_Q13, channel_state[ 0 ].fs_kHz, nSamplesOutDec );
+ } else {
+ /* Buffering */
+ silk_memcpy( samplesOut1_tmp[ 0 ], psDec->sStereo.sMid, 2 * sizeof( opus_int16 ) );
+ silk_memcpy( psDec->sStereo.sMid, &samplesOut1_tmp[ 0 ][ nSamplesOutDec ], 2 * sizeof( opus_int16 ) );
+ }
+
+ /* Number of output samples */
+ *nSamplesOut = silk_DIV32( nSamplesOutDec * decControl->API_sampleRate, silk_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ) );
+
+ /* Set up pointers to temp buffers */
+ ALLOC( samplesOut2_tmp, *nSamplesOut, opus_int16 );
+ resample_out_ptr = samplesOut2_tmp;
+
+#ifdef ENABLE_OSCE_BWE
+ ALLOC(resamp_buffer, 3 * MAX_FRAME_LENGTH, opus_int16);
+#endif
+
+ for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) {
+
+#ifdef ENABLE_OSCE_BWE
+ /* Resample or extend decoded signal to API_sampleRate */
+ if (decControl->osce_extended_mode == OSCE_MODE_SILK_BBWE) {
+ silk_assert(decControl->API_sampleRate == 48000);
+
+ if (decControl->prev_osce_extended_mode != OSCE_MODE_SILK_BBWE) {
+ /* Reset the BWE state */
+ osce_bwe_reset( &channel_state[ n ].osce_bwe );
+ }
+
+ osce_bwe(&psDec->osce_model, &channel_state[ n ].osce_bwe,
+ resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec, arch);
+
+ if (decControl->prev_osce_extended_mode == OSCE_MODE_SILK_ONLY ||
+ decControl->prev_osce_extended_mode == OSCE_MODE_HYBRID) {
+ /* cross-fade with upsampled signal */
+ silk_resampler( &channel_state[ n ].resampler_state, resamp_buffer, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec );
+ osce_bwe_cross_fade_10ms(resample_out_ptr, resamp_buffer, 480);
+ }
+ } else {
+ ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec );
+ if (decControl->prev_osce_extended_mode == OSCE_MODE_SILK_BBWE && decControl->internalSampleRate == 16000) {
+ /* fade out if internal sample rate did not change */
+ osce_bwe(&psDec->osce_model, &channel_state[ n ].osce_bwe,
+ resamp_buffer, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec, arch);
+ /* cross-fade with upsampled signal */
+ osce_bwe_cross_fade_10ms(resample_out_ptr, resamp_buffer, 480);
+ }
+ }
+#else
+ /* Resample decoded signal to API_sampleRate */
+ ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec );
+#endif
+ /* Interleave if stereo output and stereo stream */
+ if( decControl->nChannelsAPI == 2 ) {
+ for( i = 0; i < *nSamplesOut; i++ ) {
+ samplesOut[ n + 2 * i ] = INT16TORES(resample_out_ptr[ i ]);
+ }
+ } else {
+ for( i = 0; i < *nSamplesOut; i++ ) {
+ samplesOut[ i ] = INT16TORES(resample_out_ptr[ i ]);
+ }
+ }
+ }
+
+#ifdef ENABLE_OSCE_BWE
+ decControl->prev_osce_extended_mode = decControl->osce_extended_mode;
+#endif
+
+ /* Create two channel output from mono stream */
+ if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 1 ) {
+ if ( stereo_to_mono ){
+ /* Resample right channel for newly collapsed stereo just in case
+ we weren't doing collapsing when switching to mono */
+ ret += silk_resampler( &channel_state[ 1 ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ 0 ][ 1 ], nSamplesOutDec );
+
+ for( i = 0; i < *nSamplesOut; i++ ) {
+ samplesOut[ 1 + 2 * i ] = INT16TORES(resample_out_ptr[ i ]);
+ }
+ } else {
+ for( i = 0; i < *nSamplesOut; i++ ) {
+ samplesOut[ 1 + 2 * i ] = samplesOut[ 0 + 2 * i ];
+ }
+ }
+ }
+
+ /* Export pitch lag, measured at 48 kHz sampling rate */
+ if( channel_state[ 0 ].prevSignalType == TYPE_VOICED ) {
+ int mult_tab[ 3 ] = { 6, 4, 3 };
+ decControl->prevPitchLag = channel_state[ 0 ].lagPrev * mult_tab[ ( channel_state[ 0 ].fs_kHz - 8 ) >> 2 ];
+ } else {
+ decControl->prevPitchLag = 0;
+ }
+
+ if( lostFlag == FLAG_PACKET_LOST ) {
+ /* On packet loss, remove the gain clamping to prevent having the energy "bounce back"
+ if we lose packets when the energy is going down */
+ for ( i = 0; i < psDec->nChannelsInternal; i++ )
+ psDec->channel_state[ i ].LastGainIndex = 10;
+ } else {
+ psDec->prev_decode_only_middle = decode_only_middle;
+ }
+ RESTORE_STACK;
+ return ret;
+}
+
+#if 0
+/* Getting table of contents for a packet */
+opus_int silk_get_TOC(
+ const opus_uint8 *payload, /* I Payload data */
+ const opus_int nBytesIn, /* I Number of input bytes */
+ const opus_int nFramesPerPayload, /* I Number of SILK frames per payload */
+ silk_TOC_struct *Silk_TOC /* O Type of content */
+)
+{
+ opus_int i, flags, ret = SILK_NO_ERROR;
+
+ if( nBytesIn < 1 ) {
+ return -1;
+ }
+ if( nFramesPerPayload < 0 || nFramesPerPayload > 3 ) {
+ return -1;
+ }
+
+ silk_memset( Silk_TOC, 0, sizeof( *Silk_TOC ) );
+
+ /* For stereo, extract the flags for the mid channel */
+ flags = silk_RSHIFT( payload[ 0 ], 7 - nFramesPerPayload ) & ( silk_LSHIFT( 1, nFramesPerPayload + 1 ) - 1 );
+
+ Silk_TOC->inbandFECFlag = flags & 1;
+ for( i = nFramesPerPayload - 1; i >= 0 ; i-- ) {
+ flags = silk_RSHIFT( flags, 1 );
+ Silk_TOC->VADFlags[ i ] = flags & 1;
+ Silk_TOC->VADFlag |= flags & 1;
+ }
+
+ return ret;
+}
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "stack_alloc.h"
+
+/**********************************************************/
+/* Core decoder. Performs inverse NSQ operation LTP + LPC */
+/**********************************************************/
+void silk_decode_core(
+ silk_decoder_state *psDec, /* I/O Decoder state */
+ silk_decoder_control *psDecCtrl, /* I Decoder control */
+ opus_int16 xq[], /* O Decoded speech */
+ const opus_int16 pulses[ MAX_FRAME_LENGTH ], /* I Pulse signal */
+ int arch /* I Run-time architecture */
+)
+{
+ opus_int i, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType;
+ opus_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ];
+ VARDECL( opus_int16, sLTP );
+ VARDECL( opus_int32, sLTP_Q15 );
+ opus_int32 LTP_pred_Q13, LPC_pred_Q10, Gain_Q10, inv_gain_Q31, gain_adj_Q16, rand_seed, offset_Q10;
+ opus_int32 *pred_lag_ptr, *pexc_Q14, *pres_Q14;
+ VARDECL( opus_int32, res_Q14 );
+ VARDECL( opus_int32, sLPC_Q14 );
+ SAVE_STACK;
+
+ silk_assert( psDec->prev_gain_Q16 != 0 );
+
+ ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
+ ALLOC( sLTP_Q15, psDec->ltp_mem_length + psDec->frame_length, opus_int32 );
+ ALLOC( res_Q14, psDec->subfr_length, opus_int32 );
+ /* Work around a clang bug (verified with clang 6.0 through clang 20.1.0) that causes the last
+ memset to be flagged as an invalid read by valgrind (not caught by asan). */
+#if defined(__clang__) && defined(VAR_ARRAYS)
+ ALLOC( sLPC_Q14, MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER, opus_int32 );
+#else
+ ALLOC( sLPC_Q14, psDec->subfr_length + MAX_LPC_ORDER, opus_int32 );
+#endif
+
+ offset_Q10 = silk_Quantization_Offsets_Q10[ psDec->indices.signalType >> 1 ][ psDec->indices.quantOffsetType ];
+
+ if( psDec->indices.NLSFInterpCoef_Q2 < 1 << 2 ) {
+ NLSF_interpolation_flag = 1;
+ } else {
+ NLSF_interpolation_flag = 0;
+ }
+
+ /* Decode excitation */
+ rand_seed = psDec->indices.Seed;
+ for( i = 0; i < psDec->frame_length; i++ ) {
+ rand_seed = silk_RAND( rand_seed );
+ psDec->exc_Q14[ i ] = silk_LSHIFT( (opus_int32)pulses[ i ], 14 );
+ if( psDec->exc_Q14[ i ] > 0 ) {
+ psDec->exc_Q14[ i ] -= QUANT_LEVEL_ADJUST_Q10 << 4;
+ } else
+ if( psDec->exc_Q14[ i ] < 0 ) {
+ psDec->exc_Q14[ i ] += QUANT_LEVEL_ADJUST_Q10 << 4;
+ }
+ psDec->exc_Q14[ i ] += offset_Q10 << 4;
+ if( rand_seed < 0 ) {
+ psDec->exc_Q14[ i ] = -psDec->exc_Q14[ i ];
+ }
+
+ rand_seed = silk_ADD32_ovflw( rand_seed, pulses[ i ] );
+ }
+
+ /* Copy LPC state */
+ silk_memcpy( sLPC_Q14, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
+
+ pexc_Q14 = psDec->exc_Q14;
+ pxq = xq;
+ sLTP_buf_idx = psDec->ltp_mem_length;
+ /* Loop over subframes */
+ for( k = 0; k < psDec->nb_subfr; k++ ) {
+ pres_Q14 = res_Q14;
+ A_Q12 = psDecCtrl->PredCoef_Q12[ k >> 1 ];
+
+ /* Preload LPC coefficients to array on stack. Gives small performance gain */
+ silk_memcpy( A_Q12_tmp, A_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
+ B_Q14 = &psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER ];
+ signalType = psDec->indices.signalType;
+
+ Gain_Q10 = silk_RSHIFT( psDecCtrl->Gains_Q16[ k ], 6 );
+ inv_gain_Q31 = silk_INVERSE32_varQ( psDecCtrl->Gains_Q16[ k ], 47 );
+
+ /* Calculate gain adjustment factor */
+ if( psDecCtrl->Gains_Q16[ k ] != psDec->prev_gain_Q16 ) {
+ gain_adj_Q16 = silk_DIV32_varQ( psDec->prev_gain_Q16, psDecCtrl->Gains_Q16[ k ], 16 );
+
+ /* Scale short term state */
+ for( i = 0; i < MAX_LPC_ORDER; i++ ) {
+ sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, sLPC_Q14[ i ] );
+ }
+ } else {
+ gain_adj_Q16 = (opus_int32)1 << 16;
+ }
+
+ /* Save inv_gain */
+ silk_assert( inv_gain_Q31 != 0 );
+ psDec->prev_gain_Q16 = psDecCtrl->Gains_Q16[ k ];
+
+ /* Avoid abrupt transition from voiced PLC to unvoiced normal decoding */
+ if( psDec->lossCnt && psDec->prevSignalType == TYPE_VOICED &&
+ psDec->indices.signalType != TYPE_VOICED && k < MAX_NB_SUBFR/2 ) {
+
+ silk_memset( B_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
+ B_Q14[ LTP_ORDER/2 ] = SILK_FIX_CONST( 0.25, 14 );
+
+ signalType = TYPE_VOICED;
+ psDecCtrl->pitchL[ k ] = psDec->lagPrev;
+ }
+
+ if( signalType == TYPE_VOICED ) {
+ /* Voiced */
+ lag = psDecCtrl->pitchL[ k ];
+
+ /* Re-whitening */
+ if( k == 0 || ( k == 2 && NLSF_interpolation_flag ) ) {
+ /* Rewhiten with new A coefs */
+ start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
+ celt_assert( start_idx > 0 );
+
+ if( k == 2 ) {
+ silk_memcpy( &psDec->outBuf[ psDec->ltp_mem_length ], xq, 2 * psDec->subfr_length * sizeof( opus_int16 ) );
+ }
+
+ silk_LPC_analysis_filter( &sLTP[ start_idx ], &psDec->outBuf[ start_idx + k * psDec->subfr_length ],
+ A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order, arch );
+
+ /* After rewhitening the LTP state is unscaled */
+ if( k == 0 ) {
+ /* Do LTP downscaling to reduce inter-packet dependency */
+ inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, psDecCtrl->LTP_scale_Q14 ), 2 );
+ }
+ for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
+ sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWB( inv_gain_Q31, sLTP[ psDec->ltp_mem_length - i - 1 ] );
+ }
+ } else {
+ /* Update LTP state when Gain changes */
+ if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
+ for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
+ sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ sLTP_buf_idx - i - 1 ] );
+ }
+ }
+ }
+ }
+
+ /* Long-term prediction */
+ if( signalType == TYPE_VOICED ) {
+ /* Set up pointer */
+ pred_lag_ptr = &sLTP_Q15[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
+ for( i = 0; i < psDec->subfr_length; i++ ) {
+ /* Unrolled loop */
+ /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+ LTP_pred_Q13 = 2;
+ LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ 0 ], B_Q14[ 0 ] );
+ LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
+ LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
+ LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
+ LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
+ pred_lag_ptr++;
+
+ /* Generate LPC excitation */
+ pres_Q14[ i ] = silk_ADD_LSHIFT32( pexc_Q14[ i ], LTP_pred_Q13, 1 );
+
+ /* Update states */
+ sLTP_Q15[ sLTP_buf_idx ] = silk_LSHIFT( pres_Q14[ i ], 1 );
+ sLTP_buf_idx++;
+ }
+ } else {
+ pres_Q14 = pexc_Q14;
+ }
+
+ for( i = 0; i < psDec->subfr_length; i++ ) {
+ /* Short-term prediction */
+ celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
+ /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+ LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12_tmp[ 1 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp[ 2 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12_tmp[ 3 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12_tmp[ 4 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12_tmp[ 5 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12_tmp[ 6 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp[ 7 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12_tmp[ 8 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] );
+ if( psDec->LPC_order == 16 ) {
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12_tmp[ 10 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12_tmp[ 11 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12_tmp[ 12 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12_tmp[ 13 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12_tmp[ 14 ] );
+ LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12_tmp[ 15 ] );
+ }
+
+ /* Add prediction to LPC excitation */
+ sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( pres_Q14[ i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
+
+ /* Scale with gain */
+ pxq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) );
+ }
+
+ /* Update LPC filter state */
+ silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
+ pexc_Q14 += psDec->subfr_length;
+ pxq += psDec->subfr_length;
+ }
+
+ /* Save LPC state */
+ silk_memcpy( psDec->sLPC_Q14_buf, sLPC_Q14, MAX_LPC_ORDER * sizeof( opus_int32 ) );
+ RESTORE_STACK;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "stack_alloc.h"
+#include "PLC.h"
+
+#ifdef ENABLE_OSCE
+#include "osce.h"
+#endif
+
+/****************/
+/* Decode frame */
+/****************/
+opus_int silk_decode_frame(
+ silk_decoder_state *psDec, /* I/O Pointer to Silk decoder state */
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int16 pOut[], /* O Pointer to output speech frame */
+ opus_int32 *pN, /* O Pointer to size of output frame */
+ opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
+ opus_int condCoding, /* I The type of conditional coding to use */
+#ifdef ENABLE_DEEP_PLC
+ LPCNetPLCState *lpcnet,
+#endif
+#ifdef ENABLE_OSCE
+ OSCEModel *osce_model,
+#endif
+ int arch /* I Run-time architecture */
+)
+{
+ VARDECL( silk_decoder_control, psDecCtrl );
+ opus_int L, mv_len, ret = 0;
+ SAVE_STACK;
+
+ L = psDec->frame_length;
+ ALLOC( psDecCtrl, 1, silk_decoder_control );
+ psDecCtrl->LTP_scale_Q14 = 0;
+
+ /* Safety checks */
+ celt_assert( L > 0 && L <= MAX_FRAME_LENGTH );
+
+ if( lostFlag == FLAG_DECODE_NORMAL ||
+ ( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) )
+ {
+ VARDECL( opus_int16, pulses );
+#ifdef ENABLE_OSCE
+ opus_int32 ec_start;
+ ec_start = ec_tell(psRangeDec);
+#endif
+ ALLOC( pulses, (L + SHELL_CODEC_FRAME_LENGTH - 1) &
+ ~(SHELL_CODEC_FRAME_LENGTH - 1), opus_int16 );
+ /*********************************************/
+ /* Decode quantization indices of side info */
+ /*********************************************/
+ silk_decode_indices( psDec, psRangeDec, psDec->nFramesDecoded, lostFlag, condCoding );
+
+ /*********************************************/
+ /* Decode quantization indices of excitation */
+ /*********************************************/
+ silk_decode_pulses( psRangeDec, pulses, psDec->indices.signalType,
+ psDec->indices.quantOffsetType, psDec->frame_length );
+
+ /********************************************/
+ /* Decode parameters and pulse signal */
+ /********************************************/
+ silk_decode_parameters( psDec, psDecCtrl, condCoding );
+
+ /********************************************************/
+ /* Run inverse NSQ */
+ /********************************************************/
+ silk_decode_core( psDec, psDecCtrl, pOut, pulses, arch );
+
+ /*************************/
+ /* Update output buffer. */
+ /*************************/
+ celt_assert( psDec->ltp_mem_length >= psDec->frame_length );
+ mv_len = psDec->ltp_mem_length - psDec->frame_length;
+ silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
+ silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );
+
+#ifdef ENABLE_OSCE
+ /********************************************************/
+ /* Run SILK enhancer */
+ /********************************************************/
+ osce_enhance_frame( osce_model, psDec, psDecCtrl, pOut, ec_tell(psRangeDec) - ec_start, arch );
+#endif
+
+ /********************************************************/
+ /* Update PLC state */
+ /********************************************************/
+ silk_PLC( psDec, psDecCtrl, pOut, 0,
+#ifdef ENABLE_DEEP_PLC
+ lpcnet,
+#endif
+ arch );
+
+ psDec->lossCnt = 0;
+ psDec->prevSignalType = psDec->indices.signalType;
+ celt_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );
+
+ /* A frame has been decoded without errors */
+ psDec->first_frame_after_reset = 0;
+ } else {
+ /* Handle packet loss by extrapolation */
+ silk_PLC( psDec, psDecCtrl, pOut, 1,
+#ifdef ENABLE_DEEP_PLC
+ lpcnet,
+#endif
+ arch );
+
+#ifdef ENABLE_OSCE
+ osce_reset( &psDec->osce, psDec->osce.method );
+#endif
+ /*************************/
+ /* Update output buffer. */
+ /*************************/
+ celt_assert( psDec->ltp_mem_length >= psDec->frame_length );
+ mv_len = psDec->ltp_mem_length - psDec->frame_length;
+ silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
+ silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );
+ }
+
+ /************************************************/
+ /* Comfort noise generation / estimation */
+ /************************************************/
+ silk_CNG( psDec, psDecCtrl, pOut, L );
+
+ /****************************************************************/
+ /* Ensure smooth connection of extrapolated and good frames */
+ /****************************************************************/
+ silk_PLC_glue_frames( psDec, pOut, L );
+
+ /* Update some decoder state variables */
+ psDec->lagPrev = psDecCtrl->pitchL[ psDec->nb_subfr - 1 ];
+
+ /* Set output frame length */
+ *pN = L;
+
+ RESTORE_STACK;
+ return ret;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Decode side-information parameters from payload */
+void silk_decode_indices(
+ silk_decoder_state *psDec, /* I/O State */
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int FrameIndex, /* I Frame number */
+ opus_int decode_LBRR, /* I Flag indicating LBRR data is being decoded */
+ opus_int condCoding /* I The type of conditional coding to use */
+)
+{
+ opus_int i, k, Ix;
+ opus_int decode_absolute_lagIndex, delta_lagIndex;
+ opus_int16 ec_ix[ MAX_LPC_ORDER ];
+ opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
+
+ /*******************************************/
+ /* Decode signal type and quantizer offset */
+ /*******************************************/
+ if( decode_LBRR || psDec->VAD_flags[ FrameIndex ] ) {
+ Ix = ec_dec_icdf( psRangeDec, silk_type_offset_VAD_iCDF, 8 ) + 2;
+ } else {
+ Ix = ec_dec_icdf( psRangeDec, silk_type_offset_no_VAD_iCDF, 8 );
+ }
+ psDec->indices.signalType = (opus_int8)silk_RSHIFT( Ix, 1 );
+ psDec->indices.quantOffsetType = (opus_int8)( Ix & 1 );
+
+ /****************/
+ /* Decode gains */
+ /****************/
+ /* First subframe */
+ if( condCoding == CODE_CONDITIONALLY ) {
+ /* Conditional coding */
+ psDec->indices.GainsIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 );
+ } else {
+ /* Independent coding, in two stages: MSB bits followed by 3 LSBs */
+ psDec->indices.GainsIndices[ 0 ] = (opus_int8)silk_LSHIFT( ec_dec_icdf( psRangeDec, silk_gain_iCDF[ psDec->indices.signalType ], 8 ), 3 );
+ psDec->indices.GainsIndices[ 0 ] += (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform8_iCDF, 8 );
+ }
+
+ /* Remaining subframes */
+ for( i = 1; i < psDec->nb_subfr; i++ ) {
+ psDec->indices.GainsIndices[ i ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 );
+ }
+
+ /**********************/
+ /* Decode LSF Indices */
+ /**********************/
+ psDec->indices.NLSFIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 );
+ silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] );
+ celt_assert( psDec->psNLSF_CB->order == psDec->LPC_order );
+ for( i = 0; i < psDec->psNLSF_CB->order; i++ ) {
+ Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
+ if( Ix == 0 ) {
+ Ix -= ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 );
+ } else if( Ix == 2 * NLSF_QUANT_MAX_AMPLITUDE ) {
+ Ix += ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 );
+ }
+ psDec->indices.NLSFIndices[ i+1 ] = (opus_int8)( Ix - NLSF_QUANT_MAX_AMPLITUDE );
+ }
+
+ /* Decode LSF interpolation factor */
+ if( psDec->nb_subfr == MAX_NB_SUBFR ) {
+ psDec->indices.NLSFInterpCoef_Q2 = (opus_int8)ec_dec_icdf( psRangeDec, silk_NLSF_interpolation_factor_iCDF, 8 );
+ } else {
+ psDec->indices.NLSFInterpCoef_Q2 = 4;
+ }
+
+ if( psDec->indices.signalType == TYPE_VOICED )
+ {
+ /*********************/
+ /* Decode pitch lags */
+ /*********************/
+ /* Get lag index */
+ decode_absolute_lagIndex = 1;
+ if( condCoding == CODE_CONDITIONALLY && psDec->ec_prevSignalType == TYPE_VOICED ) {
+ /* Decode Delta index */
+ delta_lagIndex = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_delta_iCDF, 8 );
+ if( delta_lagIndex > 0 ) {
+ delta_lagIndex = delta_lagIndex - 9;
+ psDec->indices.lagIndex = (opus_int16)( psDec->ec_prevLagIndex + delta_lagIndex );
+ decode_absolute_lagIndex = 0;
+ }
+ }
+ if( decode_absolute_lagIndex ) {
+ /* Absolute decoding */
+ psDec->indices.lagIndex = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_lag_iCDF, 8 ) * silk_RSHIFT( psDec->fs_kHz, 1 );
+ psDec->indices.lagIndex += (opus_int16)ec_dec_icdf( psRangeDec, psDec->pitch_lag_low_bits_iCDF, 8 );
+ }
+ psDec->ec_prevLagIndex = psDec->indices.lagIndex;
+
+ /* Get contour index */
+ psDec->indices.contourIndex = (opus_int8)ec_dec_icdf( psRangeDec, psDec->pitch_contour_iCDF, 8 );
+
+ /********************/
+ /* Decode LTP gains */
+ /********************/
+ /* Decode PERIndex value */
+ psDec->indices.PERIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_per_index_iCDF, 8 );
+
+ for( k = 0; k < psDec->nb_subfr; k++ ) {
+ psDec->indices.LTPIndex[ k ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_gain_iCDF_ptrs[ psDec->indices.PERIndex ], 8 );
+ }
+
+ /**********************/
+ /* Decode LTP scaling */
+ /**********************/
+ if( condCoding == CODE_INDEPENDENTLY ) {
+ psDec->indices.LTP_scaleIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTPscale_iCDF, 8 );
+ } else {
+ psDec->indices.LTP_scaleIndex = 0;
+ }
+ }
+ psDec->ec_prevSignalType = psDec->indices.signalType;
+
+ /***************/
+ /* Decode seed */
+ /***************/
+ psDec->indices.Seed = (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform4_iCDF, 8 );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Decode parameters from payload */
+void silk_decode_parameters(
+ silk_decoder_state *psDec, /* I/O State */
+ silk_decoder_control *psDecCtrl, /* I/O Decoder control */
+ opus_int condCoding /* I The type of conditional coding to use */
+)
+{
+ opus_int i, k, Ix;
+ opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], pNLSF0_Q15[ MAX_LPC_ORDER ];
+ const opus_int8 *cbk_ptr_Q7;
+
+ /* Dequant Gains */
+ silk_gains_dequant( psDecCtrl->Gains_Q16, psDec->indices.GainsIndices,
+ &psDec->LastGainIndex, condCoding == CODE_CONDITIONALLY, psDec->nb_subfr );
+
+ /****************/
+ /* Decode NLSFs */
+ /****************/
+ silk_NLSF_decode( pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB );
+
+ /* Convert NLSF parameters to AR prediction filter coefficients */
+ silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order, psDec->arch );
+
+ /* If just reset, e.g., because internal Fs changed, do not allow interpolation */
+ /* improves the case of packet loss in the first frame after a switch */
+ if( psDec->first_frame_after_reset == 1 ) {
+ psDec->indices.NLSFInterpCoef_Q2 = 4;
+ }
+
+ if( psDec->indices.NLSFInterpCoef_Q2 < 4 ) {
+ /* Calculation of the interpolated NLSF0 vector from the interpolation factor, */
+ /* the previous NLSF1, and the current NLSF1 */
+ for( i = 0; i < psDec->LPC_order; i++ ) {
+ pNLSF0_Q15[ i ] = psDec->prevNLSF_Q15[ i ] + silk_RSHIFT( silk_MUL( psDec->indices.NLSFInterpCoef_Q2,
+ pNLSF_Q15[ i ] - psDec->prevNLSF_Q15[ i ] ), 2 );
+ }
+
+ /* Convert NLSF parameters to AR prediction filter coefficients */
+ silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order, psDec->arch );
+ } else {
+ /* Copy LPC coefficients for first half from second half */
+ silk_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
+ }
+
+ silk_memcpy( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( opus_int16 ) );
+
+ /* After a packet loss do BWE of LPC coefs */
+ if( psDec->lossCnt ) {
+ silk_bwexpander( psDecCtrl->PredCoef_Q12[ 0 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 );
+ silk_bwexpander( psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 );
+ }
+
+ if( psDec->indices.signalType == TYPE_VOICED ) {
+ /*********************/
+ /* Decode pitch lags */
+ /*********************/
+
+ /* Decode pitch values */
+ silk_decode_pitch( psDec->indices.lagIndex, psDec->indices.contourIndex, psDecCtrl->pitchL, psDec->fs_kHz, psDec->nb_subfr );
+
+ /* Decode Codebook Index */
+ cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ psDec->indices.PERIndex ]; /* set pointer to start of codebook */
+
+ for( k = 0; k < psDec->nb_subfr; k++ ) {
+ Ix = psDec->indices.LTPIndex[ k ];
+ for( i = 0; i < LTP_ORDER; i++ ) {
+ psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER + i ] = silk_LSHIFT( cbk_ptr_Q7[ Ix * LTP_ORDER + i ], 7 );
+ }
+ }
+
+ /**********************/
+ /* Decode LTP scaling */
+ /**********************/
+ Ix = psDec->indices.LTP_scaleIndex;
+ psDecCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ Ix ];
+ } else {
+ silk_memset( psDecCtrl->pitchL, 0, psDec->nb_subfr * sizeof( opus_int ) );
+ silk_memset( psDecCtrl->LTPCoef_Q14, 0, LTP_ORDER * psDec->nb_subfr * sizeof( opus_int16 ) );
+ psDec->indices.PERIndex = 0;
+ psDecCtrl->LTP_scale_Q14 = 0;
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/***********************************************************
+* Pitch analyser function
+********************************************************** */
+#include "SigProc_FIX.h"
+#include "pitch_est_defines.h"
+
+void silk_decode_pitch(
+ opus_int16 lagIndex, /* I */
+ opus_int8 contourIndex, /* O */
+ opus_int pitch_lags[], /* O 4 pitch values */
+ const opus_int Fs_kHz, /* I sampling frequency (kHz) */
+ const opus_int nb_subfr /* I number of sub frames */
+)
+{
+ opus_int lag, k, min_lag, max_lag, cbk_size;
+ const opus_int8 *Lag_CB_ptr;
+
+ if( Fs_kHz == 8 ) {
+ if( nb_subfr == PE_MAX_NB_SUBFR ) {
+ Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
+ cbk_size = PE_NB_CBKS_STAGE2_EXT;
+ } else {
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
+ Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ];
+ cbk_size = PE_NB_CBKS_STAGE2_10MS;
+ }
+ } else {
+ if( nb_subfr == PE_MAX_NB_SUBFR ) {
+ Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
+ cbk_size = PE_NB_CBKS_STAGE3_MAX;
+ } else {
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
+ Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
+ cbk_size = PE_NB_CBKS_STAGE3_10MS;
+ }
+ }
+
+ min_lag = silk_SMULBB( PE_MIN_LAG_MS, Fs_kHz );
+ max_lag = silk_SMULBB( PE_MAX_LAG_MS, Fs_kHz );
+ lag = min_lag + lagIndex;
+
+ for( k = 0; k < nb_subfr; k++ ) {
+ pitch_lags[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, contourIndex, cbk_size );
+ pitch_lags[ k ] = silk_LIMIT( pitch_lags[ k ], min_lag, max_lag );
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/*********************************************/
+/* Decode quantization indices of excitation */
+/*********************************************/
+void silk_decode_pulses(
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int16 pulses[], /* O Excitation signal */
+ const opus_int signalType, /* I Sigtype */
+ const opus_int quantOffsetType, /* I quantOffsetType */
+ const opus_int frame_length /* I Frame length */
+)
+{
+ opus_int i, j, k, iter, abs_q, nLS, RateLevelIndex;
+ opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ], nLshifts[ MAX_NB_SHELL_BLOCKS ];
+ opus_int16 *pulses_ptr;
+ const opus_uint8 *cdf_ptr;
+
+ /*********************/
+ /* Decode rate level */
+ /*********************/
+ RateLevelIndex = ec_dec_icdf( psRangeDec, silk_rate_levels_iCDF[ signalType >> 1 ], 8 );
+
+ /* Calculate number of shell blocks */
+ silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
+ iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
+ if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) {
+ celt_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
+ iter++;
+ }
+
+ /***************************************************/
+ /* Sum-Weighted-Pulses Decoding */
+ /***************************************************/
+ cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ];
+ for( i = 0; i < iter; i++ ) {
+ nLshifts[ i ] = 0;
+ sum_pulses[ i ] = ec_dec_icdf( psRangeDec, cdf_ptr, 8 );
+
+ /* LSB indication */
+ while( sum_pulses[ i ] == SILK_MAX_PULSES + 1 ) {
+ nLshifts[ i ]++;
+ /* When we've already got 10 LSBs, we shift the table to not allow (SILK_MAX_PULSES + 1) */
+ sum_pulses[ i ] = ec_dec_icdf( psRangeDec,
+ silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1] + ( nLshifts[ i ] == 10 ), 8 );
+ }
+ }
+
+ /***************************************************/
+ /* Shell decoding */
+ /***************************************************/
+ for( i = 0; i < iter; i++ ) {
+ if( sum_pulses[ i ] > 0 ) {
+ silk_shell_decoder( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], psRangeDec, sum_pulses[ i ] );
+ } else {
+ silk_memset( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof( pulses[0] ) );
+ }
+ }
+
+ /***************************************************/
+ /* LSB Decoding */
+ /***************************************************/
+ for( i = 0; i < iter; i++ ) {
+ if( nLshifts[ i ] > 0 ) {
+ nLS = nLshifts[ i ];
+ pulses_ptr = &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ];
+ for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) {
+ abs_q = pulses_ptr[ k ];
+ for( j = 0; j < nLS; j++ ) {
+ abs_q = silk_LSHIFT( abs_q, 1 );
+ abs_q += ec_dec_icdf( psRangeDec, silk_lsb_iCDF, 8 );
+ }
+ pulses_ptr[ k ] = abs_q;
+ }
+ /* Mark the number of pulses non-zero for sign decoding. */
+ sum_pulses[ i ] |= nLS << 5;
+ }
+ }
+
+ /****************************************/
+ /* Decode and add signs to pulse signal */
+ /****************************************/
+ silk_decode_signs( psRangeDec, pulses, frame_length, signalType, quantOffsetType, sum_pulses );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Set decoder sampling rate */
+opus_int silk_decoder_set_fs(
+ silk_decoder_state *psDec, /* I/O Decoder state pointer */
+ opus_int fs_kHz, /* I Sampling frequency (kHz) */
+ opus_int32 fs_API_Hz /* I API Sampling frequency (Hz) */
+)
+{
+ opus_int frame_length, ret = 0;
+
+ celt_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
+ celt_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 );
+
+ /* New (sub)frame length */
+ psDec->subfr_length = silk_SMULBB( SUB_FRAME_LENGTH_MS, fs_kHz );
+ frame_length = silk_SMULBB( psDec->nb_subfr, psDec->subfr_length );
+
+ /* Initialize resampler when switching internal or external sampling frequency */
+ if( psDec->fs_kHz != fs_kHz || psDec->fs_API_hz != fs_API_Hz ) {
+ /* Initialize the resampler for dec_API.c preparing resampling from fs_kHz to API_fs_Hz */
+ ret += silk_resampler_init( &psDec->resampler_state, silk_SMULBB( fs_kHz, 1000 ), fs_API_Hz, 0 );
+
+ psDec->fs_API_hz = fs_API_Hz;
+ }
+
+ if( psDec->fs_kHz != fs_kHz || frame_length != psDec->frame_length ) {
+ if( fs_kHz == 8 ) {
+ if( psDec->nb_subfr == MAX_NB_SUBFR ) {
+ psDec->pitch_contour_iCDF = silk_pitch_contour_NB_iCDF;
+ } else {
+ psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF;
+ }
+ } else {
+ if( psDec->nb_subfr == MAX_NB_SUBFR ) {
+ psDec->pitch_contour_iCDF = silk_pitch_contour_iCDF;
+ } else {
+ psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF;
+ }
+ }
+ if( psDec->fs_kHz != fs_kHz ) {
+ psDec->ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz );
+ if( fs_kHz == 8 || fs_kHz == 12 ) {
+ psDec->LPC_order = MIN_LPC_ORDER;
+ psDec->psNLSF_CB = &silk_NLSF_CB_NB_MB;
+ } else {
+ psDec->LPC_order = MAX_LPC_ORDER;
+ psDec->psNLSF_CB = &silk_NLSF_CB_WB;
+ }
+ if( fs_kHz == 16 ) {
+ psDec->pitch_lag_low_bits_iCDF = silk_uniform8_iCDF;
+ } else if( fs_kHz == 12 ) {
+ psDec->pitch_lag_low_bits_iCDF = silk_uniform6_iCDF;
+ } else if( fs_kHz == 8 ) {
+ psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
+ } else {
+ /* unsupported sampling rate */
+ celt_assert( 0 );
+ }
+ psDec->first_frame_after_reset = 1;
+ psDec->lagPrev = 100;
+ psDec->LastGainIndex = 10;
+ psDec->prevSignalType = TYPE_NO_VOICE_ACTIVITY;
+ silk_memset( psDec->outBuf, 0, sizeof(psDec->outBuf));
+ silk_memset( psDec->sLPC_Q14_buf, 0, sizeof(psDec->sLPC_Q14_buf) );
+ }
+
+ psDec->fs_kHz = fs_kHz;
+ psDec->frame_length = frame_length;
+ }
+
+ /* Check that settings are valid */
+ celt_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
+
+ return ret;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_DEFINE_H
+#define SILK_DEFINE_H
+
+#include "errors.h"
+#include "typedef.h"
+
+
+/* Max number of encoder channels (1/2) */
+#define ENCODER_NUM_CHANNELS 2
+/* Number of decoder channels (1/2) */
+#define DECODER_NUM_CHANNELS 2
+
+#define MAX_FRAMES_PER_PACKET 3
+
+/* Limits on bitrate */
+#define MIN_TARGET_RATE_BPS 5000
+#define MAX_TARGET_RATE_BPS 80000
+
+/* LBRR thresholds */
+#define LBRR_NB_MIN_RATE_BPS 12000
+#define LBRR_MB_MIN_RATE_BPS 14000
+#define LBRR_WB_MIN_RATE_BPS 16000
+
+/* DTX settings */
+#define NB_SPEECH_FRAMES_BEFORE_DTX 10 /* eq 200 ms */
+#define MAX_CONSECUTIVE_DTX 20 /* eq 400 ms */
+#define DTX_ACTIVITY_THRESHOLD 0.1f
+
+/* VAD decision */
+#define VAD_NO_DECISION -1
+#define VAD_NO_ACTIVITY 0
+#define VAD_ACTIVITY 1
+
+/* Maximum sampling frequency */
+#define MAX_FS_KHZ 16
+#ifdef ENABLE_QEXT
+#define MAX_API_FS_KHZ 96
+#else
+#define MAX_API_FS_KHZ 48
+#endif
+
+/* Signal types */
+#define TYPE_NO_VOICE_ACTIVITY 0
+#define TYPE_UNVOICED 1
+#define TYPE_VOICED 2
+
+/* Conditional coding types */
+#define CODE_INDEPENDENTLY 0
+#define CODE_INDEPENDENTLY_NO_LTP_SCALING 1
+#define CODE_CONDITIONALLY 2
+
+/* Settings for stereo processing */
+#define STEREO_QUANT_TAB_SIZE 16
+#define STEREO_QUANT_SUB_STEPS 5
+#define STEREO_INTERP_LEN_MS 8 /* must be even */
+#define STEREO_RATIO_SMOOTH_COEF 0.01 /* smoothing coef for signal norms and stereo width */
+
+/* Range of pitch lag estimates */
+#define PITCH_EST_MIN_LAG_MS 2 /* 2 ms -> 500 Hz */
+#define PITCH_EST_MAX_LAG_MS 18 /* 18 ms -> 56 Hz */
+
+/* Maximum number of subframes */
+#define MAX_NB_SUBFR 4
+
+/* Number of samples per frame */
+#define LTP_MEM_LENGTH_MS 20
+#define SUB_FRAME_LENGTH_MS 5
+#define MAX_SUB_FRAME_LENGTH ( SUB_FRAME_LENGTH_MS * MAX_FS_KHZ )
+#define MAX_FRAME_LENGTH_MS ( SUB_FRAME_LENGTH_MS * MAX_NB_SUBFR )
+#define MAX_FRAME_LENGTH ( MAX_FRAME_LENGTH_MS * MAX_FS_KHZ )
+
+/* Milliseconds of lookahead for pitch analysis */
+#define LA_PITCH_MS 2
+#define LA_PITCH_MAX ( LA_PITCH_MS * MAX_FS_KHZ )
+
+/* Order of LPC used in find pitch */
+#define MAX_FIND_PITCH_LPC_ORDER 16
+
+/* Length of LPC window used in find pitch */
+#define FIND_PITCH_LPC_WIN_MS ( 20 + (LA_PITCH_MS << 1) )
+#define FIND_PITCH_LPC_WIN_MS_2_SF ( 10 + (LA_PITCH_MS << 1) )
+#define FIND_PITCH_LPC_WIN_MAX ( FIND_PITCH_LPC_WIN_MS * MAX_FS_KHZ )
+
+/* Milliseconds of lookahead for noise shape analysis */
+#define LA_SHAPE_MS 5
+#define LA_SHAPE_MAX ( LA_SHAPE_MS * MAX_FS_KHZ )
+
+/* Maximum length of LPC window used in noise shape analysis */
+#define SHAPE_LPC_WIN_MAX ( 15 * MAX_FS_KHZ )
+
+/* dB level of lowest gain quantization level */
+#define MIN_QGAIN_DB 2
+/* dB level of highest gain quantization level */
+#define MAX_QGAIN_DB 88
+/* Number of gain quantization levels */
+#define N_LEVELS_QGAIN 64
+/* Max increase in gain quantization index */
+#define MAX_DELTA_GAIN_QUANT 36
+/* Max decrease in gain quantization index */
+#define MIN_DELTA_GAIN_QUANT -4
+
+/* Quantization offsets (multiples of 4) */
+#define OFFSET_VL_Q10 32
+#define OFFSET_VH_Q10 100
+#define OFFSET_UVL_Q10 100
+#define OFFSET_UVH_Q10 240
+
+#define QUANT_LEVEL_ADJUST_Q10 80
+
+/* Maximum numbers of iterations used to stabilize an LPC vector */
+#define MAX_LPC_STABILIZE_ITERATIONS 16
+#define MAX_PREDICTION_POWER_GAIN 1e4f
+#define MAX_PREDICTION_POWER_GAIN_AFTER_RESET 1e2f
+
+#define MAX_LPC_ORDER 16
+#define MIN_LPC_ORDER 10
+
+/* Find Pred Coef defines */
+#define LTP_ORDER 5
+
+/* LTP quantization settings */
+#define NB_LTP_CBKS 3
+
+/* Flag to use harmonic noise shaping */
+#define USE_HARM_SHAPING 1
+
+/* Max LPC order of noise shaping filters */
+#define MAX_SHAPE_LPC_ORDER 24
+
+#define HARM_SHAPE_FIR_TAPS 3
+
+/* Maximum number of delayed decision states */
+#define MAX_DEL_DEC_STATES 4
+
+#define LTP_BUF_LENGTH 512
+#define LTP_MASK ( LTP_BUF_LENGTH - 1 )
+
+#define DECISION_DELAY 40
+
+/* Number of subframes for excitation entropy coding */
+#define SHELL_CODEC_FRAME_LENGTH 16
+#define LOG2_SHELL_CODEC_FRAME_LENGTH 4
+#define MAX_NB_SHELL_BLOCKS ( MAX_FRAME_LENGTH / SHELL_CODEC_FRAME_LENGTH )
+
+/* Number of rate levels, for entropy coding of excitation */
+#define N_RATE_LEVELS 10
+
+/* Maximum sum of pulses per shell coding frame */
+#define SILK_MAX_PULSES 16
+
+#define MAX_MATRIX_SIZE MAX_LPC_ORDER /* Max of LPC Order and LTP order */
+
+# define NSQ_LPC_BUF_LENGTH MAX_LPC_ORDER
+
+/***************************/
+/* Voice activity detector */
+/***************************/
+#define VAD_N_BANDS 4
+
+#define VAD_INTERNAL_SUBFRAMES_LOG2 2
+#define VAD_INTERNAL_SUBFRAMES ( 1 << VAD_INTERNAL_SUBFRAMES_LOG2 )
+
+#define VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 1024 /* Must be < 4096 */
+#define VAD_NOISE_LEVELS_BIAS 50
+
+/* Sigmoid settings */
+#define VAD_NEGATIVE_OFFSET_Q5 128 /* sigmoid is 0 at -128 */
+#define VAD_SNR_FACTOR_Q16 45000
+
+/* smoothing for SNR measurement */
+#define VAD_SNR_SMOOTH_COEF_Q18 4096
+
+/* Size of the piecewise linear cosine approximation table for the LSFs */
+#define LSF_COS_TAB_SZ_FIX 128
+
+/******************/
+/* NLSF quantizer */
+/******************/
+#define NLSF_W_Q 2
+#define NLSF_VQ_MAX_VECTORS 32
+#define NLSF_QUANT_MAX_AMPLITUDE 4
+#define NLSF_QUANT_MAX_AMPLITUDE_EXT 10
+#define NLSF_QUANT_LEVEL_ADJ 0.1
+#define NLSF_QUANT_DEL_DEC_STATES_LOG2 2
+#define NLSF_QUANT_DEL_DEC_STATES ( 1 << NLSF_QUANT_DEL_DEC_STATES_LOG2 )
+
+/* Transition filtering for mode switching */
+#define TRANSITION_TIME_MS 5120 /* 5120 = 64 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 64*(20*4)*/
+#define TRANSITION_NB 3 /* Hardcoded in tables */
+#define TRANSITION_NA 2 /* Hardcoded in tables */
+#define TRANSITION_INT_NUM 5 /* Hardcoded in tables */
+#define TRANSITION_FRAMES ( TRANSITION_TIME_MS / MAX_FRAME_LENGTH_MS )
+#define TRANSITION_INT_STEPS ( TRANSITION_FRAMES / ( TRANSITION_INT_NUM - 1 ) )
+
+/* BWE factors to apply after packet loss */
+#define BWE_AFTER_LOSS_Q16 63570
+
+/* Defines for CN generation */
+#define CNG_BUF_MASK_MAX 255 /* 2^floor(log2(MAX_FRAME_LENGTH))-1 */
+#define CNG_GAIN_SMTH_Q16 4634 /* 0.25^(1/4) */
+#define CNG_GAIN_SMTH_THRESHOLD_Q16 46396 /* -3 dB */
+#define CNG_NLSF_SMTH_Q16 16348 /* 0.25 */
+
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_ERRORS_H
+#define SILK_ERRORS_H
+
+
+/******************/
+/* Error messages */
+/******************/
+#define SILK_NO_ERROR 0
+
+/**************************/
+/* Encoder error messages */
+/**************************/
+
+/* Input length is not a multiple of 10 ms, or length is longer than the packet length */
+#define SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES -101
+
+/* Sampling frequency not 8000, 12000 or 16000 Hertz */
+#define SILK_ENC_FS_NOT_SUPPORTED -102
+
+/* Packet size not 10, 20, 40, or 60 ms */
+#define SILK_ENC_PACKET_SIZE_NOT_SUPPORTED -103
+
+/* Allocated payload buffer too short */
+#define SILK_ENC_PAYLOAD_BUF_TOO_SHORT -104
+
+/* Loss rate not between 0 and 100 percent */
+#define SILK_ENC_INVALID_LOSS_RATE -105
+
+/* Complexity setting not valid, use 0...10 */
+#define SILK_ENC_INVALID_COMPLEXITY_SETTING -106
+
+/* Inband FEC setting not valid, use 0 or 1 */
+#define SILK_ENC_INVALID_INBAND_FEC_SETTING -107
+
+/* DTX setting not valid, use 0 or 1 */
+#define SILK_ENC_INVALID_DTX_SETTING -108
+
+/* CBR setting not valid, use 0 or 1 */
+#define SILK_ENC_INVALID_CBR_SETTING -109
+
+/* Internal encoder error */
+#define SILK_ENC_INTERNAL_ERROR -110
+
+/* Internal encoder error */
+#define SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR -111
+
+/**************************/
+/* Decoder error messages */
+/**************************/
+
+/* Output sampling frequency lower than internal decoded sampling frequency */
+#define SILK_DEC_INVALID_SAMPLING_FREQUENCY -200
+
+/* Payload size exceeded the maximum allowed 1024 bytes */
+#define SILK_DEC_PAYLOAD_TOO_LARGE -201
+
+/* Payload has bit errors */
+#define SILK_DEC_PAYLOAD_ERROR -202
+
+/* Payload has bit errors */
+#define SILK_DEC_INVALID_FRAME_SIZE -203
+
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include "main_FLP.h"
+
+/************************************************/
+/* LPC analysis filter */
+/* NB! State is kept internally and the */
+/* filter always starts with zero state */
+/* first Order output samples are set to zero */
+/************************************************/
+
+/* 16th order LPC analysis filter, does not write first 16 samples */
+static OPUS_INLINE void silk_LPC_analysis_filter16_FLP(
+ silk_float r_LPC[], /* O LPC residual signal */
+ const silk_float PredCoef[], /* I LPC coefficients */
+ const silk_float s[], /* I Input signal */
+ const opus_int length /* I Length of input signal */
+)
+{
+ opus_int ix;
+ silk_float LPC_pred;
+ const silk_float *s_ptr;
+
+ for( ix = 16; ix < length; ix++ ) {
+ s_ptr = &s[ix - 1];
+
+ /* short-term prediction */
+ LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] +
+ s_ptr[ -1 ] * PredCoef[ 1 ] +
+ s_ptr[ -2 ] * PredCoef[ 2 ] +
+ s_ptr[ -3 ] * PredCoef[ 3 ] +
+ s_ptr[ -4 ] * PredCoef[ 4 ] +
+ s_ptr[ -5 ] * PredCoef[ 5 ] +
+ s_ptr[ -6 ] * PredCoef[ 6 ] +
+ s_ptr[ -7 ] * PredCoef[ 7 ] +
+ s_ptr[ -8 ] * PredCoef[ 8 ] +
+ s_ptr[ -9 ] * PredCoef[ 9 ] +
+ s_ptr[ -10 ] * PredCoef[ 10 ] +
+ s_ptr[ -11 ] * PredCoef[ 11 ] +
+ s_ptr[ -12 ] * PredCoef[ 12 ] +
+ s_ptr[ -13 ] * PredCoef[ 13 ] +
+ s_ptr[ -14 ] * PredCoef[ 14 ] +
+ s_ptr[ -15 ] * PredCoef[ 15 ];
+
+ /* prediction error */
+ r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
+ }
+}
+
+/* 12th order LPC analysis filter, does not write first 12 samples */
+static OPUS_INLINE void silk_LPC_analysis_filter12_FLP(
+ silk_float r_LPC[], /* O LPC residual signal */
+ const silk_float PredCoef[], /* I LPC coefficients */
+ const silk_float s[], /* I Input signal */
+ const opus_int length /* I Length of input signal */
+)
+{
+ opus_int ix;
+ silk_float LPC_pred;
+ const silk_float *s_ptr;
+
+ for( ix = 12; ix < length; ix++ ) {
+ s_ptr = &s[ix - 1];
+
+ /* short-term prediction */
+ LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] +
+ s_ptr[ -1 ] * PredCoef[ 1 ] +
+ s_ptr[ -2 ] * PredCoef[ 2 ] +
+ s_ptr[ -3 ] * PredCoef[ 3 ] +
+ s_ptr[ -4 ] * PredCoef[ 4 ] +
+ s_ptr[ -5 ] * PredCoef[ 5 ] +
+ s_ptr[ -6 ] * PredCoef[ 6 ] +
+ s_ptr[ -7 ] * PredCoef[ 7 ] +
+ s_ptr[ -8 ] * PredCoef[ 8 ] +
+ s_ptr[ -9 ] * PredCoef[ 9 ] +
+ s_ptr[ -10 ] * PredCoef[ 10 ] +
+ s_ptr[ -11 ] * PredCoef[ 11 ];
+
+ /* prediction error */
+ r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
+ }
+}
+
+/* 10th order LPC analysis filter, does not write first 10 samples */
+static OPUS_INLINE void silk_LPC_analysis_filter10_FLP(
+ silk_float r_LPC[], /* O LPC residual signal */
+ const silk_float PredCoef[], /* I LPC coefficients */
+ const silk_float s[], /* I Input signal */
+ const opus_int length /* I Length of input signal */
+)
+{
+ opus_int ix;
+ silk_float LPC_pred;
+ const silk_float *s_ptr;
+
+ for( ix = 10; ix < length; ix++ ) {
+ s_ptr = &s[ix - 1];
+
+ /* short-term prediction */
+ LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] +
+ s_ptr[ -1 ] * PredCoef[ 1 ] +
+ s_ptr[ -2 ] * PredCoef[ 2 ] +
+ s_ptr[ -3 ] * PredCoef[ 3 ] +
+ s_ptr[ -4 ] * PredCoef[ 4 ] +
+ s_ptr[ -5 ] * PredCoef[ 5 ] +
+ s_ptr[ -6 ] * PredCoef[ 6 ] +
+ s_ptr[ -7 ] * PredCoef[ 7 ] +
+ s_ptr[ -8 ] * PredCoef[ 8 ] +
+ s_ptr[ -9 ] * PredCoef[ 9 ];
+
+ /* prediction error */
+ r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
+ }
+}
+
+/* 8th order LPC analysis filter, does not write first 8 samples */
+static OPUS_INLINE void silk_LPC_analysis_filter8_FLP(
+ silk_float r_LPC[], /* O LPC residual signal */
+ const silk_float PredCoef[], /* I LPC coefficients */
+ const silk_float s[], /* I Input signal */
+ const opus_int length /* I Length of input signal */
+)
+{
+ opus_int ix;
+ silk_float LPC_pred;
+ const silk_float *s_ptr;
+
+ for( ix = 8; ix < length; ix++ ) {
+ s_ptr = &s[ix - 1];
+
+ /* short-term prediction */
+ LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] +
+ s_ptr[ -1 ] * PredCoef[ 1 ] +
+ s_ptr[ -2 ] * PredCoef[ 2 ] +
+ s_ptr[ -3 ] * PredCoef[ 3 ] +
+ s_ptr[ -4 ] * PredCoef[ 4 ] +
+ s_ptr[ -5 ] * PredCoef[ 5 ] +
+ s_ptr[ -6 ] * PredCoef[ 6 ] +
+ s_ptr[ -7 ] * PredCoef[ 7 ];
+
+ /* prediction error */
+ r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
+ }
+}
+
+/* 6th order LPC analysis filter, does not write first 6 samples */
+static OPUS_INLINE void silk_LPC_analysis_filter6_FLP(
+ silk_float r_LPC[], /* O LPC residual signal */
+ const silk_float PredCoef[], /* I LPC coefficients */
+ const silk_float s[], /* I Input signal */
+ const opus_int length /* I Length of input signal */
+)
+{
+ opus_int ix;
+ silk_float LPC_pred;
+ const silk_float *s_ptr;
+
+ for( ix = 6; ix < length; ix++ ) {
+ s_ptr = &s[ix - 1];
+
+ /* short-term prediction */
+ LPC_pred = s_ptr[ 0 ] * PredCoef[ 0 ] +
+ s_ptr[ -1 ] * PredCoef[ 1 ] +
+ s_ptr[ -2 ] * PredCoef[ 2 ] +
+ s_ptr[ -3 ] * PredCoef[ 3 ] +
+ s_ptr[ -4 ] * PredCoef[ 4 ] +
+ s_ptr[ -5 ] * PredCoef[ 5 ];
+
+ /* prediction error */
+ r_LPC[ix] = s_ptr[ 1 ] - LPC_pred;
+ }
+}
+
+/************************************************/
+/* LPC analysis filter */
+/* NB! State is kept internally and the */
+/* filter always starts with zero state */
+/* first Order output samples are set to zero */
+/************************************************/
+void silk_LPC_analysis_filter_FLP(
+ silk_float r_LPC[], /* O LPC residual signal */
+ const silk_float PredCoef[], /* I LPC coefficients */
+ const silk_float s[], /* I Input signal */
+ const opus_int length, /* I Length of input signal */
+ const opus_int Order /* I LPC order */
+)
+{
+ celt_assert( Order <= length );
+
+ switch( Order ) {
+ case 6:
+ silk_LPC_analysis_filter6_FLP( r_LPC, PredCoef, s, length );
+ break;
+
+ case 8:
+ silk_LPC_analysis_filter8_FLP( r_LPC, PredCoef, s, length );
+ break;
+
+ case 10:
+ silk_LPC_analysis_filter10_FLP( r_LPC, PredCoef, s, length );
+ break;
+
+ case 12:
+ silk_LPC_analysis_filter12_FLP( r_LPC, PredCoef, s, length );
+ break;
+
+ case 16:
+ silk_LPC_analysis_filter16_FLP( r_LPC, PredCoef, s, length );
+ break;
+
+ default:
+ celt_assert( 0 );
+ break;
+ }
+
+ /* Set first Order output samples to zero */
+ silk_memset( r_LPC, 0, Order * sizeof( silk_float ) );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "SigProc_FLP.h"
+#include "define.h"
+
+/* compute inverse of LPC prediction gain, and */
+/* test if LPC coefficients are stable (all poles within unit circle) */
+/* this code is based on silk_a2k_FLP() */
+silk_float silk_LPC_inverse_pred_gain_FLP( /* O return inverse prediction gain, energy domain */
+ const silk_float *A, /* I prediction coefficients [order] */
+ opus_int32 order /* I prediction order */
+)
+{
+ opus_int k, n;
+ double invGain, rc, rc_mult1, rc_mult2, tmp1, tmp2;
+ silk_float Atmp[ SILK_MAX_ORDER_LPC ];
+
+ silk_memcpy( Atmp, A, order * sizeof(silk_float) );
+
+ invGain = 1.0;
+ for( k = order - 1; k > 0; k-- ) {
+ rc = -Atmp[ k ];
+ rc_mult1 = 1.0f - rc * rc;
+ invGain *= rc_mult1;
+ if( invGain * MAX_PREDICTION_POWER_GAIN < 1.0f ) {
+ return 0.0f;
+ }
+ rc_mult2 = 1.0f / rc_mult1;
+ for( n = 0; n < (k + 1) >> 1; n++ ) {
+ tmp1 = Atmp[ n ];
+ tmp2 = Atmp[ k - n - 1 ];
+ Atmp[ n ] = (silk_float)( ( tmp1 - tmp2 * rc ) * rc_mult2 );
+ Atmp[ k - n - 1 ] = (silk_float)( ( tmp2 - tmp1 * rc ) * rc_mult2 );
+ }
+ }
+ rc = -Atmp[ 0 ];
+ rc_mult1 = 1.0f - rc * rc;
+ invGain *= rc_mult1;
+ if( invGain * MAX_PREDICTION_POWER_GAIN < 1.0f ) {
+ return 0.0f;
+ }
+ return (silk_float)invGain;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+void silk_LTP_analysis_filter_FLP(
+ silk_float *LTP_res, /* O LTP res MAX_NB_SUBFR*(pre_lgth+subfr_lngth) */
+ const silk_float *x, /* I Input signal, with preceding samples */
+ const silk_float B[ LTP_ORDER * MAX_NB_SUBFR ], /* I LTP coefficients for each subframe */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const silk_float invGains[ MAX_NB_SUBFR ], /* I Inverse quantization gains */
+ const opus_int subfr_length, /* I Length of each subframe */
+ const opus_int nb_subfr, /* I number of subframes */
+ const opus_int pre_length /* I Preceding samples for each subframe */
+)
+{
+ const silk_float *x_ptr, *x_lag_ptr;
+ silk_float Btmp[ LTP_ORDER ];
+ silk_float *LTP_res_ptr;
+ silk_float inv_gain;
+ opus_int k, i, j;
+
+ x_ptr = x;
+ LTP_res_ptr = LTP_res;
+ for( k = 0; k < nb_subfr; k++ ) {
+ x_lag_ptr = x_ptr - pitchL[ k ];
+ inv_gain = invGains[ k ];
+ for( i = 0; i < LTP_ORDER; i++ ) {
+ Btmp[ i ] = B[ k * LTP_ORDER + i ];
+ }
+
+ /* LTP analysis FIR filter */
+ for( i = 0; i < subfr_length + pre_length; i++ ) {
+ LTP_res_ptr[ i ] = x_ptr[ i ];
+ /* Subtract long-term prediction */
+ for( j = 0; j < LTP_ORDER; j++ ) {
+ LTP_res_ptr[ i ] -= Btmp[ j ] * x_lag_ptr[ LTP_ORDER / 2 - j ];
+ }
+ LTP_res_ptr[ i ] *= inv_gain;
+ x_lag_ptr++;
+ }
+
+ /* Update pointers */
+ LTP_res_ptr += subfr_length + pre_length;
+ x_ptr += subfr_length;
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+void silk_LTP_scale_ctrl_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ opus_int condCoding /* I The type of conditional coding to use */
+)
+{
+ opus_int round_loss;
+
+ if( condCoding == CODE_INDEPENDENTLY ) {
+ /* Only scale if first frame in packet */
+ round_loss = psEnc->sCmn.PacketLoss_perc * psEnc->sCmn.nFramesPerPacket;
+ if ( psEnc->sCmn.LBRR_flag ) {
+ /* LBRR reduces the effective loss. In practice, it does not square the loss because
+ losses aren't independent, but that still seems to work best. We also never go below 2%. */
+ round_loss = 2 + silk_SMULBB( round_loss, round_loss) / 100;
+ }
+ psEnc->sCmn.indices.LTP_scaleIndex = silk_SMULBB( psEncCtrl->LTPredCodGain, round_loss ) > silk_log2lin( 2900 - psEnc->sCmn.SNR_dB_Q7 );
+ psEnc->sCmn.indices.LTP_scaleIndex += silk_SMULBB( psEncCtrl->LTPredCodGain, round_loss ) > silk_log2lin( 3900 - psEnc->sCmn.SNR_dB_Q7 );
+ } else {
+ /* Default is minimum scaling */
+ psEnc->sCmn.indices.LTP_scaleIndex = 0;
+ }
+
+ psEncCtrl->LTP_scale = (silk_float)silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ] / 16384.0f;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+/* Apply sine window to signal vector */
+/* Window types: */
+/* 1 -> sine window from 0 to pi/2 */
+/* 2 -> sine window from pi/2 to pi */
+void silk_apply_sine_window_FLP(
+ silk_float px_win[], /* O Pointer to windowed signal */
+ const silk_float px[], /* I Pointer to input signal */
+ const opus_int win_type, /* I Selects a window type */
+ const opus_int length /* I Window length, multiple of 4 */
+)
+{
+ opus_int k;
+ silk_float freq, c, S0, S1;
+
+ celt_assert( win_type == 1 || win_type == 2 );
+
+ /* Length must be multiple of 4 */
+ celt_assert( ( length & 3 ) == 0 );
+
+ freq = PI / ( length + 1 );
+
+ /* Approximation of 2 * cos(f) */
+ c = 2.0f - freq * freq;
+
+ /* Initialize state */
+ if( win_type < 2 ) {
+ /* Start from 0 */
+ S0 = 0.0f;
+ /* Approximation of sin(f) */
+ S1 = freq;
+ } else {
+ /* Start from 1 */
+ S0 = 1.0f;
+ /* Approximation of cos(f) */
+ S1 = 0.5f * c;
+ }
+
+ /* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */
+ /* 4 samples at a time */
+ for( k = 0; k < length; k += 4 ) {
+ px_win[ k + 0 ] = px[ k + 0 ] * 0.5f * ( S0 + S1 );
+ px_win[ k + 1 ] = px[ k + 1 ] * S1;
+ S0 = c * S1 - S0;
+ px_win[ k + 2 ] = px[ k + 2 ] * 0.5f * ( S1 + S0 );
+ px_win[ k + 3 ] = px[ k + 3 ] * S0;
+ S1 = c * S0 - S1;
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "typedef.h"
+#include "SigProc_FLP.h"
+
+/* compute autocorrelation */
+void silk_autocorrelation_FLP(
+ silk_float *results, /* O result (length correlationCount) */
+ const silk_float *inputData, /* I input data to correlate */
+ opus_int inputDataSize, /* I length of input */
+ opus_int correlationCount, /* I number of correlation taps to compute */
+ int arch
+)
+{
+ opus_int i;
+
+ if( correlationCount > inputDataSize ) {
+ correlationCount = inputDataSize;
+ }
+
+ for( i = 0; i < correlationCount; i++ ) {
+ results[ i ] = (silk_float)silk_inner_product_FLP( inputData, inputData + i, inputDataSize - i, arch );
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+#include "tuning_parameters.h"
+#include "define.h"
+
+#define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384*/
+
+/* Compute reflection coefficients from input signal */
+silk_float silk_burg_modified_FLP( /* O returns residual energy */
+ silk_float A[], /* O prediction coefficients (length order) */
+ const silk_float x[], /* I input signal, length: nb_subfr*(D+L_sub) */
+ const silk_float minInvGain, /* I minimum inverse prediction gain */
+ const opus_int subfr_length, /* I input signal subframe length (incl. D preceding samples) */
+ const opus_int nb_subfr, /* I number of subframes stacked in x */
+ const opus_int D, /* I order */
+ int arch
+)
+{
+ opus_int k, n, s, reached_max_gain;
+ double C0, invGain, num, nrg_f, nrg_b, rc, Atmp, tmp1, tmp2;
+ const silk_float *x_ptr;
+ double C_first_row[ SILK_MAX_ORDER_LPC ], C_last_row[ SILK_MAX_ORDER_LPC ];
+ double CAf[ SILK_MAX_ORDER_LPC + 1 ], CAb[ SILK_MAX_ORDER_LPC + 1 ];
+ double Af[ SILK_MAX_ORDER_LPC ];
+
+ celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
+
+ /* Compute autocorrelations, added over subframes */
+ C0 = silk_energy_FLP( x, nb_subfr * subfr_length );
+ silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( double ) );
+ for( s = 0; s < nb_subfr; s++ ) {
+ x_ptr = x + s * subfr_length;
+ for( n = 1; n < D + 1; n++ ) {
+ C_first_row[ n - 1 ] += silk_inner_product_FLP( x_ptr, x_ptr + n, subfr_length - n, arch );
+ }
+ }
+ silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( double ) );
+
+ /* Initialize */
+ CAb[ 0 ] = CAf[ 0 ] = C0 + FIND_LPC_COND_FAC * C0 + 1e-9f;
+ invGain = 1.0f;
+ reached_max_gain = 0;
+ for( n = 0; n < D; n++ ) {
+ /* Update first row of correlation matrix (without first element) */
+ /* Update last row of correlation matrix (without last element, stored in reversed order) */
+ /* Update C * Af */
+ /* Update C * flipud(Af) (stored in reversed order) */
+ for( s = 0; s < nb_subfr; s++ ) {
+ x_ptr = x + s * subfr_length;
+ tmp1 = x_ptr[ n ];
+ tmp2 = x_ptr[ subfr_length - n - 1 ];
+ for( k = 0; k < n; k++ ) {
+ C_first_row[ k ] -= x_ptr[ n ] * x_ptr[ n - k - 1 ];
+ C_last_row[ k ] -= x_ptr[ subfr_length - n - 1 ] * x_ptr[ subfr_length - n + k ];
+ Atmp = Af[ k ];
+ tmp1 += x_ptr[ n - k - 1 ] * Atmp;
+ tmp2 += x_ptr[ subfr_length - n + k ] * Atmp;
+ }
+ for( k = 0; k <= n; k++ ) {
+ CAf[ k ] -= tmp1 * x_ptr[ n - k ];
+ CAb[ k ] -= tmp2 * x_ptr[ subfr_length - n + k - 1 ];
+ }
+ }
+ tmp1 = C_first_row[ n ];
+ tmp2 = C_last_row[ n ];
+ for( k = 0; k < n; k++ ) {
+ Atmp = Af[ k ];
+ tmp1 += C_last_row[ n - k - 1 ] * Atmp;
+ tmp2 += C_first_row[ n - k - 1 ] * Atmp;
+ }
+ CAf[ n + 1 ] = tmp1;
+ CAb[ n + 1 ] = tmp2;
+
+ /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */
+ num = CAb[ n + 1 ];
+ nrg_b = CAb[ 0 ];
+ nrg_f = CAf[ 0 ];
+ for( k = 0; k < n; k++ ) {
+ Atmp = Af[ k ];
+ num += CAb[ n - k ] * Atmp;
+ nrg_b += CAb[ k + 1 ] * Atmp;
+ nrg_f += CAf[ k + 1 ] * Atmp;
+ }
+ silk_assert( nrg_f > 0.0 );
+ silk_assert( nrg_b > 0.0 );
+
+ /* Calculate the next order reflection (parcor) coefficient */
+ rc = -2.0 * num / ( nrg_f + nrg_b );
+ silk_assert( rc > -1.0 && rc < 1.0 );
+
+ /* Update inverse prediction gain */
+ tmp1 = invGain * ( 1.0 - rc * rc );
+ if( tmp1 <= minInvGain ) {
+ /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */
+ rc = sqrt( 1.0 - minInvGain / invGain );
+ if( num > 0 ) {
+ /* Ensure adjusted reflection coefficients has the original sign */
+ rc = -rc;
+ }
+ invGain = minInvGain;
+ reached_max_gain = 1;
+ } else {
+ invGain = tmp1;
+ }
+
+ /* Update the AR coefficients */
+ for( k = 0; k < (n + 1) >> 1; k++ ) {
+ tmp1 = Af[ k ];
+ tmp2 = Af[ n - k - 1 ];
+ Af[ k ] = tmp1 + rc * tmp2;
+ Af[ n - k - 1 ] = tmp2 + rc * tmp1;
+ }
+ Af[ n ] = rc;
+
+ if( reached_max_gain ) {
+ /* Reached max prediction gain; set remaining coefficients to zero and exit loop */
+ for( k = n + 1; k < D; k++ ) {
+ Af[ k ] = 0.0;
+ }
+ break;
+ }
+
+ /* Update C * Af and C * Ab */
+ for( k = 0; k <= n + 1; k++ ) {
+ tmp1 = CAf[ k ];
+ CAf[ k ] += rc * CAb[ n - k + 1 ];
+ CAb[ n - k + 1 ] += rc * tmp1;
+ }
+ }
+
+ if( reached_max_gain ) {
+ /* Convert to silk_float */
+ for( k = 0; k < D; k++ ) {
+ A[ k ] = (silk_float)( -Af[ k ] );
+ }
+ /* Subtract energy of preceding samples from C0 */
+ for( s = 0; s < nb_subfr; s++ ) {
+ C0 -= silk_energy_FLP( x + s * subfr_length, D );
+ }
+ /* Approximate residual energy */
+ nrg_f = C0 * invGain;
+ } else {
+ /* Compute residual energy and store coefficients as silk_float */
+ nrg_f = CAf[ 0 ];
+ tmp1 = 1.0;
+ for( k = 0; k < D; k++ ) {
+ Atmp = Af[ k ];
+ nrg_f += CAf[ k + 1 ] * Atmp;
+ tmp1 += Atmp * Atmp;
+ A[ k ] = (silk_float)(-Atmp);
+ }
+ nrg_f -= FIND_LPC_COND_FAC * C0 * tmp1;
+ }
+
+ /* Return residual energy */
+ return (silk_float)nrg_f;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* Chirp (bw expand) LP AR filter */
+void silk_bwexpander_FLP(
+ silk_float *ar, /* I/O AR filter to be expanded (without leading 1) */
+ const opus_int d, /* I length of ar */
+ const silk_float chirp /* I chirp factor (typically in range (0..1) ) */
+)
+{
+ opus_int i;
+ silk_float cfac = chirp;
+
+ for( i = 0; i < d - 1; i++ ) {
+ ar[ i ] *= cfac;
+ cfac *= chirp;
+ }
+ ar[ d - 1 ] *= cfac;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/**********************************************************************
+ * Correlation matrix computations for LS estimate.
+ **********************************************************************/
+
+#include "main_FLP.h"
+
+/* Calculates correlation vector X'*t */
+void silk_corrVector_FLP(
+ const silk_float *x, /* I x vector [L+order-1] used to create X */
+ const silk_float *t, /* I Target vector [L] */
+ const opus_int L, /* I Length of vecors */
+ const opus_int Order, /* I Max lag for correlation */
+ silk_float *Xt, /* O X'*t correlation vector [order] */
+ int arch
+)
+{
+ opus_int lag;
+ const silk_float *ptr1;
+
+ ptr1 = &x[ Order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */
+ for( lag = 0; lag < Order; lag++ ) {
+ /* Calculate X[:,lag]'*t */
+ Xt[ lag ] = (silk_float)silk_inner_product_FLP( ptr1, t, L, arch );
+ ptr1--; /* Next column of X */
+ }
+}
+
+/* Calculates correlation matrix X'*X */
+void silk_corrMatrix_FLP(
+ const silk_float *x, /* I x vector [ L+order-1 ] used to create X */
+ const opus_int L, /* I Length of vectors */
+ const opus_int Order, /* I Max lag for correlation */
+ silk_float *XX, /* O X'*X correlation matrix [order x order] */
+ int arch
+)
+{
+ opus_int j, lag;
+ double energy;
+ const silk_float *ptr1, *ptr2;
+
+ ptr1 = &x[ Order - 1 ]; /* First sample of column 0 of X */
+ energy = silk_energy_FLP( ptr1, L ); /* X[:,0]'*X[:,0] */
+ matrix_ptr( XX, 0, 0, Order ) = ( silk_float )energy;
+ for( j = 1; j < Order; j++ ) {
+ /* Calculate X[:,j]'*X[:,j] */
+ energy += ptr1[ -j ] * ptr1[ -j ] - ptr1[ L - j ] * ptr1[ L - j ];
+ matrix_ptr( XX, j, j, Order ) = ( silk_float )energy;
+ }
+
+ ptr2 = &x[ Order - 2 ]; /* First sample of column 1 of X */
+ for( lag = 1; lag < Order; lag++ ) {
+ /* Calculate X[:,0]'*X[:,lag] */
+ energy = silk_inner_product_FLP( ptr1, ptr2, L, arch );
+ matrix_ptr( XX, lag, 0, Order ) = ( silk_float )energy;
+ matrix_ptr( XX, 0, lag, Order ) = ( silk_float )energy;
+ /* Calculate X[:,j]'*X[:,j + lag] */
+ for( j = 1; j < ( Order - lag ); j++ ) {
+ energy += ptr1[ -j ] * ptr2[ -j ] - ptr1[ L - j ] * ptr2[ L - j ];
+ matrix_ptr( XX, lag + j, j, Order ) = ( silk_float )energy;
+ matrix_ptr( XX, j, lag + j, Order ) = ( silk_float )energy;
+ }
+ ptr2--; /* Next column of X */
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+#include "stack_alloc.h"
+
+/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */
+static OPUS_INLINE void silk_LBRR_encode_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ const silk_float xfw[], /* I Input signal */
+ opus_int condCoding /* I The type of conditional coding used so far for this frame */
+);
+
+void silk_encode_do_VAD_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ opus_int activity /* I Decision of Opus voice activity detector */
+)
+{
+ const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
+
+ /****************************/
+ /* Voice Activity Detection */
+ /****************************/
+ silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
+ /* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */
+ if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
+ psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
+ }
+
+ /**************************************************/
+ /* Convert speech activity into VAD and DTX flags */
+ /**************************************************/
+ if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
+ psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
+ psEnc->sCmn.noSpeechCounter++;
+ if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
+ psEnc->sCmn.inDTX = 0;
+ } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
+ psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
+ psEnc->sCmn.inDTX = 0;
+ }
+ psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0;
+ } else {
+ psEnc->sCmn.noSpeechCounter = 0;
+ psEnc->sCmn.inDTX = 0;
+ psEnc->sCmn.indices.signalType = TYPE_UNVOICED;
+ psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
+ }
+}
+
+/****************/
+/* Encode frame */
+/****************/
+opus_int silk_encode_frame_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ opus_int32 *pnBytesOut, /* O Number of payload bytes; */
+ ec_enc *psRangeEnc, /* I/O compressor data structure */
+ opus_int condCoding, /* I The type of conditional coding to use */
+ opus_int maxBits, /* I If > 0: maximum number of output bits */
+ opus_int useCBR /* I Flag to force constant-bitrate operation */
+)
+{
+ silk_encoder_control_FLP sEncCtrl;
+ opus_int i, iter, maxIter, found_upper, found_lower, ret = 0;
+ silk_float *x_frame, *res_pitch_frame;
+ silk_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
+ ec_enc sRangeEnc_copy, sRangeEnc_copy2;
+ VARDECL(silk_nsq_state, sNSQ_copy);
+ opus_int32 seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper;
+ opus_int32 gainsID, gainsID_lower, gainsID_upper;
+ opus_int16 gainMult_Q8;
+ opus_int16 ec_prevLagIndex_copy;
+ opus_int ec_prevSignalType_copy;
+ opus_int8 LastGainIndex_copy2;
+ opus_int32 pGains_Q16[ MAX_NB_SUBFR ];
+ opus_int gain_lock[ MAX_NB_SUBFR ] = {0};
+ opus_int16 best_gain_mult[ MAX_NB_SUBFR ];
+ opus_int best_sum[ MAX_NB_SUBFR ];
+ opus_int bits_margin;
+ SAVE_STACK;
+
+ /* Using ALLOC() instead of a regular stack allocation to minimize real stack use when using the pseudostack.
+ This is useful on some embedded systems. */
+ ALLOC(sNSQ_copy, 2, silk_nsq_state);
+
+ /* For CBR, 5 bits below budget is close enough. For VBR, allow up to 25% below the cap if we initially busted the budget. */
+ bits_margin = useCBR ? 5 : maxBits/4;
+ /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
+ LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
+
+ psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;
+
+ /**************************************************************/
+ /* Set up Input Pointers, and insert frame in input buffer */
+ /**************************************************************/
+ /* pointers aligned with start of frame to encode */
+ x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; /* start of frame to encode */
+ res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length; /* start of pitch LPC residual frame */
+
+ /***************************************/
+ /* Ensure smooth bandwidth transitions */
+ /***************************************/
+ silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length );
+
+ /*******************************************/
+ /* Copy new frame to front of input buffer */
+ /*******************************************/
+ silk_short2float_array( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length );
+
+ /* Add tiny signal to avoid high CPU load from denormalized floating point numbers */
+ for( i = 0; i < 8; i++ ) {
+ x_frame[ LA_SHAPE_MS * psEnc->sCmn.fs_kHz + i * ( psEnc->sCmn.frame_length >> 3 ) ] += ( 1 - ( i & 2 ) ) * 1e-6f;
+ }
+
+ if( !psEnc->sCmn.prefillFlag ) {
+ VARDECL( opus_uint8, ec_buf_copy );
+ /*****************************************/
+ /* Find pitch lags, initial LPC analysis */
+ /*****************************************/
+ silk_find_pitch_lags_FLP( psEnc, &sEncCtrl, res_pitch, x_frame, psEnc->sCmn.arch );
+
+ /************************/
+ /* Noise shape analysis */
+ /************************/
+ silk_noise_shape_analysis_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame );
+
+ /***************************************************/
+ /* Find linear prediction coefficients (LPC + LTP) */
+ /***************************************************/
+ silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
+
+ /****************************************/
+ /* Process gains */
+ /****************************************/
+ silk_process_gains_FLP( psEnc, &sEncCtrl, condCoding );
+
+ /****************************************/
+ /* Low Bitrate Redundant Encoding */
+ /****************************************/
+ silk_LBRR_encode_FLP( psEnc, &sEncCtrl, x_frame, condCoding );
+
+ /* Loop over quantizer and entroy coding to control bitrate */
+ maxIter = 6;
+ gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
+ found_lower = 0;
+ found_upper = 0;
+ gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
+ gainsID_lower = -1;
+ gainsID_upper = -1;
+ /* Copy part of the input state */
+ silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) );
+ silk_memcpy( &sNSQ_copy[0], &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
+ seed_copy = psEnc->sCmn.indices.Seed;
+ ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex;
+ ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType;
+ ALLOC( ec_buf_copy, 1275, opus_uint8 );
+ for( iter = 0; ; iter++ ) {
+ if( gainsID == gainsID_lower ) {
+ nBits = nBits_lower;
+ } else if( gainsID == gainsID_upper ) {
+ nBits = nBits_upper;
+ } else {
+ /* Restore part of the input state */
+ if( iter > 0 ) {
+ silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) );
+ silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy[0], sizeof( silk_nsq_state ) );
+ psEnc->sCmn.indices.Seed = seed_copy;
+ psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
+ psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
+ }
+
+ /*****************************************/
+ /* Noise shaping quantization */
+ /*****************************************/
+ silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, x_frame );
+
+ if ( iter == maxIter && !found_lower ) {
+ silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
+ }
+
+ /****************************************/
+ /* Encode Parameters */
+ /****************************************/
+ silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
+
+ /****************************************/
+ /* Encode Excitation Signal */
+ /****************************************/
+ silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
+ psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
+
+ nBits = ec_tell( psRangeEnc );
+
+ /* If we still bust after the last iteration, do some damage control. */
+ if ( iter == maxIter && !found_lower && nBits > maxBits ) {
+ silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
+
+ /* Keep gains the same as the last frame. */
+ psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
+ for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ psEnc->sCmn.indices.GainsIndices[ i ] = 4;
+ }
+ if (condCoding != CODE_CONDITIONALLY) {
+ psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
+ }
+ psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
+ psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
+ /* Clear all pulses. */
+ for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
+ psEnc->sCmn.pulses[ i ] = 0;
+ }
+
+ silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
+
+ silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
+ psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
+
+ nBits = ec_tell( psRangeEnc );
+ }
+
+ if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
+ break;
+ }
+ }
+
+ if( iter == maxIter ) {
+ if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
+ /* Restore output state from earlier iteration that did meet the bitrate budget */
+ silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
+ celt_assert( sRangeEnc_copy2.offs <= 1275 );
+ silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
+ silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy[1], sizeof( silk_nsq_state ) );
+ psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
+ }
+ break;
+ }
+
+ if( nBits > maxBits ) {
+ if( found_lower == 0 && iter >= 2 ) {
+ /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
+ sEncCtrl.Lambda = silk_max_float(sEncCtrl.Lambda*1.5f, 1.5f);
+ /* Reducing dithering can help us hit the target. */
+ psEnc->sCmn.indices.quantOffsetType = 0;
+ found_upper = 0;
+ gainsID_upper = -1;
+ } else {
+ found_upper = 1;
+ nBits_upper = nBits;
+ gainMult_upper = gainMult_Q8;
+ gainsID_upper = gainsID;
+ }
+ } else if( nBits < maxBits - bits_margin ) {
+ found_lower = 1;
+ nBits_lower = nBits;
+ gainMult_lower = gainMult_Q8;
+ if( gainsID != gainsID_lower ) {
+ gainsID_lower = gainsID;
+ /* Copy part of the output state */
+ silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
+ celt_assert( psRangeEnc->offs <= 1275 );
+ silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
+ silk_memcpy( &sNSQ_copy[1], &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
+ LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
+ }
+ } else {
+ /* Close enough */
+ break;
+ }
+
+ if ( !found_lower && nBits > maxBits ) {
+ int j;
+ for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ int sum=0;
+ for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
+ sum += abs( psEnc->sCmn.pulses[j] );
+ }
+ if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
+ best_sum[i] = sum;
+ best_gain_mult[i] = gainMult_Q8;
+ } else {
+ gain_lock[i] = 1;
+ }
+ }
+ }
+ if( ( found_lower & found_upper ) == 0 ) {
+ /* Adjust gain according to high-rate rate/distortion curve */
+ if( nBits > maxBits ) {
+ gainMult_Q8 = silk_min_32( 1024, gainMult_Q8*3/2 );
+ } else {
+ gainMult_Q8 = silk_max_32( 64, gainMult_Q8*4/5 );
+ }
+ } else {
+ /* Adjust gain by interpolating */
+ gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower );
+ /* New gain multiplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */
+ if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) {
+ gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 );
+ } else
+ if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) {
+ gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 );
+ }
+ }
+
+ for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ opus_int16 tmp;
+ if ( gain_lock[i] ) {
+ tmp = best_gain_mult[i];
+ } else {
+ tmp = gainMult_Q8;
+ }
+ pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
+ }
+
+ /* Quantize gains */
+ psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
+ silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16,
+ &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
+
+ /* Unique identifier of gains vector */
+ gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
+
+ /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */
+ for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ sEncCtrl.Gains[ i ] = pGains_Q16[ i ] / 65536.0f;
+ }
+ }
+ }
+
+ /* Update input buffer */
+ silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ],
+ ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( silk_float ) );
+
+ /* Exit without entropy coding */
+ if( psEnc->sCmn.prefillFlag ) {
+ /* No payload */
+ *pnBytesOut = 0;
+ RESTORE_STACK;
+ return ret;
+ }
+
+ /* Parameters needed for next frame */
+ psEnc->sCmn.prevLag = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ];
+ psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType;
+
+ /****************************************/
+ /* Finalize payload */
+ /****************************************/
+ psEnc->sCmn.first_frame_after_reset = 0;
+ /* Payload size */
+ *pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );
+
+ RESTORE_STACK;
+ return ret;
+}
+
+/* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate */
+static OPUS_INLINE void silk_LBRR_encode_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ const silk_float xfw[], /* I Input signal */
+ opus_int condCoding /* I The type of conditional coding used so far for this frame */
+)
+{
+ opus_int k;
+ opus_int32 Gains_Q16[ MAX_NB_SUBFR ];
+ silk_float TempGains[ MAX_NB_SUBFR ];
+ SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ];
+ VARDECL(silk_nsq_state, sNSQ_LBRR);
+ SAVE_STACK;
+
+ /*******************************************/
+ /* Control use of inband LBRR */
+ /*******************************************/
+ if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) {
+ /* Using ALLOC() instead of a regular stack allocation to minimize real stack use when using the pseudostack.
+ This is useful on some embedded systems. */
+ ALLOC(sNSQ_LBRR, 1, silk_nsq_state);
+
+ psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
+
+ /* Copy noise shaping quantizer state and quantization indices from regular encoding */
+ silk_memcpy( &sNSQ_LBRR[0], &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
+ silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) );
+
+ /* Save original gains */
+ silk_memcpy( TempGains, psEncCtrl->Gains, psEnc->sCmn.nb_subfr * sizeof( silk_float ) );
+
+ if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) {
+ /* First frame in packet or previous frame not LBRR coded */
+ psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex;
+
+ /* Increase Gains to get target LBRR rate */
+ psIndices_LBRR->GainsIndices[ 0 ] += psEnc->sCmn.LBRR_GainIncreases;
+ psIndices_LBRR->GainsIndices[ 0 ] = silk_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 );
+ }
+
+ /* Decode to get gains in sync with decoder */
+ silk_gains_dequant( Gains_Q16, psIndices_LBRR->GainsIndices,
+ &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
+
+ /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ psEncCtrl->Gains[ k ] = Gains_Q16[ k ] * ( 1.0f / 65536.0f );
+ }
+
+ /*****************************************/
+ /* Noise shaping quantization */
+ /*****************************************/
+ silk_NSQ_wrapper_FLP( psEnc, psEncCtrl, psIndices_LBRR, &sNSQ_LBRR[0],
+ psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], xfw );
+
+ /* Restore original gains */
+ silk_memcpy( psEncCtrl->Gains, TempGains, psEnc->sCmn.nb_subfr * sizeof( silk_float ) );
+ }
+ RESTORE_STACK;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* sum of squares of a silk_float array, with result as double */
+double silk_energy_FLP(
+ const silk_float *data,
+ opus_int dataSize
+)
+{
+ opus_int i;
+ double result;
+
+ /* 4x unrolled loop */
+ result = 0.0;
+ for( i = 0; i < dataSize - 3; i += 4 ) {
+ result += data[ i + 0 ] * (double)data[ i + 0 ] +
+ data[ i + 1 ] * (double)data[ i + 1 ] +
+ data[ i + 2 ] * (double)data[ i + 2 ] +
+ data[ i + 3 ] * (double)data[ i + 3 ];
+ }
+
+ /* add any remaining products */
+ for( ; i < dataSize; i++ ) {
+ result += data[ i ] * (double)data[ i ];
+ }
+
+ silk_assert( result >= 0.0 );
+ return result;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "define.h"
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+
+/* LPC analysis */
+void silk_find_LPC_FLP(
+ silk_encoder_state *psEncC, /* I/O Encoder state */
+ opus_int16 NLSF_Q15[], /* O NLSFs */
+ const silk_float x[], /* I Input signal */
+ const silk_float minInvGain, /* I Inverse of max prediction gain */
+ int arch
+)
+{
+ opus_int k, subfr_length;
+ silk_float a[ MAX_LPC_ORDER ];
+
+ /* Used only for NLSF interpolation */
+ silk_float res_nrg, res_nrg_2nd, res_nrg_interp;
+ opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ];
+ silk_float a_tmp[ MAX_LPC_ORDER ];
+ silk_float LPC_res[ MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ];
+
+ subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder;
+
+ /* Default: No interpolation */
+ psEncC->indices.NLSFInterpCoef_Q2 = 4;
+
+ /* Burg AR analysis for the full frame */
+ res_nrg = silk_burg_modified_FLP( a, x, minInvGain, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder, arch );
+
+ if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) {
+ /* Optimal solution for last 10 ms; subtract residual energy here, as that's easier than */
+ /* adding it to the residual energy of the first 10 ms in each iteration of the search below */
+ res_nrg -= silk_burg_modified_FLP( a_tmp, x + ( MAX_NB_SUBFR / 2 ) * subfr_length, minInvGain, subfr_length, MAX_NB_SUBFR / 2, psEncC->predictLPCOrder, arch );
+
+ /* Convert to NLSFs */
+ silk_A2NLSF_FLP( NLSF_Q15, a_tmp, psEncC->predictLPCOrder );
+
+ /* Search over interpolation indices to find the one with lowest residual energy */
+ res_nrg_2nd = silk_float_MAX;
+ for( k = 3; k >= 0; k-- ) {
+ /* Interpolate NLSFs for first half */
+ silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
+
+ /* Convert to LPC for residual energy evaluation */
+ silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder, psEncC->arch );
+
+ /* Calculate residual energy with LSF interpolation */
+ silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, psEncC->predictLPCOrder );
+ res_nrg_interp = (silk_float)(
+ silk_energy_FLP( LPC_res + psEncC->predictLPCOrder, subfr_length - psEncC->predictLPCOrder ) +
+ silk_energy_FLP( LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder ) );
+
+ /* Determine whether current interpolated NLSFs are best so far */
+ if( res_nrg_interp < res_nrg ) {
+ /* Interpolation has lower residual energy */
+ res_nrg = res_nrg_interp;
+ psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k;
+ } else if( res_nrg_interp > res_nrg_2nd ) {
+ /* No reason to continue iterating - residual energies will continue to climb */
+ break;
+ }
+ res_nrg_2nd = res_nrg_interp;
+ }
+ }
+
+ if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) {
+ /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */
+ silk_A2NLSF_FLP( NLSF_Q15, a, psEncC->predictLPCOrder );
+ }
+
+ celt_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 ||
+ ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+
+void silk_find_LTP_FLP(
+ silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
+ silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* O Weight for LTP quantization */
+ const silk_float r_ptr[], /* I LPC residual */
+ const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
+ const opus_int subfr_length, /* I Subframe length */
+ const opus_int nb_subfr, /* I number of subframes */
+ int arch
+)
+{
+ opus_int k;
+ silk_float *xX_ptr, *XX_ptr;
+ const silk_float *lag_ptr;
+ silk_float xx, temp;
+
+ xX_ptr = xX;
+ XX_ptr = XX;
+ for( k = 0; k < nb_subfr; k++ ) {
+ lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 );
+ silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, XX_ptr, arch );
+ silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, xX_ptr, arch );
+ xx = ( silk_float )silk_energy_FLP( r_ptr, subfr_length + LTP_ORDER );
+ temp = 1.0f / silk_max( xx, LTP_CORR_INV_MAX * 0.5f * ( XX_ptr[ 0 ] + XX_ptr[ 24 ] ) + 1.0f );
+ silk_scale_vector_FLP( XX_ptr, temp, LTP_ORDER * LTP_ORDER );
+ silk_scale_vector_FLP( xX_ptr, temp, LTP_ORDER );
+
+ r_ptr += subfr_length;
+ XX_ptr += LTP_ORDER * LTP_ORDER;
+ xX_ptr += LTP_ORDER;
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+
+void silk_find_pitch_lags_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ silk_float res[], /* O Residual */
+ const silk_float x[], /* I Speech signal */
+ int arch /* I Run-time architecture */
+)
+{
+ opus_int buf_len;
+ silk_float thrhld, res_nrg;
+ const silk_float *x_buf_ptr, *x_buf;
+ silk_float auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ];
+ silk_float A[ MAX_FIND_PITCH_LPC_ORDER ];
+ silk_float refl_coef[ MAX_FIND_PITCH_LPC_ORDER ];
+ silk_float Wsig[ FIND_PITCH_LPC_WIN_MAX ];
+ silk_float *Wsig_ptr;
+
+ /******************************************/
+ /* Set up buffer lengths etc based on Fs */
+ /******************************************/
+ buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
+
+ /* Safety check */
+ celt_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
+
+ x_buf = x - psEnc->sCmn.ltp_mem_length;
+
+ /******************************************/
+ /* Estimate LPC AR coefficients */
+ /******************************************/
+
+ /* Calculate windowed signal */
+
+ /* First LA_LTP samples */
+ x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length;
+ Wsig_ptr = Wsig;
+ silk_apply_sine_window_FLP( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch );
+
+ /* Middle non-windowed samples */
+ Wsig_ptr += psEnc->sCmn.la_pitch;
+ x_buf_ptr += psEnc->sCmn.la_pitch;
+ silk_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 ) ) * sizeof( silk_float ) );
+
+ /* Last LA_LTP samples */
+ Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 );
+ x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - ( psEnc->sCmn.la_pitch << 1 );
+ silk_apply_sine_window_FLP( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch );
+
+ /* Calculate autocorrelation sequence */
+ silk_autocorrelation_FLP( auto_corr, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1, arch );
+
+ /* Add white noise, as a fraction of the energy */
+ auto_corr[ 0 ] += auto_corr[ 0 ] * FIND_PITCH_WHITE_NOISE_FRACTION + 1;
+
+ /* Calculate the reflection coefficients using Schur */
+ res_nrg = silk_schur_FLP( refl_coef, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder );
+
+ /* Prediction gain */
+ psEncCtrl->predGain = auto_corr[ 0 ] / silk_max_float( res_nrg, 1.0f );
+
+ /* Convert reflection coefficients to prediction coefficients */
+ silk_k2a_FLP( A, refl_coef, psEnc->sCmn.pitchEstimationLPCOrder );
+
+ /* Bandwidth expansion */
+ silk_bwexpander_FLP( A, psEnc->sCmn.pitchEstimationLPCOrder, FIND_PITCH_BANDWIDTH_EXPANSION );
+
+ /*****************************************/
+ /* LPC analysis filtering */
+ /*****************************************/
+ silk_LPC_analysis_filter_FLP( res, A, x_buf, buf_len, psEnc->sCmn.pitchEstimationLPCOrder );
+
+ if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) {
+ /* Threshold for pitch estimator */
+ thrhld = 0.6f;
+ thrhld -= 0.004f * psEnc->sCmn.pitchEstimationLPCOrder;
+ thrhld -= 0.1f * psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f );
+ thrhld -= 0.15f * (psEnc->sCmn.prevSignalType >> 1);
+ thrhld -= 0.1f * psEnc->sCmn.input_tilt_Q15 * ( 1.0f / 32768.0f );
+
+ /*****************************************/
+ /* Call Pitch estimator */
+ /*****************************************/
+ if( silk_pitch_analysis_core_FLP( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex,
+ &psEnc->sCmn.indices.contourIndex, &psEnc->LTPCorr, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16 / 65536.0f,
+ thrhld, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr, arch ) == 0 )
+ {
+ psEnc->sCmn.indices.signalType = TYPE_VOICED;
+ } else {
+ psEnc->sCmn.indices.signalType = TYPE_UNVOICED;
+ }
+ } else {
+ silk_memset( psEncCtrl->pitchL, 0, sizeof( psEncCtrl->pitchL ) );
+ psEnc->sCmn.indices.lagIndex = 0;
+ psEnc->sCmn.indices.contourIndex = 0;
+ psEnc->LTPCorr = 0;
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+/* Find LPC and LTP coefficients */
+void silk_find_pred_coefs_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ const silk_float res_pitch[], /* I Residual from pitch analysis */
+ const silk_float x[], /* I Speech signal */
+ opus_int condCoding /* I The type of conditional coding to use */
+)
+{
+ opus_int i;
+ silk_float XXLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
+ silk_float xXLTP[ MAX_NB_SUBFR * LTP_ORDER ];
+ silk_float invGains[ MAX_NB_SUBFR ];
+ /* Set to NLSF_Q15 to zero so we don't copy junk to the state. */
+ opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]={0};
+ const silk_float *x_ptr;
+ silk_float *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ];
+ silk_float minInvGain;
+
+ /* Weighting for weighted least squares */
+ for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ silk_assert( psEncCtrl->Gains[ i ] > 0.0f );
+ invGains[ i ] = 1.0f / psEncCtrl->Gains[ i ];
+ }
+
+ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+ /**********/
+ /* VOICED */
+ /**********/
+ celt_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
+
+ /* LTP analysis */
+ silk_find_LTP_FLP( XXLTP, xXLTP, res_pitch, psEncCtrl->pitchL, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
+
+ /* Quantize LTP gain parameters */
+ silk_quant_LTP_gains_FLP( psEncCtrl->LTPCoef, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex,
+ &psEnc->sCmn.sum_log_gain_Q7, &psEncCtrl->LTPredCodGain, XXLTP, xXLTP, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
+
+ /* Control LTP scaling */
+ silk_LTP_scale_ctrl_FLP( psEnc, psEncCtrl, condCoding );
+
+ /* Create LTP residual */
+ silk_LTP_analysis_filter_FLP( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef,
+ psEncCtrl->pitchL, invGains, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );
+ } else {
+ /************/
+ /* UNVOICED */
+ /************/
+ /* Create signal with prepended subframes, scaled by inverse gains */
+ x_ptr = x - psEnc->sCmn.predictLPCOrder;
+ x_pre_ptr = LPC_in_pre;
+ for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ silk_scale_copy_vector_FLP( x_pre_ptr, x_ptr, invGains[ i ],
+ psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder );
+ x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder;
+ x_ptr += psEnc->sCmn.subfr_length;
+ }
+ silk_memset( psEncCtrl->LTPCoef, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( silk_float ) );
+ psEncCtrl->LTPredCodGain = 0.0f;
+ psEnc->sCmn.sum_log_gain_Q7 = 0;
+ }
+
+ /* Limit on total predictive coding gain */
+ if( psEnc->sCmn.first_frame_after_reset ) {
+ minInvGain = 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET;
+ } else {
+ minInvGain = (silk_float)pow( 2, psEncCtrl->LTPredCodGain / 3 ) / MAX_PREDICTION_POWER_GAIN;
+ minInvGain /= 0.25f + 0.75f * psEncCtrl->coding_quality;
+ }
+
+ /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */
+ silk_find_LPC_FLP( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain, psEnc->sCmn.arch );
+
+ /* Quantize LSFs */
+ silk_process_NLSFs_FLP( &psEnc->sCmn, psEncCtrl->PredCoef, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 );
+
+ /* Calculate residual energy using quantized LPC coefficients */
+ silk_residual_energy_FLP( psEncCtrl->ResNrg, LPC_in_pre, psEncCtrl->PredCoef, psEncCtrl->Gains,
+ psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );
+
+ /* Copy to prediction struct for use in next frame for interpolation */
+ silk_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* inner product of two silk_float arrays, with result as double */
+double silk_inner_product_FLP_c(
+ const silk_float *data1,
+ const silk_float *data2,
+ opus_int dataSize
+)
+{
+ opus_int i;
+ double result;
+
+ /* 4x unrolled loop */
+ result = 0.0;
+ for( i = 0; i < dataSize - 3; i += 4 ) {
+ result += data1[ i + 0 ] * (double)data2[ i + 0 ] +
+ data1[ i + 1 ] * (double)data2[ i + 1 ] +
+ data1[ i + 2 ] * (double)data2[ i + 2 ] +
+ data1[ i + 3 ] * (double)data2[ i + 3 ];
+ }
+
+ /* add any remaining products */
+ for( ; i < dataSize; i++ ) {
+ result += data1[ i ] * (double)data2[ i ];
+ }
+
+ return result;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+ 2023 Amazon
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+#include <immintrin.h>
+
+
+/* inner product of two silk_float arrays, with result as double */
+double silk_inner_product_FLP_avx2(
+ const silk_float *data1,
+ const silk_float *data2,
+ opus_int dataSize
+)
+{
+ opus_int i;
+ __m256d accum1, accum2;
+ double result;
+
+ /* 4x unrolled loop */
+ result = 0.0;
+ accum1 = accum2 = _mm256_setzero_pd();
+ for( i = 0; i < dataSize - 7; i += 8 ) {
+ __m128 x1f, x2f;
+ __m256d x1d, x2d;
+ x1f = _mm_loadu_ps( &data1[ i ] );
+ x2f = _mm_loadu_ps( &data2[ i ] );
+ x1d = _mm256_cvtps_pd( x1f );
+ x2d = _mm256_cvtps_pd( x2f );
+ accum1 = _mm256_fmadd_pd( x1d, x2d, accum1 );
+ x1f = _mm_loadu_ps( &data1[ i + 4 ] );
+ x2f = _mm_loadu_ps( &data2[ i + 4 ] );
+ x1d = _mm256_cvtps_pd( x1f );
+ x2d = _mm256_cvtps_pd( x2f );
+ accum2 = _mm256_fmadd_pd( x1d, x2d, accum2 );
+ }
+ for( ; i < dataSize - 3; i += 4 ) {
+ __m128 x1f, x2f;
+ __m256d x1d, x2d;
+ x1f = _mm_loadu_ps( &data1[ i ] );
+ x2f = _mm_loadu_ps( &data2[ i ] );
+ x1d = _mm256_cvtps_pd( x1f );
+ x2d = _mm256_cvtps_pd( x2f );
+ accum1 = _mm256_fmadd_pd( x1d, x2d, accum1 );
+ }
+ accum1 = _mm256_add_pd(accum1, accum2);
+ accum1 = _mm256_add_pd(accum1, _mm256_permute2f128_pd(accum1, accum1, 1));
+ accum1 = _mm256_hadd_pd(accum1,accum1);
+ result = _mm256_cvtsd_f64(accum1);
+
+ /* add any remaining products */
+ for( ; i < dataSize; i++ ) {
+ result += data1[ i ] * (double)data2[ i ];
+ }
+
+ return result;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* step up function, converts reflection coefficients to prediction coefficients */
+void silk_k2a_FLP(
+ silk_float *A, /* O prediction coefficients [order] */
+ const silk_float *rc, /* I reflection coefficients [order] */
+ opus_int32 order /* I prediction order */
+)
+{
+ opus_int k, n;
+ silk_float rck, tmp1, tmp2;
+
+ for( k = 0; k < order; k++ ) {
+ rck = rc[ k ];
+ for( n = 0; n < (k + 1) >> 1; n++ ) {
+ tmp1 = A[ n ];
+ tmp2 = A[ k - n - 1 ];
+ A[ n ] = tmp1 + tmp2 * rck;
+ A[ k - n - 1 ] = tmp2 + tmp1 * rck;
+ }
+ A[ k ] = -rck;
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+
+/* Compute gain to make warped filter coefficients have a zero mean log frequency response on a */
+/* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */
+/* Note: A monic filter is one with the first coefficient equal to 1.0. In Silk we omit the first */
+/* coefficient in an array of coefficients, for monic filters. */
+static OPUS_INLINE silk_float warped_gain(
+ const silk_float *coefs,
+ silk_float lambda,
+ opus_int order
+) {
+ opus_int i;
+ silk_float gain;
+
+ lambda = -lambda;
+ gain = coefs[ order - 1 ];
+ for( i = order - 2; i >= 0; i-- ) {
+ gain = lambda * gain + coefs[ i ];
+ }
+ return (silk_float)( 1.0f / ( 1.0f - lambda * gain ) );
+}
+
+/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */
+/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
+static OPUS_INLINE void warped_true2monic_coefs(
+ silk_float *coefs,
+ silk_float lambda,
+ silk_float limit,
+ opus_int order
+) {
+ opus_int i, iter, ind = 0;
+ silk_float tmp, maxabs, chirp, gain;
+
+ /* Convert to monic coefficients */
+ for( i = order - 1; i > 0; i-- ) {
+ coefs[ i - 1 ] -= lambda * coefs[ i ];
+ }
+ gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
+ for( i = 0; i < order; i++ ) {
+ coefs[ i ] *= gain;
+ }
+
+ /* Limit */
+ for( iter = 0; iter < 10; iter++ ) {
+ /* Find maximum absolute value */
+ maxabs = -1.0f;
+ for( i = 0; i < order; i++ ) {
+ tmp = silk_abs_float( coefs[ i ] );
+ if( tmp > maxabs ) {
+ maxabs = tmp;
+ ind = i;
+ }
+ }
+ if( maxabs <= limit ) {
+ /* Coefficients are within range - done */
+ return;
+ }
+
+ /* Convert back to true warped coefficients */
+ for( i = 1; i < order; i++ ) {
+ coefs[ i - 1 ] += lambda * coefs[ i ];
+ }
+ gain = 1.0f / gain;
+ for( i = 0; i < order; i++ ) {
+ coefs[ i ] *= gain;
+ }
+
+ /* Apply bandwidth expansion */
+ chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
+ silk_bwexpander_FLP( coefs, order, chirp );
+
+ /* Convert to monic warped coefficients */
+ for( i = order - 1; i > 0; i-- ) {
+ coefs[ i - 1 ] -= lambda * coefs[ i ];
+ }
+ gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
+ for( i = 0; i < order; i++ ) {
+ coefs[ i ] *= gain;
+ }
+ }
+ silk_assert( 0 );
+}
+
+static OPUS_INLINE void limit_coefs(
+ silk_float *coefs,
+ silk_float limit,
+ opus_int order
+) {
+ opus_int i, iter, ind = 0;
+ silk_float tmp, maxabs, chirp;
+
+ for( iter = 0; iter < 10; iter++ ) {
+ /* Find maximum absolute value */
+ maxabs = -1.0f;
+ for( i = 0; i < order; i++ ) {
+ tmp = silk_abs_float( coefs[ i ] );
+ if( tmp > maxabs ) {
+ maxabs = tmp;
+ ind = i;
+ }
+ }
+ if( maxabs <= limit ) {
+ /* Coefficients are within range - done */
+ return;
+ }
+
+ /* Apply bandwidth expansion */
+ chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
+ silk_bwexpander_FLP( coefs, order, chirp );
+ }
+ silk_assert( 0 );
+}
+
+/* Compute noise shaping coefficients and initial gain values */
+void silk_noise_shape_analysis_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ const silk_float *pitch_res, /* I LPC residual from pitch analysis */
+ const silk_float *x /* I Input signal [frame_length + la_shape] */
+)
+{
+ silk_shape_state_FLP *psShapeSt = &psEnc->sShape;
+ opus_int k, nSamples, nSegs;
+ silk_float SNR_adj_dB, HarmShapeGain, Tilt;
+ silk_float nrg, log_energy, log_energy_prev, energy_variation;
+ silk_float BWExp, gain_mult, gain_add, strength, b, warping;
+ silk_float x_windowed[ SHAPE_LPC_WIN_MAX ];
+ silk_float auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
+ silk_float rc[ MAX_SHAPE_LPC_ORDER + 1 ];
+ const silk_float *x_ptr, *pitch_res_ptr;
+
+ /* Point to start of first LPC analysis block */
+ x_ptr = x - psEnc->sCmn.la_shape;
+
+ /****************/
+ /* GAIN CONTROL */
+ /****************/
+ SNR_adj_dB = psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f );
+
+ /* Input quality is the average of the quality in the lowest two VAD bands */
+ psEncCtrl->input_quality = 0.5f * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ] ) * ( 1.0f / 32768.0f );
+
+ /* Coding quality level, between 0.0 and 1.0 */
+ psEncCtrl->coding_quality = silk_sigmoid( 0.25f * ( SNR_adj_dB - 20.0f ) );
+
+ if( psEnc->sCmn.useCBR == 0 ) {
+ /* Reduce coding SNR during low speech activity */
+ b = 1.0f - psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f );
+ SNR_adj_dB -= BG_SNR_DECR_dB * psEncCtrl->coding_quality * ( 0.5f + 0.5f * psEncCtrl->input_quality ) * b * b;
+ }
+
+ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+ /* Reduce gains for periodic signals */
+ SNR_adj_dB += HARM_SNR_INCR_dB * psEnc->LTPCorr;
+ } else {
+ /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */
+ SNR_adj_dB += ( -0.4f * psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ) + 6.0f ) * ( 1.0f - psEncCtrl->input_quality );
+ }
+
+ /*************************/
+ /* SPARSENESS PROCESSING */
+ /*************************/
+ /* Set quantizer offset */
+ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+ /* Initially set to 0; may be overruled in process_gains(..) */
+ psEnc->sCmn.indices.quantOffsetType = 0;
+ } else {
+ /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
+ nSamples = 2 * psEnc->sCmn.fs_kHz;
+ energy_variation = 0.0f;
+ log_energy_prev = 0.0f;
+ pitch_res_ptr = pitch_res;
+ nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2;
+ for( k = 0; k < nSegs; k++ ) {
+ nrg = ( silk_float )nSamples + ( silk_float )silk_energy_FLP( pitch_res_ptr, nSamples );
+ log_energy = silk_log2( nrg );
+ if( k > 0 ) {
+ energy_variation += silk_abs_float( log_energy - log_energy_prev );
+ }
+ log_energy_prev = log_energy;
+ pitch_res_ptr += nSamples;
+ }
+
+ /* Set quantization offset depending on sparseness measure */
+ if( energy_variation > ENERGY_VARIATION_THRESHOLD_QNT_OFFSET * (nSegs-1) ) {
+ psEnc->sCmn.indices.quantOffsetType = 0;
+ } else {
+ psEnc->sCmn.indices.quantOffsetType = 1;
+ }
+ }
+
+ /*******************************/
+ /* Control bandwidth expansion */
+ /*******************************/
+ /* More BWE for signals with high prediction gain */
+ strength = FIND_PITCH_WHITE_NOISE_FRACTION * psEncCtrl->predGain; /* between 0.0 and 1.0 */
+ BWExp = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
+
+ /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
+ warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
+
+ /********************************************/
+ /* Compute noise shaping AR coefs and gains */
+ /********************************************/
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ /* Apply window: sine slope followed by flat part followed by cosine slope */
+ opus_int shift, slope_part, flat_part;
+ flat_part = psEnc->sCmn.fs_kHz * 3;
+ slope_part = ( psEnc->sCmn.shapeWinLength - flat_part ) / 2;
+
+ silk_apply_sine_window_FLP( x_windowed, x_ptr, 1, slope_part );
+ shift = slope_part;
+ silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(silk_float) );
+ shift += flat_part;
+ silk_apply_sine_window_FLP( x_windowed + shift, x_ptr + shift, 2, slope_part );
+
+ /* Update pointer: next LPC analysis block */
+ x_ptr += psEnc->sCmn.subfr_length;
+
+ if( psEnc->sCmn.warping_Q16 > 0 ) {
+ /* Calculate warped auto correlation */
+ silk_warped_autocorrelation_FLP( auto_corr, x_windowed, warping,
+ psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
+ } else {
+ /* Calculate regular auto correlation */
+ silk_autocorrelation_FLP( auto_corr, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, psEnc->sCmn.arch );
+ }
+
+ /* Add white noise, as a fraction of energy */
+ auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION + 1.0f;
+
+ /* Convert correlations to prediction coefficients, and compute residual energy */
+ nrg = silk_schur_FLP( rc, auto_corr, psEnc->sCmn.shapingLPCOrder );
+ silk_k2a_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], rc, psEnc->sCmn.shapingLPCOrder );
+ psEncCtrl->Gains[ k ] = ( silk_float )sqrt( nrg );
+
+ if( psEnc->sCmn.warping_Q16 > 0 ) {
+ /* Adjust gain for warping */
+ psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
+ }
+
+ /* Bandwidth expansion for synthesis filter shaping */
+ silk_bwexpander_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp );
+
+ if( psEnc->sCmn.warping_Q16 > 0 ) {
+ /* Convert to monic warped prediction coefficients and limit absolute values */
+ warped_true2monic_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
+ } else {
+ /* Limit absolute values */
+ limit_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], 3.999f, psEnc->sCmn.shapingLPCOrder );
+ }
+ }
+
+ /*****************/
+ /* Gain tweaking */
+ /*****************/
+ /* Increase gains during low speech activity */
+ gain_mult = (silk_float)pow( 2.0f, -0.16f * SNR_adj_dB );
+ gain_add = (silk_float)pow( 2.0f, 0.16f * MIN_QGAIN_DB );
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ psEncCtrl->Gains[ k ] *= gain_mult;
+ psEncCtrl->Gains[ k ] += gain_add;
+ }
+
+ /************************************************/
+ /* Control low-frequency shaping and noise tilt */
+ /************************************************/
+ /* Less low frequency shaping for noisy inputs */
+ strength = LOW_FREQ_SHAPING * ( 1.0f + LOW_QUALITY_LOW_FREQ_SHAPING_DECR * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] * ( 1.0f / 32768.0f ) - 1.0f ) );
+ strength *= psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f );
+ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+ /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */
+ /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ b = 0.2f / psEnc->sCmn.fs_kHz + 3.0f / psEncCtrl->pitchL[ k ];
+ psEncCtrl->LF_MA_shp[ k ] = -1.0f + b;
+ psEncCtrl->LF_AR_shp[ k ] = 1.0f - b - b * strength;
+ }
+ Tilt = - HP_NOISE_COEF -
+ (1 - HP_NOISE_COEF) * HARM_HP_NOISE_COEF * psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f );
+ } else {
+ b = 1.3f / psEnc->sCmn.fs_kHz;
+ psEncCtrl->LF_MA_shp[ 0 ] = -1.0f + b;
+ psEncCtrl->LF_AR_shp[ 0 ] = 1.0f - b - b * strength * 0.6f;
+ for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) {
+ psEncCtrl->LF_MA_shp[ k ] = psEncCtrl->LF_MA_shp[ 0 ];
+ psEncCtrl->LF_AR_shp[ k ] = psEncCtrl->LF_AR_shp[ 0 ];
+ }
+ Tilt = -HP_NOISE_COEF;
+ }
+
+ /****************************/
+ /* HARMONIC SHAPING CONTROL */
+ /****************************/
+ if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+ /* Harmonic noise shaping */
+ HarmShapeGain = HARMONIC_SHAPING;
+
+ /* More harmonic noise shaping for high bitrates or noisy input */
+ HarmShapeGain += HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING *
+ ( 1.0f - ( 1.0f - psEncCtrl->coding_quality ) * psEncCtrl->input_quality );
+
+ /* Less harmonic noise shaping for less periodic signals */
+ HarmShapeGain *= ( silk_float )sqrt( psEnc->LTPCorr );
+ } else {
+ HarmShapeGain = 0.0f;
+ }
+
+ /*************************/
+ /* Smooth over subframes */
+ /*************************/
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth );
+ psEncCtrl->HarmShapeGain[ k ] = psShapeSt->HarmShapeGain_smth;
+ psShapeSt->Tilt_smth += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth );
+ psEncCtrl->Tilt[ k ] = psShapeSt->Tilt_smth;
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*****************************************************************************
+* Pitch analyser function
+******************************************************************************/
+#include "SigProc_FLP.h"
+#include "SigProc_FIX.h"
+#include "pitch_est_defines.h"
+#include "pitch.h"
+
+#define SCRATCH_SIZE 22
+
+/************************************************************/
+/* Internally used functions */
+/************************************************************/
+static void silk_P_Ana_calc_corr_st3(
+ silk_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */
+ const silk_float frame[], /* I vector to correlate */
+ opus_int start_lag, /* I start lag */
+ opus_int sf_length, /* I sub frame length */
+ opus_int nb_subfr, /* I number of subframes */
+ opus_int complexity, /* I Complexity setting */
+ int arch /* I Run-time architecture */
+);
+
+static void silk_P_Ana_calc_energy_st3(
+ silk_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */
+ const silk_float frame[], /* I vector to correlate */
+ opus_int start_lag, /* I start lag */
+ opus_int sf_length, /* I sub frame length */
+ opus_int nb_subfr, /* I number of subframes */
+ opus_int complexity /* I Complexity setting */
+);
+
+/************************************************************/
+/* CORE PITCH ANALYSIS FUNCTION */
+/************************************************************/
+opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced, 1 unvoiced */
+ const silk_float *frame, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */
+ opus_int *pitch_out, /* O Pitch lag values [nb_subfr] */
+ opus_int16 *lagIndex, /* O Lag Index */
+ opus_int8 *contourIndex, /* O Pitch contour Index */
+ silk_float *LTPCorr, /* I/O Normalized correlation; input: value from previous frame */
+ opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */
+ const silk_float search_thres1, /* I First stage threshold for lag candidates 0 - 1 */
+ const silk_float search_thres2, /* I Final threshold for lag candidates 0 - 1 */
+ const opus_int Fs_kHz, /* I sample frequency (kHz) */
+ const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */
+ const opus_int nb_subfr, /* I Number of 5 ms subframes */
+ int arch /* I Run-time architecture */
+)
+{
+ opus_int i, k, d, j;
+ silk_float frame_8kHz[ PE_MAX_FRAME_LENGTH_MS * 8 ];
+ silk_float frame_4kHz[ PE_MAX_FRAME_LENGTH_MS * 4 ];
+ opus_int16 frame_8_FIX[ PE_MAX_FRAME_LENGTH_MS * 8 ];
+ opus_int16 frame_4_FIX[ PE_MAX_FRAME_LENGTH_MS * 4 ];
+ opus_int32 filt_state[ 6 ];
+ silk_float threshold, contour_bias;
+ silk_float C[ PE_MAX_NB_SUBFR][ (PE_MAX_LAG >> 1) + 5 ];
+ opus_val32 xcorr[ PE_MAX_LAG_MS * 4 - PE_MIN_LAG_MS * 4 + 1 ];
+ silk_float CC[ PE_NB_CBKS_STAGE2_EXT ];
+ const silk_float *target_ptr, *basis_ptr;
+ double cross_corr, normalizer, energy, energy_tmp;
+ opus_int d_srch[ PE_D_SRCH_LENGTH ];
+ opus_int16 d_comp[ (PE_MAX_LAG >> 1) + 5 ];
+ opus_int length_d_srch, length_d_comp;
+ silk_float Cmax, CCmax, CCmax_b, CCmax_new_b, CCmax_new;
+ opus_int CBimax, CBimax_new, lag, start_lag, end_lag, lag_new;
+ opus_int cbk_size;
+ silk_float lag_log2, prevLag_log2, delta_lag_log2_sqr;
+ silk_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ];
+ silk_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ];
+ opus_int lag_counter;
+ opus_int frame_length, frame_length_8kHz, frame_length_4kHz;
+ opus_int sf_length, sf_length_8kHz, sf_length_4kHz;
+ opus_int min_lag, min_lag_8kHz, min_lag_4kHz;
+ opus_int max_lag, max_lag_8kHz, max_lag_4kHz;
+ opus_int nb_cbk_search;
+ const opus_int8 *Lag_CB_ptr;
+
+ /* Check for valid sampling frequency */
+ celt_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
+
+ /* Check for valid complexity setting */
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
+
+ silk_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f );
+ silk_assert( search_thres2 >= 0.0f && search_thres2 <= 1.0f );
+
+ /* Set up frame lengths max / min lag for the sampling frequency */
+ frame_length = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * Fs_kHz;
+ frame_length_4kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 4;
+ frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8;
+ sf_length = PE_SUBFR_LENGTH_MS * Fs_kHz;
+ sf_length_4kHz = PE_SUBFR_LENGTH_MS * 4;
+ sf_length_8kHz = PE_SUBFR_LENGTH_MS * 8;
+ min_lag = PE_MIN_LAG_MS * Fs_kHz;
+ min_lag_4kHz = PE_MIN_LAG_MS * 4;
+ min_lag_8kHz = PE_MIN_LAG_MS * 8;
+ max_lag = PE_MAX_LAG_MS * Fs_kHz - 1;
+ max_lag_4kHz = PE_MAX_LAG_MS * 4;
+ max_lag_8kHz = PE_MAX_LAG_MS * 8 - 1;
+
+ /* Resample from input sampled at Fs_kHz to 8 kHz */
+ if( Fs_kHz == 16 ) {
+ /* Resample to 16 -> 8 khz */
+ opus_int16 frame_16_FIX[ 16 * PE_MAX_FRAME_LENGTH_MS ];
+ silk_float2short_array( frame_16_FIX, frame, frame_length );
+ silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );
+ silk_resampler_down2( filt_state, frame_8_FIX, frame_16_FIX, frame_length );
+ silk_short2float_array( frame_8kHz, frame_8_FIX, frame_length_8kHz );
+ } else if( Fs_kHz == 12 ) {
+ /* Resample to 12 -> 8 khz */
+ opus_int16 frame_12_FIX[ 12 * PE_MAX_FRAME_LENGTH_MS ];
+ silk_float2short_array( frame_12_FIX, frame, frame_length );
+ silk_memset( filt_state, 0, 6 * sizeof( opus_int32 ) );
+ silk_resampler_down2_3( filt_state, frame_8_FIX, frame_12_FIX, frame_length );
+ silk_short2float_array( frame_8kHz, frame_8_FIX, frame_length_8kHz );
+ } else {
+ celt_assert( Fs_kHz == 8 );
+ silk_float2short_array( frame_8_FIX, frame, frame_length_8kHz );
+ }
+
+ /* Decimate again to 4 kHz */
+ silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );
+ silk_resampler_down2( filt_state, frame_4_FIX, frame_8_FIX, frame_length_8kHz );
+ silk_short2float_array( frame_4kHz, frame_4_FIX, frame_length_4kHz );
+
+ /* Low-pass filter */
+ for( i = frame_length_4kHz - 1; i > 0; i-- ) {
+ frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] );
+ }
+
+ /******************************************************************************
+ * FIRST STAGE, operating in 4 khz
+ ******************************************************************************/
+ silk_memset(C, 0, sizeof(silk_float) * nb_subfr * ((PE_MAX_LAG >> 1) + 5));
+ target_ptr = &frame_4kHz[ silk_LSHIFT( sf_length_4kHz, 2 ) ];
+ for( k = 0; k < nb_subfr >> 1; k++ ) {
+ /* Check that we are within range of the array */
+ celt_assert( target_ptr >= frame_4kHz );
+ celt_assert( target_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
+
+ basis_ptr = target_ptr - min_lag_4kHz;
+
+ /* Check that we are within range of the array */
+ celt_assert( basis_ptr >= frame_4kHz );
+ celt_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
+
+ celt_pitch_xcorr( target_ptr, target_ptr-max_lag_4kHz, xcorr, sf_length_8kHz, max_lag_4kHz - min_lag_4kHz + 1, arch );
+
+ /* Calculate first vector products before loop */
+ cross_corr = xcorr[ max_lag_4kHz - min_lag_4kHz ];
+ normalizer = silk_energy_FLP( target_ptr, sf_length_8kHz ) +
+ silk_energy_FLP( basis_ptr, sf_length_8kHz ) +
+ sf_length_8kHz * 4000.0f;
+
+ C[ 0 ][ min_lag_4kHz ] += (silk_float)( 2 * cross_corr / normalizer );
+
+ /* From now on normalizer is computed recursively */
+ for( d = min_lag_4kHz + 1; d <= max_lag_4kHz; d++ ) {
+ basis_ptr--;
+
+ /* Check that we are within range of the array */
+ silk_assert( basis_ptr >= frame_4kHz );
+ silk_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
+
+ cross_corr = xcorr[ max_lag_4kHz - d ];
+
+ /* Add contribution of new sample and remove contribution from oldest sample */
+ normalizer +=
+ basis_ptr[ 0 ] * (double)basis_ptr[ 0 ] -
+ basis_ptr[ sf_length_8kHz ] * (double)basis_ptr[ sf_length_8kHz ];
+ C[ 0 ][ d ] += (silk_float)( 2 * cross_corr / normalizer );
+ }
+ /* Update target pointer */
+ target_ptr += sf_length_8kHz;
+ }
+
+ /* Apply short-lag bias */
+ for( i = max_lag_4kHz; i >= min_lag_4kHz; i-- ) {
+ C[ 0 ][ i ] -= C[ 0 ][ i ] * i / 4096.0f;
+ }
+
+ /* Sort */
+ length_d_srch = 4 + 2 * complexity;
+ celt_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
+ silk_insertion_sort_decreasing_FLP( &C[ 0 ][ min_lag_4kHz ], d_srch, max_lag_4kHz - min_lag_4kHz + 1, length_d_srch );
+
+ /* Escape if correlation is very low already here */
+ Cmax = C[ 0 ][ min_lag_4kHz ];
+ if( Cmax < 0.2f ) {
+ silk_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) );
+ *LTPCorr = 0.0f;
+ *lagIndex = 0;
+ *contourIndex = 0;
+ return 1;
+ }
+
+ threshold = search_thres1 * Cmax;
+ for( i = 0; i < length_d_srch; i++ ) {
+ /* Convert to 8 kHz indices for the sorted correlation that exceeds the threshold */
+ if( C[ 0 ][ min_lag_4kHz + i ] > threshold ) {
+ d_srch[ i ] = silk_LSHIFT( d_srch[ i ] + min_lag_4kHz, 1 );
+ } else {
+ length_d_srch = i;
+ break;
+ }
+ }
+ celt_assert( length_d_srch > 0 );
+
+ for( i = min_lag_8kHz - 5; i < max_lag_8kHz + 5; i++ ) {
+ d_comp[ i ] = 0;
+ }
+ for( i = 0; i < length_d_srch; i++ ) {
+ d_comp[ d_srch[ i ] ] = 1;
+ }
+
+ /* Convolution */
+ for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) {
+ d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ];
+ }
+
+ length_d_srch = 0;
+ for( i = min_lag_8kHz; i < max_lag_8kHz + 1; i++ ) {
+ if( d_comp[ i + 1 ] > 0 ) {
+ d_srch[ length_d_srch ] = i;
+ length_d_srch++;
+ }
+ }
+
+ /* Convolution */
+ for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) {
+ d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ] + d_comp[ i - 3 ];
+ }
+
+ length_d_comp = 0;
+ for( i = min_lag_8kHz; i < max_lag_8kHz + 4; i++ ) {
+ if( d_comp[ i ] > 0 ) {
+ d_comp[ length_d_comp ] = (opus_int16)( i - 2 );
+ length_d_comp++;
+ }
+ }
+
+ /**********************************************************************************
+ ** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation
+ *************************************************************************************/
+ /*********************************************************************************
+ * Find energy of each subframe projected onto its history, for a range of delays
+ *********************************************************************************/
+ silk_memset( C, 0, PE_MAX_NB_SUBFR*((PE_MAX_LAG >> 1) + 5) * sizeof(silk_float));
+
+ if( Fs_kHz == 8 ) {
+ target_ptr = &frame[ PE_LTP_MEM_LENGTH_MS * 8 ];
+ } else {
+ target_ptr = &frame_8kHz[ PE_LTP_MEM_LENGTH_MS * 8 ];
+ }
+ for( k = 0; k < nb_subfr; k++ ) {
+ energy_tmp = silk_energy_FLP( target_ptr, sf_length_8kHz ) + 1.0;
+ for( j = 0; j < length_d_comp; j++ ) {
+ d = d_comp[ j ];
+ basis_ptr = target_ptr - d;
+ cross_corr = silk_inner_product_FLP( basis_ptr, target_ptr, sf_length_8kHz, arch );
+ if( cross_corr > 0.0f ) {
+ energy = silk_energy_FLP( basis_ptr, sf_length_8kHz );
+ C[ k ][ d ] = (silk_float)( 2 * cross_corr / ( energy + energy_tmp ) );
+ } else {
+ C[ k ][ d ] = 0.0f;
+ }
+ }
+ target_ptr += sf_length_8kHz;
+ }
+
+ /* search over lag range and lags codebook */
+ /* scale factor for lag codebook, as a function of center lag */
+
+ CCmax = 0.0f; /* This value doesn't matter */
+ CCmax_b = -1000.0f;
+
+ CBimax = 0; /* To avoid returning undefined lag values */
+ lag = -1; /* To check if lag with strong enough correlation has been found */
+
+ if( prevLag > 0 ) {
+ if( Fs_kHz == 12 ) {
+ prevLag = silk_LSHIFT( prevLag, 1 ) / 3;
+ } else if( Fs_kHz == 16 ) {
+ prevLag = silk_RSHIFT( prevLag, 1 );
+ }
+ prevLag_log2 = silk_log2( (silk_float)prevLag );
+ } else {
+ prevLag_log2 = 0;
+ }
+
+ /* Set up stage 2 codebook based on number of subframes */
+ if( nb_subfr == PE_MAX_NB_SUBFR ) {
+ cbk_size = PE_NB_CBKS_STAGE2_EXT;
+ Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
+ if( Fs_kHz == 8 && complexity > SILK_PE_MIN_COMPLEX ) {
+ /* If input is 8 khz use a larger codebook here because it is last stage */
+ nb_cbk_search = PE_NB_CBKS_STAGE2_EXT;
+ } else {
+ nb_cbk_search = PE_NB_CBKS_STAGE2;
+ }
+ } else {
+ cbk_size = PE_NB_CBKS_STAGE2_10MS;
+ Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ];
+ nb_cbk_search = PE_NB_CBKS_STAGE2_10MS;
+ }
+
+ for( k = 0; k < length_d_srch; k++ ) {
+ d = d_srch[ k ];
+ for( j = 0; j < nb_cbk_search; j++ ) {
+ CC[j] = 0.0f;
+ for( i = 0; i < nb_subfr; i++ ) {
+ /* Try all codebooks */
+ CC[ j ] += C[ i ][ d + matrix_ptr( Lag_CB_ptr, i, j, cbk_size )];
+ }
+ }
+ /* Find best codebook */
+ CCmax_new = -1000.0f;
+ CBimax_new = 0;
+ for( i = 0; i < nb_cbk_search; i++ ) {
+ if( CC[ i ] > CCmax_new ) {
+ CCmax_new = CC[ i ];
+ CBimax_new = i;
+ }
+ }
+
+ /* Bias towards shorter lags */
+ lag_log2 = silk_log2( (silk_float)d );
+ CCmax_new_b = CCmax_new - PE_SHORTLAG_BIAS * nb_subfr * lag_log2;
+
+ /* Bias towards previous lag */
+ if( prevLag > 0 ) {
+ delta_lag_log2_sqr = lag_log2 - prevLag_log2;
+ delta_lag_log2_sqr *= delta_lag_log2_sqr;
+ CCmax_new_b -= PE_PREVLAG_BIAS * nb_subfr * (*LTPCorr) * delta_lag_log2_sqr / ( delta_lag_log2_sqr + 0.5f );
+ }
+
+ if( CCmax_new_b > CCmax_b && /* Find maximum biased correlation */
+ CCmax_new > nb_subfr * search_thres2 /* Correlation needs to be high enough to be voiced */
+ ) {
+ CCmax_b = CCmax_new_b;
+ CCmax = CCmax_new;
+ lag = d;
+ CBimax = CBimax_new;
+ }
+ }
+
+ if( lag == -1 ) {
+ /* No suitable candidate found */
+ silk_memset( pitch_out, 0, PE_MAX_NB_SUBFR * sizeof(opus_int) );
+ *LTPCorr = 0.0f;
+ *lagIndex = 0;
+ *contourIndex = 0;
+ return 1;
+ }
+
+ /* Output normalized correlation */
+ *LTPCorr = (silk_float)( CCmax / nb_subfr );
+ silk_assert( *LTPCorr >= 0.0f );
+
+ if( Fs_kHz > 8 ) {
+ /* Search in original signal */
+
+ /* Compensate for decimation */
+ silk_assert( lag == silk_SAT16( lag ) );
+ if( Fs_kHz == 12 ) {
+ lag = silk_RSHIFT_ROUND( silk_SMULBB( lag, 3 ), 1 );
+ } else { /* Fs_kHz == 16 */
+ lag = silk_LSHIFT( lag, 1 );
+ }
+
+ lag = silk_LIMIT_int( lag, min_lag, max_lag );
+ start_lag = silk_max_int( lag - 2, min_lag );
+ end_lag = silk_min_int( lag + 2, max_lag );
+ lag_new = lag; /* to avoid undefined lag */
+ CBimax = 0; /* to avoid undefined lag */
+
+ CCmax = -1000.0f;
+
+ /* Calculate the correlations and energies needed in stage 3 */
+ silk_P_Ana_calc_corr_st3( cross_corr_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch );
+ silk_P_Ana_calc_energy_st3( energies_st3, frame, start_lag, sf_length, nb_subfr, complexity );
+
+ lag_counter = 0;
+ silk_assert( lag == silk_SAT16( lag ) );
+ contour_bias = PE_FLATCONTOUR_BIAS / lag;
+
+ /* Set up cbk parameters according to complexity setting and frame length */
+ if( nb_subfr == PE_MAX_NB_SUBFR ) {
+ nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ];
+ cbk_size = PE_NB_CBKS_STAGE3_MAX;
+ Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
+ } else {
+ nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
+ cbk_size = PE_NB_CBKS_STAGE3_10MS;
+ Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
+ }
+
+ target_ptr = &frame[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ];
+ energy_tmp = silk_energy_FLP( target_ptr, nb_subfr * sf_length ) + 1.0;
+ for( d = start_lag; d <= end_lag; d++ ) {
+ for( j = 0; j < nb_cbk_search; j++ ) {
+ cross_corr = 0.0;
+ energy = energy_tmp;
+ for( k = 0; k < nb_subfr; k++ ) {
+ cross_corr += cross_corr_st3[ k ][ j ][ lag_counter ];
+ energy += energies_st3[ k ][ j ][ lag_counter ];
+ }
+ if( cross_corr > 0.0 ) {
+ CCmax_new = (silk_float)( 2 * cross_corr / energy );
+ /* Reduce depending on flatness of contour */
+ CCmax_new *= 1.0f - contour_bias * j;
+ } else {
+ CCmax_new = 0.0f;
+ }
+
+ if( CCmax_new > CCmax && ( d + (opus_int)silk_CB_lags_stage3[ 0 ][ j ] ) <= max_lag ) {
+ CCmax = CCmax_new;
+ lag_new = d;
+ CBimax = j;
+ }
+ }
+ lag_counter++;
+ }
+
+ for( k = 0; k < nb_subfr; k++ ) {
+ pitch_out[ k ] = lag_new + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size );
+ pitch_out[ k ] = silk_LIMIT( pitch_out[ k ], min_lag, PE_MAX_LAG_MS * Fs_kHz );
+ }
+ *lagIndex = (opus_int16)( lag_new - min_lag );
+ *contourIndex = (opus_int8)CBimax;
+ } else { /* Fs_kHz == 8 */
+ /* Save Lags */
+ for( k = 0; k < nb_subfr; k++ ) {
+ pitch_out[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size );
+ pitch_out[ k ] = silk_LIMIT( pitch_out[ k ], min_lag_8kHz, PE_MAX_LAG_MS * 8 );
+ }
+ *lagIndex = (opus_int16)( lag - min_lag_8kHz );
+ *contourIndex = (opus_int8)CBimax;
+ }
+ celt_assert( *lagIndex >= 0 );
+ /* return as voiced */
+ return 0;
+}
+
+/***********************************************************************
+ * Calculates the correlations used in stage 3 search. In order to cover
+ * the whole lag codebook for all the searched offset lags (lag +- 2),
+ * the following correlations are needed in each sub frame:
+ *
+ * sf1: lag range [-8,...,7] total 16 correlations
+ * sf2: lag range [-4,...,4] total 9 correlations
+ * sf3: lag range [-3,....4] total 8 correltions
+ * sf4: lag range [-6,....8] total 15 correlations
+ *
+ * In total 48 correlations. The direct implementation computed in worst
+ * case 4*12*5 = 240 correlations, but more likely around 120.
+ ***********************************************************************/
+static void silk_P_Ana_calc_corr_st3(
+ silk_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */
+ const silk_float frame[], /* I vector to correlate */
+ opus_int start_lag, /* I start lag */
+ opus_int sf_length, /* I sub frame length */
+ opus_int nb_subfr, /* I number of subframes */
+ opus_int complexity, /* I Complexity setting */
+ int arch /* I Run-time architecture */
+)
+{
+ const silk_float *target_ptr;
+ opus_int i, j, k, lag_counter, lag_low, lag_high;
+ opus_int nb_cbk_search, delta, idx, cbk_size;
+ silk_float scratch_mem[ SCRATCH_SIZE ];
+ opus_val32 xcorr[ SCRATCH_SIZE ];
+ const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
+
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
+
+ if( nb_subfr == PE_MAX_NB_SUBFR ) {
+ Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
+ Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
+ nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
+ cbk_size = PE_NB_CBKS_STAGE3_MAX;
+ } else {
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
+ Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
+ nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
+ cbk_size = PE_NB_CBKS_STAGE3_10MS;
+ }
+
+ target_ptr = &frame[ silk_LSHIFT( sf_length, 2 ) ]; /* Pointer to middle of frame */
+ for( k = 0; k < nb_subfr; k++ ) {
+ lag_counter = 0;
+
+ /* Calculate the correlations for each subframe */
+ lag_low = matrix_ptr( Lag_range_ptr, k, 0, 2 );
+ lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 );
+ silk_assert(lag_high-lag_low+1 <= SCRATCH_SIZE);
+ celt_pitch_xcorr( target_ptr, target_ptr - start_lag - lag_high, xcorr, sf_length, lag_high - lag_low + 1, arch );
+ for( j = lag_low; j <= lag_high; j++ ) {
+ silk_assert( lag_counter < SCRATCH_SIZE );
+ scratch_mem[ lag_counter ] = xcorr[ lag_high - j ];
+ lag_counter++;
+ }
+
+ delta = matrix_ptr( Lag_range_ptr, k, 0, 2 );
+ for( i = 0; i < nb_cbk_search; i++ ) {
+ /* Fill out the 3 dim array that stores the correlations for */
+ /* each code_book vector for each start lag */
+ idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta;
+ for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) {
+ silk_assert( idx + j < SCRATCH_SIZE );
+ silk_assert( idx + j < lag_counter );
+ cross_corr_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ];
+ }
+ }
+ target_ptr += sf_length;
+ }
+}
+
+/********************************************************************/
+/* Calculate the energies for first two subframes. The energies are */
+/* calculated recursively. */
+/********************************************************************/
+static void silk_P_Ana_calc_energy_st3(
+ silk_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */
+ const silk_float frame[], /* I vector to correlate */
+ opus_int start_lag, /* I start lag */
+ opus_int sf_length, /* I sub frame length */
+ opus_int nb_subfr, /* I number of subframes */
+ opus_int complexity /* I Complexity setting */
+)
+{
+ const silk_float *target_ptr, *basis_ptr;
+ double energy;
+ opus_int k, i, j, lag_counter;
+ opus_int nb_cbk_search, delta, idx, cbk_size, lag_diff;
+ silk_float scratch_mem[ SCRATCH_SIZE ];
+ const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
+
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
+
+ if( nb_subfr == PE_MAX_NB_SUBFR ) {
+ Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
+ Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
+ nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
+ cbk_size = PE_NB_CBKS_STAGE3_MAX;
+ } else {
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
+ Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
+ nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
+ cbk_size = PE_NB_CBKS_STAGE3_10MS;
+ }
+
+ target_ptr = &frame[ silk_LSHIFT( sf_length, 2 ) ];
+ for( k = 0; k < nb_subfr; k++ ) {
+ lag_counter = 0;
+
+ /* Calculate the energy for first lag */
+ basis_ptr = target_ptr - ( start_lag + matrix_ptr( Lag_range_ptr, k, 0, 2 ) );
+ energy = silk_energy_FLP( basis_ptr, sf_length ) + 1e-3;
+ silk_assert( energy >= 0.0 );
+ scratch_mem[lag_counter] = (silk_float)energy;
+ lag_counter++;
+
+ lag_diff = ( matrix_ptr( Lag_range_ptr, k, 1, 2 ) - matrix_ptr( Lag_range_ptr, k, 0, 2 ) + 1 );
+ for( i = 1; i < lag_diff; i++ ) {
+ /* remove part outside new window */
+ energy -= basis_ptr[sf_length - i] * (double)basis_ptr[sf_length - i];
+ silk_assert( energy >= 0.0 );
+
+ /* add part that comes into window */
+ energy += basis_ptr[ -i ] * (double)basis_ptr[ -i ];
+ silk_assert( energy >= 0.0 );
+ silk_assert( lag_counter < SCRATCH_SIZE );
+ scratch_mem[lag_counter] = (silk_float)energy;
+ lag_counter++;
+ }
+
+ delta = matrix_ptr( Lag_range_ptr, k, 0, 2 );
+ for( i = 0; i < nb_cbk_search; i++ ) {
+ /* Fill out the 3 dim array that stores the correlations for */
+ /* each code_book vector for each start lag */
+ idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta;
+ for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) {
+ silk_assert( idx + j < SCRATCH_SIZE );
+ silk_assert( idx + j < lag_counter );
+ energies_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ];
+ silk_assert( energies_st3[ k ][ i ][ j ] >= 0.0f );
+ }
+ }
+ target_ptr += sf_length;
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+#include "tuning_parameters.h"
+
+/* Processing of gains */
+void silk_process_gains_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ opus_int condCoding /* I The type of conditional coding to use */
+)
+{
+ silk_shape_state_FLP *psShapeSt = &psEnc->sShape;
+ opus_int k;
+ opus_int32 pGains_Q16[ MAX_NB_SUBFR ];
+ silk_float s, InvMaxSqrVal, gain, quant_offset;
+
+ /* Gain reduction when LTP coding gain is high */
+ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+ s = 1.0f - 0.5f * silk_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) );
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ psEncCtrl->Gains[ k ] *= s;
+ }
+ }
+
+ /* Limit the quantized signal */
+ InvMaxSqrVal = ( silk_float )( pow( 2.0f, 0.33f * ( 21.0f - psEnc->sCmn.SNR_dB_Q7 * ( 1 / 128.0f ) ) ) / psEnc->sCmn.subfr_length );
+
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ /* Soft limit on ratio residual energy and squared gains */
+ gain = psEncCtrl->Gains[ k ];
+ gain = ( silk_float )sqrt( gain * gain + psEncCtrl->ResNrg[ k ] * InvMaxSqrVal );
+ psEncCtrl->Gains[ k ] = silk_min_float( gain, 32767.0f );
+ }
+
+ /* Prepare gains for noise shaping quantization */
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ pGains_Q16[ k ] = (opus_int32)( psEncCtrl->Gains[ k ] * 65536.0f );
+ }
+
+ /* Save unquantized gains and gain Index */
+ silk_memcpy( psEncCtrl->GainsUnq_Q16, pGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
+ psEncCtrl->lastGainIndexPrev = psShapeSt->LastGainIndex;
+
+ /* Quantize gains */
+ silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16,
+ &psShapeSt->LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
+
+ /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */
+ for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
+ psEncCtrl->Gains[ k ] = pGains_Q16[ k ] / 65536.0f;
+ }
+
+ /* Set quantizer offset for voiced signals. Larger offset when LTP coding gain is low or tilt is high (ie low-pass) */
+ if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
+ if( psEncCtrl->LTPredCodGain + psEnc->sCmn.input_tilt_Q15 * ( 1.0f / 32768.0f ) > 1.0f ) {
+ psEnc->sCmn.indices.quantOffsetType = 0;
+ } else {
+ psEnc->sCmn.indices.quantOffsetType = 1;
+ }
+ }
+
+ /* Quantizer boundary adjustment */
+ quant_offset = silk_Quantization_Offsets_Q10[ psEnc->sCmn.indices.signalType >> 1 ][ psEnc->sCmn.indices.quantOffsetType ] / 1024.0f;
+ psEncCtrl->Lambda = LAMBDA_OFFSET
+ + LAMBDA_DELAYED_DECISIONS * psEnc->sCmn.nStatesDelayedDecision
+ + LAMBDA_SPEECH_ACT * psEnc->sCmn.speech_activity_Q8 * ( 1.0f / 256.0f )
+ + LAMBDA_INPUT_QUALITY * psEncCtrl->input_quality
+ + LAMBDA_CODING_QUALITY * psEncCtrl->coding_quality
+ + LAMBDA_QUANT_OFFSET * quant_offset;
+
+ silk_assert( psEncCtrl->Lambda > 0.0f );
+ silk_assert( psEncCtrl->Lambda < 2.0f );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+/* Add noise to matrix diagonal */
+void silk_regularize_correlations_FLP(
+ silk_float *XX, /* I/O Correlation matrices */
+ silk_float *xx, /* I/O Correlation values */
+ const silk_float noise, /* I Noise energy to add */
+ const opus_int D /* I Dimension of XX */
+)
+{
+ opus_int i;
+
+ for( i = 0; i < D; i++ ) {
+ matrix_ptr( &XX[ 0 ], i, i, D ) += noise;
+ }
+ xx[ 0 ] += noise;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+#define MAX_ITERATIONS_RESIDUAL_NRG 10
+#define REGULARIZATION_FACTOR 1e-8f
+
+/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */
+silk_float silk_residual_energy_covar_FLP( /* O Weighted residual energy */
+ const silk_float *c, /* I Filter coefficients */
+ silk_float *wXX, /* I/O Weighted correlation matrix, reg. out */
+ const silk_float *wXx, /* I Weighted correlation vector */
+ const silk_float wxx, /* I Weighted correlation value */
+ const opus_int D /* I Dimension */
+)
+{
+ opus_int i, j, k;
+ silk_float tmp, nrg = 0.0f, regularization;
+
+ /* Safety checks */
+ celt_assert( D >= 0 );
+
+ regularization = REGULARIZATION_FACTOR * ( wXX[ 0 ] + wXX[ D * D - 1 ] );
+ for( k = 0; k < MAX_ITERATIONS_RESIDUAL_NRG; k++ ) {
+ nrg = wxx;
+
+ tmp = 0.0f;
+ for( i = 0; i < D; i++ ) {
+ tmp += wXx[ i ] * c[ i ];
+ }
+ nrg -= 2.0f * tmp;
+
+ /* compute c' * wXX * c, assuming wXX is symmetric */
+ for( i = 0; i < D; i++ ) {
+ tmp = 0.0f;
+ for( j = i + 1; j < D; j++ ) {
+ tmp += matrix_c_ptr( wXX, i, j, D ) * c[ j ];
+ }
+ nrg += c[ i ] * ( 2.0f * tmp + matrix_c_ptr( wXX, i, i, D ) * c[ i ] );
+ }
+ if( nrg > 0 ) {
+ break;
+ } else {
+ /* Add white noise */
+ for( i = 0; i < D; i++ ) {
+ matrix_c_ptr( wXX, i, i, D ) += regularization;
+ }
+ /* Increase noise for next run */
+ regularization *= 2.0f;
+ }
+ }
+ if( k == MAX_ITERATIONS_RESIDUAL_NRG ) {
+ silk_assert( nrg == 0 );
+ nrg = 1.0f;
+ }
+
+ return nrg;
+}
+
+/* Calculates residual energies of input subframes where all subframes have LPC_order */
+/* of preceding samples */
+void silk_residual_energy_FLP(
+ silk_float nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */
+ const silk_float x[], /* I Input signal */
+ silk_float a[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */
+ const silk_float gains[], /* I Quantization gains */
+ const opus_int subfr_length, /* I Subframe length */
+ const opus_int nb_subfr, /* I number of subframes */
+ const opus_int LPC_order /* I LPC order */
+)
+{
+ opus_int shift;
+ silk_float *LPC_res_ptr, LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ];
+
+ LPC_res_ptr = LPC_res + LPC_order;
+ shift = LPC_order + subfr_length;
+
+ /* Filter input to create the LPC residual for each frame half, and measure subframe energies */
+ silk_LPC_analysis_filter_FLP( LPC_res, a[ 0 ], x + 0 * shift, 2 * shift, LPC_order );
+ nrgs[ 0 ] = ( silk_float )( gains[ 0 ] * gains[ 0 ] * silk_energy_FLP( LPC_res_ptr + 0 * shift, subfr_length ) );
+ nrgs[ 1 ] = ( silk_float )( gains[ 1 ] * gains[ 1 ] * silk_energy_FLP( LPC_res_ptr + 1 * shift, subfr_length ) );
+
+ if( nb_subfr == MAX_NB_SUBFR ) {
+ silk_LPC_analysis_filter_FLP( LPC_res, a[ 1 ], x + 2 * shift, 2 * shift, LPC_order );
+ nrgs[ 2 ] = ( silk_float )( gains[ 2 ] * gains[ 2 ] * silk_energy_FLP( LPC_res_ptr + 0 * shift, subfr_length ) );
+ nrgs[ 3 ] = ( silk_float )( gains[ 3 ] * gains[ 3 ] * silk_energy_FLP( LPC_res_ptr + 1 * shift, subfr_length ) );
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* copy and multiply a vector by a constant */
+void silk_scale_copy_vector_FLP(
+ silk_float *data_out,
+ const silk_float *data_in,
+ silk_float gain,
+ opus_int dataSize
+)
+{
+ opus_int i, dataSize4;
+
+ /* 4x unrolled loop */
+ dataSize4 = dataSize & 0xFFFC;
+ for( i = 0; i < dataSize4; i += 4 ) {
+ data_out[ i + 0 ] = gain * data_in[ i + 0 ];
+ data_out[ i + 1 ] = gain * data_in[ i + 1 ];
+ data_out[ i + 2 ] = gain * data_in[ i + 2 ];
+ data_out[ i + 3 ] = gain * data_in[ i + 3 ];
+ }
+
+ /* any remaining elements */
+ for( ; i < dataSize; i++ ) {
+ data_out[ i ] = gain * data_in[ i ];
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+/* multiply a vector by a constant */
+void silk_scale_vector_FLP(
+ silk_float *data1,
+ silk_float gain,
+ opus_int dataSize
+)
+{
+ opus_int i, dataSize4;
+
+ /* 4x unrolled loop */
+ dataSize4 = dataSize & 0xFFFC;
+ for( i = 0; i < dataSize4; i += 4 ) {
+ data1[ i + 0 ] *= gain;
+ data1[ i + 1 ] *= gain;
+ data1[ i + 2 ] *= gain;
+ data1[ i + 3 ] *= gain;
+ }
+
+ /* any remaining elements */
+ for( ; i < dataSize; i++ ) {
+ data1[ i ] *= gain;
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FLP.h"
+
+silk_float silk_schur_FLP( /* O returns residual energy */
+ silk_float refl_coef[], /* O reflection coefficients (length order) */
+ const silk_float auto_corr[], /* I autocorrelation sequence (length order+1) */
+ opus_int order /* I order */
+)
+{
+ opus_int k, n;
+ double C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
+ double Ctmp1, Ctmp2, rc_tmp;
+
+ celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
+
+ /* Copy correlations */
+ k = 0;
+ do {
+ C[ k ][ 0 ] = C[ k ][ 1 ] = auto_corr[ k ];
+ } while( ++k <= order );
+
+ for( k = 0; k < order; k++ ) {
+ /* Get reflection coefficient */
+ rc_tmp = -C[ k + 1 ][ 0 ] / silk_max_float( C[ 0 ][ 1 ], 1e-9f );
+
+ /* Save the output */
+ refl_coef[ k ] = (silk_float)rc_tmp;
+
+ /* Update correlations */
+ for( n = 0; n < order - k; n++ ) {
+ Ctmp1 = C[ n + k + 1 ][ 0 ];
+ Ctmp2 = C[ n ][ 1 ];
+ C[ n + k + 1 ][ 0 ] = Ctmp1 + Ctmp2 * rc_tmp;
+ C[ n ][ 1 ] = Ctmp2 + Ctmp1 * rc_tmp;
+ }
+ }
+
+ /* Return residual energy */
+ return (silk_float)C[ 0 ][ 1 ];
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Insertion sort (fast for already almost sorted arrays): */
+/* Best case: O(n) for an already sorted array */
+/* Worst case: O(n^2) for an inversely sorted array */
+
+#include "typedef.h"
+#include "SigProc_FLP.h"
+
+void silk_insertion_sort_decreasing_FLP(
+ silk_float *a, /* I/O Unsorted / Sorted vector */
+ opus_int *idx, /* O Index vector for the sorted elements */
+ const opus_int L, /* I Vector length */
+ const opus_int K /* I Number of correctly sorted positions */
+)
+{
+ silk_float value;
+ opus_int i, j;
+
+ /* Safety checks */
+ celt_assert( K > 0 );
+ celt_assert( L > 0 );
+ celt_assert( L >= K );
+
+ /* Write start indices in index vector */
+ for( i = 0; i < K; i++ ) {
+ idx[ i ] = i;
+ }
+
+ /* Sort vector elements by value, decreasing order */
+ for( i = 1; i < K; i++ ) {
+ value = a[ i ];
+ for( j = i - 1; ( j >= 0 ) && ( value > a[ j ] ); j-- ) {
+ a[ j + 1 ] = a[ j ]; /* Shift value */
+ idx[ j + 1 ] = idx[ j ]; /* Shift index */
+ }
+ a[ j + 1 ] = value; /* Write value */
+ idx[ j + 1 ] = i; /* Write index */
+ }
+
+ /* If less than L values are asked check the remaining values, */
+ /* but only spend CPU to ensure that the K first values are correct */
+ for( i = K; i < L; i++ ) {
+ value = a[ i ];
+ if( value > a[ K - 1 ] ) {
+ for( j = K - 2; ( j >= 0 ) && ( value > a[ j ] ); j-- ) {
+ a[ j + 1 ] = a[ j ]; /* Shift value */
+ idx[ j + 1 ] = idx[ j ]; /* Shift index */
+ }
+ a[ j + 1 ] = value; /* Write value */
+ idx[ j + 1 ] = i; /* Write index */
+ }
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+/* Autocorrelations for a warped frequency axis */
+void silk_warped_autocorrelation_FLP(
+ silk_float *corr, /* O Result [order + 1] */
+ const silk_float *input, /* I Input data to correlate */
+ const silk_float warping, /* I Warping coefficient */
+ const opus_int length, /* I Length of input */
+ const opus_int order /* I Correlation order (even) */
+)
+{
+ opus_int n, i;
+ double tmp1, tmp2;
+ double state[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
+ double C[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
+
+ /* Order must be even */
+ celt_assert( ( order & 1 ) == 0 );
+
+ /* Loop over samples */
+ for( n = 0; n < length; n++ ) {
+ tmp1 = input[ n ];
+ /* Loop over allpass sections */
+ for( i = 0; i < order; i += 2 ) {
+ /* Output of allpass section */
+ /* We voluntarily use two multiples instead of factoring the expression to
+ reduce the length of the dependency chain (tmp1->tmp2->tmp1... ). */
+ tmp2 = state[ i ] + warping * state[ i + 1 ] - warping * tmp1;
+ state[ i ] = tmp1;
+ C[ i ] += state[ 0 ] * tmp1;
+ /* Output of allpass section */
+ tmp1 = state[ i + 1 ] + warping * state[ i + 2 ] - warping * tmp2;
+ state[ i + 1 ] = tmp2;
+ C[ i + 1 ] += state[ 0 ] * tmp2;
+ }
+ state[ order ] = tmp1;
+ C[ order ] += state[ 0 ] * tmp1;
+ }
+
+ /* Copy correlations in silk_float output format */
+ for( i = 0; i < order + 1; i++ ) {
+ corr[ i ] = ( silk_float )C[ i ];
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FLP.h"
+
+/* Wrappers. Calls flp / fix code */
+
+/* Convert AR filter coefficients to NLSF parameters */
+void silk_A2NLSF_FLP(
+ opus_int16 *NLSF_Q15, /* O NLSF vector [ LPC_order ] */
+ const silk_float *pAR, /* I LPC coefficients [ LPC_order ] */
+ const opus_int LPC_order /* I LPC order */
+)
+{
+ opus_int i;
+ opus_int32 a_fix_Q16[ MAX_LPC_ORDER ];
+
+ for( i = 0; i < LPC_order; i++ ) {
+ a_fix_Q16[ i ] = silk_float2int( pAR[ i ] * 65536.0f );
+ }
+
+ silk_A2NLSF( NLSF_Q15, a_fix_Q16, LPC_order );
+}
+
+/* Convert LSF parameters to AR prediction filter coefficients */
+void silk_NLSF2A_FLP(
+ silk_float *pAR, /* O LPC coefficients [ LPC_order ] */
+ const opus_int16 *NLSF_Q15, /* I NLSF vector [ LPC_order ] */
+ const opus_int LPC_order, /* I LPC order */
+ int arch /* I Run-time architecture */
+)
+{
+ opus_int i;
+ opus_int16 a_fix_Q12[ MAX_LPC_ORDER ];
+
+ silk_NLSF2A( a_fix_Q12, NLSF_Q15, LPC_order, arch );
+
+ for( i = 0; i < LPC_order; i++ ) {
+ pAR[ i ] = ( silk_float )a_fix_Q12[ i ] * ( 1.0f / 4096.0f );
+ }
+}
+
+/******************************************/
+/* Floating-point NLSF processing wrapper */
+/******************************************/
+void silk_process_NLSFs_FLP(
+ silk_encoder_state *psEncC, /* I/O Encoder state */
+ silk_float PredCoef[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */
+ opus_int16 NLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */
+ const opus_int16 prev_NLSF_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */
+)
+{
+ opus_int i, j;
+ opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
+
+ silk_process_NLSFs( psEncC, PredCoef_Q12, NLSF_Q15, prev_NLSF_Q15);
+
+ for( j = 0; j < 2; j++ ) {
+ for( i = 0; i < psEncC->predictLPCOrder; i++ ) {
+ PredCoef[ j ][ i ] = ( silk_float )PredCoef_Q12[ j ][ i ] * ( 1.0f / 4096.0f );
+ }
+ }
+}
+
+/****************************************/
+/* Floating-point Silk NSQ wrapper */
+/****************************************/
+void silk_NSQ_wrapper_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ SideInfoIndices *psIndices, /* I/O Quantization indices */
+ silk_nsq_state *psNSQ, /* I/O Noise Shaping Quantzation state */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const silk_float x[] /* I Prefiltered input signal */
+)
+{
+ opus_int i, j;
+ opus_int16 x16[ MAX_FRAME_LENGTH ];
+ opus_int32 Gains_Q16[ MAX_NB_SUBFR ];
+ silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
+ opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ];
+ opus_int LTP_scale_Q14;
+
+ /* Noise shaping parameters */
+ opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+ opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */
+ opus_int Lambda_Q10;
+ opus_int Tilt_Q14[ MAX_NB_SUBFR ];
+ opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ];
+
+ /* Convert control struct to fix control struct */
+ /* Noise shape parameters */
+ for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ for( j = 0; j < psEnc->sCmn.shapingLPCOrder; j++ ) {
+ AR_Q13[ i * MAX_SHAPE_LPC_ORDER + j ] = silk_float2int( psEncCtrl->AR[ i * MAX_SHAPE_LPC_ORDER + j ] * 8192.0f );
+ }
+ }
+
+ for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ LF_shp_Q14[ i ] = silk_LSHIFT32( silk_float2int( psEncCtrl->LF_AR_shp[ i ] * 16384.0f ), 16 ) |
+ (opus_uint16)silk_float2int( psEncCtrl->LF_MA_shp[ i ] * 16384.0f );
+ Tilt_Q14[ i ] = (opus_int)silk_float2int( psEncCtrl->Tilt[ i ] * 16384.0f );
+ HarmShapeGain_Q14[ i ] = (opus_int)silk_float2int( psEncCtrl->HarmShapeGain[ i ] * 16384.0f );
+ }
+ Lambda_Q10 = ( opus_int )silk_float2int( psEncCtrl->Lambda * 1024.0f );
+
+ /* prediction and coding parameters */
+ for( i = 0; i < psEnc->sCmn.nb_subfr * LTP_ORDER; i++ ) {
+ LTPCoef_Q14[ i ] = (opus_int16)silk_float2int( psEncCtrl->LTPCoef[ i ] * 16384.0f );
+ }
+
+ for( j = 0; j < 2; j++ ) {
+ for( i = 0; i < psEnc->sCmn.predictLPCOrder; i++ ) {
+ PredCoef_Q12[ j ][ i ] = (opus_int16)silk_float2int( psEncCtrl->PredCoef[ j ][ i ] * 4096.0f );
+ }
+ }
+
+ for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+ Gains_Q16[ i ] = silk_float2int( psEncCtrl->Gains[ i ] * 65536.0f );
+ silk_assert( Gains_Q16[ i ] > 0 );
+ }
+
+ if( psIndices->signalType == TYPE_VOICED ) {
+ LTP_scale_Q14 = silk_LTPScales_table_Q14[ psIndices->LTP_scaleIndex ];
+ } else {
+ LTP_scale_Q14 = 0;
+ }
+
+ /* Convert input to fix */
+ for( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
+ x16[ i ] = silk_float2int( x[ i ] );
+ }
+
+ /* Call NSQ */
+ if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
+ silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
+ AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
+ } else {
+ silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
+ AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
+ }
+}
+
+/***********************************************/
+/* Floating-point Silk LTP quantiation wrapper */
+/***********************************************/
+void silk_quant_LTP_gains_FLP(
+ silk_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* O Quantized LTP gains */
+ opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook index */
+ opus_int8 *periodicity_index, /* O Periodicity index */
+ opus_int32 *sum_log_gain_Q7, /* I/O Cumulative max prediction gain */
+ silk_float *pred_gain_dB, /* O LTP prediction gain */
+ const silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Correlation matrix */
+ const silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* I Correlation vector */
+ const opus_int subfr_len, /* I Number of samples per subframe */
+ const opus_int nb_subfr, /* I Number of subframes */
+ int arch /* I Run-time architecture */
+)
+{
+ opus_int i, pred_gain_dB_Q7;
+ opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ];
+ opus_int32 XX_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
+ opus_int32 xX_Q17[ MAX_NB_SUBFR * LTP_ORDER ];
+
+ i = 0;
+ do {
+ XX_Q17[ i ] = (opus_int32)silk_float2int( XX[ i ] * 131072.0f );
+ } while ( ++i < nb_subfr * LTP_ORDER * LTP_ORDER );
+ i = 0;
+ do {
+ xX_Q17[ i ] = (opus_int32)silk_float2int( xX[ i ] * 131072.0f );
+ } while ( ++i < nb_subfr * LTP_ORDER );
+
+ silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, sum_log_gain_Q7, &pred_gain_dB_Q7, XX_Q17, xX_Q17, subfr_len, nb_subfr, arch );
+
+ for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) {
+ B[ i ] = (silk_float)B_Q14[ i ] * ( 1.0f / 16384.0f );
+ }
+
+ *pred_gain_dB = (silk_float)pred_gain_dB_Q7 * ( 1.0f / 128.0f );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+#define OFFSET ( ( MIN_QGAIN_DB * 128 ) / 6 + 16 * 128 )
+#define SCALE_Q16 ( ( 65536 * ( N_LEVELS_QGAIN - 1 ) ) / ( ( ( MAX_QGAIN_DB - MIN_QGAIN_DB ) * 128 ) / 6 ) )
+#define INV_SCALE_Q16 ( ( 65536 * ( ( ( MAX_QGAIN_DB - MIN_QGAIN_DB ) * 128 ) / 6 ) ) / ( N_LEVELS_QGAIN - 1 ) )
+
+/* Gain scalar quantization with hysteresis, uniform on log scale */
+void silk_gains_quant(
+ opus_int8 ind[ MAX_NB_SUBFR ], /* O gain indices */
+ opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* I/O gains (quantized out) */
+ opus_int8 *prev_ind, /* I/O last index in previous frame */
+ const opus_int conditional, /* I first gain is delta coded if 1 */
+ const opus_int nb_subfr /* I number of subframes */
+)
+{
+ opus_int k, double_step_size_threshold;
+
+ for( k = 0; k < nb_subfr; k++ ) {
+ /* Convert to log scale, scale, floor() */
+ ind[ k ] = silk_SMULWB( SCALE_Q16, silk_lin2log( gain_Q16[ k ] ) - OFFSET );
+
+ /* Round towards previous quantized gain (hysteresis) */
+ if( ind[ k ] < *prev_ind ) {
+ ind[ k ]++;
+ }
+ ind[ k ] = silk_LIMIT_int( ind[ k ], 0, N_LEVELS_QGAIN - 1 );
+
+ /* Compute delta indices and limit */
+ if( k == 0 && conditional == 0 ) {
+ /* Full index */
+ ind[ k ] = silk_LIMIT_int( ind[ k ], *prev_ind + MIN_DELTA_GAIN_QUANT, N_LEVELS_QGAIN - 1 );
+ *prev_ind = ind[ k ];
+ } else {
+ /* Delta index */
+ ind[ k ] = ind[ k ] - *prev_ind;
+
+ /* Double the quantization step size for large gain increases, so that the max gain level can be reached */
+ double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind;
+ if( ind[ k ] > double_step_size_threshold ) {
+ ind[ k ] = double_step_size_threshold + silk_RSHIFT( ind[ k ] - double_step_size_threshold + 1, 1 );
+ }
+
+ ind[ k ] = silk_LIMIT_int( ind[ k ], MIN_DELTA_GAIN_QUANT, MAX_DELTA_GAIN_QUANT );
+
+ /* Accumulate deltas */
+ if( ind[ k ] > double_step_size_threshold ) {
+ *prev_ind += silk_LSHIFT( ind[ k ], 1 ) - double_step_size_threshold;
+ *prev_ind = silk_min_int( *prev_ind, N_LEVELS_QGAIN - 1 );
+ } else {
+ *prev_ind += ind[ k ];
+ }
+
+ /* Shift to make non-negative */
+ ind[ k ] -= MIN_DELTA_GAIN_QUANT;
+ }
+
+ /* Scale and convert to linear scale */
+ gain_Q16[ k ] = silk_log2lin( silk_min_32( silk_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */
+ }
+}
+
+/* Gains scalar dequantization, uniform on log scale */
+void silk_gains_dequant(
+ opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* O quantized gains */
+ const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */
+ opus_int8 *prev_ind, /* I/O last index in previous frame */
+ const opus_int conditional, /* I first gain is delta coded if 1 */
+ const opus_int nb_subfr /* I number of subframes */
+)
+{
+ opus_int k, ind_tmp, double_step_size_threshold;
+
+ for( k = 0; k < nb_subfr; k++ ) {
+ if( k == 0 && conditional == 0 ) {
+ /* Gain index is not allowed to go down more than 16 steps (~21.8 dB) */
+ *prev_ind = silk_max_int( ind[ k ], *prev_ind - 16 );
+ } else {
+ /* Delta index */
+ ind_tmp = ind[ k ] + MIN_DELTA_GAIN_QUANT;
+
+ /* Accumulate deltas */
+ double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind;
+ if( ind_tmp > double_step_size_threshold ) {
+ *prev_ind += silk_LSHIFT( ind_tmp, 1 ) - double_step_size_threshold;
+ } else {
+ *prev_ind += ind_tmp;
+ }
+ }
+ *prev_ind = silk_LIMIT_int( *prev_ind, 0, N_LEVELS_QGAIN - 1 );
+
+ /* Scale and convert to linear scale */
+ gain_Q16[ k ] = silk_log2lin( silk_min_32( silk_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */
+ }
+}
+
+/* Compute unique identifier of gain indices vector */
+opus_int32 silk_gains_ID( /* O returns unique identifier of gains */
+ const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */
+ const opus_int nb_subfr /* I number of subframes */
+)
+{
+ opus_int k;
+ opus_int32 gainsID;
+
+ gainsID = 0;
+ for( k = 0; k < nb_subfr; k++ ) {
+ gainsID = silk_ADD_LSHIFT32( ind[ k ], gainsID, 8 );
+ }
+
+ return gainsID;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+#ifdef ENABLE_OSCE
+#include "osce.h"
+#endif
+
+#include "structs.h"
+
+/************************/
+/* Reset Decoder State */
+/************************/
+opus_int silk_reset_decoder(
+ silk_decoder_state *psDec /* I/O Decoder state pointer */
+)
+{
+ /* Clear the entire encoder state, except anything copied */
+ silk_memset( &psDec->SILK_DECODER_STATE_RESET_START, 0, sizeof( silk_decoder_state ) - ((char*) &psDec->SILK_DECODER_STATE_RESET_START - (char*)psDec) );
+
+ /* Used to deactivate LSF interpolation */
+ psDec->first_frame_after_reset = 1;
+ psDec->prev_gain_Q16 = 65536;
+ psDec->arch = opus_select_arch();
+
+ /* Reset CNG state */
+ silk_CNG_Reset( psDec );
+
+ /* Reset PLC state */
+ silk_PLC_Reset( psDec );
+
+#ifdef ENABLE_OSCE
+ /* Reset OSCE state and method */
+ osce_reset(&psDec->osce, OSCE_DEFAULT_METHOD);
+#endif
+
+ return 0;
+}
+
+
+/************************/
+/* Init Decoder State */
+/************************/
+opus_int silk_init_decoder(
+ silk_decoder_state *psDec /* I/O Decoder state pointer */
+)
+{
+ /* Clear the entire encoder state, except anything copied */
+ silk_memset( psDec, 0, sizeof( silk_decoder_state ) );
+
+ silk_reset_decoder( psDec );
+
+ return(0);
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+opus_int32 silk_inner_prod_aligned_scale(
+ const opus_int16 *const inVec1, /* I input vector 1 */
+ const opus_int16 *const inVec2, /* I input vector 2 */
+ const opus_int scale, /* I number of bits to shift */
+ const opus_int len /* I vector lengths */
+)
+{
+ opus_int i;
+ opus_int32 sum = 0;
+ for( i = 0; i < len; i++ ) {
+ sum = silk_ADD_RSHIFT32( sum, silk_SMULBB( inVec1[ i ], inVec2[ i ] ), scale );
+ }
+ return sum;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Interpolate two vectors */
+void silk_interpolate(
+ opus_int16 xi[ MAX_LPC_ORDER ], /* O interpolated vector */
+ const opus_int16 x0[ MAX_LPC_ORDER ], /* I first vector */
+ const opus_int16 x1[ MAX_LPC_ORDER ], /* I second vector */
+ const opus_int ifact_Q2, /* I interp. factor, weight on 2nd vector */
+ const opus_int d /* I number of parameters */
+)
+{
+ opus_int i;
+
+ celt_assert( ifact_Q2 >= 0 );
+ celt_assert( ifact_Q2 <= 4 );
+
+ for( i = 0; i < d; i++ ) {
+ xi[ i ] = (opus_int16)silk_ADD_RSHIFT( x0[ i ], silk_SMULBB( x1[ i ] - x0[ i ], ifact_Q2 ), 2 );
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+/* Approximation of 128 * log2() (very close inverse of silk_log2lin()) */
+/* Convert input to a log scale */
+opus_int32 silk_lin2log(
+ const opus_int32 inLin /* I input in linear scale */
+)
+{
+ opus_int32 lz, frac_Q7;
+
+ silk_CLZ_FRAC( inLin, &lz, &frac_Q7 );
+
+ /* Piece-wise parabolic approximation */
+ return silk_ADD_LSHIFT32( silk_SMLAWB( frac_Q7, silk_MUL( frac_Q7, 128 - frac_Q7 ), 179 ), 31 - lz, 7 );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Approximation of 2^() (very close inverse of silk_lin2log()) */
+/* Convert input to a linear scale */
+opus_int32 silk_log2lin(
+ const opus_int32 inLog_Q7 /* I input on log scale */
+)
+{
+ opus_int32 out, frac_Q7;
+
+ if( inLog_Q7 < 0 ) {
+ return 0;
+ } else if ( inLog_Q7 >= 3967 ) {
+ return silk_int32_MAX;
+ }
+
+ out = silk_LSHIFT( 1, silk_RSHIFT( inLog_Q7, 7 ) );
+ frac_Q7 = inLog_Q7 & 0x7F;
+ if( inLog_Q7 < 2048 ) {
+ /* Piece-wise parabolic approximation */
+ out = silk_ADD_RSHIFT32( out, silk_MUL( out, silk_SMLAWB( frac_Q7, silk_SMULBB( frac_Q7, 128 - frac_Q7 ), -174 ) ), 7 );
+ } else {
+ /* Piece-wise parabolic approximation */
+ out = silk_MLA( out, silk_RSHIFT( out, 7 ), silk_SMLAWB( frac_Q7, silk_SMULBB( frac_Q7, 128 - frac_Q7 ), -174 ) );
+ }
+ return out;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_MACROS_H
+#define SILK_MACROS_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "opus_types.h"
+#include "opus_defines.h"
+#include "arch.h"
+
+/* This is an OPUS_INLINE header file for general platform. */
+
+/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
+#if OPUS_FAST_INT64
+#define silk_SMULWB(a32, b32) ((opus_int32)(((a32) * (opus_int64)((opus_int16)(b32))) >> 16))
+#else
+#define silk_SMULWB(a32, b32) ((((a32) >> 16) * (opus_int32)((opus_int16)(b32))) + ((((a32) & 0x0000FFFF) * (opus_int32)((opus_int16)(b32))) >> 16))
+#endif
+
+/* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */
+#if OPUS_FAST_INT64
+#define silk_SMLAWB(a32, b32, c32) ((opus_int32)((a32) + (((b32) * (opus_int64)((opus_int16)(c32))) >> 16)))
+#else
+#define silk_SMLAWB(a32, b32, c32) ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16)))
+#endif
+
+/* (a32 * (b32 >> 16)) >> 16 */
+#if OPUS_FAST_INT64
+#define silk_SMULWT(a32, b32) ((opus_int32)(((a32) * (opus_int64)((b32) >> 16)) >> 16))
+#else
+#define silk_SMULWT(a32, b32) (((a32) >> 16) * ((b32) >> 16) + ((((a32) & 0x0000FFFF) * ((b32) >> 16)) >> 16))
+#endif
+
+/* a32 + (b32 * (c32 >> 16)) >> 16 */
+#if OPUS_FAST_INT64
+#define silk_SMLAWT(a32, b32, c32) ((opus_int32)((a32) + (((b32) * ((opus_int64)(c32) >> 16)) >> 16)))
+#else
+#define silk_SMLAWT(a32, b32, c32) ((a32) + (((b32) >> 16) * ((c32) >> 16)) + ((((b32) & 0x0000FFFF) * ((c32) >> 16)) >> 16))
+#endif
+
+/* (opus_int32)((opus_int16)(a3))) * (opus_int32)((opus_int16)(b32)) output have to be 32bit int */
+#define silk_SMULBB(a32, b32) ((opus_int32)((opus_int16)(a32)) * (opus_int32)((opus_int16)(b32)))
+
+/* a32 + (opus_int32)((opus_int16)(b32)) * (opus_int32)((opus_int16)(c32)) output have to be 32bit int */
+#define silk_SMLABB(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32)))
+
+/* (opus_int32)((opus_int16)(a32)) * (b32 >> 16) */
+#define silk_SMULBT(a32, b32) ((opus_int32)((opus_int16)(a32)) * ((b32) >> 16))
+
+/* a32 + (opus_int32)((opus_int16)(b32)) * (c32 >> 16) */
+#define silk_SMLABT(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * ((c32) >> 16))
+
+/* a64 + (b32 * c32) */
+#define silk_SMLAL(a64, b32, c32) (silk_ADD64((a64), ((opus_int64)(b32) * (opus_int64)(c32))))
+
+/* (a32 * b32) >> 16 */
+#if OPUS_FAST_INT64
+#define silk_SMULWW(a32, b32) ((opus_int32)(((opus_int64)(a32) * (b32)) >> 16))
+#else
+#define silk_SMULWW(a32, b32) silk_MLA(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16))
+#endif
+
+/* a32 + ((b32 * c32) >> 16) */
+#if OPUS_FAST_INT64
+#define silk_SMLAWW(a32, b32, c32) ((opus_int32)((a32) + (((opus_int64)(b32) * (c32)) >> 16)))
+#else
+#define silk_SMLAWW(a32, b32, c32) silk_MLA(silk_SMLAWB((a32), (b32), (c32)), (b32), silk_RSHIFT_ROUND((c32), 16))
+#endif
+
+/* add/subtract with output saturated */
+#define silk_ADD_SAT32(a, b) ((((opus_uint32)(a) + (opus_uint32)(b)) & 0x80000000) == 0 ? \
+ ((((a) & (b)) & 0x80000000) != 0 ? silk_int32_MIN : (a)+(b)) : \
+ ((((a) | (b)) & 0x80000000) == 0 ? silk_int32_MAX : (a)+(b)) )
+
+#define silk_SUB_SAT32(a, b) ((((opus_uint32)(a)-(opus_uint32)(b)) & 0x80000000) == 0 ? \
+ (( (a) & ((b)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a)-(b)) : \
+ ((((a)^0x80000000) & (b) & 0x80000000) ? silk_int32_MAX : (a)-(b)) )
+
+#if defined(FIXED_POINT) && defined(__mips)
+#include "mips/macros_mipsr1.h"
+#endif
+
+#include "ecintrin.h"
+#ifndef OVERRIDE_silk_CLZ16
+static OPUS_INLINE opus_int32 silk_CLZ16(opus_int16 in16)
+{
+ return 32 - EC_ILOG(in16<<16|0x8000);
+}
+#endif
+
+#ifndef OVERRIDE_silk_CLZ32
+static OPUS_INLINE opus_int32 silk_CLZ32(opus_int32 in32)
+{
+ return in32 ? 32 - EC_ILOG(in32) : 32;
+}
+#endif
+
+/* Row based */
+#define matrix_ptr(Matrix_base_adr, row, column, N) \
+ (*((Matrix_base_adr) + ((row)*(N)+(column))))
+#define matrix_adr(Matrix_base_adr, row, column, N) \
+ ((Matrix_base_adr) + ((row)*(N)+(column)))
+
+/* Column based */
+#ifndef matrix_c_ptr
+# define matrix_c_ptr(Matrix_base_adr, row, column, M) \
+ (*((Matrix_base_adr) + ((row)+(M)*(column))))
+#endif
+
+#ifdef OPUS_ARM_INLINE_ASM
+#include "arm/macros_armv4.h"
+#endif
+
+#ifdef OPUS_ARM_INLINE_EDSP
+#include "arm/macros_armv5e.h"
+#endif
+
+#ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR
+#include "arm/macros_arm64.h"
+#endif
+
+#ifdef OPUS_XTENSA_LX7
+#include "xtensa/macros_lx7.h"
+#endif
+
+#endif /* SILK_MACROS_H */
--- /dev/null
+/***********************************************************************
+Copyright (C) 2015 Vidyo
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_MACROS_ARM64_H
+#define SILK_MACROS_ARM64_H
+
+#include <arm_neon.h>
+
+#undef silk_ADD_SAT32
+#define silk_ADD_SAT32(a, b) (vqadds_s32((a), (b)))
+
+#undef silk_SUB_SAT32
+#define silk_SUB_SAT32(a, b) (vqsubs_s32((a), (b)))
+
+#endif /* SILK_MACROS_ARM64_H */
--- /dev/null
+/***********************************************************************
+Copyright (C) 2013 Xiph.Org Foundation and contributors.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_MACROS_ARMv4_H
+#define SILK_MACROS_ARMv4_H
+
+/* This macro only avoids the undefined behaviour from a left shift of
+ a negative value. It should only be used in macros that can't include
+ SigProc_FIX.h. In other cases, use silk_LSHIFT32(). */
+#define SAFE_SHL(a,b) ((opus_int32)((opus_uint32)(a) << (b)))
+
+/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
+#undef silk_SMULWB
+static OPUS_INLINE opus_int32 silk_SMULWB_armv4(opus_int32 a, opus_int16 b)
+{
+ unsigned rd_lo;
+ int rd_hi;
+ __asm__(
+ "#silk_SMULWB\n\t"
+ "smull %0, %1, %2, %3\n\t"
+ : "=&r"(rd_lo), "=&r"(rd_hi)
+ : "%r"(a), "r"(SAFE_SHL(b,16))
+ );
+ return rd_hi;
+}
+#define silk_SMULWB(a, b) (silk_SMULWB_armv4(a, b))
+
+/* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */
+#undef silk_SMLAWB
+#define silk_SMLAWB(a, b, c) ((a) + silk_SMULWB(b, c))
+
+/* (a32 * (b32 >> 16)) >> 16 */
+#undef silk_SMULWT
+static OPUS_INLINE opus_int32 silk_SMULWT_armv4(opus_int32 a, opus_int32 b)
+{
+ unsigned rd_lo;
+ int rd_hi;
+ __asm__(
+ "#silk_SMULWT\n\t"
+ "smull %0, %1, %2, %3\n\t"
+ : "=&r"(rd_lo), "=&r"(rd_hi)
+ : "%r"(a), "r"(b&~0xFFFF)
+ );
+ return rd_hi;
+}
+#define silk_SMULWT(a, b) (silk_SMULWT_armv4(a, b))
+
+/* a32 + (b32 * (c32 >> 16)) >> 16 */
+#undef silk_SMLAWT
+#define silk_SMLAWT(a, b, c) ((a) + silk_SMULWT(b, c))
+
+/* (a32 * b32) >> 16 */
+#undef silk_SMULWW
+static OPUS_INLINE opus_int32 silk_SMULWW_armv4(opus_int32 a, opus_int32 b)
+{
+ unsigned rd_lo;
+ int rd_hi;
+ __asm__(
+ "#silk_SMULWW\n\t"
+ "smull %0, %1, %2, %3\n\t"
+ : "=&r"(rd_lo), "=&r"(rd_hi)
+ : "%r"(a), "r"(b)
+ );
+ return SAFE_SHL(rd_hi,16)+(rd_lo>>16);
+}
+#define silk_SMULWW(a, b) (silk_SMULWW_armv4(a, b))
+
+#undef silk_SMLAWW
+static OPUS_INLINE opus_int32 silk_SMLAWW_armv4(opus_int32 a, opus_int32 b,
+ opus_int32 c)
+{
+ unsigned rd_lo;
+ int rd_hi;
+ __asm__(
+ "#silk_SMLAWW\n\t"
+ "smull %0, %1, %2, %3\n\t"
+ : "=&r"(rd_lo), "=&r"(rd_hi)
+ : "%r"(b), "r"(c)
+ );
+ return a+SAFE_SHL(rd_hi,16)+(rd_lo>>16);
+}
+#define silk_SMLAWW(a, b, c) (silk_SMLAWW_armv4(a, b, c))
+
+#undef SAFE_SHL
+
+#endif /* SILK_MACROS_ARMv4_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Copyright (c) 2013 Parrot
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_MACROS_ARMv5E_H
+#define SILK_MACROS_ARMv5E_H
+
+/* This macro only avoids the undefined behaviour from a left shift of
+ a negative value. It should only be used in macros that can't include
+ SigProc_FIX.h. In other cases, use silk_LSHIFT32(). */
+#define SAFE_SHL(a,b) ((opus_int32)((opus_uint32)(a) << (b)))
+
+/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
+#undef silk_SMULWB
+static OPUS_INLINE opus_int32 silk_SMULWB_armv5e(opus_int32 a, opus_int16 b)
+{
+ int res;
+ __asm__(
+ "#silk_SMULWB\n\t"
+ "smulwb %0, %1, %2\n\t"
+ : "=r"(res)
+ : "r"(a), "r"(b)
+ );
+ return res;
+}
+#define silk_SMULWB(a, b) (silk_SMULWB_armv5e(a, b))
+
+/* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */
+#undef silk_SMLAWB
+static OPUS_INLINE opus_int32 silk_SMLAWB_armv5e(opus_int32 a, opus_int32 b,
+ opus_int16 c)
+{
+ int res;
+ __asm__(
+ "#silk_SMLAWB\n\t"
+ "smlawb %0, %1, %2, %3\n\t"
+ : "=r"(res)
+ : "r"(b), "r"(c), "r"(a)
+ );
+ return res;
+}
+#define silk_SMLAWB(a, b, c) (silk_SMLAWB_armv5e(a, b, c))
+
+/* (a32 * (b32 >> 16)) >> 16 */
+#undef silk_SMULWT
+static OPUS_INLINE opus_int32 silk_SMULWT_armv5e(opus_int32 a, opus_int32 b)
+{
+ int res;
+ __asm__(
+ "#silk_SMULWT\n\t"
+ "smulwt %0, %1, %2\n\t"
+ : "=r"(res)
+ : "r"(a), "r"(b)
+ );
+ return res;
+}
+#define silk_SMULWT(a, b) (silk_SMULWT_armv5e(a, b))
+
+/* a32 + (b32 * (c32 >> 16)) >> 16 */
+#undef silk_SMLAWT
+static OPUS_INLINE opus_int32 silk_SMLAWT_armv5e(opus_int32 a, opus_int32 b,
+ opus_int32 c)
+{
+ int res;
+ __asm__(
+ "#silk_SMLAWT\n\t"
+ "smlawt %0, %1, %2, %3\n\t"
+ : "=r"(res)
+ : "r"(b), "r"(c), "r"(a)
+ );
+ return res;
+}
+#define silk_SMLAWT(a, b, c) (silk_SMLAWT_armv5e(a, b, c))
+
+/* (opus_int32)((opus_int16)(a3))) * (opus_int32)((opus_int16)(b32)) output have to be 32bit int */
+#undef silk_SMULBB
+static OPUS_INLINE opus_int32 silk_SMULBB_armv5e(opus_int32 a, opus_int32 b)
+{
+ int res;
+ __asm__(
+ "#silk_SMULBB\n\t"
+ "smulbb %0, %1, %2\n\t"
+ : "=r"(res)
+ : "%r"(a), "r"(b)
+ );
+ return res;
+}
+#define silk_SMULBB(a, b) (silk_SMULBB_armv5e(a, b))
+
+/* a32 + (opus_int32)((opus_int16)(b32)) * (opus_int32)((opus_int16)(c32)) output have to be 32bit int */
+#undef silk_SMLABB
+static OPUS_INLINE opus_int32 silk_SMLABB_armv5e(opus_int32 a, opus_int32 b,
+ opus_int32 c)
+{
+ int res;
+ __asm__(
+ "#silk_SMLABB\n\t"
+ "smlabb %0, %1, %2, %3\n\t"
+ : "=r"(res)
+ : "%r"(b), "r"(c), "r"(a)
+ );
+ return res;
+}
+#define silk_SMLABB(a, b, c) (silk_SMLABB_armv5e(a, b, c))
+
+/* (opus_int32)((opus_int16)(a32)) * (b32 >> 16) */
+#undef silk_SMULBT
+static OPUS_INLINE opus_int32 silk_SMULBT_armv5e(opus_int32 a, opus_int32 b)
+{
+ int res;
+ __asm__(
+ "#silk_SMULBT\n\t"
+ "smulbt %0, %1, %2\n\t"
+ : "=r"(res)
+ : "r"(a), "r"(b)
+ );
+ return res;
+}
+#define silk_SMULBT(a, b) (silk_SMULBT_armv5e(a, b))
+
+/* a32 + (opus_int32)((opus_int16)(b32)) * (c32 >> 16) */
+#undef silk_SMLABT
+static OPUS_INLINE opus_int32 silk_SMLABT_armv5e(opus_int32 a, opus_int32 b,
+ opus_int32 c)
+{
+ int res;
+ __asm__(
+ "#silk_SMLABT\n\t"
+ "smlabt %0, %1, %2, %3\n\t"
+ : "=r"(res)
+ : "r"(b), "r"(c), "r"(a)
+ );
+ return res;
+}
+#define silk_SMLABT(a, b, c) (silk_SMLABT_armv5e(a, b, c))
+
+/* add/subtract with output saturated */
+#undef silk_ADD_SAT32
+static OPUS_INLINE opus_int32 silk_ADD_SAT32_armv5e(opus_int32 a, opus_int32 b)
+{
+ int res;
+ __asm__(
+ "#silk_ADD_SAT32\n\t"
+ "qadd %0, %1, %2\n\t"
+ : "=r"(res)
+ : "%r"(a), "r"(b)
+ );
+ return res;
+}
+#define silk_ADD_SAT32(a, b) (silk_ADD_SAT32_armv5e(a, b))
+
+#undef silk_SUB_SAT32
+static OPUS_INLINE opus_int32 silk_SUB_SAT32_armv5e(opus_int32 a, opus_int32 b)
+{
+ int res;
+ __asm__(
+ "#silk_SUB_SAT32\n\t"
+ "qsub %0, %1, %2\n\t"
+ : "=r"(res)
+ : "r"(a), "r"(b)
+ );
+ return res;
+}
+#define silk_SUB_SAT32(a, b) (silk_SUB_SAT32_armv5e(a, b))
+
+#undef silk_CLZ16
+static OPUS_INLINE opus_int32 silk_CLZ16_armv5(opus_int16 in16)
+{
+ int res;
+ __asm__(
+ "#silk_CLZ16\n\t"
+ "clz %0, %1;\n"
+ : "=r"(res)
+ : "r"(SAFE_SHL(in16,16)|0x8000)
+ );
+ return res;
+}
+#define silk_CLZ16(in16) (silk_CLZ16_armv5(in16))
+
+#undef silk_CLZ32
+static OPUS_INLINE opus_int32 silk_CLZ32_armv5(opus_int32 in32)
+{
+ int res;
+ __asm__(
+ "#silk_CLZ32\n\t"
+ "clz %0, %1\n\t"
+ : "=r"(res)
+ : "r"(in32)
+ );
+ return res;
+}
+#define silk_CLZ32(in32) (silk_CLZ32_armv5(in32))
+
+#undef SAFE_SHL
+
+#endif /* SILK_MACROS_ARMv5E_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_MACROS_MIPSR1_H__
+#define SILK_MACROS_MIPSR1_H__
+
+
+#if defined (__mips_dsp) && __mips == 32
+
+#undef silk_SMULWB
+static inline int silk_SMULWB(int a, int b)
+{
+ long long ac;
+ int c;
+
+ ac = __builtin_mips_mult(a, (opus_int32)(opus_int16)b);
+ c = __builtin_mips_extr_w(ac, 16);
+
+ return c;
+}
+
+#undef silk_SMLAWB
+#define silk_SMLAWB(a32, b32, c32) ((a32) + silk_SMULWB(b32, c32))
+
+#undef silk_SMULWW
+static inline int silk_SMULWW(int a, int b)
+{
+ long long ac;
+ int c;
+
+ ac = __builtin_mips_mult(a, b);
+ c = __builtin_mips_extr_w(ac, 16);
+
+ return c;
+}
+
+#undef silk_SMLAWW
+static inline int silk_SMLAWW(int a, int b, int c)
+{
+ long long ac;
+ int res;
+
+ ac = __builtin_mips_mult(b, c);
+ res = __builtin_mips_extr_w(ac, 16);
+ res += a;
+
+ return res;
+}
+
+#elif defined (__mips_isa_rev) && __mips == 32
+
+#undef silk_SMULWB
+static inline int silk_SMULWB(int a, int b)
+{
+ long long ac = (long long)a * (int)(b << 16);
+
+ return ac >> 32;
+}
+
+/* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */
+#undef silk_SMLAWB
+static inline int silk_SMLAWB(int a, int b, int c)
+{
+ long long ac = (long long)b * (int)(c << 16);
+
+ return a + (ac >> 32);
+}
+
+#endif
+
+#if defined (__mips_isa_rev) /* MIPS32r1+ */
+
+static inline int mips_clz(opus_uint32 x)
+{
+ return x ? __builtin_clz(x) : 32;
+}
+
+#define OVERRIDE_silk_CLZ16
+static inline opus_int32 silk_CLZ16(opus_int16 in16)
+{
+ int re32;
+ opus_uint32 in32 = (opus_uint16)in16;
+ re32 = mips_clz(in32);
+ re32 -= 16;
+ return re32;
+}
+
+#define OVERRIDE_silk_CLZ32
+static inline opus_int32 silk_CLZ32(opus_int32 in32)
+{
+ int re32;
+ re32 = mips_clz(in32);
+ return re32;
+}
+
+#endif /* __mips_isa_rev */
+
+#endif /* SILK_MACROS_MIPSR1_H__ */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_MAIN_H
+#define SILK_MAIN_H
+
+#include "SigProc_FIX.h"
+#include "define.h"
+#include "structs.h"
+#include "tables.h"
+#include "PLC.h"
+#include "control.h"
+#include "debug.h"
+#include "entenc.h"
+#include "entdec.h"
+
+#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+#include "x86/main_sse.h"
+#endif
+
+#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "arm/NSQ_del_dec_arm.h"
+#endif
+
+/* Convert Left/Right stereo signal to adaptive Mid/Side representation */
+void silk_stereo_LR_to_MS(
+ stereo_enc_state *state, /* I/O State */
+ opus_int16 x1[], /* I/O Left input signal, becomes mid signal */
+ opus_int16 x2[], /* I/O Right input signal, becomes side signal */
+ opus_int8 ix[ 2 ][ 3 ], /* O Quantization indices */
+ opus_int8 *mid_only_flag, /* O Flag: only mid signal coded */
+ opus_int32 mid_side_rates_bps[], /* O Bitrates for mid and side signals */
+ opus_int32 total_rate_bps, /* I Total bitrate */
+ opus_int prev_speech_act_Q8, /* I Speech activity level in previous frame */
+ opus_int toMono, /* I Last frame before a stereo->mono transition */
+ opus_int fs_kHz, /* I Sample rate (kHz) */
+ opus_int frame_length /* I Number of samples */
+);
+
+/* Convert adaptive Mid/Side representation to Left/Right stereo signal */
+void silk_stereo_MS_to_LR(
+ stereo_dec_state *state, /* I/O State */
+ opus_int16 x1[], /* I/O Left input signal, becomes mid signal */
+ opus_int16 x2[], /* I/O Right input signal, becomes side signal */
+ const opus_int32 pred_Q13[], /* I Predictors */
+ opus_int fs_kHz, /* I Samples rate (kHz) */
+ opus_int frame_length /* I Number of samples */
+);
+
+/* Find least-squares prediction gain for one signal based on another and quantize it */
+opus_int32 silk_stereo_find_predictor( /* O Returns predictor in Q13 */
+ opus_int32 *ratio_Q14, /* O Ratio of residual and mid energies */
+ const opus_int16 x[], /* I Basis signal */
+ const opus_int16 y[], /* I Target signal */
+ opus_int32 mid_res_amp_Q0[], /* I/O Smoothed mid, residual norms */
+ opus_int length, /* I Number of samples */
+ opus_int smooth_coef_Q16 /* I Smoothing coefficient */
+);
+
+/* Quantize mid/side predictors */
+void silk_stereo_quant_pred(
+ opus_int32 pred_Q13[], /* I/O Predictors (out: quantized) */
+ opus_int8 ix[ 2 ][ 3 ] /* O Quantization indices */
+);
+
+/* Entropy code the mid/side quantization indices */
+void silk_stereo_encode_pred(
+ ec_enc *psRangeEnc, /* I/O Compressor data structure */
+ opus_int8 ix[ 2 ][ 3 ] /* I Quantization indices */
+);
+
+/* Entropy code the mid-only flag */
+void silk_stereo_encode_mid_only(
+ ec_enc *psRangeEnc, /* I/O Compressor data structure */
+ opus_int8 mid_only_flag
+);
+
+/* Decode mid/side predictors */
+void silk_stereo_decode_pred(
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int32 pred_Q13[] /* O Predictors */
+);
+
+/* Decode mid-only flag */
+void silk_stereo_decode_mid_only(
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int *decode_only_mid /* O Flag that only mid channel has been coded */
+);
+
+/* Encodes signs of excitation */
+void silk_encode_signs(
+ ec_enc *psRangeEnc, /* I/O Compressor data structure */
+ const opus_int8 pulses[], /* I pulse signal */
+ opus_int length, /* I length of input */
+ const opus_int signalType, /* I Signal type */
+ const opus_int quantOffsetType, /* I Quantization offset type */
+ const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
+);
+
+/* Decodes signs of excitation */
+void silk_decode_signs(
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int16 pulses[], /* I/O pulse signal */
+ opus_int length, /* I length of input */
+ const opus_int signalType, /* I Signal type */
+ const opus_int quantOffsetType, /* I Quantization offset type */
+ const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */
+);
+
+/* Check encoder control struct */
+opus_int check_control_input(
+ silk_EncControlStruct *encControl /* I Control structure */
+);
+
+/* Control internal sampling rate */
+opus_int silk_control_audio_bandwidth(
+ silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */
+ silk_EncControlStruct *encControl /* I Control structure */
+);
+
+/* Control SNR of residual quantizer */
+opus_int silk_control_SNR(
+ silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */
+ opus_int32 TargetRate_bps /* I Target max bitrate (bps) */
+);
+
+/***************/
+/* Shell coder */
+/***************/
+
+/* Encode quantization indices of excitation */
+void silk_encode_pulses(
+ ec_enc *psRangeEnc, /* I/O compressor data structure */
+ const opus_int signalType, /* I Signal type */
+ const opus_int quantOffsetType, /* I quantOffsetType */
+ opus_int8 pulses[], /* I quantization indices */
+ const opus_int frame_length /* I Frame length */
+);
+
+/* Shell encoder, operates on one shell code frame of 16 pulses */
+void silk_shell_encoder(
+ ec_enc *psRangeEnc, /* I/O compressor data structure */
+ const opus_int *pulses0 /* I data: nonnegative pulse amplitudes */
+);
+
+/* Shell decoder, operates on one shell code frame of 16 pulses */
+void silk_shell_decoder(
+ opus_int16 *pulses0, /* O data: nonnegative pulse amplitudes */
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ const opus_int pulses4 /* I number of pulses per pulse-subframe */
+);
+
+/* Gain scalar quantization with hysteresis, uniform on log scale */
+void silk_gains_quant(
+ opus_int8 ind[ MAX_NB_SUBFR ], /* O gain indices */
+ opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* I/O gains (quantized out) */
+ opus_int8 *prev_ind, /* I/O last index in previous frame */
+ const opus_int conditional, /* I first gain is delta coded if 1 */
+ const opus_int nb_subfr /* I number of subframes */
+);
+
+/* Gains scalar dequantization, uniform on log scale */
+void silk_gains_dequant(
+ opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* O quantized gains */
+ const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */
+ opus_int8 *prev_ind, /* I/O last index in previous frame */
+ const opus_int conditional, /* I first gain is delta coded if 1 */
+ const opus_int nb_subfr /* I number of subframes */
+);
+
+/* Compute unique identifier of gain indices vector */
+opus_int32 silk_gains_ID( /* O returns unique identifier of gains */
+ const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */
+ const opus_int nb_subfr /* I number of subframes */
+);
+
+/* Interpolate two vectors */
+void silk_interpolate(
+ opus_int16 xi[ MAX_LPC_ORDER ], /* O interpolated vector */
+ const opus_int16 x0[ MAX_LPC_ORDER ], /* I first vector */
+ const opus_int16 x1[ MAX_LPC_ORDER ], /* I second vector */
+ const opus_int ifact_Q2, /* I interp. factor, weight on 2nd vector */
+ const opus_int d /* I number of parameters */
+);
+
+/* LTP tap quantizer */
+void silk_quant_LTP_gains(
+ opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O Quantized LTP gains */
+ opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */
+ opus_int8 *periodicity_index, /* O Periodicity Index */
+ opus_int32 *sum_gain_dB_Q7, /* I/O Cumulative max prediction gain */
+ opus_int *pred_gain_dB_Q7, /* O LTP prediction gain */
+ const opus_int32 XX_Q17[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Correlation matrix in Q18 */
+ const opus_int32 xX_Q17[ MAX_NB_SUBFR*LTP_ORDER ], /* I Correlation vector in Q18 */
+ const opus_int subfr_len, /* I Number of samples per subframe */
+ const opus_int nb_subfr, /* I Number of subframes */
+ int arch /* I Run-time architecture */
+);
+
+/* Entropy constrained matrix-weighted VQ, for a single input data vector */
+void silk_VQ_WMat_EC_c(
+ opus_int8 *ind, /* O index of best codebook vector */
+ opus_int32 *res_nrg_Q15, /* O best residual energy */
+ opus_int32 *rate_dist_Q8, /* O best total bitrate */
+ opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
+ const opus_int32 *XX_Q17, /* I correlation matrix */
+ const opus_int32 *xX_Q17, /* I correlation vector */
+ const opus_int8 *cb_Q7, /* I codebook */
+ const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
+ const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
+ const opus_int subfr_len, /* I number of samples per subframe */
+ const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
+ const opus_int L /* I number of vectors in codebook */
+);
+
+#if !defined(OVERRIDE_silk_VQ_WMat_EC)
+#define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, subfr_len, max_gain_Q7, L, arch) \
+ ((void)(arch),silk_VQ_WMat_EC_c(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, subfr_len, max_gain_Q7, L))
+#endif
+
+/************************************/
+/* Noise shaping quantization (NSQ) */
+/************************************/
+
+void silk_NSQ_c(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+);
+
+#if !defined(OVERRIDE_silk_NSQ)
+#define silk_NSQ(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+ ((void)(arch),silk_NSQ_c(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+#endif
+
+/* Noise shaping using delayed decision */
+void silk_NSQ_del_dec_c(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+);
+
+#if !defined(OVERRIDE_silk_NSQ_del_dec)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+ ((void)(arch),silk_NSQ_del_dec_c(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+#endif
+
+/************/
+/* Silk VAD */
+/************/
+/* Initialize the Silk VAD */
+opus_int silk_VAD_Init( /* O Return value, 0 if success */
+ silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
+);
+
+/* Get speech activity level in Q8 */
+opus_int silk_VAD_GetSA_Q8_c( /* O Return value, 0 if success */
+ silk_encoder_state *psEncC, /* I/O Encoder state */
+ const opus_int16 pIn[] /* I PCM input */
+);
+
+#if !defined(OVERRIDE_silk_VAD_GetSA_Q8)
+#define silk_VAD_GetSA_Q8(psEnC, pIn, arch) ((void)(arch),silk_VAD_GetSA_Q8_c(psEnC, pIn))
+#endif
+
+/* Low-pass filter with variable cutoff frequency based on */
+/* piece-wise linear interpolation between elliptic filters */
+/* Start by setting transition_frame_no = 1; */
+void silk_LP_variable_cutoff(
+ silk_LP_state *psLP, /* I/O LP filter state */
+ opus_int16 *frame, /* I/O Low-pass filtered output signal */
+ const opus_int frame_length /* I Frame length */
+);
+
+/******************/
+/* NLSF Quantizer */
+/******************/
+/* Limit, stabilize, convert and quantize NLSFs */
+void silk_process_NLSFs(
+ silk_encoder_state *psEncC, /* I/O Encoder state */
+ opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */
+ opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */
+ const opus_int16 prev_NLSFq_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */
+);
+
+opus_int32 silk_NLSF_encode( /* O Returns RD value in Q25 */
+ opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */
+ opus_int16 *pNLSF_Q15, /* I/O Quantized NLSF vector [ LPC_ORDER ] */
+ const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
+ const opus_int16 *pW_QW, /* I NLSF weight vector [ LPC_ORDER ] */
+ const opus_int NLSF_mu_Q20, /* I Rate weight for the RD optimization */
+ const opus_int nSurvivors, /* I Max survivors after first stage */
+ const opus_int signalType /* I Signal type: 0/1/2 */
+);
+
+/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */
+void silk_NLSF_VQ(
+ opus_int32 err_Q26[], /* O Quantization errors [K] */
+ const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */
+ const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */
+ const opus_int16 pWght_Q9[], /* I Codebook weights [K*LPC_order] */
+ const opus_int K, /* I Number of codebook vectors */
+ const opus_int LPC_order /* I Number of LPCs */
+);
+
+/* Delayed-decision quantizer for NLSF residuals */
+opus_int32 silk_NLSF_del_dec_quant( /* O Returns RD value in Q25 */
+ opus_int8 indices[], /* O Quantization indices [ order ] */
+ const opus_int16 x_Q10[], /* I Input [ order ] */
+ const opus_int16 w_Q5[], /* I Weights [ order ] */
+ const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */
+ const opus_int16 ec_ix[], /* I Indices to entropy coding tables [ order ] */
+ const opus_uint8 ec_rates_Q5[], /* I Rates [] */
+ const opus_int quant_step_size_Q16, /* I Quantization step size */
+ const opus_int16 inv_quant_step_size_Q6, /* I Inverse quantization step size */
+ const opus_int32 mu_Q20, /* I R/D tradeoff */
+ const opus_int16 order /* I Number of input values */
+);
+
+/* Unpack predictor values and indices for entropy coding tables */
+void silk_NLSF_unpack(
+ opus_int16 ec_ix[], /* O Indices to entropy tables [ LPC_ORDER ] */
+ opus_uint8 pred_Q8[], /* O LSF predictor [ LPC_ORDER ] */
+ const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
+ const opus_int CB1_index /* I Index of vector in first LSF codebook */
+);
+
+/***********************/
+/* NLSF vector decoder */
+/***********************/
+void silk_NLSF_decode(
+ opus_int16 *pNLSF_Q15, /* O Quantized NLSF vector [ LPC_ORDER ] */
+ opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */
+ const silk_NLSF_CB_struct *psNLSF_CB /* I Codebook object */
+);
+
+/****************************************************/
+/* Decoder Functions */
+/****************************************************/
+opus_int silk_reset_decoder(
+ silk_decoder_state *psDec /* I/O Decoder state pointer */
+);
+
+opus_int silk_init_decoder(
+ silk_decoder_state *psDec /* I/O Decoder state pointer */
+);
+
+/* Set decoder sampling rate */
+opus_int silk_decoder_set_fs(
+ silk_decoder_state *psDec, /* I/O Decoder state pointer */
+ opus_int fs_kHz, /* I Sampling frequency (kHz) */
+ opus_int32 fs_API_Hz /* I API Sampling frequency (Hz) */
+);
+
+/****************/
+/* Decode frame */
+/****************/
+opus_int silk_decode_frame(
+ silk_decoder_state *psDec, /* I/O Pointer to Silk decoder state */
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int16 pOut[], /* O Pointer to output speech frame */
+ opus_int32 *pN, /* O Pointer to size of output frame */
+ opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
+ opus_int condCoding, /* I The type of conditional coding to use */
+#ifdef ENABLE_DEEP_PLC
+ LPCNetPLCState *lpcnet,
+#endif
+#ifdef ENABLE_OSCE
+ OSCEModel *osce_model,
+#endif
+ int arch /* I Run-time architecture */
+);
+
+/* Decode indices from bitstream */
+void silk_decode_indices(
+ silk_decoder_state *psDec, /* I/O State */
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int FrameIndex, /* I Frame number */
+ opus_int decode_LBRR, /* I Flag indicating LBRR data is being decoded */
+ opus_int condCoding /* I The type of conditional coding to use */
+);
+
+/* Decode parameters from payload */
+void silk_decode_parameters(
+ silk_decoder_state *psDec, /* I/O State */
+ silk_decoder_control *psDecCtrl, /* I/O Decoder control */
+ opus_int condCoding /* I The type of conditional coding to use */
+);
+
+/* Core decoder. Performs inverse NSQ operation LTP + LPC */
+void silk_decode_core(
+ silk_decoder_state *psDec, /* I/O Decoder state */
+ silk_decoder_control *psDecCtrl, /* I Decoder control */
+ opus_int16 xq[], /* O Decoded speech */
+ const opus_int16 pulses[ MAX_FRAME_LENGTH ], /* I Pulse signal */
+ int arch /* I Run-time architecture */
+);
+
+/* Decode quantization indices of excitation (Shell coding) */
+void silk_decode_pulses(
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int16 pulses[], /* O Excitation signal */
+ const opus_int signalType, /* I Sigtype */
+ const opus_int quantOffsetType, /* I quantOffsetType */
+ const opus_int frame_length /* I Frame length */
+);
+
+/******************/
+/* CNG */
+/******************/
+
+/* Reset CNG */
+void silk_CNG_Reset(
+ silk_decoder_state *psDec /* I/O Decoder state */
+);
+
+/* Updates CNG estimate, and applies the CNG when packet was lost */
+void silk_CNG(
+ silk_decoder_state *psDec, /* I/O Decoder state */
+ silk_decoder_control *psDecCtrl, /* I/O Decoder control */
+ opus_int16 frame[], /* I/O Signal */
+ opus_int length /* I Length of residual */
+);
+
+/* Encoding of various parameters */
+void silk_encode_indices(
+ silk_encoder_state *psEncC, /* I/O Encoder state */
+ ec_enc *psRangeEnc, /* I/O Compressor data structure */
+ opus_int FrameIndex, /* I Frame number */
+ opus_int encode_LBRR, /* I Flag indicating LBRR data is being encoded */
+ opus_int condCoding /* I The type of conditional coding to use */
+);
+
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_MAIN_FIX_H
+#define SILK_MAIN_FIX_H
+
+#include "SigProc_FIX.h"
+#include "structs_FIX.h"
+#include "control.h"
+#include "main.h"
+#include "PLC.h"
+#include "debug.h"
+#include "entenc.h"
+
+#if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \
+ || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "fixed/arm/warped_autocorrelation_FIX_arm.h"
+#endif
+
+
+#define silk_encoder_state_Fxx silk_encoder_state_FIX
+#define silk_encode_do_VAD_Fxx silk_encode_do_VAD_FIX
+#define silk_encode_frame_Fxx silk_encode_frame_FIX
+
+#define QC 10
+#define QS 13
+
+/*********************/
+/* Encoder Functions */
+/*********************/
+
+/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */
+void silk_HP_variable_cutoff(
+ silk_encoder_state_Fxx state_Fxx[] /* I/O Encoder states */
+);
+
+/* Encoder main function */
+void silk_encode_do_VAD_FIX(
+ silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
+ opus_int activity /* I Decision of Opus voice activity detector */
+);
+
+/* Encoder main function */
+opus_int silk_encode_frame_FIX(
+ silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
+ opus_int32 *pnBytesOut, /* O Pointer to number of payload bytes; */
+ ec_enc *psRangeEnc, /* I/O compressor data structure */
+ opus_int condCoding, /* I The type of conditional coding to use */
+ opus_int maxBits, /* I If > 0: maximum number of output bits */
+ opus_int useCBR /* I Flag to force constant-bitrate operation */
+);
+
+/* Initializes the Silk encoder state */
+opus_int silk_init_encoder(
+ silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk FIX encoder state */
+ int arch /* I Run-time architecture */
+);
+
+/* Control the Silk encoder */
+opus_int silk_control_encoder(
+ silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */
+ silk_EncControlStruct *encControl, /* I Control structure */
+ const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
+ const opus_int channelNb, /* I Channel number */
+ const opus_int force_fs_kHz
+);
+
+/**************************/
+/* Noise shaping analysis */
+/**************************/
+/* Compute noise shaping coefficients and initial gain values */
+void silk_noise_shape_analysis_FIX(
+ silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */
+ silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */
+ const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */
+ const opus_int16 *x, /* I Input signal [ frame_length + la_shape ] */
+ int arch /* I Run-time architecture */
+);
+
+/* Autocorrelations for a warped frequency axis */
+void silk_warped_autocorrelation_FIX_c(
+ opus_int32 *corr, /* O Result [order + 1] */
+ opus_int *scale, /* O Scaling of the correlation vector */
+ const opus_int16 *input, /* I Input data to correlate */
+ const opus_int warping_Q16, /* I Warping coefficient */
+ const opus_int length, /* I Length of input */
+ const opus_int order /* I Correlation order (even) */
+);
+
+#if !defined(OVERRIDE_silk_warped_autocorrelation_FIX)
+#define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+ ((void)(arch), silk_warped_autocorrelation_FIX_c(corr, scale, input, warping_Q16, length, order))
+#endif
+
+/* Calculation of LTP state scaling */
+void silk_LTP_scale_ctrl_FIX(
+ silk_encoder_state_FIX *psEnc, /* I/O encoder state */
+ silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */
+ opus_int condCoding /* I The type of conditional coding to use */
+);
+
+/**********************************************/
+/* Prediction Analysis */
+/**********************************************/
+/* Find pitch lags */
+void silk_find_pitch_lags_FIX(
+ silk_encoder_state_FIX *psEnc, /* I/O encoder state */
+ silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */
+ opus_int16 res[], /* O residual */
+ const opus_int16 x[], /* I Speech signal */
+ int arch /* I Run-time architecture */
+);
+
+/* Find LPC and LTP coefficients */
+void silk_find_pred_coefs_FIX(
+ silk_encoder_state_FIX *psEnc, /* I/O encoder state */
+ silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */
+ const opus_int16 res_pitch[], /* I Residual from pitch analysis */
+ const opus_int16 x[], /* I Speech signal */
+ opus_int condCoding /* I The type of conditional coding to use */
+);
+
+/* LPC analysis */
+void silk_find_LPC_FIX(
+ silk_encoder_state *psEncC, /* I/O Encoder state */
+ opus_int16 NLSF_Q15[], /* O NLSFs */
+ const opus_int16 x[], /* I Input signal */
+ const opus_int32 minInvGain_Q30 /* I Inverse of max prediction gain */
+);
+
+/* LTP analysis */
+void silk_find_LTP_FIX(
+ opus_int32 XXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Correlation matrix */
+ opus_int32 xXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER ], /* O Correlation vector */
+ const opus_int16 r_lpc[], /* I Residual signal after LPC */
+ const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
+ const opus_int subfr_length, /* I Subframe length */
+ const opus_int nb_subfr, /* I Number of subframes */
+ int arch /* I Run-time architecture */
+);
+
+void silk_LTP_analysis_filter_FIX(
+ opus_int16 *LTP_res, /* O LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length ) */
+ const opus_int16 *x, /* I Pointer to input signal with at least max( pitchL ) preceding samples */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag, one for each subframe */
+ const opus_int32 invGains_Q16[ MAX_NB_SUBFR ], /* I Inverse quantization gains, one for each subframe */
+ const opus_int subfr_length, /* I Length of each subframe */
+ const opus_int nb_subfr, /* I Number of subframes */
+ const opus_int pre_length /* I Length of the preceding samples starting at &x[0] for each subframe */
+);
+
+/* Calculates residual energies of input subframes where all subframes have LPC_order */
+/* of preceding samples */
+void silk_residual_energy_FIX(
+ opus_int32 nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */
+ opus_int nrgsQ[ MAX_NB_SUBFR ], /* O Q value per subframe */
+ const opus_int16 x[], /* I Input signal */
+ opus_int16 a_Q12[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */
+ const opus_int32 gains[ MAX_NB_SUBFR ], /* I Quantization gains */
+ const opus_int subfr_length, /* I Subframe length */
+ const opus_int nb_subfr, /* I Number of subframes */
+ const opus_int LPC_order, /* I LPC order */
+ int arch /* I Run-time architecture */
+);
+
+/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */
+opus_int32 silk_residual_energy16_covar_FIX(
+ const opus_int16 *c, /* I Prediction vector */
+ const opus_int32 *wXX, /* I Correlation matrix */
+ const opus_int32 *wXx, /* I Correlation vector */
+ opus_int32 wxx, /* I Signal energy */
+ opus_int D, /* I Dimension */
+ opus_int cQ /* I Q value for c vector 0 - 15 */
+);
+
+/* Processing of gains */
+void silk_process_gains_FIX(
+ silk_encoder_state_FIX *psEnc, /* I/O Encoder state */
+ silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control */
+ opus_int condCoding /* I The type of conditional coding to use */
+);
+
+/******************/
+/* Linear Algebra */
+/******************/
+/* Calculates correlation matrix X'*X */
+void silk_corrMatrix_FIX(
+ const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */
+ const opus_int L, /* I Length of vectors */
+ const opus_int order, /* I Max lag for correlation */
+ opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */
+ opus_int32 *nrg, /* O Energy of x vector */
+ opus_int *rshifts, /* O Right shifts of correlations */
+ int arch /* I Run-time architecture */
+);
+
+/* Calculates correlation vector X'*t */
+void silk_corrVector_FIX(
+ const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */
+ const opus_int16 *t, /* I Target vector [L] */
+ const opus_int L, /* I Length of vectors */
+ const opus_int order, /* I Max lag for correlation */
+ opus_int32 *Xt, /* O Pointer to X'*t correlation vector [order] */
+ const opus_int rshifts, /* I Right shifts of correlations */
+ int arch /* I Run-time architecture */
+);
+
+#endif /* SILK_MAIN_FIX_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_MAIN_FLP_H
+#define SILK_MAIN_FLP_H
+
+#include "SigProc_FLP.h"
+#include "SigProc_FIX.h"
+#include "structs_FLP.h"
+#include "main.h"
+#include "define.h"
+#include "debug.h"
+#include "entenc.h"
+
+
+#define silk_encoder_state_Fxx silk_encoder_state_FLP
+#define silk_encode_do_VAD_Fxx silk_encode_do_VAD_FLP
+#define silk_encode_frame_Fxx silk_encode_frame_FLP
+
+/*********************/
+/* Encoder Functions */
+/*********************/
+
+/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */
+void silk_HP_variable_cutoff(
+ silk_encoder_state_Fxx state_Fxx[] /* I/O Encoder states */
+);
+
+/* Encoder main function */
+void silk_encode_do_VAD_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ opus_int activity /* I Decision of Opus voice activity detector */
+);
+
+/* Encoder main function */
+opus_int silk_encode_frame_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ opus_int32 *pnBytesOut, /* O Number of payload bytes; */
+ ec_enc *psRangeEnc, /* I/O compressor data structure */
+ opus_int condCoding, /* I The type of conditional coding to use */
+ opus_int maxBits, /* I If > 0: maximum number of output bits */
+ opus_int useCBR /* I Flag to force constant-bitrate operation */
+);
+
+/* Initializes the Silk encoder state */
+opus_int silk_init_encoder(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ int arch /* I Run-tim architecture */
+);
+
+/* Control the Silk encoder */
+opus_int silk_control_encoder(
+ silk_encoder_state_FLP *psEnc, /* I/O Pointer to Silk encoder state FLP */
+ silk_EncControlStruct *encControl, /* I Control structure */
+ const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
+ const opus_int channelNb, /* I Channel number */
+ const opus_int force_fs_kHz
+);
+
+/**************************/
+/* Noise shaping analysis */
+/**************************/
+/* Compute noise shaping coefficients and initial gain values */
+void silk_noise_shape_analysis_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ const silk_float *pitch_res, /* I LPC residual from pitch analysis */
+ const silk_float *x /* I Input signal [frame_length + la_shape] */
+);
+
+/* Autocorrelations for a warped frequency axis */
+void silk_warped_autocorrelation_FLP(
+ silk_float *corr, /* O Result [order + 1] */
+ const silk_float *input, /* I Input data to correlate */
+ const silk_float warping, /* I Warping coefficient */
+ const opus_int length, /* I Length of input */
+ const opus_int order /* I Correlation order (even) */
+);
+
+/* Calculation of LTP state scaling */
+void silk_LTP_scale_ctrl_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ opus_int condCoding /* I The type of conditional coding to use */
+);
+
+/**********************************************/
+/* Prediction Analysis */
+/**********************************************/
+/* Find pitch lags */
+void silk_find_pitch_lags_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ silk_float res[], /* O Residual */
+ const silk_float x[], /* I Speech signal */
+ int arch /* I Run-time architecture */
+);
+
+/* Find LPC and LTP coefficients */
+void silk_find_pred_coefs_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ const silk_float res_pitch[], /* I Residual from pitch analysis */
+ const silk_float x[], /* I Speech signal */
+ opus_int condCoding /* I The type of conditional coding to use */
+);
+
+/* LPC analysis */
+void silk_find_LPC_FLP(
+ silk_encoder_state *psEncC, /* I/O Encoder state */
+ opus_int16 NLSF_Q15[], /* O NLSFs */
+ const silk_float x[], /* I Input signal */
+ const silk_float minInvGain, /* I Prediction gain from LTP (dB) */
+ int arch
+);
+
+/* LTP analysis */
+void silk_find_LTP_FLP(
+ silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
+ silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* O Weight for LTP quantization */
+ const silk_float r_ptr[], /* I LPC residual */
+ const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */
+ const opus_int subfr_length, /* I Subframe length */
+ const opus_int nb_subfr, /* I number of subframes */
+ int arch
+);
+
+void silk_LTP_analysis_filter_FLP(
+ silk_float *LTP_res, /* O LTP res MAX_NB_SUBFR*(pre_lgth+subfr_lngth) */
+ const silk_float *x, /* I Input signal, with preceding samples */
+ const silk_float B[ LTP_ORDER * MAX_NB_SUBFR ], /* I LTP coefficients for each subframe */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const silk_float invGains[ MAX_NB_SUBFR ], /* I Inverse quantization gains */
+ const opus_int subfr_length, /* I Length of each subframe */
+ const opus_int nb_subfr, /* I number of subframes */
+ const opus_int pre_length /* I Preceding samples for each subframe */
+);
+
+/* Calculates residual energies of input subframes where all subframes have LPC_order */
+/* of preceding samples */
+void silk_residual_energy_FLP(
+ silk_float nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */
+ const silk_float x[], /* I Input signal */
+ silk_float a[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */
+ const silk_float gains[], /* I Quantization gains */
+ const opus_int subfr_length, /* I Subframe length */
+ const opus_int nb_subfr, /* I number of subframes */
+ const opus_int LPC_order /* I LPC order */
+);
+
+/* 16th order LPC analysis filter */
+void silk_LPC_analysis_filter_FLP(
+ silk_float r_LPC[], /* O LPC residual signal */
+ const silk_float PredCoef[], /* I LPC coefficients */
+ const silk_float s[], /* I Input signal */
+ const opus_int length, /* I Length of input signal */
+ const opus_int Order /* I LPC order */
+);
+
+/* LTP tap quantizer */
+void silk_quant_LTP_gains_FLP(
+ silk_float B[ MAX_NB_SUBFR * LTP_ORDER ], /* O Quantized LTP gains */
+ opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook index */
+ opus_int8 *periodicity_index, /* O Periodicity index */
+ opus_int32 *sum_log_gain_Q7, /* I/O Cumulative max prediction gain */
+ silk_float *pred_gain_dB, /* O LTP prediction gain */
+ const silk_float XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I Correlation matrix */
+ const silk_float xX[ MAX_NB_SUBFR * LTP_ORDER ], /* I Correlation vector */
+ const opus_int subfr_len, /* I Number of samples per subframe */
+ const opus_int nb_subfr, /* I Number of subframes */
+ int arch /* I Run-time architecture */
+);
+
+/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */
+silk_float silk_residual_energy_covar_FLP( /* O Weighted residual energy */
+ const silk_float *c, /* I Filter coefficients */
+ silk_float *wXX, /* I/O Weighted correlation matrix, reg. out */
+ const silk_float *wXx, /* I Weighted correlation vector */
+ const silk_float wxx, /* I Weighted correlation value */
+ const opus_int D /* I Dimension */
+);
+
+/* Processing of gains */
+void silk_process_gains_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ opus_int condCoding /* I The type of conditional coding to use */
+);
+
+/******************/
+/* Linear Algebra */
+/******************/
+/* Calculates correlation matrix X'*X */
+void silk_corrMatrix_FLP(
+ const silk_float *x, /* I x vector [ L+order-1 ] used to create X */
+ const opus_int L, /* I Length of vectors */
+ const opus_int Order, /* I Max lag for correlation */
+ silk_float *XX, /* O X'*X correlation matrix [order x order] */
+ int arch
+);
+
+/* Calculates correlation vector X'*t */
+void silk_corrVector_FLP(
+ const silk_float *x, /* I x vector [L+order-1] used to create X */
+ const silk_float *t, /* I Target vector [L] */
+ const opus_int L, /* I Length of vecors */
+ const opus_int Order, /* I Max lag for correlation */
+ silk_float *Xt, /* O X'*t correlation vector [order] */
+ int arch
+);
+
+/* Apply sine window to signal vector. */
+/* Window types: */
+/* 1 -> sine window from 0 to pi/2 */
+/* 2 -> sine window from pi/2 to pi */
+void silk_apply_sine_window_FLP(
+ silk_float px_win[], /* O Pointer to windowed signal */
+ const silk_float px[], /* I Pointer to input signal */
+ const opus_int win_type, /* I Selects a window type */
+ const opus_int length /* I Window length, multiple of 4 */
+);
+
+/* Wrapper functions. Call flp / fix code */
+
+/* Convert AR filter coefficients to NLSF parameters */
+void silk_A2NLSF_FLP(
+ opus_int16 *NLSF_Q15, /* O NLSF vector [ LPC_order ] */
+ const silk_float *pAR, /* I LPC coefficients [ LPC_order ] */
+ const opus_int LPC_order /* I LPC order */
+);
+
+/* Convert NLSF parameters to AR prediction filter coefficients */
+void silk_NLSF2A_FLP(
+ silk_float *pAR, /* O LPC coefficients [ LPC_order ] */
+ const opus_int16 *NLSF_Q15, /* I NLSF vector [ LPC_order ] */
+ const opus_int LPC_order, /* I LPC order */
+ int arch /* I Run-time architecture */
+);
+
+/* Limit, stabilize, and quantize NLSFs */
+void silk_process_NLSFs_FLP(
+ silk_encoder_state *psEncC, /* I/O Encoder state */
+ silk_float PredCoef[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */
+ opus_int16 NLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */
+ const opus_int16 prev_NLSF_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */
+);
+
+/* Floating-point Silk NSQ wrapper */
+void silk_NSQ_wrapper_FLP(
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
+ SideInfoIndices *psIndices, /* I/O Quantization indices */
+ silk_nsq_state *psNSQ, /* I/O Noise Shaping Quantzation state */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const silk_float x[] /* I Prefiltered input signal */
+);
+
+#endif
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 MAIN_SSE_H
+# define MAIN_SSE_H
+
+# ifdef HAVE_CONFIG_H
+# include "config.h"
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+
+void silk_VQ_WMat_EC_sse4_1(
+ opus_int8 *ind, /* O index of best codebook vector */
+ opus_int32 *res_nrg_Q15, /* O best residual energy */
+ opus_int32 *rate_dist_Q8, /* O best total bitrate */
+ opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
+ const opus_int32 *XX_Q17, /* I correlation matrix */
+ const opus_int32 *xX_Q17, /* I correlation vector */
+ const opus_int8 *cb_Q7, /* I codebook */
+ const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
+ const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
+ const opus_int subfr_len, /* I number of samples per subframe */
+ const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
+ const opus_int L /* I number of vectors in codebook */
+);
+
+# if defined OPUS_X86_PRESUME_SSE4_1
+
+# define OVERRIDE_silk_VQ_WMat_EC
+# define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+ subfr_len, max_gain_Q7, L, arch) \
+ ((void)(arch),silk_VQ_WMat_EC_sse4_1(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+ subfr_len, max_gain_Q7, L))
+
+# elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_VQ_WMAT_EC_IMPL[OPUS_ARCHMASK + 1])(
+ opus_int8 *ind, /* O index of best codebook vector */
+ opus_int32 *res_nrg_Q15, /* O best residual energy */
+ opus_int32 *rate_dist_Q8, /* O best total bitrate */
+ opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
+ const opus_int32 *XX_Q17, /* I correlation matrix */
+ const opus_int32 *xX_Q17, /* I correlation vector */
+ const opus_int8 *cb_Q7, /* I codebook */
+ const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
+ const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
+ const opus_int subfr_len, /* I number of samples per subframe */
+ const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
+ const opus_int L /* I number of vectors in codebook */
+);
+
+# define OVERRIDE_silk_VQ_WMat_EC
+# define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+ subfr_len, max_gain_Q7, L, arch) \
+ ((*SILK_VQ_WMAT_EC_IMPL[(arch) & OPUS_ARCHMASK])(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+ subfr_len, max_gain_Q7, L))
+
+# endif
+
+void silk_NSQ_sse4_1(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+);
+
+# if defined OPUS_X86_PRESUME_SSE4_1
+
+# define OVERRIDE_silk_NSQ
+# define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+ ((void)(arch),silk_NSQ_sse4_1(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+# elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_NSQ_IMPL[OPUS_ARCHMASK + 1])(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+);
+
+# define OVERRIDE_silk_NSQ
+# define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+ ((*SILK_NSQ_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+# endif
+
+void silk_NSQ_del_dec_sse4_1(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+);
+
+void silk_NSQ_del_dec_avx2(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[MAX_NB_SUBFR], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[MAX_NB_SUBFR], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[MAX_NB_SUBFR], /* I Quantization step sizes */
+ const opus_int32 pitchL[MAX_NB_SUBFR], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+);
+
+# if defined (OPUS_X86_PRESUME_AVX2)
+
+# define OVERRIDE_silk_NSQ_del_dec
+# define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+ ((void)(arch),silk_NSQ_del_dec_avx2(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+# elif defined (OPUS_X86_PRESUME_SSE4_1) && !defined(OPUS_X86_MAY_HAVE_AVX2)
+
+# define OVERRIDE_silk_NSQ_del_dec
+# define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+ ((void)(arch),silk_NSQ_del_dec_sse4_1(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+# elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+);
+
+# define OVERRIDE_silk_NSQ_del_dec
+# define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+ ((*SILK_NSQ_DEL_DEC_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+# endif
+
+void silk_noise_shape_quantizer(
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ opus_int signalType, /* I Signal type */
+ const opus_int32 x_sc_Q10[], /* I */
+ opus_int8 pulses[], /* O */
+ opus_int16 xq[], /* O */
+ opus_int32 sLTP_Q15[], /* I/O LTP state */
+ const opus_int16 a_Q12[], /* I Short term prediction coefs */
+ const opus_int16 b_Q14[], /* I Long term prediction coefs */
+ const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
+ opus_int lag, /* I Pitch lag */
+ opus_int32 HarmShapeFIRPacked_Q14, /* I */
+ opus_int Tilt_Q14, /* I Spectral tilt */
+ opus_int32 LF_shp_Q14, /* I */
+ opus_int32 Gain_Q16, /* I */
+ opus_int Lambda_Q10, /* I */
+ opus_int offset_Q10, /* I */
+ opus_int length, /* I Input length */
+ opus_int shapingLPCOrder, /* I Noise shaping AR filter order */
+ opus_int predictLPCOrder, /* I Prediction filter order */
+ int arch /* I Architecture */
+);
+
+/**************************/
+/* Noise level estimation */
+/**************************/
+void silk_VAD_GetNoiseLevels(
+ const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */
+ silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
+);
+
+opus_int silk_VAD_GetSA_Q8_sse4_1(
+ silk_encoder_state *psEnC,
+ const opus_int16 pIn[]
+);
+
+# if defined(OPUS_X86_PRESUME_SSE4_1)
+
+# define OVERRIDE_silk_VAD_GetSA_Q8
+# define silk_VAD_GetSA_Q8(psEnC, pIn, arch) ((void)(arch),silk_VAD_GetSA_Q8_sse4_1(psEnC, pIn))
+
+# elif defined(OPUS_HAVE_RTCD)
+
+extern opus_int (*const SILK_VAD_GETSA_Q8_IMPL[OPUS_ARCHMASK + 1])(
+ silk_encoder_state *psEnC,
+ const opus_int16 pIn[]);
+
+# define OVERRIDE_silk_VAD_GetSA_Q8
+# define silk_VAD_GetSA_Q8(psEnC, pIn, arch) \
+ ((*SILK_VAD_GETSA_Q8_IMPL[(arch) & OPUS_ARCHMASK])(psEnC, pIn))
+
+# endif
+
+#ifndef FIXED_POINT
+double silk_inner_product_FLP_avx2(
+ const silk_float *data1,
+ const silk_float *data2,
+ opus_int dataSize
+);
+
+#if defined (OPUS_X86_PRESUME_AVX2)
+
+#define OVERRIDE_inner_product_FLP
+#define silk_inner_product_FLP(data1, data2, dataSize, arch) ((void)arch,silk_inner_product_FLP_avx2(data1, data2, dataSize))
+
+#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_X86_MAY_HAVE_AVX2)
+
+#define OVERRIDE_inner_product_FLP
+extern double (*const SILK_INNER_PRODUCT_FLP_IMPL[OPUS_ARCHMASK + 1])(
+ const silk_float *data1,
+ const silk_float *data2,
+ opus_int dataSize
+);
+
+#define silk_inner_product_FLP(data1, data2, dataSize, arch) ((void)arch,(*SILK_INNER_PRODUCT_FLP_IMPL[(arch) & OPUS_ARCHMASK])(data1, data2, dataSize))
+
+#endif
+#endif
+
+# endif
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_PE_DEFINES_H
+#define SILK_PE_DEFINES_H
+
+#include "SigProc_FIX.h"
+
+/********************************************************/
+/* Definitions for pitch estimator */
+/********************************************************/
+
+#define PE_MAX_FS_KHZ 16 /* Maximum sampling frequency used */
+
+#define PE_MAX_NB_SUBFR 4
+#define PE_SUBFR_LENGTH_MS 5 /* 5 ms */
+
+#define PE_LTP_MEM_LENGTH_MS ( 4 * PE_SUBFR_LENGTH_MS )
+
+#define PE_MAX_FRAME_LENGTH_MS ( PE_LTP_MEM_LENGTH_MS + PE_MAX_NB_SUBFR * PE_SUBFR_LENGTH_MS )
+#define PE_MAX_FRAME_LENGTH ( PE_MAX_FRAME_LENGTH_MS * PE_MAX_FS_KHZ )
+#define PE_MAX_FRAME_LENGTH_ST_1 ( PE_MAX_FRAME_LENGTH >> 2 )
+#define PE_MAX_FRAME_LENGTH_ST_2 ( PE_MAX_FRAME_LENGTH >> 1 )
+
+#define PE_MAX_LAG_MS 18 /* 18 ms -> 56 Hz */
+#define PE_MIN_LAG_MS 2 /* 2 ms -> 500 Hz */
+#define PE_MAX_LAG ( PE_MAX_LAG_MS * PE_MAX_FS_KHZ )
+#define PE_MIN_LAG ( PE_MIN_LAG_MS * PE_MAX_FS_KHZ )
+
+#define PE_D_SRCH_LENGTH 24
+
+#define PE_NB_STAGE3_LAGS 5
+
+#define PE_NB_CBKS_STAGE2 3
+#define PE_NB_CBKS_STAGE2_EXT 11
+
+#define PE_NB_CBKS_STAGE3_MAX 34
+#define PE_NB_CBKS_STAGE3_MID 24
+#define PE_NB_CBKS_STAGE3_MIN 16
+
+#define PE_NB_CBKS_STAGE3_10MS 12
+#define PE_NB_CBKS_STAGE2_10MS 3
+
+#define PE_SHORTLAG_BIAS 0.2f /* for logarithmic weighting */
+#define PE_PREVLAG_BIAS 0.2f /* for logarithmic weighting */
+#define PE_FLATCONTOUR_BIAS 0.05f
+
+#define SILK_PE_MIN_COMPLEX 0
+#define SILK_PE_MID_COMPLEX 1
+#define SILK_PE_MAX_COMPLEX 2
+
+/* Tables for 20 ms frames */
+extern const opus_int8 silk_CB_lags_stage2[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE2_EXT ];
+extern const opus_int8 silk_CB_lags_stage3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ];
+extern const opus_int8 silk_Lag_range_stage3[ SILK_PE_MAX_COMPLEX + 1 ] [ PE_MAX_NB_SUBFR ][ 2 ];
+extern const opus_int8 silk_nb_cbk_searchs_stage3[ SILK_PE_MAX_COMPLEX + 1 ];
+
+/* Tables for 10 ms frames */
+extern const opus_int8 silk_CB_lags_stage2_10_ms[ PE_MAX_NB_SUBFR >> 1][ 3 ];
+extern const opus_int8 silk_CB_lags_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 12 ];
+extern const opus_int8 silk_Lag_range_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 2 ];
+
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "typedef.h"
+#include "pitch_est_defines.h"
+
+const opus_int8 silk_CB_lags_stage2_10_ms[ PE_MAX_NB_SUBFR >> 1][ PE_NB_CBKS_STAGE2_10MS ] =
+{
+ {0, 1, 0},
+ {0, 0, 1}
+};
+
+const opus_int8 silk_CB_lags_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ PE_NB_CBKS_STAGE3_10MS ] =
+{
+ { 0, 0, 1,-1, 1,-1, 2,-2, 2,-2, 3,-3},
+ { 0, 1, 0, 1,-1, 2,-1, 2,-2, 3,-2, 3}
+};
+
+const opus_int8 silk_Lag_range_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 2 ] =
+{
+ {-3, 7},
+ {-2, 7}
+};
+
+const opus_int8 silk_CB_lags_stage2[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE2_EXT ] =
+{
+ {0, 2,-1,-1,-1, 0, 0, 1, 1, 0, 1},
+ {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0},
+ {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0},
+ {0,-1, 2, 1, 0, 1, 1, 0, 0,-1,-1}
+};
+
+const opus_int8 silk_CB_lags_stage3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ] =
+{
+ {0, 0, 1,-1, 0, 1,-1, 0,-1, 1,-2, 2,-2,-2, 2,-3, 2, 3,-3,-4, 3,-4, 4, 4,-5, 5,-6,-5, 6,-7, 6, 5, 8,-9},
+ {0, 0, 1, 0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1,-1, 0, 1,-1,-1, 1,-1, 2, 1,-1, 2,-2,-2, 2,-2, 2, 2, 3,-3},
+ {0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1,-1, 1, 0, 0, 2, 1,-1, 2,-1,-1, 2,-1, 2, 2,-1, 3,-2,-2,-2, 3},
+ {0, 1, 0, 0, 1, 0, 1,-1, 2,-1, 2,-1, 2, 3,-2, 3,-2,-2, 4, 4,-3, 5,-3,-4, 6,-4, 6, 5,-5, 8,-6,-5,-7, 9}
+};
+
+const opus_int8 silk_Lag_range_stage3[ SILK_PE_MAX_COMPLEX + 1 ] [ PE_MAX_NB_SUBFR ][ 2 ] =
+{
+ /* Lags to search for low number of stage3 cbks */
+ {
+ {-5,8},
+ {-1,6},
+ {-1,6},
+ {-4,10}
+ },
+ /* Lags to search for middle number of stage3 cbks */
+ {
+ {-6,10},
+ {-2,6},
+ {-1,6},
+ {-5,10}
+ },
+ /* Lags to search for max number of stage3 cbks */
+ {
+ {-9,12},
+ {-3,7},
+ {-2,7},
+ {-7,13}
+ }
+};
+
+const opus_int8 silk_nb_cbk_searchs_stage3[ SILK_PE_MAX_COMPLEX + 1 ] =
+{
+ PE_NB_CBKS_STAGE3_MIN,
+ PE_NB_CBKS_STAGE3_MID,
+ PE_NB_CBKS_STAGE3_MAX
+};
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Matrix of resampling methods used:
+ * Fs_out (kHz)
+ * 8 12 16 24 48
+ *
+ * 8 C UF U UF UF
+ * 12 AF C UF U UF
+ * Fs_in (kHz) 16 D AF C UF UF
+ * 24 AF D AF C U
+ * 48 AF AF AF D C
+ *
+ * C -> Copy (no resampling)
+ * D -> Allpass-based 2x downsampling
+ * U -> Allpass-based 2x upsampling
+ * UF -> Allpass-based 2x upsampling followed by FIR interpolation
+ * AF -> AR2 filter followed by FIR interpolation
+ */
+
+#include "resampler_private.h"
+
+/* Tables with delay compensation values to equalize total delay for different modes */
+static const opus_int8 delay_matrix_enc[ 6 ][ 3 ] = {
+/* in \ out 8 12 16 */
+/* 8 */ { 6, 0, 3 },
+/* 12 */ { 0, 7, 3 },
+/* 16 */ { 0, 1, 10 },
+/* 24 */ { 0, 2, 6 },
+/* 48 */ { 18, 10, 12 },
+/* 96 */ { 0, 0, 44 }
+};
+
+static const opus_int8 delay_matrix_dec[ 3 ][ 6 ] = {
+/* in \ out 8 12 16 24 48 96*/
+/* 8 */ { 4, 0, 2, 0, 0, 0 },
+/* 12 */ { 0, 9, 4, 7, 4, 4 },
+/* 16 */ { 0, 3, 12, 7, 7, 7 }
+};
+
+/* Simple way to make [8000, 12000, 16000, 24000, 48000] to [0, 1, 2, 3, 4] */
+#define rateID(R) IMIN(5, ( ( ( ((R)>>12) - ((R)>16000) ) >> ((R)>24000) ) - 1 ))
+
+#define USE_silk_resampler_copy (0)
+#define USE_silk_resampler_private_up2_HQ_wrapper (1)
+#define USE_silk_resampler_private_IIR_FIR (2)
+#define USE_silk_resampler_private_down_FIR (3)
+
+/* Initialize/reset the resampler state for a given pair of input/output sampling rates */
+opus_int silk_resampler_init(
+ silk_resampler_state_struct *S, /* I/O Resampler state */
+ opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */
+ opus_int32 Fs_Hz_out, /* I Output sampling rate (Hz) */
+ opus_int forEnc /* I If 1: encoder; if 0: decoder */
+)
+{
+ opus_int up2x;
+
+ /* Clear state */
+ silk_memset( S, 0, sizeof( silk_resampler_state_struct ) );
+
+ /* Input checking */
+ if( forEnc ) {
+ if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 && Fs_Hz_in != 24000 && Fs_Hz_in != 48000
+#ifdef ENABLE_QEXT
+ && Fs_Hz_in != 96000
+#endif
+ ) ||
+ ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 ) ) {
+ celt_assert( 0 );
+ return -1;
+ }
+ S->inputDelay = delay_matrix_enc[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ];
+ } else {
+ if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 ) ||
+ ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000
+#ifdef ENABLE_QEXT
+ && Fs_Hz_out != 96000
+#endif
+ ) ) {
+ celt_assert( 0 );
+ return -1;
+ }
+ S->inputDelay = delay_matrix_dec[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ];
+ }
+
+ S->Fs_in_kHz = silk_DIV32_16( Fs_Hz_in, 1000 );
+ S->Fs_out_kHz = silk_DIV32_16( Fs_Hz_out, 1000 );
+
+ /* Number of samples processed per batch */
+ S->batchSize = S->Fs_in_kHz * RESAMPLER_MAX_BATCH_SIZE_MS;
+
+ /* Find resampler with the right sampling ratio */
+ up2x = 0;
+ if( Fs_Hz_out > Fs_Hz_in ) {
+ /* Upsample */
+ if( Fs_Hz_out == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 1 */
+ /* Special case: directly use 2x upsampler */
+ S->resampler_function = USE_silk_resampler_private_up2_HQ_wrapper;
+ } else {
+ /* Default resampler */
+ S->resampler_function = USE_silk_resampler_private_IIR_FIR;
+ up2x = 1;
+ }
+ } else if ( Fs_Hz_out < Fs_Hz_in ) {
+ /* Downsample */
+ S->resampler_function = USE_silk_resampler_private_down_FIR;
+ if( silk_MUL( Fs_Hz_out, 4 ) == silk_MUL( Fs_Hz_in, 3 ) ) { /* Fs_out : Fs_in = 3 : 4 */
+ S->FIR_Fracs = 3;
+ S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0;
+ S->Coefs = silk_Resampler_3_4_COEFS;
+ } else if( silk_MUL( Fs_Hz_out, 3 ) == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 3 */
+ S->FIR_Fracs = 2;
+ S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0;
+ S->Coefs = silk_Resampler_2_3_COEFS;
+ } else if( silk_MUL( Fs_Hz_out, 2 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 2 */
+ S->FIR_Fracs = 1;
+ S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR1;
+ S->Coefs = silk_Resampler_1_2_COEFS;
+ } else if( silk_MUL( Fs_Hz_out, 3 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 3 */
+ S->FIR_Fracs = 1;
+ S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
+ S->Coefs = silk_Resampler_1_3_COEFS;
+ } else if( silk_MUL( Fs_Hz_out, 4 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 4 */
+ S->FIR_Fracs = 1;
+ S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
+ S->Coefs = silk_Resampler_1_4_COEFS;
+ } else if( silk_MUL( Fs_Hz_out, 6 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 6 */
+ S->FIR_Fracs = 1;
+ S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
+ S->Coefs = silk_Resampler_1_6_COEFS;
+ } else {
+ /* None available */
+ celt_assert( 0 );
+ return -1;
+ }
+ } else {
+ /* Input and output sampling rates are equal: copy */
+ S->resampler_function = USE_silk_resampler_copy;
+ }
+
+ /* Ratio of input/output samples */
+ S->invRatio_Q16 = silk_LSHIFT32( silk_DIV32( silk_LSHIFT32( Fs_Hz_in, 14 + up2x ), Fs_Hz_out ), 2 );
+ /* Make sure the ratio is rounded up */
+ while( silk_SMULWW( S->invRatio_Q16, Fs_Hz_out ) < silk_LSHIFT32( Fs_Hz_in, up2x ) ) {
+ S->invRatio_Q16++;
+ }
+
+ return 0;
+}
+
+/* Resampler: convert from one sampling rate to another */
+/* Input and output sampling rate are at most 48000 Hz */
+opus_int silk_resampler(
+ silk_resampler_state_struct *S, /* I/O Resampler state */
+ opus_int16 out[], /* O Output signal */
+ const opus_int16 in[], /* I Input signal */
+ opus_int32 inLen /* I Number of input samples */
+)
+{
+ opus_int nSamples;
+
+ /* Need at least 1 ms of input data */
+ celt_assert( inLen >= S->Fs_in_kHz );
+ /* Delay can't exceed the 1 ms of buffering */
+ celt_assert( S->inputDelay <= S->Fs_in_kHz );
+
+ nSamples = S->Fs_in_kHz - S->inputDelay;
+
+ /* Copy to delay buffer */
+ silk_memcpy( &S->delayBuf[ S->inputDelay ], in, nSamples * sizeof( opus_int16 ) );
+
+ switch( S->resampler_function ) {
+ case USE_silk_resampler_private_up2_HQ_wrapper:
+ silk_resampler_private_up2_HQ_wrapper( S, out, S->delayBuf, S->Fs_in_kHz );
+ silk_resampler_private_up2_HQ_wrapper( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz );
+ break;
+ case USE_silk_resampler_private_IIR_FIR:
+ silk_resampler_private_IIR_FIR( S, out, S->delayBuf, S->Fs_in_kHz );
+ silk_resampler_private_IIR_FIR( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz );
+ break;
+ case USE_silk_resampler_private_down_FIR:
+ silk_resampler_private_down_FIR( S, out, S->delayBuf, S->Fs_in_kHz );
+ silk_resampler_private_down_FIR( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz );
+ break;
+ default:
+ silk_memcpy( out, S->delayBuf, S->Fs_in_kHz * sizeof( opus_int16 ) );
+ silk_memcpy( &out[ S->Fs_out_kHz ], &in[ nSamples ], ( inLen - S->Fs_in_kHz ) * sizeof( opus_int16 ) );
+ }
+
+ /* Copy to delay buffer */
+ silk_memcpy( S->delayBuf, &in[ inLen - S->inputDelay ], S->inputDelay * sizeof( opus_int16 ) );
+
+ return 0;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "resampler_rom.h"
+
+/* Downsample by a factor 2 */
+void silk_resampler_down2(
+ opus_int32 *S, /* I/O State vector [ 2 ] */
+ opus_int16 *out, /* O Output signal [ floor(len/2) ] */
+ const opus_int16 *in, /* I Input signal [ len ] */
+ opus_int32 inLen /* I Number of input samples */
+)
+{
+ opus_int32 k, len2 = silk_RSHIFT32( inLen, 1 );
+ opus_int32 in32, out32, Y, X;
+
+ celt_assert( silk_resampler_down2_0 > 0 );
+ celt_assert( silk_resampler_down2_1 < 0 );
+
+ /* Internal variables and state are in Q10 format */
+ for( k = 0; k < len2; k++ ) {
+ /* Convert to Q10 */
+ in32 = silk_LSHIFT( (opus_int32)in[ 2 * k ], 10 );
+
+ /* All-pass section for even input sample */
+ Y = silk_SUB32( in32, S[ 0 ] );
+ X = silk_SMLAWB( Y, Y, silk_resampler_down2_1 );
+ out32 = silk_ADD32( S[ 0 ], X );
+ S[ 0 ] = silk_ADD32( in32, X );
+
+ /* Convert to Q10 */
+ in32 = silk_LSHIFT( (opus_int32)in[ 2 * k + 1 ], 10 );
+
+ /* All-pass section for odd input sample, and add to output of previous section */
+ Y = silk_SUB32( in32, S[ 1 ] );
+ X = silk_SMULWB( Y, silk_resampler_down2_0 );
+ out32 = silk_ADD32( out32, S[ 1 ] );
+ out32 = silk_ADD32( out32, X );
+ S[ 1 ] = silk_ADD32( in32, X );
+
+ /* Add, convert back to int16 and store to output */
+ out[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32, 11 ) );
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "resampler_private.h"
+#include "stack_alloc.h"
+
+#define ORDER_FIR 4
+
+/* Downsample by a factor 2/3, low quality */
+void silk_resampler_down2_3(
+ opus_int32 *S, /* I/O State vector [ 6 ] */
+ opus_int16 *out, /* O Output signal [ floor(2*inLen/3) ] */
+ const opus_int16 *in, /* I Input signal [ inLen ] */
+ opus_int32 inLen /* I Number of input samples */
+)
+{
+ opus_int32 nSamplesIn, counter, res_Q6;
+ VARDECL( opus_int32, buf );
+ opus_int32 *buf_ptr;
+ SAVE_STACK;
+
+ ALLOC( buf, RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR, opus_int32 );
+
+ /* Copy buffered samples to start of buffer */
+ silk_memcpy( buf, S, ORDER_FIR * sizeof( opus_int32 ) );
+
+ /* Iterate over blocks of frameSizeIn input samples */
+ while( 1 ) {
+ nSamplesIn = silk_min( inLen, RESAMPLER_MAX_BATCH_SIZE_IN );
+
+ /* Second-order AR filter (output in Q8) */
+ silk_resampler_private_AR2( &S[ ORDER_FIR ], &buf[ ORDER_FIR ], in,
+ silk_Resampler_2_3_COEFS_LQ, nSamplesIn );
+
+ /* Interpolate filtered signal */
+ buf_ptr = buf;
+ counter = nSamplesIn;
+ while( counter > 2 ) {
+ /* Inner product */
+ res_Q6 = silk_SMULWB( buf_ptr[ 0 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] );
+
+ /* Scale down, saturate and store in output array */
+ *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+
+ res_Q6 = silk_SMULWB( buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] );
+
+ /* Scale down, saturate and store in output array */
+ *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+
+ buf_ptr += 3;
+ counter -= 3;
+ }
+
+ in += nSamplesIn;
+ inLen -= nSamplesIn;
+
+ if( inLen > 0 ) {
+ /* More iterations to do; copy last part of filtered signal to beginning of buffer */
+ silk_memcpy( buf, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) );
+ } else {
+ break;
+ }
+ }
+
+ /* Copy last part of filtered signal to the state for the next call */
+ silk_memcpy( S, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) );
+ RESTORE_STACK;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_RESAMPLER_PRIVATE_H
+#define SILK_RESAMPLER_PRIVATE_H
+
+#include "SigProc_FIX.h"
+#include "resampler_structs.h"
+#include "resampler_rom.h"
+
+/* Number of input samples to process in the inner loop */
+#define RESAMPLER_MAX_BATCH_SIZE_MS 10
+#define RESAMPLER_MAX_FS_KHZ 48
+#define RESAMPLER_MAX_BATCH_SIZE_IN ( RESAMPLER_MAX_BATCH_SIZE_MS * RESAMPLER_MAX_FS_KHZ )
+
+/* Description: Hybrid IIR/FIR polyphase implementation of resampling */
+void silk_resampler_private_IIR_FIR(
+ void *SS, /* I/O Resampler state */
+ opus_int16 out[], /* O Output signal */
+ const opus_int16 in[], /* I Input signal */
+ opus_int32 inLen /* I Number of input samples */
+);
+
+/* Description: Hybrid IIR/FIR polyphase implementation of resampling */
+void silk_resampler_private_down_FIR(
+ void *SS, /* I/O Resampler state */
+ opus_int16 out[], /* O Output signal */
+ const opus_int16 in[], /* I Input signal */
+ opus_int32 inLen /* I Number of input samples */
+);
+
+/* Upsample by a factor 2, high quality */
+void silk_resampler_private_up2_HQ_wrapper(
+ void *SS, /* I/O Resampler state (unused) */
+ opus_int16 *out, /* O Output signal [ 2 * len ] */
+ const opus_int16 *in, /* I Input signal [ len ] */
+ opus_int32 len /* I Number of input samples */
+);
+
+/* Upsample by a factor 2, high quality */
+void silk_resampler_private_up2_HQ(
+ opus_int32 *S, /* I/O Resampler state [ 6 ] */
+ opus_int16 *out, /* O Output signal [ 2 * len ] */
+ const opus_int16 *in, /* I Input signal [ len ] */
+ opus_int32 len /* I Number of input samples */
+);
+
+/* Second order AR filter */
+void silk_resampler_private_AR2(
+ opus_int32 S[], /* I/O State vector [ 2 ] */
+ opus_int32 out_Q8[], /* O Output signal */
+ const opus_int16 in[], /* I Input signal */
+ const opus_int16 A_Q14[], /* I AR coefficients, Q14 */
+ opus_int32 len /* I Signal length */
+);
+
+#endif /* SILK_RESAMPLER_PRIVATE_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "resampler_private.h"
+
+/* Second order AR filter with single delay elements */
+void silk_resampler_private_AR2(
+ opus_int32 S[], /* I/O State vector [ 2 ] */
+ opus_int32 out_Q8[], /* O Output signal */
+ const opus_int16 in[], /* I Input signal */
+ const opus_int16 A_Q14[], /* I AR coefficients, Q14 */
+ opus_int32 len /* I Signal length */
+)
+{
+ opus_int32 k;
+ opus_int32 out32;
+
+ for( k = 0; k < len; k++ ) {
+ out32 = silk_ADD_LSHIFT32( S[ 0 ], (opus_int32)in[ k ], 8 );
+ out_Q8[ k ] = out32;
+ out32 = silk_LSHIFT( out32, 2 );
+ S[ 0 ] = silk_SMLAWB( S[ 1 ], out32, A_Q14[ 0 ] );
+ S[ 1 ] = silk_SMULWB( out32, A_Q14[ 1 ] );
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "resampler_private.h"
+#include "stack_alloc.h"
+
+static OPUS_INLINE opus_int16 *silk_resampler_private_IIR_FIR_INTERPOL(
+ opus_int16 *out,
+ opus_int16 *buf,
+ opus_int32 max_index_Q16,
+ opus_int32 index_increment_Q16
+)
+{
+ opus_int32 index_Q16, res_Q15;
+ opus_int16 *buf_ptr;
+ opus_int32 table_index;
+
+ /* Interpolate upsampled signal and store in output array */
+ for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
+ table_index = silk_SMULWB( index_Q16 & 0xFFFF, 12 );
+ buf_ptr = &buf[ index_Q16 >> 16 ];
+
+ res_Q15 = silk_SMULBB( buf_ptr[ 0 ], silk_resampler_frac_FIR_12[ table_index ][ 0 ] );
+ res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 1 ], silk_resampler_frac_FIR_12[ table_index ][ 1 ] );
+ res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 2 ], silk_resampler_frac_FIR_12[ table_index ][ 2 ] );
+ res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 3 ], silk_resampler_frac_FIR_12[ table_index ][ 3 ] );
+ res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 4 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 3 ] );
+ res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 5 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 2 ] );
+ res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 6 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 1 ] );
+ res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 7 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 0 ] );
+ *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q15, 15 ) );
+ }
+ return out;
+}
+/* Upsample using a combination of allpass-based 2x upsampling and FIR interpolation */
+void silk_resampler_private_IIR_FIR(
+ void *SS, /* I/O Resampler state */
+ opus_int16 out[], /* O Output signal */
+ const opus_int16 in[], /* I Input signal */
+ opus_int32 inLen /* I Number of input samples */
+)
+{
+ silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
+ opus_int32 nSamplesIn;
+ opus_int32 max_index_Q16, index_increment_Q16;
+ VARDECL( opus_int16, buf );
+ SAVE_STACK;
+
+ ALLOC( buf, 2 * S->batchSize + RESAMPLER_ORDER_FIR_12, opus_int16 );
+
+ /* Copy buffered samples to start of buffer */
+ silk_memcpy( buf, S->sFIR.i16, RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) );
+
+ /* Iterate over blocks of frameSizeIn input samples */
+ index_increment_Q16 = S->invRatio_Q16;
+ while( 1 ) {
+ nSamplesIn = silk_min( inLen, S->batchSize );
+
+ /* Upsample 2x */
+ silk_resampler_private_up2_HQ( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_12 ], in, nSamplesIn );
+
+ max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 + 1 ); /* + 1 because 2x upsampling */
+ out = silk_resampler_private_IIR_FIR_INTERPOL( out, buf, max_index_Q16, index_increment_Q16 );
+ in += nSamplesIn;
+ inLen -= nSamplesIn;
+
+ if( inLen > 0 ) {
+ /* More iterations to do; copy last part of filtered signal to beginning of buffer */
+ silk_memcpy( buf, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) );
+ } else {
+ break;
+ }
+ }
+
+ /* Copy last part of filtered signal to the state for the next call */
+ silk_memcpy( S->sFIR.i16, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) );
+ RESTORE_STACK;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "resampler_private.h"
+#include "stack_alloc.h"
+
+static OPUS_INLINE opus_int16 *silk_resampler_private_down_FIR_INTERPOL(
+ opus_int16 *out,
+ opus_int32 *buf,
+ const opus_int16 *FIR_Coefs,
+ opus_int FIR_Order,
+ opus_int FIR_Fracs,
+ opus_int32 max_index_Q16,
+ opus_int32 index_increment_Q16
+)
+{
+ opus_int32 index_Q16, res_Q6;
+ opus_int32 *buf_ptr;
+ opus_int32 interpol_ind;
+ const opus_int16 *interpol_ptr;
+
+ switch( FIR_Order ) {
+ case RESAMPLER_DOWN_ORDER_FIR0:
+ for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
+ /* Integer part gives pointer to buffered input */
+ buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
+
+ /* Fractional part gives interpolation coefficients */
+ interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs );
+
+ /* Inner product */
+ interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * interpol_ind ];
+ res_Q6 = silk_SMULWB( buf_ptr[ 0 ], interpol_ptr[ 0 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 6 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 8 ] );
+ interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * ( FIR_Fracs - 1 - interpol_ind ) ];
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 17 ], interpol_ptr[ 0 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 16 ], interpol_ptr[ 1 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 2 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 3 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 4 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 5 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 6 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 7 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 9 ], interpol_ptr[ 8 ] );
+
+ /* Scale down, saturate and store in output array */
+ *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+ }
+ break;
+ case RESAMPLER_DOWN_ORDER_FIR1:
+ for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
+ /* Integer part gives pointer to buffered input */
+ buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
+
+ /* Inner product */
+ res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 23 ] ), FIR_Coefs[ 0 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 22 ] ), FIR_Coefs[ 1 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 21 ] ), FIR_Coefs[ 2 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 20 ] ), FIR_Coefs[ 3 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 19 ] ), FIR_Coefs[ 4 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 18 ] ), FIR_Coefs[ 5 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 17 ] ), FIR_Coefs[ 6 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 16 ] ), FIR_Coefs[ 7 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 8 ], buf_ptr[ 15 ] ), FIR_Coefs[ 8 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 9 ], buf_ptr[ 14 ] ), FIR_Coefs[ 9 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 13 ] ), FIR_Coefs[ 10 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 12 ] ), FIR_Coefs[ 11 ] );
+
+ /* Scale down, saturate and store in output array */
+ *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+ }
+ break;
+ case RESAMPLER_DOWN_ORDER_FIR2:
+ for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
+ /* Integer part gives pointer to buffered input */
+ buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
+
+ /* Inner product */
+ res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 35 ] ), FIR_Coefs[ 0 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 34 ] ), FIR_Coefs[ 1 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 33 ] ), FIR_Coefs[ 2 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 32 ] ), FIR_Coefs[ 3 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 31 ] ), FIR_Coefs[ 4 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 30 ] ), FIR_Coefs[ 5 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 29 ] ), FIR_Coefs[ 6 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 28 ] ), FIR_Coefs[ 7 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 8 ], buf_ptr[ 27 ] ), FIR_Coefs[ 8 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 9 ], buf_ptr[ 26 ] ), FIR_Coefs[ 9 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 25 ] ), FIR_Coefs[ 10 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 24 ] ), FIR_Coefs[ 11 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 12 ], buf_ptr[ 23 ] ), FIR_Coefs[ 12 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 13 ], buf_ptr[ 22 ] ), FIR_Coefs[ 13 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 14 ], buf_ptr[ 21 ] ), FIR_Coefs[ 14 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 15 ], buf_ptr[ 20 ] ), FIR_Coefs[ 15 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 16 ], buf_ptr[ 19 ] ), FIR_Coefs[ 16 ] );
+ res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 17 ], buf_ptr[ 18 ] ), FIR_Coefs[ 17 ] );
+
+ /* Scale down, saturate and store in output array */
+ *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+ }
+ break;
+ default:
+ celt_assert( 0 );
+ }
+ return out;
+}
+
+/* Resample with a 2nd order AR filter followed by FIR interpolation */
+void silk_resampler_private_down_FIR(
+ void *SS, /* I/O Resampler state */
+ opus_int16 out[], /* O Output signal */
+ const opus_int16 in[], /* I Input signal */
+ opus_int32 inLen /* I Number of input samples */
+)
+{
+ silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
+ opus_int32 nSamplesIn;
+ opus_int32 max_index_Q16, index_increment_Q16;
+ VARDECL( opus_int32, buf );
+ const opus_int16 *FIR_Coefs;
+ SAVE_STACK;
+
+ ALLOC( buf, S->batchSize + S->FIR_Order, opus_int32 );
+
+ /* Copy buffered samples to start of buffer */
+ silk_memcpy( buf, S->sFIR.i32, S->FIR_Order * sizeof( opus_int32 ) );
+
+ FIR_Coefs = &S->Coefs[ 2 ];
+
+ /* Iterate over blocks of frameSizeIn input samples */
+ index_increment_Q16 = S->invRatio_Q16;
+ while( 1 ) {
+ nSamplesIn = silk_min( inLen, S->batchSize );
+
+ /* Second-order AR filter (output in Q8) */
+ silk_resampler_private_AR2( S->sIIR, &buf[ S->FIR_Order ], in, S->Coefs, nSamplesIn );
+
+ max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 );
+
+ /* Interpolate filtered signal */
+ out = silk_resampler_private_down_FIR_INTERPOL( out, buf, FIR_Coefs, S->FIR_Order,
+ S->FIR_Fracs, max_index_Q16, index_increment_Q16 );
+
+ in += nSamplesIn;
+ inLen -= nSamplesIn;
+
+ if( inLen > 1 ) {
+ /* More iterations to do; copy last part of filtered signal to beginning of buffer */
+ silk_memcpy( buf, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) );
+ } else {
+ break;
+ }
+ }
+
+ /* Copy last part of filtered signal to the state for the next call */
+ silk_memcpy( S->sFIR.i32, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) );
+ RESTORE_STACK;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "resampler_private.h"
+
+/* Upsample by a factor 2, high quality */
+/* Uses 2nd order allpass filters for the 2x upsampling, followed by a */
+/* notch filter just above Nyquist. */
+void silk_resampler_private_up2_HQ(
+ opus_int32 *S, /* I/O Resampler state [ 6 ] */
+ opus_int16 *out, /* O Output signal [ 2 * len ] */
+ const opus_int16 *in, /* I Input signal [ len ] */
+ opus_int32 len /* I Number of input samples */
+)
+{
+ opus_int32 k;
+ opus_int32 in32, out32_1, out32_2, Y, X;
+
+ silk_assert( silk_resampler_up2_hq_0[ 0 ] > 0 );
+ silk_assert( silk_resampler_up2_hq_0[ 1 ] > 0 );
+ silk_assert( silk_resampler_up2_hq_0[ 2 ] < 0 );
+ silk_assert( silk_resampler_up2_hq_1[ 0 ] > 0 );
+ silk_assert( silk_resampler_up2_hq_1[ 1 ] > 0 );
+ silk_assert( silk_resampler_up2_hq_1[ 2 ] < 0 );
+
+ /* Internal variables and state are in Q10 format */
+ for( k = 0; k < len; k++ ) {
+ /* Convert to Q10 */
+ in32 = silk_LSHIFT( (opus_int32)in[ k ], 10 );
+
+ /* First all-pass section for even output sample */
+ Y = silk_SUB32( in32, S[ 0 ] );
+ X = silk_SMULWB( Y, silk_resampler_up2_hq_0[ 0 ] );
+ out32_1 = silk_ADD32( S[ 0 ], X );
+ S[ 0 ] = silk_ADD32( in32, X );
+
+ /* Second all-pass section for even output sample */
+ Y = silk_SUB32( out32_1, S[ 1 ] );
+ X = silk_SMULWB( Y, silk_resampler_up2_hq_0[ 1 ] );
+ out32_2 = silk_ADD32( S[ 1 ], X );
+ S[ 1 ] = silk_ADD32( out32_1, X );
+
+ /* Third all-pass section for even output sample */
+ Y = silk_SUB32( out32_2, S[ 2 ] );
+ X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_0[ 2 ] );
+ out32_1 = silk_ADD32( S[ 2 ], X );
+ S[ 2 ] = silk_ADD32( out32_2, X );
+
+ /* Apply gain in Q15, convert back to int16 and store to output */
+ out[ 2 * k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) );
+
+ /* First all-pass section for odd output sample */
+ Y = silk_SUB32( in32, S[ 3 ] );
+ X = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 0 ] );
+ out32_1 = silk_ADD32( S[ 3 ], X );
+ S[ 3 ] = silk_ADD32( in32, X );
+
+ /* Second all-pass section for odd output sample */
+ Y = silk_SUB32( out32_1, S[ 4 ] );
+ X = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 1 ] );
+ out32_2 = silk_ADD32( S[ 4 ], X );
+ S[ 4 ] = silk_ADD32( out32_1, X );
+
+ /* Third all-pass section for odd output sample */
+ Y = silk_SUB32( out32_2, S[ 5 ] );
+ X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_1[ 2 ] );
+ out32_1 = silk_ADD32( S[ 5 ], X );
+ S[ 5 ] = silk_ADD32( out32_2, X );
+
+ /* Apply gain in Q15, convert back to int16 and store to output */
+ out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) );
+ }
+}
+
+void silk_resampler_private_up2_HQ_wrapper(
+ void *SS, /* I/O Resampler state (unused) */
+ opus_int16 *out, /* O Output signal [ 2 * len ] */
+ const opus_int16 *in, /* I Input signal [ len ] */
+ opus_int32 len /* I Number of input samples */
+)
+{
+ silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
+ silk_resampler_private_up2_HQ( S->sIIR, out, in, len );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Filter coefficients for IIR/FIR polyphase resampling *
+ * Total size: 179 Words (358 Bytes) */
+
+#include "resampler_private.h"
+
+/* Matlab code for the notch filter coefficients: */
+/* B = [1, 0.147, 1]; A = [1, 0.107, 0.89]; G = 0.93; freqz(G * B, A, 2^14, 16e3); axis([0, 8000, -10, 1]) */
+/* fprintf('\t%6d, %6d, %6d, %6d\n', round(B(2)*2^16), round(-A(2)*2^16), round((1-A(3))*2^16), round(G*2^15)) */
+/* const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 9634, -7012, 7209, 30474 }; */
+
+/* Tables with IIR and FIR coefficients for fractional downsamplers (123 Words) */
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = {
+ -20694, -13867,
+ -49, 64, 17, -157, 353, -496, 163, 11047, 22205,
+ -39, 6, 91, -170, 186, 23, -896, 6336, 19928,
+ -19, -36, 102, -89, -24, 328, -951, 2568, 15909,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = {
+ -14457, -14019,
+ 64, 128, -122, 36, 310, -768, 584, 9267, 17733,
+ 12, 128, 18, -142, 288, -117, -865, 4123, 14459,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR1 / 2 ] = {
+ 616, -14323,
+ -10, 39, 58, -46, -84, 120, 184, -315, -541, 1284, 5380, 9024,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
+ 16102, -15162,
+ -13, 0, 20, 26, 5, -31, -43, -4, 65, 90, 7, -157, -248, -44, 593, 1583, 2612, 3271,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_4_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
+ 22500, -15099,
+ 3, -14, -20, -15, 2, 25, 37, 25, -16, -71, -107, -79, 50, 292, 623, 982, 1288, 1464,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_6_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
+ 27540, -15257,
+ 17, 12, 8, 1, -10, -22, -30, -32, -22, 3, 44, 100, 168, 243, 317, 381, 429, 455,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = {
+ -2797, -6507,
+ 4697, 10739,
+ 1567, 8276,
+};
+
+/* Table with interplation fractions of 1/24, 3/24, 5/24, ... , 23/24 : 23/24 (46 Words) */
+silk_DWORD_ALIGN const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ] = {
+ { 189, -600, 617, 30567 },
+ { 117, -159, -1070, 29704 },
+ { 52, 221, -2392, 28276 },
+ { -4, 529, -3350, 26341 },
+ { -48, 758, -3956, 23973 },
+ { -80, 905, -4235, 21254 },
+ { -99, 972, -4222, 18278 },
+ { -107, 967, -3957, 15143 },
+ { -103, 896, -3487, 11950 },
+ { -91, 773, -2865, 8798 },
+ { -71, 611, -2143, 5784 },
+ { -46, 425, -1375, 2996 },
+};
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_FIX_RESAMPLER_ROM_H
+#define SILK_FIX_RESAMPLER_ROM_H
+
+
+#include "typedef.h"
+#include "resampler_structs.h"
+
+#define RESAMPLER_DOWN_ORDER_FIR0 18
+#define RESAMPLER_DOWN_ORDER_FIR1 24
+#define RESAMPLER_DOWN_ORDER_FIR2 36
+#define RESAMPLER_ORDER_FIR_12 8
+
+/* Tables for 2x downsampler */
+static const opus_int16 silk_resampler_down2_0 = 9872;
+static const opus_int16 silk_resampler_down2_1 = 39809 - 65536;
+
+/* Tables for 2x upsampler, high quality */
+static const opus_int16 silk_resampler_up2_hq_0[ 3 ] = { 1746, 14986, 39083 - 65536 };
+static const opus_int16 silk_resampler_up2_hq_1[ 3 ] = { 6854, 25769, 55542 - 65536 };
+
+/* Tables with IIR and FIR coefficients for fractional downsamplers */
+extern const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ];
+extern const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ];
+extern const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR1 / 2 ];
+extern const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ];
+extern const opus_int16 silk_Resampler_1_4_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ];
+extern const opus_int16 silk_Resampler_1_6_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ];
+extern const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ];
+
+/* Table with interplation fractions of 1/24, 3/24, ..., 23/24 */
+extern const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ];
+
+#endif /* SILK_FIX_RESAMPLER_ROM_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_RESAMPLER_STRUCTS_H
+#define SILK_RESAMPLER_STRUCTS_H
+
+#define SILK_RESAMPLER_MAX_FIR_ORDER 36
+#define SILK_RESAMPLER_MAX_IIR_ORDER 6
+
+typedef struct _silk_resampler_state_struct{
+ opus_int32 sIIR[ SILK_RESAMPLER_MAX_IIR_ORDER ]; /* this must be the first element of this struct */
+ union{
+ opus_int32 i32[ SILK_RESAMPLER_MAX_FIR_ORDER ];
+ opus_int16 i16[ SILK_RESAMPLER_MAX_FIR_ORDER ];
+ } sFIR;
+ opus_int16 delayBuf[ 96 ];
+ opus_int resampler_function;
+ opus_int batchSize;
+ opus_int32 invRatio_Q16;
+ opus_int FIR_Order;
+ opus_int FIR_Fracs;
+ opus_int Fs_in_kHz;
+ opus_int Fs_out_kHz;
+ opus_int inputDelay;
+ const opus_int16 *Coefs;
+} silk_resampler_state_struct;
+
+#endif /* SILK_RESAMPLER_STRUCTS_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* shell coder; pulse-subframe length is hardcoded */
+
+static OPUS_INLINE void combine_pulses(
+ opus_int *out, /* O combined pulses vector [len] */
+ const opus_int *in, /* I input vector [2 * len] */
+ const opus_int len /* I number of OUTPUT samples */
+)
+{
+ opus_int k;
+ for( k = 0; k < len; k++ ) {
+ out[ k ] = in[ 2 * k ] + in[ 2 * k + 1 ];
+ }
+}
+
+static OPUS_INLINE void encode_split(
+ ec_enc *psRangeEnc, /* I/O compressor data structure */
+ const opus_int p_child1, /* I pulse amplitude of first child subframe */
+ const opus_int p, /* I pulse amplitude of current subframe */
+ const opus_uint8 *shell_table /* I table of shell cdfs */
+)
+{
+ if( p > 0 ) {
+ ec_enc_icdf( psRangeEnc, p_child1, &shell_table[ silk_shell_code_table_offsets[ p ] ], 8 );
+ }
+}
+
+static OPUS_INLINE void decode_split(
+ opus_int16 *p_child1, /* O pulse amplitude of first child subframe */
+ opus_int16 *p_child2, /* O pulse amplitude of second child subframe */
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ const opus_int p, /* I pulse amplitude of current subframe */
+ const opus_uint8 *shell_table /* I table of shell cdfs */
+)
+{
+ if( p > 0 ) {
+ p_child1[ 0 ] = ec_dec_icdf( psRangeDec, &shell_table[ silk_shell_code_table_offsets[ p ] ], 8 );
+ p_child2[ 0 ] = p - p_child1[ 0 ];
+ } else {
+ p_child1[ 0 ] = 0;
+ p_child2[ 0 ] = 0;
+ }
+}
+
+/* Shell encoder, operates on one shell code frame of 16 pulses */
+void silk_shell_encoder(
+ ec_enc *psRangeEnc, /* I/O compressor data structure */
+ const opus_int *pulses0 /* I data: nonnegative pulse amplitudes */
+)
+{
+ opus_int pulses1[ 8 ], pulses2[ 4 ], pulses3[ 2 ], pulses4[ 1 ];
+
+ /* this function operates on one shell code frame of 16 pulses */
+ silk_assert( SHELL_CODEC_FRAME_LENGTH == 16 );
+
+ /* tree representation per pulse-subframe */
+ combine_pulses( pulses1, pulses0, 8 );
+ combine_pulses( pulses2, pulses1, 4 );
+ combine_pulses( pulses3, pulses2, 2 );
+ combine_pulses( pulses4, pulses3, 1 );
+
+ encode_split( psRangeEnc, pulses3[ 0 ], pulses4[ 0 ], silk_shell_code_table3 );
+
+ encode_split( psRangeEnc, pulses2[ 0 ], pulses3[ 0 ], silk_shell_code_table2 );
+
+ encode_split( psRangeEnc, pulses1[ 0 ], pulses2[ 0 ], silk_shell_code_table1 );
+ encode_split( psRangeEnc, pulses0[ 0 ], pulses1[ 0 ], silk_shell_code_table0 );
+ encode_split( psRangeEnc, pulses0[ 2 ], pulses1[ 1 ], silk_shell_code_table0 );
+
+ encode_split( psRangeEnc, pulses1[ 2 ], pulses2[ 1 ], silk_shell_code_table1 );
+ encode_split( psRangeEnc, pulses0[ 4 ], pulses1[ 2 ], silk_shell_code_table0 );
+ encode_split( psRangeEnc, pulses0[ 6 ], pulses1[ 3 ], silk_shell_code_table0 );
+
+ encode_split( psRangeEnc, pulses2[ 2 ], pulses3[ 1 ], silk_shell_code_table2 );
+
+ encode_split( psRangeEnc, pulses1[ 4 ], pulses2[ 2 ], silk_shell_code_table1 );
+ encode_split( psRangeEnc, pulses0[ 8 ], pulses1[ 4 ], silk_shell_code_table0 );
+ encode_split( psRangeEnc, pulses0[ 10 ], pulses1[ 5 ], silk_shell_code_table0 );
+
+ encode_split( psRangeEnc, pulses1[ 6 ], pulses2[ 3 ], silk_shell_code_table1 );
+ encode_split( psRangeEnc, pulses0[ 12 ], pulses1[ 6 ], silk_shell_code_table0 );
+ encode_split( psRangeEnc, pulses0[ 14 ], pulses1[ 7 ], silk_shell_code_table0 );
+}
+
+
+/* Shell decoder, operates on one shell code frame of 16 pulses */
+void silk_shell_decoder(
+ opus_int16 *pulses0, /* O data: nonnegative pulse amplitudes */
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ const opus_int pulses4 /* I number of pulses per pulse-subframe */
+)
+{
+ opus_int16 pulses3[ 2 ], pulses2[ 4 ], pulses1[ 8 ];
+
+ /* this function operates on one shell code frame of 16 pulses */
+ silk_assert( SHELL_CODEC_FRAME_LENGTH == 16 );
+
+ decode_split( &pulses3[ 0 ], &pulses3[ 1 ], psRangeDec, pulses4, silk_shell_code_table3 );
+
+ decode_split( &pulses2[ 0 ], &pulses2[ 1 ], psRangeDec, pulses3[ 0 ], silk_shell_code_table2 );
+
+ decode_split( &pulses1[ 0 ], &pulses1[ 1 ], psRangeDec, pulses2[ 0 ], silk_shell_code_table1 );
+ decode_split( &pulses0[ 0 ], &pulses0[ 1 ], psRangeDec, pulses1[ 0 ], silk_shell_code_table0 );
+ decode_split( &pulses0[ 2 ], &pulses0[ 3 ], psRangeDec, pulses1[ 1 ], silk_shell_code_table0 );
+
+ decode_split( &pulses1[ 2 ], &pulses1[ 3 ], psRangeDec, pulses2[ 1 ], silk_shell_code_table1 );
+ decode_split( &pulses0[ 4 ], &pulses0[ 5 ], psRangeDec, pulses1[ 2 ], silk_shell_code_table0 );
+ decode_split( &pulses0[ 6 ], &pulses0[ 7 ], psRangeDec, pulses1[ 3 ], silk_shell_code_table0 );
+
+ decode_split( &pulses2[ 2 ], &pulses2[ 3 ], psRangeDec, pulses3[ 1 ], silk_shell_code_table2 );
+
+ decode_split( &pulses1[ 4 ], &pulses1[ 5 ], psRangeDec, pulses2[ 2 ], silk_shell_code_table1 );
+ decode_split( &pulses0[ 8 ], &pulses0[ 9 ], psRangeDec, pulses1[ 4 ], silk_shell_code_table0 );
+ decode_split( &pulses0[ 10 ], &pulses0[ 11 ], psRangeDec, pulses1[ 5 ], silk_shell_code_table0 );
+
+ decode_split( &pulses1[ 6 ], &pulses1[ 7 ], psRangeDec, pulses2[ 3 ], silk_shell_code_table1 );
+ decode_split( &pulses0[ 12 ], &pulses0[ 13 ], psRangeDec, pulses1[ 6 ], silk_shell_code_table0 );
+ decode_split( &pulses0[ 14 ], &pulses0[ 15 ], psRangeDec, pulses1[ 7 ], silk_shell_code_table0 );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Approximate sigmoid function */
+
+#include "SigProc_FIX.h"
+
+/* fprintf(1, '%d, ', round(1024 * ([1 ./ (1 + exp(-(1:5))), 1] - 1 ./ (1 + exp(-(0:5)))))); */
+static const opus_int32 sigm_LUT_slope_Q10[ 6 ] = {
+ 237, 153, 73, 30, 12, 7
+};
+/* fprintf(1, '%d, ', round(32767 * 1 ./ (1 + exp(-(0:5))))); */
+static const opus_int32 sigm_LUT_pos_Q15[ 6 ] = {
+ 16384, 23955, 28861, 31213, 32178, 32548
+};
+/* fprintf(1, '%d, ', round(32767 * 1 ./ (1 + exp((0:5))))); */
+static const opus_int32 sigm_LUT_neg_Q15[ 6 ] = {
+ 16384, 8812, 3906, 1554, 589, 219
+};
+
+opus_int silk_sigm_Q15(
+ opus_int in_Q5 /* I */
+)
+{
+ opus_int ind;
+
+ if( in_Q5 < 0 ) {
+ /* Negative input */
+ in_Q5 = -in_Q5;
+ if( in_Q5 >= 6 * 32 ) {
+ return 0; /* Clip */
+ } else {
+ /* Linear interpolation of look up table */
+ ind = silk_RSHIFT( in_Q5, 5 );
+ return( sigm_LUT_neg_Q15[ ind ] - silk_SMULBB( sigm_LUT_slope_Q10[ ind ], in_Q5 & 0x1F ) );
+ }
+ } else {
+ /* Positive input */
+ if( in_Q5 >= 6 * 32 ) {
+ return 32767; /* clip */
+ } else {
+ /* Linear interpolation of look up table */
+ ind = silk_RSHIFT( in_Q5, 5 );
+ return( sigm_LUT_pos_Q15[ ind ] + silk_SMULBB( sigm_LUT_slope_Q10[ ind ], in_Q5 & 0x1F ) );
+ }
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_SIGPROC_FIX_MIPSR1_H
+#define SILK_SIGPROC_FIX_MIPSR1_H
+
+#undef silk_SAT16
+static inline short int silk_SAT16(int a)
+{
+ int c;
+ c = __builtin_mips_shll_s_w(a, 16);
+ c = c>>16;
+
+ return c;
+}
+
+#undef silk_LSHIFT_SAT32
+static inline int silk_LSHIFT_SAT32(int a, int shift)
+{
+ int r;
+
+ r = __builtin_mips_shll_s_w(a, shift);
+
+ return r;
+}
+
+#undef silk_RSHIFT_ROUND
+static inline int silk_RSHIFT_ROUND(int a, int shift)
+{
+ int r;
+
+ r = __builtin_mips_shra_r_w(a, shift);
+ return r;
+}
+
+#endif /* SILK_SIGPROC_FIX_MIPSR1_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Insertion sort (fast for already almost sorted arrays): */
+/* Best case: O(n) for an already sorted array */
+/* Worst case: O(n^2) for an inversely sorted array */
+/* */
+/* Shell short: https://en.wikipedia.org/wiki/Shell_sort */
+
+#include "SigProc_FIX.h"
+
+void silk_insertion_sort_increasing(
+ opus_int32 *a, /* I/O Unsorted / Sorted vector */
+ opus_int *idx, /* O Index vector for the sorted elements */
+ const opus_int L, /* I Vector length */
+ const opus_int K /* I Number of correctly sorted positions */
+)
+{
+ opus_int32 value;
+ opus_int i, j;
+
+ /* Safety checks */
+ celt_assert( K > 0 );
+ celt_assert( L > 0 );
+ celt_assert( L >= K );
+
+ /* Write start indices in index vector */
+ for( i = 0; i < K; i++ ) {
+ idx[ i ] = i;
+ }
+
+ /* Sort vector elements by value, increasing order */
+ for( i = 1; i < K; i++ ) {
+ value = a[ i ];
+ for( j = i - 1; ( j >= 0 ) && ( value < a[ j ] ); j-- ) {
+ a[ j + 1 ] = a[ j ]; /* Shift value */
+ idx[ j + 1 ] = idx[ j ]; /* Shift index */
+ }
+ a[ j + 1 ] = value; /* Write value */
+ idx[ j + 1 ] = i; /* Write index */
+ }
+
+ /* If less than L values are asked for, check the remaining values, */
+ /* but only spend CPU to ensure that the K first values are correct */
+ for( i = K; i < L; i++ ) {
+ value = a[ i ];
+ if( value < a[ K - 1 ] ) {
+ for( j = K - 2; ( j >= 0 ) && ( value < a[ j ] ); j-- ) {
+ a[ j + 1 ] = a[ j ]; /* Shift value */
+ idx[ j + 1 ] = idx[ j ]; /* Shift index */
+ }
+ a[ j + 1 ] = value; /* Write value */
+ idx[ j + 1 ] = i; /* Write index */
+ }
+ }
+}
+
+#ifdef FIXED_POINT
+/* This function is only used by the fixed-point build */
+void silk_insertion_sort_decreasing_int16(
+ opus_int16 *a, /* I/O Unsorted / Sorted vector */
+ opus_int *idx, /* O Index vector for the sorted elements */
+ const opus_int L, /* I Vector length */
+ const opus_int K /* I Number of correctly sorted positions */
+)
+{
+ opus_int i, j;
+ opus_int value;
+
+ /* Safety checks */
+ celt_assert( K > 0 );
+ celt_assert( L > 0 );
+ celt_assert( L >= K );
+
+ /* Write start indices in index vector */
+ for( i = 0; i < K; i++ ) {
+ idx[ i ] = i;
+ }
+
+ /* Sort vector elements by value, decreasing order */
+ for( i = 1; i < K; i++ ) {
+ value = a[ i ];
+ for( j = i - 1; ( j >= 0 ) && ( value > a[ j ] ); j-- ) {
+ a[ j + 1 ] = a[ j ]; /* Shift value */
+ idx[ j + 1 ] = idx[ j ]; /* Shift index */
+ }
+ a[ j + 1 ] = value; /* Write value */
+ idx[ j + 1 ] = i; /* Write index */
+ }
+
+ /* If less than L values are asked for, check the remaining values, */
+ /* but only spend CPU to ensure that the K first values are correct */
+ for( i = K; i < L; i++ ) {
+ value = a[ i ];
+ if( value > a[ K - 1 ] ) {
+ for( j = K - 2; ( j >= 0 ) && ( value > a[ j ] ); j-- ) {
+ a[ j + 1 ] = a[ j ]; /* Shift value */
+ idx[ j + 1 ] = idx[ j ]; /* Shift index */
+ }
+ a[ j + 1 ] = value; /* Write value */
+ idx[ j + 1 ] = i; /* Write index */
+ }
+ }
+}
+#endif
+
+void silk_insertion_sort_increasing_all_values_int16(
+ opus_int16 *a, /* I/O Unsorted / Sorted vector */
+ const opus_int L /* I Vector length */
+)
+{
+ opus_int value;
+ opus_int i, j;
+
+ /* Safety checks */
+ celt_assert( L > 0 );
+
+ /* Sort vector elements by value, increasing order */
+ for( i = 1; i < L; i++ ) {
+ value = a[ i ];
+ for( j = i - 1; ( j >= 0 ) && ( value < a[ j ] ); j-- ) {
+ a[ j + 1 ] = a[ j ]; /* Shift value */
+ }
+ a[ j + 1 ] = value; /* Write value */
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Convert adaptive Mid/Side representation to Left/Right stereo signal */
+void silk_stereo_MS_to_LR(
+ stereo_dec_state *state, /* I/O State */
+ opus_int16 x1[], /* I/O Left input signal, becomes mid signal */
+ opus_int16 x2[], /* I/O Right input signal, becomes side signal */
+ const opus_int32 pred_Q13[], /* I Predictors */
+ opus_int fs_kHz, /* I Samples rate (kHz) */
+ opus_int frame_length /* I Number of samples */
+)
+{
+ opus_int n, denom_Q16, delta0_Q13, delta1_Q13;
+ opus_int32 sum, diff, pred0_Q13, pred1_Q13;
+
+ /* Buffering */
+ silk_memcpy( x1, state->sMid, 2 * sizeof( opus_int16 ) );
+ silk_memcpy( x2, state->sSide, 2 * sizeof( opus_int16 ) );
+ silk_memcpy( state->sMid, &x1[ frame_length ], 2 * sizeof( opus_int16 ) );
+ silk_memcpy( state->sSide, &x2[ frame_length ], 2 * sizeof( opus_int16 ) );
+
+ /* Interpolate predictors and add prediction to side channel */
+ pred0_Q13 = state->pred_prev_Q13[ 0 ];
+ pred1_Q13 = state->pred_prev_Q13[ 1 ];
+ denom_Q16 = silk_DIV32_16( (opus_int32)1 << 16, STEREO_INTERP_LEN_MS * fs_kHz );
+ delta0_Q13 = silk_RSHIFT_ROUND( silk_SMULBB( pred_Q13[ 0 ] - state->pred_prev_Q13[ 0 ], denom_Q16 ), 16 );
+ delta1_Q13 = silk_RSHIFT_ROUND( silk_SMULBB( pred_Q13[ 1 ] - state->pred_prev_Q13[ 1 ], denom_Q16 ), 16 );
+ for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) {
+ pred0_Q13 += delta0_Q13;
+ pred1_Q13 += delta1_Q13;
+ sum = silk_LSHIFT( silk_ADD_LSHIFT32( x1[ n ] + (opus_int32)x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */
+ sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */
+ sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */
+ x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
+ }
+ pred0_Q13 = pred_Q13[ 0 ];
+ pred1_Q13 = pred_Q13[ 1 ];
+ for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) {
+ sum = silk_LSHIFT( silk_ADD_LSHIFT32( x1[ n ] + (opus_int32)x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */
+ sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */
+ sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */
+ x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
+ }
+ state->pred_prev_Q13[ 0 ] = pred_Q13[ 0 ];
+ state->pred_prev_Q13[ 1 ] = pred_Q13[ 1 ];
+
+ /* Convert to left/right signals */
+ for( n = 0; n < frame_length; n++ ) {
+ sum = x1[ n + 1 ] + (opus_int32)x2[ n + 1 ];
+ diff = x1[ n + 1 ] - (opus_int32)x2[ n + 1 ];
+ x1[ n + 1 ] = (opus_int16)silk_SAT16( sum );
+ x2[ n + 1 ] = (opus_int16)silk_SAT16( diff );
+ }
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Decode mid/side predictors */
+void silk_stereo_decode_pred(
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int32 pred_Q13[] /* O Predictors */
+)
+{
+ opus_int n, ix[ 2 ][ 3 ];
+ opus_int32 low_Q13, step_Q13;
+
+ /* Entropy decoding */
+ n = ec_dec_icdf( psRangeDec, silk_stereo_pred_joint_iCDF, 8 );
+ ix[ 0 ][ 2 ] = silk_DIV32_16( n, 5 );
+ ix[ 1 ][ 2 ] = n - 5 * ix[ 0 ][ 2 ];
+ for( n = 0; n < 2; n++ ) {
+ ix[ n ][ 0 ] = ec_dec_icdf( psRangeDec, silk_uniform3_iCDF, 8 );
+ ix[ n ][ 1 ] = ec_dec_icdf( psRangeDec, silk_uniform5_iCDF, 8 );
+ }
+
+ /* Dequantize */
+ for( n = 0; n < 2; n++ ) {
+ ix[ n ][ 0 ] += 3 * ix[ n ][ 2 ];
+ low_Q13 = silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] ];
+ step_Q13 = silk_SMULWB( silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] + 1 ] - low_Q13,
+ SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) );
+ pred_Q13[ n ] = silk_SMLABB( low_Q13, step_Q13, 2 * ix[ n ][ 1 ] + 1 );
+ }
+
+ /* Subtract second from first predictor (helps when actually applying these) */
+ pred_Q13[ 0 ] -= pred_Q13[ 1 ];
+}
+
+/* Decode mid-only flag */
+void silk_stereo_decode_mid_only(
+ ec_dec *psRangeDec, /* I/O Compressor data structure */
+ opus_int *decode_only_mid /* O Flag that only mid channel has been coded */
+)
+{
+ /* Decode flag that only mid channel is coded */
+ *decode_only_mid = ec_dec_icdf( psRangeDec, silk_stereo_only_code_mid_iCDF, 8 );
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Find least-squares prediction gain for one signal based on another and quantize it */
+opus_int32 silk_stereo_find_predictor( /* O Returns predictor in Q13 */
+ opus_int32 *ratio_Q14, /* O Ratio of residual and mid energies */
+ const opus_int16 x[], /* I Basis signal */
+ const opus_int16 y[], /* I Target signal */
+ opus_int32 mid_res_amp_Q0[], /* I/O Smoothed mid, residual norms */
+ opus_int length, /* I Number of samples */
+ opus_int smooth_coef_Q16 /* I Smoothing coefficient */
+)
+{
+ opus_int scale, scale1, scale2;
+ opus_int32 nrgx, nrgy, corr, pred_Q13, pred2_Q10;
+
+ /* Find predictor */
+ silk_sum_sqr_shift( &nrgx, &scale1, x, length );
+ silk_sum_sqr_shift( &nrgy, &scale2, y, length );
+ scale = silk_max_int( scale1, scale2 );
+ scale = scale + ( scale & 1 ); /* make even */
+ nrgy = silk_RSHIFT32( nrgy, scale - scale2 );
+ nrgx = silk_RSHIFT32( nrgx, scale - scale1 );
+ nrgx = silk_max_int( nrgx, 1 );
+ corr = silk_inner_prod_aligned_scale( x, y, scale, length );
+ pred_Q13 = silk_DIV32_varQ( corr, nrgx, 13 );
+ pred_Q13 = silk_LIMIT( pred_Q13, -(1 << 14), 1 << 14 );
+ pred2_Q10 = silk_SMULWB( pred_Q13, pred_Q13 );
+
+ /* Faster update for signals with large prediction parameters */
+ smooth_coef_Q16 = (opus_int)silk_max_int( smooth_coef_Q16, silk_abs( pred2_Q10 ) );
+
+ /* Smoothed mid and residual norms */
+ silk_assert( smooth_coef_Q16 < 32768 );
+ scale = silk_RSHIFT( scale, 1 );
+ mid_res_amp_Q0[ 0 ] = silk_SMLAWB( mid_res_amp_Q0[ 0 ], silk_LSHIFT( silk_SQRT_APPROX( nrgx ), scale ) - mid_res_amp_Q0[ 0 ],
+ smooth_coef_Q16 );
+ /* Residual energy = nrgy - 2 * pred * corr + pred^2 * nrgx */
+ nrgy = silk_SUB_LSHIFT32( nrgy, silk_SMULWB( corr, pred_Q13 ), 3 + 1 );
+ nrgy = silk_ADD_LSHIFT32( nrgy, silk_SMULWB( nrgx, pred2_Q10 ), 6 );
+ mid_res_amp_Q0[ 1 ] = silk_SMLAWB( mid_res_amp_Q0[ 1 ], silk_LSHIFT( silk_SQRT_APPROX( nrgy ), scale ) - mid_res_amp_Q0[ 1 ],
+ smooth_coef_Q16 );
+
+ /* Ratio of smoothed residual and mid norms */
+ *ratio_Q14 = silk_DIV32_varQ( mid_res_amp_Q0[ 1 ], silk_max( mid_res_amp_Q0[ 0 ], 1 ), 14 );
+ *ratio_Q14 = silk_LIMIT( *ratio_Q14, 0, 32767 );
+
+ return pred_Q13;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_STRUCTS_H
+#define SILK_STRUCTS_H
+
+#include "typedef.h"
+#include "SigProc_FIX.h"
+#include "define.h"
+#include "entenc.h"
+#include "entdec.h"
+
+#ifdef ENABLE_DEEP_PLC
+#include "lpcnet.h"
+#include "lpcnet_private.h"
+#endif
+
+#ifdef ENABLE_DRED
+#include "dred_encoder.h"
+#include "dred_decoder.h"
+#endif
+
+#ifdef ENABLE_OSCE
+#include "osce_config.h"
+#include "osce_structs.h"
+#endif
+
+
+/************************************/
+/* Noise shaping quantization state */
+/************************************/
+typedef struct {
+ opus_int16 xq[ 2 * MAX_FRAME_LENGTH ]; /* Buffer for quantized output signal */
+ opus_int32 sLTP_shp_Q14[ 2 * MAX_FRAME_LENGTH ];
+ opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ];
+ opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
+ opus_int32 sLF_AR_shp_Q14;
+ opus_int32 sDiff_shp_Q14;
+ opus_int lagPrev;
+ opus_int sLTP_buf_idx;
+ opus_int sLTP_shp_buf_idx;
+ opus_int32 rand_seed;
+ opus_int32 prev_gain_Q16;
+ opus_int rewhite_flag;
+} silk_nsq_state;
+
+/********************************/
+/* VAD state */
+/********************************/
+typedef struct {
+ opus_int32 AnaState[ 2 ]; /* Analysis filterbank state: 0-8 kHz */
+ opus_int32 AnaState1[ 2 ]; /* Analysis filterbank state: 0-4 kHz */
+ opus_int32 AnaState2[ 2 ]; /* Analysis filterbank state: 0-2 kHz */
+ opus_int32 XnrgSubfr[ VAD_N_BANDS ]; /* Subframe energies */
+ opus_int32 NrgRatioSmth_Q8[ VAD_N_BANDS ]; /* Smoothed energy level in each band */
+ opus_int16 HPstate; /* State of differentiator in the lowest band */
+ opus_int32 NL[ VAD_N_BANDS ]; /* Noise energy level in each band */
+ opus_int32 inv_NL[ VAD_N_BANDS ]; /* Inverse noise energy level in each band */
+ opus_int32 NoiseLevelBias[ VAD_N_BANDS ]; /* Noise level estimator bias/offset */
+ opus_int32 counter; /* Frame counter used in the initial phase */
+} silk_VAD_state;
+
+/* Variable cut-off low-pass filter state */
+typedef struct {
+ opus_int32 In_LP_State[ 2 ]; /* Low pass filter state */
+ opus_int32 transition_frame_no; /* Counter which is mapped to a cut-off frequency */
+ opus_int mode; /* Operating mode, <0: switch down, >0: switch up; 0: do nothing */
+ opus_int32 saved_fs_kHz; /* If non-zero, holds the last sampling rate before a bandwidth switching reset. */
+} silk_LP_state;
+
+/* Structure containing NLSF codebook */
+typedef struct {
+ const opus_int16 nVectors;
+ const opus_int16 order;
+ const opus_int16 quantStepSize_Q16;
+ const opus_int16 invQuantStepSize_Q6;
+ const opus_uint8 *CB1_NLSF_Q8;
+ const opus_int16 *CB1_Wght_Q9;
+ const opus_uint8 *CB1_iCDF;
+ const opus_uint8 *pred_Q8;
+ const opus_uint8 *ec_sel;
+ const opus_uint8 *ec_iCDF;
+ const opus_uint8 *ec_Rates_Q5;
+ const opus_int16 *deltaMin_Q15;
+} silk_NLSF_CB_struct;
+
+typedef struct {
+ opus_int16 pred_prev_Q13[ 2 ];
+ opus_int16 sMid[ 2 ];
+ opus_int16 sSide[ 2 ];
+ opus_int32 mid_side_amp_Q0[ 4 ];
+ opus_int16 smth_width_Q14;
+ opus_int16 width_prev_Q14;
+ opus_int16 silent_side_len;
+ opus_int8 predIx[ MAX_FRAMES_PER_PACKET ][ 2 ][ 3 ];
+ opus_int8 mid_only_flags[ MAX_FRAMES_PER_PACKET ];
+} stereo_enc_state;
+
+typedef struct {
+ opus_int16 pred_prev_Q13[ 2 ];
+ opus_int16 sMid[ 2 ];
+ opus_int16 sSide[ 2 ];
+} stereo_dec_state;
+
+typedef struct {
+ opus_int8 GainsIndices[ MAX_NB_SUBFR ];
+ opus_int8 LTPIndex[ MAX_NB_SUBFR ];
+ opus_int8 NLSFIndices[ MAX_LPC_ORDER + 1 ];
+ opus_int16 lagIndex;
+ opus_int8 contourIndex;
+ opus_int8 signalType;
+ opus_int8 quantOffsetType;
+ opus_int8 NLSFInterpCoef_Q2;
+ opus_int8 PERIndex;
+ opus_int8 LTP_scaleIndex;
+ opus_int8 Seed;
+} SideInfoIndices;
+
+/********************************/
+/* Encoder state */
+/********************************/
+typedef struct {
+ opus_int32 In_HP_State[ 2 ]; /* High pass filter state */
+ opus_int32 variable_HP_smth1_Q15; /* State of first smoother */
+ opus_int32 variable_HP_smth2_Q15; /* State of second smoother */
+ silk_LP_state sLP; /* Low pass filter state */
+ silk_VAD_state sVAD; /* Voice activity detector state */
+ silk_nsq_state sNSQ; /* Noise Shape Quantizer State */
+ opus_int16 prev_NLSFq_Q15[ MAX_LPC_ORDER ]; /* Previously quantized NLSF vector */
+ opus_int speech_activity_Q8; /* Speech activity */
+ opus_int allow_bandwidth_switch; /* Flag indicating that switching of internal bandwidth is allowed */
+ opus_int8 LBRRprevLastGainIndex;
+ opus_int8 prevSignalType;
+ opus_int prevLag;
+ opus_int pitch_LPC_win_length;
+ opus_int max_pitch_lag; /* Highest possible pitch lag (samples) */
+ opus_int32 API_fs_Hz; /* API sampling frequency (Hz) */
+ opus_int32 prev_API_fs_Hz; /* Previous API sampling frequency (Hz) */
+ opus_int maxInternal_fs_Hz; /* Maximum internal sampling frequency (Hz) */
+ opus_int minInternal_fs_Hz; /* Minimum internal sampling frequency (Hz) */
+ opus_int desiredInternal_fs_Hz; /* Soft request for internal sampling frequency (Hz) */
+ opus_int fs_kHz; /* Internal sampling frequency (kHz) */
+ opus_int nb_subfr; /* Number of 5 ms subframes in a frame */
+ opus_int frame_length; /* Frame length (samples) */
+ opus_int subfr_length; /* Subframe length (samples) */
+ opus_int ltp_mem_length; /* Length of LTP memory */
+ opus_int la_pitch; /* Look-ahead for pitch analysis (samples) */
+ opus_int la_shape; /* Look-ahead for noise shape analysis (samples) */
+ opus_int shapeWinLength; /* Window length for noise shape analysis (samples) */
+ opus_int32 TargetRate_bps; /* Target bitrate (bps) */
+ opus_int PacketSize_ms; /* Number of milliseconds to put in each packet */
+ opus_int PacketLoss_perc; /* Packet loss rate measured by farend */
+ opus_int32 frameCounter;
+ opus_int Complexity; /* Complexity setting */
+ opus_int nStatesDelayedDecision; /* Number of states in delayed decision quantization */
+ opus_int useInterpolatedNLSFs; /* Flag for using NLSF interpolation */
+ opus_int shapingLPCOrder; /* Filter order for noise shaping filters */
+ opus_int predictLPCOrder; /* Filter order for prediction filters */
+ opus_int pitchEstimationComplexity; /* Complexity level for pitch estimator */
+ opus_int pitchEstimationLPCOrder; /* Whitening filter order for pitch estimator */
+ opus_int32 pitchEstimationThreshold_Q16; /* Threshold for pitch estimator */
+ opus_int32 sum_log_gain_Q7; /* Cumulative max prediction gain */
+ opus_int NLSF_MSVQ_Survivors; /* Number of survivors in NLSF MSVQ */
+ opus_int first_frame_after_reset; /* Flag for deactivating NLSF interpolation, pitch prediction */
+ opus_int controlled_since_last_payload; /* Flag for ensuring codec_control only runs once per packet */
+ opus_int warping_Q16; /* Warping parameter for warped noise shaping */
+ opus_int useCBR; /* Flag to enable constant bitrate */
+ opus_int prefillFlag; /* Flag to indicate that only buffers are prefilled, no coding */
+ const opus_uint8 *pitch_lag_low_bits_iCDF; /* Pointer to iCDF table for low bits of pitch lag index */
+ const opus_uint8 *pitch_contour_iCDF; /* Pointer to iCDF table for pitch contour index */
+ const silk_NLSF_CB_struct *psNLSF_CB; /* Pointer to NLSF codebook */
+ opus_int input_quality_bands_Q15[ VAD_N_BANDS ];
+ opus_int input_tilt_Q15;
+ opus_int SNR_dB_Q7; /* Quality setting */
+
+ opus_int8 VAD_flags[ MAX_FRAMES_PER_PACKET ];
+ opus_int8 LBRR_flag;
+ opus_int LBRR_flags[ MAX_FRAMES_PER_PACKET ];
+
+ SideInfoIndices indices;
+ opus_int8 pulses[ MAX_FRAME_LENGTH ];
+
+ int arch;
+
+ /* Input/output buffering */
+ opus_int16 inputBuf[ MAX_FRAME_LENGTH + 2 ]; /* Buffer containing input signal */
+ opus_int inputBufIx;
+ opus_int nFramesPerPacket;
+ opus_int nFramesEncoded; /* Number of frames analyzed in current packet */
+
+ opus_int nChannelsAPI;
+ opus_int nChannelsInternal;
+ opus_int channelNb;
+
+ /* Parameters For LTP scaling Control */
+ opus_int frames_since_onset;
+
+ /* Specifically for entropy coding */
+ opus_int ec_prevSignalType;
+ opus_int16 ec_prevLagIndex;
+
+ silk_resampler_state_struct resampler_state;
+
+ /* DTX */
+ opus_int useDTX; /* Flag to enable DTX */
+ opus_int inDTX; /* Flag to signal DTX period */
+ opus_int noSpeechCounter; /* Counts concecutive nonactive frames, used by DTX */
+
+ /* Inband Low Bitrate Redundancy (LBRR) data */
+ opus_int useInBandFEC; /* Saves the API setting for query */
+ opus_int LBRR_enabled; /* Depends on useInBandFRC, bitrate and packet loss rate */
+ opus_int LBRR_GainIncreases; /* Gains increment for coding LBRR frames */
+ SideInfoIndices indices_LBRR[ MAX_FRAMES_PER_PACKET ];
+ opus_int8 pulses_LBRR[ MAX_FRAMES_PER_PACKET ][ MAX_FRAME_LENGTH ];
+} silk_encoder_state;
+
+
+#ifdef ENABLE_OSCE
+typedef struct {
+ OSCEFeatureState features;
+ OSCEState state;
+ int method;
+} silk_OSCE_struct;
+
+typedef struct {
+ OSCEBWEFeatureState features;
+ OSCEBWEState state;
+} silk_OSCE_BWE_struct;
+#endif
+
+/* Struct for Packet Loss Concealment */
+typedef struct {
+ opus_int32 pitchL_Q8; /* Pitch lag to use for voiced concealment */
+ opus_int16 LTPCoef_Q14[ LTP_ORDER ]; /* LTP coefficients to use for voiced concealment */
+ opus_int16 prevLPC_Q12[ MAX_LPC_ORDER ];
+ opus_int last_frame_lost; /* Was previous frame lost */
+ opus_int32 rand_seed; /* Seed for unvoiced signal generation */
+ opus_int16 randScale_Q14; /* Scaling of unvoiced random signal */
+ opus_int32 conc_energy;
+ opus_int conc_energy_shift;
+ opus_int16 prevLTP_scale_Q14;
+ opus_int32 prevGain_Q16[ 2 ];
+ opus_int fs_kHz;
+ opus_int nb_subfr;
+ opus_int subfr_length;
+ opus_int enable_deep_plc;
+} silk_PLC_struct;
+
+/* Struct for CNG */
+typedef struct {
+ opus_int32 CNG_exc_buf_Q14[ MAX_FRAME_LENGTH ];
+ opus_int16 CNG_smth_NLSF_Q15[ MAX_LPC_ORDER ];
+ opus_int32 CNG_synth_state[ MAX_LPC_ORDER ];
+ opus_int32 CNG_smth_Gain_Q16;
+ opus_int32 rand_seed;
+ opus_int fs_kHz;
+} silk_CNG_struct;
+
+/********************************/
+/* Decoder state */
+/********************************/
+typedef struct {
+#ifdef ENABLE_OSCE
+ silk_OSCE_struct osce;
+#ifdef ENABLE_OSCE_BWE
+ silk_OSCE_BWE_struct osce_bwe;
+#endif
+#endif
+#define SILK_DECODER_STATE_RESET_START prev_gain_Q16
+ opus_int32 prev_gain_Q16;
+ opus_int32 exc_Q14[ MAX_FRAME_LENGTH ];
+ opus_int32 sLPC_Q14_buf[ MAX_LPC_ORDER ];
+ opus_int16 outBuf[ MAX_FRAME_LENGTH + 2 * MAX_SUB_FRAME_LENGTH ]; /* Buffer for output signal */
+ opus_int lagPrev; /* Previous Lag */
+ opus_int8 LastGainIndex; /* Previous gain index */
+ opus_int fs_kHz; /* Sampling frequency in kHz */
+ opus_int32 fs_API_hz; /* API sample frequency (Hz) */
+ opus_int nb_subfr; /* Number of 5 ms subframes in a frame */
+ opus_int frame_length; /* Frame length (samples) */
+ opus_int subfr_length; /* Subframe length (samples) */
+ opus_int ltp_mem_length; /* Length of LTP memory */
+ opus_int LPC_order; /* LPC order */
+ opus_int16 prevNLSF_Q15[ MAX_LPC_ORDER ]; /* Used to interpolate LSFs */
+ opus_int first_frame_after_reset; /* Flag for deactivating NLSF interpolation */
+ const opus_uint8 *pitch_lag_low_bits_iCDF; /* Pointer to iCDF table for low bits of pitch lag index */
+ const opus_uint8 *pitch_contour_iCDF; /* Pointer to iCDF table for pitch contour index */
+
+ /* For buffering payload in case of more frames per packet */
+ opus_int nFramesDecoded;
+ opus_int nFramesPerPacket;
+
+ /* Specifically for entropy coding */
+ opus_int ec_prevSignalType;
+ opus_int16 ec_prevLagIndex;
+
+ opus_int VAD_flags[ MAX_FRAMES_PER_PACKET ];
+ opus_int LBRR_flag;
+ opus_int LBRR_flags[ MAX_FRAMES_PER_PACKET ];
+
+ silk_resampler_state_struct resampler_state;
+
+ const silk_NLSF_CB_struct *psNLSF_CB; /* Pointer to NLSF codebook */
+
+ /* Quantization indices */
+ SideInfoIndices indices;
+
+ /* CNG state */
+ silk_CNG_struct sCNG;
+
+ /* Stuff used for PLC */
+ opus_int lossCnt;
+ opus_int prevSignalType;
+ int arch;
+
+ silk_PLC_struct sPLC;
+
+} silk_decoder_state;
+
+/************************/
+/* Decoder control */
+/************************/
+typedef struct {
+ /* Prediction and coding parameters */
+ opus_int pitchL[ MAX_NB_SUBFR ];
+ opus_int32 Gains_Q16[ MAX_NB_SUBFR ];
+ /* Holds interpolated and final coefficients, 4-byte aligned */
+ silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
+ opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ];
+ opus_int LTP_scale_Q14;
+} silk_decoder_control;
+
+
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_STRUCTS_FIX_H
+#define SILK_STRUCTS_FIX_H
+
+#include "typedef.h"
+#include "main.h"
+#include "structs.h"
+
+
+/********************************/
+/* Noise shaping analysis state */
+/********************************/
+typedef struct {
+ opus_int8 LastGainIndex;
+ opus_int32 HarmBoost_smth_Q16;
+ opus_int32 HarmShapeGain_smth_Q16;
+ opus_int32 Tilt_smth_Q16;
+} silk_shape_state_FIX;
+
+/********************************/
+/* Encoder state FIX */
+/********************************/
+typedef struct {
+ silk_encoder_state sCmn; /* Common struct, shared with floating-point code */
+ silk_shape_state_FIX sShape; /* Shape state */
+
+ /* Buffer for find pitch and noise shape analysis */
+ silk_DWORD_ALIGN opus_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */
+ opus_int LTPCorr_Q15; /* Normalized correlation from pitch lag estimator */
+ opus_int32 resNrgSmth;
+} silk_encoder_state_FIX;
+
+/************************/
+/* Encoder control FIX */
+/************************/
+typedef struct {
+ /* Prediction and coding parameters */
+ opus_int32 Gains_Q16[ MAX_NB_SUBFR ];
+ silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
+ opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ];
+ opus_int LTP_scale_Q14;
+ opus_int pitchL[ MAX_NB_SUBFR ];
+
+ /* Noise shaping parameters */
+ /* Testing */
+ silk_DWORD_ALIGN opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+ opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */
+ opus_int Tilt_Q14[ MAX_NB_SUBFR ];
+ opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ];
+ opus_int Lambda_Q10;
+ opus_int input_quality_Q14;
+ opus_int coding_quality_Q14;
+
+ /* measures */
+ opus_int32 predGain_Q16;
+ opus_int LTPredCodGain_Q7;
+ opus_int32 ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */
+ opus_int ResNrgQ[ MAX_NB_SUBFR ]; /* Q domain for the residual energy > 0 */
+
+ /* Parameters for CBR mode */
+ opus_int32 GainsUnq_Q16[ MAX_NB_SUBFR ];
+ opus_int8 lastGainIndexPrev;
+} silk_encoder_control_FIX;
+
+/************************/
+/* Encoder Super Struct */
+/************************/
+typedef struct {
+ stereo_enc_state sStereo;
+ opus_int32 nBitsUsedLBRR;
+ opus_int32 nBitsExceeded;
+ opus_int nChannelsAPI;
+ opus_int nChannelsInternal;
+ opus_int nPrevChannelsInternal;
+ opus_int timeSinceSwitchAllowed_ms;
+ opus_int allowBandwidthSwitch;
+ opus_int prev_decode_only_middle;
+ /* This needs to be last so we can skip the second state for mono. */
+ silk_encoder_state_FIX state_Fxx[ ENCODER_NUM_CHANNELS ];
+} silk_encoder;
+
+
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_STRUCTS_FLP_H
+#define SILK_STRUCTS_FLP_H
+
+#include "typedef.h"
+#include "main.h"
+#include "structs.h"
+
+
+/********************************/
+/* Noise shaping analysis state */
+/********************************/
+typedef struct {
+ opus_int8 LastGainIndex;
+ silk_float HarmShapeGain_smth;
+ silk_float Tilt_smth;
+} silk_shape_state_FLP;
+
+/********************************/
+/* Encoder state FLP */
+/********************************/
+typedef struct {
+ silk_encoder_state sCmn; /* Common struct, shared with fixed-point code */
+ silk_shape_state_FLP sShape; /* Noise shaping state */
+
+ /* Buffer for find pitch and noise shape analysis */
+ silk_float x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */
+ silk_float LTPCorr; /* Normalized correlation from pitch lag estimator */
+} silk_encoder_state_FLP;
+
+/************************/
+/* Encoder control FLP */
+/************************/
+typedef struct {
+ /* Prediction and coding parameters */
+ silk_float Gains[ MAX_NB_SUBFR ];
+ silk_float PredCoef[ 2 ][ MAX_LPC_ORDER ]; /* holds interpolated and final coefficients */
+ silk_float LTPCoef[LTP_ORDER * MAX_NB_SUBFR];
+ silk_float LTP_scale;
+ opus_int pitchL[ MAX_NB_SUBFR ];
+
+ /* Noise shaping parameters */
+ silk_float AR[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+ silk_float LF_MA_shp[ MAX_NB_SUBFR ];
+ silk_float LF_AR_shp[ MAX_NB_SUBFR ];
+ silk_float Tilt[ MAX_NB_SUBFR ];
+ silk_float HarmShapeGain[ MAX_NB_SUBFR ];
+ silk_float Lambda;
+ silk_float input_quality;
+ silk_float coding_quality;
+
+ /* Measures */
+ silk_float predGain;
+ silk_float LTPredCodGain;
+ silk_float ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */
+
+ /* Parameters for CBR mode */
+ opus_int32 GainsUnq_Q16[ MAX_NB_SUBFR ];
+ opus_int8 lastGainIndexPrev;
+} silk_encoder_control_FLP;
+
+/************************/
+/* Encoder Super Struct */
+/************************/
+typedef struct {
+ stereo_enc_state sStereo;
+ opus_int32 nBitsUsedLBRR;
+ opus_int32 nBitsExceeded;
+ opus_int nChannelsAPI;
+ opus_int nChannelsInternal;
+ opus_int nPrevChannelsInternal;
+ opus_int timeSinceSwitchAllowed_ms;
+ opus_int allowBandwidthSwitch;
+ opus_int prev_decode_only_middle;
+ /* This needs to be last so we can skip the second state for mono. */
+ silk_encoder_state_FLP state_Fxx[ ENCODER_NUM_CHANNELS ];
+} silk_encoder;
+
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Compute number of bits to right shift the sum of squares of a vector */
+/* of int16s to make it fit in an int32 */
+void silk_sum_sqr_shift(
+ opus_int32 *energy, /* O Energy of x, after shifting to the right */
+ opus_int *shift, /* O Number of bits right shift applied to energy */
+ const opus_int16 *x, /* I Input vector */
+ opus_int len /* I Length of input vector */
+)
+{
+ opus_int i, shft;
+ opus_uint32 nrg_tmp;
+ opus_int32 nrg;
+
+ /* Do a first run with the maximum shift we could have. */
+ shft = 31-silk_CLZ32(len);
+ /* Let's be conservative with rounding and start with nrg=len. */
+ nrg = len;
+ for( i = 0; i < len - 1; i += 2 ) {
+ nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
+ nrg_tmp = silk_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] );
+ nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+ }
+ if( i < len ) {
+ /* One sample left to process */
+ nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
+ nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+ }
+ silk_assert( nrg >= 0 );
+ /* Make sure the result will fit in a 32-bit signed integer with two bits
+ of headroom. */
+ shft = silk_max_32(0, shft+3 - silk_CLZ32(nrg));
+ nrg = 0;
+ for( i = 0 ; i < len - 1; i += 2 ) {
+ nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
+ nrg_tmp = silk_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] );
+ nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+ }
+ if( i < len ) {
+ /* One sample left to process */
+ nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
+ nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+ }
+
+ silk_assert( nrg >= 0 );
+
+ /* Output arguments */
+ *shift = shft;
+ *energy = nrg;
+}
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+/* Cosine approximation table for LSF conversion */
+/* Q12 values (even) */
+const opus_int16 silk_LSFCosTab_FIX_Q12[ LSF_COS_TAB_SZ_FIX + 1 ] = {
+ 8192, 8190, 8182, 8170,
+ 8152, 8130, 8104, 8072,
+ 8034, 7994, 7946, 7896,
+ 7840, 7778, 7714, 7644,
+ 7568, 7490, 7406, 7318,
+ 7226, 7128, 7026, 6922,
+ 6812, 6698, 6580, 6458,
+ 6332, 6204, 6070, 5934,
+ 5792, 5648, 5502, 5352,
+ 5198, 5040, 4880, 4718,
+ 4552, 4382, 4212, 4038,
+ 3862, 3684, 3502, 3320,
+ 3136, 2948, 2760, 2570,
+ 2378, 2186, 1990, 1794,
+ 1598, 1400, 1202, 1002,
+ 802, 602, 402, 202,
+ 0, -202, -402, -602,
+ -802, -1002, -1202, -1400,
+ -1598, -1794, -1990, -2186,
+ -2378, -2570, -2760, -2948,
+ -3136, -3320, -3502, -3684,
+ -3862, -4038, -4212, -4382,
+ -4552, -4718, -4880, -5040,
+ -5198, -5352, -5502, -5648,
+ -5792, -5934, -6070, -6204,
+ -6332, -6458, -6580, -6698,
+ -6812, -6922, -7026, -7128,
+ -7226, -7318, -7406, -7490,
+ -7568, -7644, -7714, -7778,
+ -7840, -7896, -7946, -7994,
+ -8034, -8072, -8104, -8130,
+ -8152, -8170, -8182, -8190,
+ -8192
+};
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_TABLES_H
+#define SILK_TABLES_H
+
+#include "define.h"
+#include "structs.h"
+
+
+/* Entropy coding tables (with size in bytes indicated) */
+extern const opus_uint8 silk_gain_iCDF[ 3 ][ N_LEVELS_QGAIN / 8 ]; /* 24 */
+extern const opus_uint8 silk_delta_gain_iCDF[ MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ]; /* 41 */
+
+extern const opus_uint8 silk_pitch_lag_iCDF[ 2 * ( PITCH_EST_MAX_LAG_MS - PITCH_EST_MIN_LAG_MS ) ];/* 32 */
+extern const opus_uint8 silk_pitch_delta_iCDF[ 21 ]; /* 21 */
+extern const opus_uint8 silk_pitch_contour_iCDF[ 34 ]; /* 34 */
+extern const opus_uint8 silk_pitch_contour_NB_iCDF[ 11 ]; /* 11 */
+extern const opus_uint8 silk_pitch_contour_10_ms_iCDF[ 12 ]; /* 12 */
+extern const opus_uint8 silk_pitch_contour_10_ms_NB_iCDF[ 3 ]; /* 3 */
+
+extern const opus_uint8 silk_pulses_per_block_iCDF[ N_RATE_LEVELS ][ SILK_MAX_PULSES + 2 ]; /* 180 */
+extern const opus_uint8 silk_pulses_per_block_BITS_Q5[ N_RATE_LEVELS - 1 ][ SILK_MAX_PULSES + 2 ]; /* 162 */
+
+extern const opus_uint8 silk_rate_levels_iCDF[ 2 ][ N_RATE_LEVELS - 1 ]; /* 18 */
+extern const opus_uint8 silk_rate_levels_BITS_Q5[ 2 ][ N_RATE_LEVELS - 1 ]; /* 18 */
+
+extern const opus_uint8 silk_max_pulses_table[ 4 ]; /* 4 */
+
+extern const opus_uint8 silk_shell_code_table0[ 152 ]; /* 152 */
+extern const opus_uint8 silk_shell_code_table1[ 152 ]; /* 152 */
+extern const opus_uint8 silk_shell_code_table2[ 152 ]; /* 152 */
+extern const opus_uint8 silk_shell_code_table3[ 152 ]; /* 152 */
+extern const opus_uint8 silk_shell_code_table_offsets[ SILK_MAX_PULSES + 1 ]; /* 17 */
+
+extern const opus_uint8 silk_lsb_iCDF[ 2 ]; /* 2 */
+
+extern const opus_uint8 silk_sign_iCDF[ 42 ]; /* 42 */
+
+extern const opus_uint8 silk_uniform3_iCDF[ 3 ]; /* 3 */
+extern const opus_uint8 silk_uniform4_iCDF[ 4 ]; /* 4 */
+extern const opus_uint8 silk_uniform5_iCDF[ 5 ]; /* 5 */
+extern const opus_uint8 silk_uniform6_iCDF[ 6 ]; /* 6 */
+extern const opus_uint8 silk_uniform8_iCDF[ 8 ]; /* 8 */
+
+extern const opus_uint8 silk_NLSF_EXT_iCDF[ 7 ]; /* 7 */
+
+extern const opus_uint8 silk_LTP_per_index_iCDF[ 3 ]; /* 3 */
+extern const opus_uint8 * const silk_LTP_gain_iCDF_ptrs[ NB_LTP_CBKS ]; /* 3 */
+extern const opus_uint8 * const silk_LTP_gain_BITS_Q5_ptrs[ NB_LTP_CBKS ]; /* 3 */
+extern const opus_int8 * const silk_LTP_vq_ptrs_Q7[ NB_LTP_CBKS ]; /* 168 */
+extern const opus_uint8 * const silk_LTP_vq_gain_ptrs_Q7[NB_LTP_CBKS];
+extern const opus_int8 silk_LTP_vq_sizes[ NB_LTP_CBKS ]; /* 3 */
+
+extern const opus_uint8 silk_LTPscale_iCDF[ 3 ]; /* 4 */
+extern const opus_int16 silk_LTPScales_table_Q14[ 3 ]; /* 6 */
+
+extern const opus_uint8 silk_type_offset_VAD_iCDF[ 4 ]; /* 4 */
+extern const opus_uint8 silk_type_offset_no_VAD_iCDF[ 2 ]; /* 2 */
+
+extern const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ]; /* 32 */
+extern const opus_uint8 silk_stereo_pred_joint_iCDF[ 25 ]; /* 25 */
+extern const opus_uint8 silk_stereo_only_code_mid_iCDF[ 2 ]; /* 2 */
+
+extern const opus_uint8 * const silk_LBRR_flags_iCDF_ptr[ 2 ]; /* 10 */
+
+extern const opus_uint8 silk_NLSF_interpolation_factor_iCDF[ 5 ]; /* 5 */
+
+extern const silk_NLSF_CB_struct silk_NLSF_CB_WB; /* 1040 */
+extern const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB; /* 728 */
+
+/* Quantization offsets */
+extern const opus_int16 silk_Quantization_Offsets_Q10[ 2 ][ 2 ]; /* 8 */
+
+/* Interpolation points for filter coefficients used in the bandwidth transition smoother */
+extern const opus_int32 silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NB ]; /* 60 */
+extern const opus_int32 silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NA ]; /* 60 */
+
+/* Rom table with cosine values */
+extern const opus_int16 silk_LSFCosTab_FIX_Q12[ LSF_COS_TAB_SZ_FIX + 1 ]; /* 258 */
+
+#endif
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+const opus_uint8 silk_LTP_per_index_iCDF[3] = {
+ 179, 99, 0
+};
+
+static const opus_uint8 silk_LTP_gain_iCDF_0[8] = {
+ 71, 56, 43, 30, 21, 12, 6, 0
+};
+
+static const opus_uint8 silk_LTP_gain_iCDF_1[16] = {
+ 199, 165, 144, 124, 109, 96, 84, 71,
+ 61, 51, 42, 32, 23, 15, 8, 0
+};
+
+static const opus_uint8 silk_LTP_gain_iCDF_2[32] = {
+ 241, 225, 211, 199, 187, 175, 164, 153,
+ 142, 132, 123, 114, 105, 96, 88, 80,
+ 72, 64, 57, 50, 44, 38, 33, 29,
+ 24, 20, 16, 12, 9, 5, 2, 0
+};
+
+static const opus_uint8 silk_LTP_gain_BITS_Q5_0[8] = {
+ 15, 131, 138, 138, 155, 155, 173, 173
+};
+
+static const opus_uint8 silk_LTP_gain_BITS_Q5_1[16] = {
+ 69, 93, 115, 118, 131, 138, 141, 138,
+ 150, 150, 155, 150, 155, 160, 166, 160
+};
+
+static const opus_uint8 silk_LTP_gain_BITS_Q5_2[32] = {
+ 131, 128, 134, 141, 141, 141, 145, 145,
+ 145, 150, 155, 155, 155, 155, 160, 160,
+ 160, 160, 166, 166, 173, 173, 182, 192,
+ 182, 192, 192, 192, 205, 192, 205, 224
+};
+
+const opus_uint8 * const silk_LTP_gain_iCDF_ptrs[NB_LTP_CBKS] = {
+ silk_LTP_gain_iCDF_0,
+ silk_LTP_gain_iCDF_1,
+ silk_LTP_gain_iCDF_2
+};
+
+const opus_uint8 * const silk_LTP_gain_BITS_Q5_ptrs[NB_LTP_CBKS] = {
+ silk_LTP_gain_BITS_Q5_0,
+ silk_LTP_gain_BITS_Q5_1,
+ silk_LTP_gain_BITS_Q5_2
+};
+
+static const opus_int8 silk_LTP_gain_vq_0[8][5] =
+{
+{
+ 4, 6, 24, 7, 5
+},
+{
+ 0, 0, 2, 0, 0
+},
+{
+ 12, 28, 41, 13, -4
+},
+{
+ -9, 15, 42, 25, 14
+},
+{
+ 1, -2, 62, 41, -9
+},
+{
+ -10, 37, 65, -4, 3
+},
+{
+ -6, 4, 66, 7, -8
+},
+{
+ 16, 14, 38, -3, 33
+}
+};
+
+static const opus_int8 silk_LTP_gain_vq_1[16][5] =
+{
+{
+ 13, 22, 39, 23, 12
+},
+{
+ -1, 36, 64, 27, -6
+},
+{
+ -7, 10, 55, 43, 17
+},
+{
+ 1, 1, 8, 1, 1
+},
+{
+ 6, -11, 74, 53, -9
+},
+{
+ -12, 55, 76, -12, 8
+},
+{
+ -3, 3, 93, 27, -4
+},
+{
+ 26, 39, 59, 3, -8
+},
+{
+ 2, 0, 77, 11, 9
+},
+{
+ -8, 22, 44, -6, 7
+},
+{
+ 40, 9, 26, 3, 9
+},
+{
+ -7, 20, 101, -7, 4
+},
+{
+ 3, -8, 42, 26, 0
+},
+{
+ -15, 33, 68, 2, 23
+},
+{
+ -2, 55, 46, -2, 15
+},
+{
+ 3, -1, 21, 16, 41
+}
+};
+
+static const opus_int8 silk_LTP_gain_vq_2[32][5] =
+{
+{
+ -6, 27, 61, 39, 5
+},
+{
+ -11, 42, 88, 4, 1
+},
+{
+ -2, 60, 65, 6, -4
+},
+{
+ -1, -5, 73, 56, 1
+},
+{
+ -9, 19, 94, 29, -9
+},
+{
+ 0, 12, 99, 6, 4
+},
+{
+ 8, -19, 102, 46, -13
+},
+{
+ 3, 2, 13, 3, 2
+},
+{
+ 9, -21, 84, 72, -18
+},
+{
+ -11, 46, 104, -22, 8
+},
+{
+ 18, 38, 48, 23, 0
+},
+{
+ -16, 70, 83, -21, 11
+},
+{
+ 5, -11, 117, 22, -8
+},
+{
+ -6, 23, 117, -12, 3
+},
+{
+ 3, -8, 95, 28, 4
+},
+{
+ -10, 15, 77, 60, -15
+},
+{
+ -1, 4, 124, 2, -4
+},
+{
+ 3, 38, 84, 24, -25
+},
+{
+ 2, 13, 42, 13, 31
+},
+{
+ 21, -4, 56, 46, -1
+},
+{
+ -1, 35, 79, -13, 19
+},
+{
+ -7, 65, 88, -9, -14
+},
+{
+ 20, 4, 81, 49, -29
+},
+{
+ 20, 0, 75, 3, -17
+},
+{
+ 5, -9, 44, 92, -8
+},
+{
+ 1, -3, 22, 69, 31
+},
+{
+ -6, 95, 41, -12, 5
+},
+{
+ 39, 67, 16, -4, 1
+},
+{
+ 0, -6, 120, 55, -36
+},
+{
+ -13, 44, 122, 4, -24
+},
+{
+ 81, 5, 11, 3, 7
+},
+{
+ 2, 0, 9, 10, 88
+}
+};
+
+const opus_int8 * const silk_LTP_vq_ptrs_Q7[NB_LTP_CBKS] = {
+ (opus_int8 *)&silk_LTP_gain_vq_0[0][0],
+ (opus_int8 *)&silk_LTP_gain_vq_1[0][0],
+ (opus_int8 *)&silk_LTP_gain_vq_2[0][0]
+};
+
+/* Maximum frequency-dependent response of the pitch taps above,
+ computed as max(abs(freqz(taps))) */
+static const opus_uint8 silk_LTP_gain_vq_0_gain[8] = {
+ 46, 2, 90, 87, 93, 91, 82, 98
+};
+
+static const opus_uint8 silk_LTP_gain_vq_1_gain[16] = {
+ 109, 120, 118, 12, 113, 115, 117, 119,
+ 99, 59, 87, 111, 63, 111, 112, 80
+};
+
+static const opus_uint8 silk_LTP_gain_vq_2_gain[32] = {
+ 126, 124, 125, 124, 129, 121, 126, 23,
+ 132, 127, 127, 127, 126, 127, 122, 133,
+ 130, 134, 101, 118, 119, 145, 126, 86,
+ 124, 120, 123, 119, 170, 173, 107, 109
+};
+
+const opus_uint8 * const silk_LTP_vq_gain_ptrs_Q7[NB_LTP_CBKS] = {
+ &silk_LTP_gain_vq_0_gain[0],
+ &silk_LTP_gain_vq_1_gain[0],
+ &silk_LTP_gain_vq_2_gain[0]
+};
+
+const opus_int8 silk_LTP_vq_sizes[NB_LTP_CBKS] = {
+ 8, 16, 32
+};
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+static const opus_uint8 silk_NLSF_CB1_NB_MB_Q8[ 320 ] = {
+ 12, 35, 60, 83, 108, 132, 157, 180,
+ 206, 228, 15, 32, 55, 77, 101, 125,
+ 151, 175, 201, 225, 19, 42, 66, 89,
+ 114, 137, 162, 184, 209, 230, 12, 25,
+ 50, 72, 97, 120, 147, 172, 200, 223,
+ 26, 44, 69, 90, 114, 135, 159, 180,
+ 205, 225, 13, 22, 53, 80, 106, 130,
+ 156, 180, 205, 228, 15, 25, 44, 64,
+ 90, 115, 142, 168, 196, 222, 19, 24,
+ 62, 82, 100, 120, 145, 168, 190, 214,
+ 22, 31, 50, 79, 103, 120, 151, 170,
+ 203, 227, 21, 29, 45, 65, 106, 124,
+ 150, 171, 196, 224, 30, 49, 75, 97,
+ 121, 142, 165, 186, 209, 229, 19, 25,
+ 52, 70, 93, 116, 143, 166, 192, 219,
+ 26, 34, 62, 75, 97, 118, 145, 167,
+ 194, 217, 25, 33, 56, 70, 91, 113,
+ 143, 165, 196, 223, 21, 34, 51, 72,
+ 97, 117, 145, 171, 196, 222, 20, 29,
+ 50, 67, 90, 117, 144, 168, 197, 221,
+ 22, 31, 48, 66, 95, 117, 146, 168,
+ 196, 222, 24, 33, 51, 77, 116, 134,
+ 158, 180, 200, 224, 21, 28, 70, 87,
+ 106, 124, 149, 170, 194, 217, 26, 33,
+ 53, 64, 83, 117, 152, 173, 204, 225,
+ 27, 34, 65, 95, 108, 129, 155, 174,
+ 210, 225, 20, 26, 72, 99, 113, 131,
+ 154, 176, 200, 219, 34, 43, 61, 78,
+ 93, 114, 155, 177, 205, 229, 23, 29,
+ 54, 97, 124, 138, 163, 179, 209, 229,
+ 30, 38, 56, 89, 118, 129, 158, 178,
+ 200, 231, 21, 29, 49, 63, 85, 111,
+ 142, 163, 193, 222, 27, 48, 77, 103,
+ 133, 158, 179, 196, 215, 232, 29, 47,
+ 74, 99, 124, 151, 176, 198, 220, 237,
+ 33, 42, 61, 76, 93, 121, 155, 174,
+ 207, 225, 29, 53, 87, 112, 136, 154,
+ 170, 188, 208, 227, 24, 30, 52, 84,
+ 131, 150, 166, 186, 203, 229, 37, 48,
+ 64, 84, 104, 118, 156, 177, 201, 230
+};
+
+static const opus_int16 silk_NLSF_CB1_Wght_Q9[ 320 ] = {
+ 2897, 2314, 2314, 2314, 2287, 2287, 2314, 2300, 2327, 2287,
+ 2888, 2580, 2394, 2367, 2314, 2274, 2274, 2274, 2274, 2194,
+ 2487, 2340, 2340, 2314, 2314, 2314, 2340, 2340, 2367, 2354,
+ 3216, 2766, 2340, 2340, 2314, 2274, 2221, 2207, 2261, 2194,
+ 2460, 2474, 2367, 2394, 2394, 2394, 2394, 2367, 2407, 2314,
+ 3479, 3056, 2127, 2207, 2274, 2274, 2274, 2287, 2314, 2261,
+ 3282, 3141, 2580, 2394, 2247, 2221, 2207, 2194, 2194, 2114,
+ 4096, 3845, 2221, 2620, 2620, 2407, 2314, 2394, 2367, 2074,
+ 3178, 3244, 2367, 2221, 2553, 2434, 2340, 2314, 2167, 2221,
+ 3338, 3488, 2726, 2194, 2261, 2460, 2354, 2367, 2207, 2101,
+ 2354, 2420, 2327, 2367, 2394, 2420, 2420, 2420, 2460, 2367,
+ 3779, 3629, 2434, 2527, 2367, 2274, 2274, 2300, 2207, 2048,
+ 3254, 3225, 2713, 2846, 2447, 2327, 2300, 2300, 2274, 2127,
+ 3263, 3300, 2753, 2806, 2447, 2261, 2261, 2247, 2127, 2101,
+ 2873, 2981, 2633, 2367, 2407, 2354, 2194, 2247, 2247, 2114,
+ 3225, 3197, 2633, 2580, 2274, 2181, 2247, 2221, 2221, 2141,
+ 3178, 3310, 2740, 2407, 2274, 2274, 2274, 2287, 2194, 2114,
+ 3141, 3272, 2460, 2061, 2287, 2500, 2367, 2487, 2434, 2181,
+ 3507, 3282, 2314, 2700, 2647, 2474, 2367, 2394, 2340, 2127,
+ 3423, 3535, 3038, 3056, 2300, 1950, 2221, 2274, 2274, 2274,
+ 3404, 3366, 2087, 2687, 2873, 2354, 2420, 2274, 2474, 2540,
+ 3760, 3488, 1950, 2660, 2897, 2527, 2394, 2367, 2460, 2261,
+ 3028, 3272, 2740, 2888, 2740, 2154, 2127, 2287, 2234, 2247,
+ 3695, 3657, 2025, 1969, 2660, 2700, 2580, 2500, 2327, 2367,
+ 3207, 3413, 2354, 2074, 2888, 2888, 2340, 2487, 2247, 2167,
+ 3338, 3366, 2846, 2780, 2327, 2154, 2274, 2287, 2114, 2061,
+ 2327, 2300, 2181, 2167, 2181, 2367, 2633, 2700, 2700, 2553,
+ 2407, 2434, 2221, 2261, 2221, 2221, 2340, 2420, 2607, 2700,
+ 3038, 3244, 2806, 2888, 2474, 2074, 2300, 2314, 2354, 2380,
+ 2221, 2154, 2127, 2287, 2500, 2793, 2793, 2620, 2580, 2367,
+ 3676, 3713, 2234, 1838, 2181, 2753, 2726, 2673, 2513, 2207,
+ 2793, 3160, 2726, 2553, 2846, 2513, 2181, 2394, 2221, 2181
+};
+
+static const opus_uint8 silk_NLSF_CB1_iCDF_NB_MB[ 64 ] = {
+ 212, 178, 148, 129, 108, 96, 85, 82,
+ 79, 77, 61, 59, 57, 56, 51, 49,
+ 48, 45, 42, 41, 40, 38, 36, 34,
+ 31, 30, 21, 12, 10, 3, 1, 0,
+ 255, 245, 244, 236, 233, 225, 217, 203,
+ 190, 176, 175, 161, 149, 136, 125, 114,
+ 102, 91, 81, 71, 60, 52, 43, 35,
+ 28, 20, 19, 18, 12, 11, 5, 0
+};
+
+static const opus_uint8 silk_NLSF_CB2_SELECT_NB_MB[ 160 ] = {
+ 16, 0, 0, 0, 0, 99, 66, 36,
+ 36, 34, 36, 34, 34, 34, 34, 83,
+ 69, 36, 52, 34, 116, 102, 70, 68,
+ 68, 176, 102, 68, 68, 34, 65, 85,
+ 68, 84, 36, 116, 141, 152, 139, 170,
+ 132, 187, 184, 216, 137, 132, 249, 168,
+ 185, 139, 104, 102, 100, 68, 68, 178,
+ 218, 185, 185, 170, 244, 216, 187, 187,
+ 170, 244, 187, 187, 219, 138, 103, 155,
+ 184, 185, 137, 116, 183, 155, 152, 136,
+ 132, 217, 184, 184, 170, 164, 217, 171,
+ 155, 139, 244, 169, 184, 185, 170, 164,
+ 216, 223, 218, 138, 214, 143, 188, 218,
+ 168, 244, 141, 136, 155, 170, 168, 138,
+ 220, 219, 139, 164, 219, 202, 216, 137,
+ 168, 186, 246, 185, 139, 116, 185, 219,
+ 185, 138, 100, 100, 134, 100, 102, 34,
+ 68, 68, 100, 68, 168, 203, 221, 218,
+ 168, 167, 154, 136, 104, 70, 164, 246,
+ 171, 137, 139, 137, 155, 218, 219, 139
+};
+
+static const opus_uint8 silk_NLSF_CB2_iCDF_NB_MB[ 72 ] = {
+ 255, 254, 253, 238, 14, 3, 2, 1,
+ 0, 255, 254, 252, 218, 35, 3, 2,
+ 1, 0, 255, 254, 250, 208, 59, 4,
+ 2, 1, 0, 255, 254, 246, 194, 71,
+ 10, 2, 1, 0, 255, 252, 236, 183,
+ 82, 8, 2, 1, 0, 255, 252, 235,
+ 180, 90, 17, 2, 1, 0, 255, 248,
+ 224, 171, 97, 30, 4, 1, 0, 255,
+ 254, 236, 173, 95, 37, 7, 1, 0
+};
+
+static const opus_uint8 silk_NLSF_CB2_BITS_NB_MB_Q5[ 72 ] = {
+ 255, 255, 255, 131, 6, 145, 255, 255,
+ 255, 255, 255, 236, 93, 15, 96, 255,
+ 255, 255, 255, 255, 194, 83, 25, 71,
+ 221, 255, 255, 255, 255, 162, 73, 34,
+ 66, 162, 255, 255, 255, 210, 126, 73,
+ 43, 57, 173, 255, 255, 255, 201, 125,
+ 71, 48, 58, 130, 255, 255, 255, 166,
+ 110, 73, 57, 62, 104, 210, 255, 255,
+ 251, 123, 65, 55, 68, 100, 171, 255
+};
+
+static const opus_uint8 silk_NLSF_PRED_NB_MB_Q8[ 18 ] = {
+ 179, 138, 140, 148, 151, 149, 153, 151,
+ 163, 116, 67, 82, 59, 92, 72, 100,
+ 89, 92
+};
+
+static const opus_int16 silk_NLSF_DELTA_MIN_NB_MB_Q15[ 11 ] = {
+ 250, 3, 6, 3, 3, 3, 4, 3,
+ 3, 3, 461
+};
+
+const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB =
+{
+ 32,
+ 10,
+ SILK_FIX_CONST( 0.18, 16 ),
+ SILK_FIX_CONST( 1.0 / 0.18, 6 ),
+ silk_NLSF_CB1_NB_MB_Q8,
+ silk_NLSF_CB1_Wght_Q9,
+ silk_NLSF_CB1_iCDF_NB_MB,
+ silk_NLSF_PRED_NB_MB_Q8,
+ silk_NLSF_CB2_SELECT_NB_MB,
+ silk_NLSF_CB2_iCDF_NB_MB,
+ silk_NLSF_CB2_BITS_NB_MB_Q5,
+ silk_NLSF_DELTA_MIN_NB_MB_Q15,
+};
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+static const opus_uint8 silk_NLSF_CB1_WB_Q8[ 512 ] = {
+ 7, 23, 38, 54, 69, 85, 100, 116,
+ 131, 147, 162, 178, 193, 208, 223, 239,
+ 13, 25, 41, 55, 69, 83, 98, 112,
+ 127, 142, 157, 171, 187, 203, 220, 236,
+ 15, 21, 34, 51, 61, 78, 92, 106,
+ 126, 136, 152, 167, 185, 205, 225, 240,
+ 10, 21, 36, 50, 63, 79, 95, 110,
+ 126, 141, 157, 173, 189, 205, 221, 237,
+ 17, 20, 37, 51, 59, 78, 89, 107,
+ 123, 134, 150, 164, 184, 205, 224, 240,
+ 10, 15, 32, 51, 67, 81, 96, 112,
+ 129, 142, 158, 173, 189, 204, 220, 236,
+ 8, 21, 37, 51, 65, 79, 98, 113,
+ 126, 138, 155, 168, 179, 192, 209, 218,
+ 12, 15, 34, 55, 63, 78, 87, 108,
+ 118, 131, 148, 167, 185, 203, 219, 236,
+ 16, 19, 32, 36, 56, 79, 91, 108,
+ 118, 136, 154, 171, 186, 204, 220, 237,
+ 11, 28, 43, 58, 74, 89, 105, 120,
+ 135, 150, 165, 180, 196, 211, 226, 241,
+ 6, 16, 33, 46, 60, 75, 92, 107,
+ 123, 137, 156, 169, 185, 199, 214, 225,
+ 11, 19, 30, 44, 57, 74, 89, 105,
+ 121, 135, 152, 169, 186, 202, 218, 234,
+ 12, 19, 29, 46, 57, 71, 88, 100,
+ 120, 132, 148, 165, 182, 199, 216, 233,
+ 17, 23, 35, 46, 56, 77, 92, 106,
+ 123, 134, 152, 167, 185, 204, 222, 237,
+ 14, 17, 45, 53, 63, 75, 89, 107,
+ 115, 132, 151, 171, 188, 206, 221, 240,
+ 9, 16, 29, 40, 56, 71, 88, 103,
+ 119, 137, 154, 171, 189, 205, 222, 237,
+ 16, 19, 36, 48, 57, 76, 87, 105,
+ 118, 132, 150, 167, 185, 202, 218, 236,
+ 12, 17, 29, 54, 71, 81, 94, 104,
+ 126, 136, 149, 164, 182, 201, 221, 237,
+ 15, 28, 47, 62, 79, 97, 115, 129,
+ 142, 155, 168, 180, 194, 208, 223, 238,
+ 8, 14, 30, 45, 62, 78, 94, 111,
+ 127, 143, 159, 175, 192, 207, 223, 239,
+ 17, 30, 49, 62, 79, 92, 107, 119,
+ 132, 145, 160, 174, 190, 204, 220, 235,
+ 14, 19, 36, 45, 61, 76, 91, 108,
+ 121, 138, 154, 172, 189, 205, 222, 238,
+ 12, 18, 31, 45, 60, 76, 91, 107,
+ 123, 138, 154, 171, 187, 204, 221, 236,
+ 13, 17, 31, 43, 53, 70, 83, 103,
+ 114, 131, 149, 167, 185, 203, 220, 237,
+ 17, 22, 35, 42, 58, 78, 93, 110,
+ 125, 139, 155, 170, 188, 206, 224, 240,
+ 8, 15, 34, 50, 67, 83, 99, 115,
+ 131, 146, 162, 178, 193, 209, 224, 239,
+ 13, 16, 41, 66, 73, 86, 95, 111,
+ 128, 137, 150, 163, 183, 206, 225, 241,
+ 17, 25, 37, 52, 63, 75, 92, 102,
+ 119, 132, 144, 160, 175, 191, 212, 231,
+ 19, 31, 49, 65, 83, 100, 117, 133,
+ 147, 161, 174, 187, 200, 213, 227, 242,
+ 18, 31, 52, 68, 88, 103, 117, 126,
+ 138, 149, 163, 177, 192, 207, 223, 239,
+ 16, 29, 47, 61, 76, 90, 106, 119,
+ 133, 147, 161, 176, 193, 209, 224, 240,
+ 15, 21, 35, 50, 61, 73, 86, 97,
+ 110, 119, 129, 141, 175, 198, 218, 237
+};
+
+static const opus_int16 silk_NLSF_CB1_WB_Wght_Q9[ 512 ] = {
+ 3657, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2963, 2963, 2925, 2846,
+ 3216, 3085, 2972, 3056, 3056, 3010, 3010, 3010, 2963, 2963, 3010, 2972, 2888, 2846, 2846, 2726,
+ 3920, 4014, 2981, 3207, 3207, 2934, 3056, 2846, 3122, 3244, 2925, 2846, 2620, 2553, 2780, 2925,
+ 3516, 3197, 3010, 3103, 3019, 2888, 2925, 2925, 2925, 2925, 2888, 2888, 2888, 2888, 2888, 2753,
+ 5054, 5054, 2934, 3573, 3385, 3056, 3085, 2793, 3160, 3160, 2972, 2846, 2513, 2540, 2753, 2888,
+ 4428, 4149, 2700, 2753, 2972, 3010, 2925, 2846, 2981, 3019, 2925, 2925, 2925, 2925, 2888, 2726,
+ 3620, 3019, 2972, 3056, 3056, 2873, 2806, 3056, 3216, 3047, 2981, 3291, 3291, 2981, 3310, 2991,
+ 5227, 5014, 2540, 3338, 3526, 3385, 3197, 3094, 3376, 2981, 2700, 2647, 2687, 2793, 2846, 2673,
+ 5081, 5174, 4615, 4428, 2460, 2897, 3047, 3207, 3169, 2687, 2740, 2888, 2846, 2793, 2846, 2700,
+ 3122, 2888, 2963, 2925, 2925, 2925, 2925, 2963, 2963, 2963, 2963, 2925, 2925, 2963, 2963, 2963,
+ 4202, 3207, 2981, 3103, 3010, 2888, 2888, 2925, 2972, 2873, 2916, 3019, 2972, 3010, 3197, 2873,
+ 3760, 3760, 3244, 3103, 2981, 2888, 2925, 2888, 2972, 2934, 2793, 2793, 2846, 2888, 2888, 2660,
+ 3854, 4014, 3207, 3122, 3244, 2934, 3047, 2963, 2963, 3085, 2846, 2793, 2793, 2793, 2793, 2580,
+ 3845, 4080, 3357, 3516, 3094, 2740, 3010, 2934, 3122, 3085, 2846, 2846, 2647, 2647, 2846, 2806,
+ 5147, 4894, 3225, 3845, 3441, 3169, 2897, 3413, 3451, 2700, 2580, 2673, 2740, 2846, 2806, 2753,
+ 4109, 3789, 3291, 3160, 2925, 2888, 2888, 2925, 2793, 2740, 2793, 2740, 2793, 2846, 2888, 2806,
+ 5081, 5054, 3047, 3545, 3244, 3056, 3085, 2944, 3103, 2897, 2740, 2740, 2740, 2846, 2793, 2620,
+ 4309, 4309, 2860, 2527, 3207, 3376, 3376, 3075, 3075, 3376, 3056, 2846, 2647, 2580, 2726, 2753,
+ 3056, 2916, 2806, 2888, 2740, 2687, 2897, 3103, 3150, 3150, 3216, 3169, 3056, 3010, 2963, 2846,
+ 4375, 3882, 2925, 2888, 2846, 2888, 2846, 2846, 2888, 2888, 2888, 2846, 2888, 2925, 2888, 2846,
+ 2981, 2916, 2916, 2981, 2981, 3056, 3122, 3216, 3150, 3056, 3010, 2972, 2972, 2972, 2925, 2740,
+ 4229, 4149, 3310, 3347, 2925, 2963, 2888, 2981, 2981, 2846, 2793, 2740, 2846, 2846, 2846, 2793,
+ 4080, 4014, 3103, 3010, 2925, 2925, 2925, 2888, 2925, 2925, 2846, 2846, 2846, 2793, 2888, 2780,
+ 4615, 4575, 3169, 3441, 3207, 2981, 2897, 3038, 3122, 2740, 2687, 2687, 2687, 2740, 2793, 2700,
+ 4149, 4269, 3789, 3657, 2726, 2780, 2888, 2888, 3010, 2972, 2925, 2846, 2687, 2687, 2793, 2888,
+ 4215, 3554, 2753, 2846, 2846, 2888, 2888, 2888, 2925, 2925, 2888, 2925, 2925, 2925, 2963, 2888,
+ 5174, 4921, 2261, 3432, 3789, 3479, 3347, 2846, 3310, 3479, 3150, 2897, 2460, 2487, 2753, 2925,
+ 3451, 3685, 3122, 3197, 3357, 3047, 3207, 3207, 2981, 3216, 3085, 2925, 2925, 2687, 2540, 2434,
+ 2981, 3010, 2793, 2793, 2740, 2793, 2846, 2972, 3056, 3103, 3150, 3150, 3150, 3103, 3010, 3010,
+ 2944, 2873, 2687, 2726, 2780, 3010, 3432, 3545, 3357, 3244, 3056, 3010, 2963, 2925, 2888, 2846,
+ 3019, 2944, 2897, 3010, 3010, 2972, 3019, 3103, 3056, 3056, 3010, 2888, 2846, 2925, 2925, 2888,
+ 3920, 3967, 3010, 3197, 3357, 3216, 3291, 3291, 3479, 3704, 3441, 2726, 2181, 2460, 2580, 2607
+};
+
+static const opus_uint8 silk_NLSF_CB1_iCDF_WB[ 64 ] = {
+ 225, 204, 201, 184, 183, 175, 158, 154,
+ 153, 135, 119, 115, 113, 110, 109, 99,
+ 98, 95, 79, 68, 52, 50, 48, 45,
+ 43, 32, 31, 27, 18, 10, 3, 0,
+ 255, 251, 235, 230, 212, 201, 196, 182,
+ 167, 166, 163, 151, 138, 124, 110, 104,
+ 90, 78, 76, 70, 69, 57, 45, 34,
+ 24, 21, 11, 6, 5, 4, 3, 0
+};
+
+static const opus_uint8 silk_NLSF_CB2_SELECT_WB[ 256 ] = {
+ 0, 0, 0, 0, 0, 0, 0, 1,
+ 100, 102, 102, 68, 68, 36, 34, 96,
+ 164, 107, 158, 185, 180, 185, 139, 102,
+ 64, 66, 36, 34, 34, 0, 1, 32,
+ 208, 139, 141, 191, 152, 185, 155, 104,
+ 96, 171, 104, 166, 102, 102, 102, 132,
+ 1, 0, 0, 0, 0, 16, 16, 0,
+ 80, 109, 78, 107, 185, 139, 103, 101,
+ 208, 212, 141, 139, 173, 153, 123, 103,
+ 36, 0, 0, 0, 0, 0, 0, 1,
+ 48, 0, 0, 0, 0, 0, 0, 32,
+ 68, 135, 123, 119, 119, 103, 69, 98,
+ 68, 103, 120, 118, 118, 102, 71, 98,
+ 134, 136, 157, 184, 182, 153, 139, 134,
+ 208, 168, 248, 75, 189, 143, 121, 107,
+ 32, 49, 34, 34, 34, 0, 17, 2,
+ 210, 235, 139, 123, 185, 137, 105, 134,
+ 98, 135, 104, 182, 100, 183, 171, 134,
+ 100, 70, 68, 70, 66, 66, 34, 131,
+ 64, 166, 102, 68, 36, 2, 1, 0,
+ 134, 166, 102, 68, 34, 34, 66, 132,
+ 212, 246, 158, 139, 107, 107, 87, 102,
+ 100, 219, 125, 122, 137, 118, 103, 132,
+ 114, 135, 137, 105, 171, 106, 50, 34,
+ 164, 214, 141, 143, 185, 151, 121, 103,
+ 192, 34, 0, 0, 0, 0, 0, 1,
+ 208, 109, 74, 187, 134, 249, 159, 137,
+ 102, 110, 154, 118, 87, 101, 119, 101,
+ 0, 2, 0, 36, 36, 66, 68, 35,
+ 96, 164, 102, 100, 36, 0, 2, 33,
+ 167, 138, 174, 102, 100, 84, 2, 2,
+ 100, 107, 120, 119, 36, 197, 24, 0
+};
+
+static const opus_uint8 silk_NLSF_CB2_iCDF_WB[ 72 ] = {
+ 255, 254, 253, 244, 12, 3, 2, 1,
+ 0, 255, 254, 252, 224, 38, 3, 2,
+ 1, 0, 255, 254, 251, 209, 57, 4,
+ 2, 1, 0, 255, 254, 244, 195, 69,
+ 4, 2, 1, 0, 255, 251, 232, 184,
+ 84, 7, 2, 1, 0, 255, 254, 240,
+ 186, 86, 14, 2, 1, 0, 255, 254,
+ 239, 178, 91, 30, 5, 1, 0, 255,
+ 248, 227, 177, 100, 19, 2, 1, 0
+};
+
+static const opus_uint8 silk_NLSF_CB2_BITS_WB_Q5[ 72 ] = {
+ 255, 255, 255, 156, 4, 154, 255, 255,
+ 255, 255, 255, 227, 102, 15, 92, 255,
+ 255, 255, 255, 255, 213, 83, 24, 72,
+ 236, 255, 255, 255, 255, 150, 76, 33,
+ 63, 214, 255, 255, 255, 190, 121, 77,
+ 43, 55, 185, 255, 255, 255, 245, 137,
+ 71, 43, 59, 139, 255, 255, 255, 255,
+ 131, 66, 50, 66, 107, 194, 255, 255,
+ 166, 116, 76, 55, 53, 125, 255, 255
+};
+
+static const opus_uint8 silk_NLSF_PRED_WB_Q8[ 30 ] = {
+ 175, 148, 160, 176, 178, 173, 174, 164,
+ 177, 174, 196, 182, 198, 192, 182, 68,
+ 62, 66, 60, 72, 117, 85, 90, 118,
+ 136, 151, 142, 160, 142, 155
+};
+
+static const opus_int16 silk_NLSF_DELTA_MIN_WB_Q15[ 17 ] = {
+ 100, 3, 40, 3, 3, 3, 5, 14,
+ 14, 10, 11, 3, 8, 9, 7, 3,
+ 347
+};
+
+const silk_NLSF_CB_struct silk_NLSF_CB_WB =
+{
+ 32,
+ 16,
+ SILK_FIX_CONST( 0.15, 16 ),
+ SILK_FIX_CONST( 1.0 / 0.15, 6 ),
+ silk_NLSF_CB1_WB_Q8,
+ silk_NLSF_CB1_WB_Wght_Q9,
+ silk_NLSF_CB1_iCDF_WB,
+ silk_NLSF_PRED_WB_Q8,
+ silk_NLSF_CB2_SELECT_WB,
+ silk_NLSF_CB2_iCDF_WB,
+ silk_NLSF_CB2_BITS_WB_Q5,
+ silk_NLSF_DELTA_MIN_WB_Q15,
+};
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+
+const opus_uint8 silk_gain_iCDF[ 3 ][ N_LEVELS_QGAIN / 8 ] =
+{
+{
+ 224, 112, 44, 15, 3, 2, 1, 0
+},
+{
+ 254, 237, 192, 132, 70, 23, 4, 0
+},
+{
+ 255, 252, 226, 155, 61, 11, 2, 0
+}
+};
+
+const opus_uint8 silk_delta_gain_iCDF[ MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ] = {
+ 250, 245, 234, 203, 71, 50, 42, 38,
+ 35, 33, 31, 29, 28, 27, 26, 25,
+ 24, 23, 22, 21, 20, 19, 18, 17,
+ 16, 15, 14, 13, 12, 11, 10, 9,
+ 8, 7, 6, 5, 4, 3, 2, 1,
+ 0
+};
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "structs.h"
+#include "define.h"
+#include "tables.h"
+
+
+/* Tables for stereo predictor coding */
+const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ] = {
+ -13732, -10050, -8266, -7526, -6500, -5000, -2950, -820,
+ 820, 2950, 5000, 6500, 7526, 8266, 10050, 13732
+};
+const opus_uint8 silk_stereo_pred_joint_iCDF[ 25 ] = {
+ 249, 247, 246, 245, 244,
+ 234, 210, 202, 201, 200,
+ 197, 174, 82, 59, 56,
+ 55, 54, 46, 22, 12,
+ 11, 10, 9, 7, 0
+};
+const opus_uint8 silk_stereo_only_code_mid_iCDF[ 2 ] = { 64, 0 };
+
+/* Tables for LBRR flags */
+static const opus_uint8 silk_LBRR_flags_2_iCDF[ 3 ] = { 203, 150, 0 };
+static const opus_uint8 silk_LBRR_flags_3_iCDF[ 7 ] = { 215, 195, 166, 125, 110, 82, 0 };
+const opus_uint8 * const silk_LBRR_flags_iCDF_ptr[ 2 ] = {
+ silk_LBRR_flags_2_iCDF,
+ silk_LBRR_flags_3_iCDF
+};
+
+/* Table for LSB coding */
+const opus_uint8 silk_lsb_iCDF[ 2 ] = { 120, 0 };
+
+/* Tables for LTPScale */
+const opus_uint8 silk_LTPscale_iCDF[ 3 ] = { 128, 64, 0 };
+
+/* Tables for signal type and offset coding */
+const opus_uint8 silk_type_offset_VAD_iCDF[ 4 ] = {
+ 232, 158, 10, 0
+};
+const opus_uint8 silk_type_offset_no_VAD_iCDF[ 2 ] = {
+ 230, 0
+};
+
+/* Tables for NLSF interpolation factor */
+const opus_uint8 silk_NLSF_interpolation_factor_iCDF[ 5 ] = { 243, 221, 192, 181, 0 };
+
+/* Quantization offsets */
+const opus_int16 silk_Quantization_Offsets_Q10[ 2 ][ 2 ] = {
+ { OFFSET_UVL_Q10, OFFSET_UVH_Q10 }, { OFFSET_VL_Q10, OFFSET_VH_Q10 }
+};
+
+/* Table for LTPScale */
+const opus_int16 silk_LTPScales_table_Q14[ 3 ] = { 15565, 12288, 8192 };
+
+/* Uniform entropy tables */
+const opus_uint8 silk_uniform3_iCDF[ 3 ] = { 171, 85, 0 };
+const opus_uint8 silk_uniform4_iCDF[ 4 ] = { 192, 128, 64, 0 };
+const opus_uint8 silk_uniform5_iCDF[ 5 ] = { 205, 154, 102, 51, 0 };
+const opus_uint8 silk_uniform6_iCDF[ 6 ] = { 213, 171, 128, 85, 43, 0 };
+const opus_uint8 silk_uniform8_iCDF[ 8 ] = { 224, 192, 160, 128, 96, 64, 32, 0 };
+
+const opus_uint8 silk_NLSF_EXT_iCDF[ 7 ] = { 100, 40, 16, 7, 3, 1, 0 };
+
+/* Elliptic/Cauer filters designed with 0.1 dB passband ripple,
+ 80 dB minimum stopband attenuation, and
+ [0.95 : 0.15 : 0.35] normalized cut off frequencies. */
+
+/* Interpolation points for filter coefficients used in the bandwidth transition smoother */
+const opus_int32 silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NB ] =
+{
+{ 250767114, 501534038, 250767114 },
+{ 209867381, 419732057, 209867381 },
+{ 170987846, 341967853, 170987846 },
+{ 131531482, 263046905, 131531482 },
+{ 89306658, 178584282, 89306658 }
+};
+
+/* Interpolation points for filter coefficients used in the bandwidth transition smoother */
+const opus_int32 silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NA ] =
+{
+{ 506393414, 239854379 },
+{ 411067935, 169683996 },
+{ 306733530, 116694253 },
+{ 185807084, 77959395 },
+{ 35497197, 57401098 }
+};
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+const opus_uint8 silk_pitch_lag_iCDF[ 2 * ( PITCH_EST_MAX_LAG_MS - PITCH_EST_MIN_LAG_MS ) ] = {
+ 253, 250, 244, 233, 212, 182, 150, 131,
+ 120, 110, 98, 85, 72, 60, 49, 40,
+ 32, 25, 19, 15, 13, 11, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0
+};
+
+const opus_uint8 silk_pitch_delta_iCDF[21] = {
+ 210, 208, 206, 203, 199, 193, 183, 168,
+ 142, 104, 74, 52, 37, 27, 20, 14,
+ 10, 6, 4, 2, 0
+};
+
+const opus_uint8 silk_pitch_contour_iCDF[34] = {
+ 223, 201, 183, 167, 152, 138, 124, 111,
+ 98, 88, 79, 70, 62, 56, 50, 44,
+ 39, 35, 31, 27, 24, 21, 18, 16,
+ 14, 12, 10, 8, 6, 4, 3, 2,
+ 1, 0
+};
+
+const opus_uint8 silk_pitch_contour_NB_iCDF[11] = {
+ 188, 176, 155, 138, 119, 97, 67, 43,
+ 26, 10, 0
+};
+
+const opus_uint8 silk_pitch_contour_10_ms_iCDF[12] = {
+ 165, 119, 80, 61, 47, 35, 27, 20,
+ 14, 9, 4, 0
+};
+
+const opus_uint8 silk_pitch_contour_10_ms_NB_iCDF[3] = {
+ 113, 63, 0
+};
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tables.h"
+
+const opus_uint8 silk_max_pulses_table[ 4 ] = {
+ 8, 10, 12, 16
+};
+
+const opus_uint8 silk_pulses_per_block_iCDF[ 10 ][ 18 ] = {
+{
+ 125, 51, 26, 18, 15, 12, 11, 10,
+ 9, 8, 7, 6, 5, 4, 3, 2,
+ 1, 0
+},
+{
+ 198, 105, 45, 22, 15, 12, 11, 10,
+ 9, 8, 7, 6, 5, 4, 3, 2,
+ 1, 0
+},
+{
+ 213, 162, 116, 83, 59, 43, 32, 24,
+ 18, 15, 12, 9, 7, 6, 5, 3,
+ 2, 0
+},
+{
+ 239, 187, 116, 59, 28, 16, 11, 10,
+ 9, 8, 7, 6, 5, 4, 3, 2,
+ 1, 0
+},
+{
+ 250, 229, 188, 135, 86, 51, 30, 19,
+ 13, 10, 8, 6, 5, 4, 3, 2,
+ 1, 0
+},
+{
+ 249, 235, 213, 185, 156, 128, 103, 83,
+ 66, 53, 42, 33, 26, 21, 17, 13,
+ 10, 0
+},
+{
+ 254, 249, 235, 206, 164, 118, 77, 46,
+ 27, 16, 10, 7, 5, 4, 3, 2,
+ 1, 0
+},
+{
+ 255, 253, 249, 239, 220, 191, 156, 119,
+ 85, 57, 37, 23, 15, 10, 6, 4,
+ 2, 0
+},
+{
+ 255, 253, 251, 246, 237, 223, 203, 179,
+ 152, 124, 98, 75, 55, 40, 29, 21,
+ 15, 0
+},
+{
+ 255, 254, 253, 247, 220, 162, 106, 67,
+ 42, 28, 18, 12, 9, 6, 4, 3,
+ 2, 0
+}
+};
+
+const opus_uint8 silk_pulses_per_block_BITS_Q5[ 9 ][ 18 ] = {
+{
+ 31, 57, 107, 160, 205, 205, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255
+},
+{
+ 69, 47, 67, 111, 166, 205, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255
+},
+{
+ 82, 74, 79, 95, 109, 128, 145, 160,
+ 173, 205, 205, 205, 224, 255, 255, 224,
+ 255, 224
+},
+{
+ 125, 74, 59, 69, 97, 141, 182, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255
+},
+{
+ 173, 115, 85, 73, 76, 92, 115, 145,
+ 173, 205, 224, 224, 255, 255, 255, 255,
+ 255, 255
+},
+{
+ 166, 134, 113, 102, 101, 102, 107, 118,
+ 125, 138, 145, 155, 166, 182, 192, 192,
+ 205, 150
+},
+{
+ 224, 182, 134, 101, 83, 79, 85, 97,
+ 120, 145, 173, 205, 224, 255, 255, 255,
+ 255, 255
+},
+{
+ 255, 224, 192, 150, 120, 101, 92, 89,
+ 93, 102, 118, 134, 160, 182, 192, 224,
+ 224, 224
+},
+{
+ 255, 224, 224, 182, 155, 134, 118, 109,
+ 104, 102, 106, 111, 118, 131, 145, 160,
+ 173, 131
+}
+};
+
+const opus_uint8 silk_rate_levels_iCDF[ 2 ][ 9 ] =
+{
+{
+ 241, 190, 178, 132, 87, 74, 41, 14,
+ 0
+},
+{
+ 223, 193, 157, 140, 106, 57, 39, 18,
+ 0
+}
+};
+
+const opus_uint8 silk_rate_levels_BITS_Q5[ 2 ][ 9 ] =
+{
+{
+ 131, 74, 141, 79, 80, 138, 95, 104,
+ 134
+},
+{
+ 95, 99, 91, 125, 93, 76, 123, 115,
+ 123
+}
+};
+
+const opus_uint8 silk_shell_code_table0[ 152 ] = {
+ 128, 0, 214, 42, 0, 235, 128, 21,
+ 0, 244, 184, 72, 11, 0, 248, 214,
+ 128, 42, 7, 0, 248, 225, 170, 80,
+ 25, 5, 0, 251, 236, 198, 126, 54,
+ 18, 3, 0, 250, 238, 211, 159, 82,
+ 35, 15, 5, 0, 250, 231, 203, 168,
+ 128, 88, 53, 25, 6, 0, 252, 238,
+ 216, 185, 148, 108, 71, 40, 18, 4,
+ 0, 253, 243, 225, 199, 166, 128, 90,
+ 57, 31, 13, 3, 0, 254, 246, 233,
+ 212, 183, 147, 109, 73, 44, 23, 10,
+ 2, 0, 255, 250, 240, 223, 198, 166,
+ 128, 90, 58, 33, 16, 6, 1, 0,
+ 255, 251, 244, 231, 210, 181, 146, 110,
+ 75, 46, 25, 12, 5, 1, 0, 255,
+ 253, 248, 238, 221, 196, 164, 128, 92,
+ 60, 35, 18, 8, 3, 1, 0, 255,
+ 253, 249, 242, 229, 208, 180, 146, 110,
+ 76, 48, 27, 14, 7, 3, 1, 0
+};
+
+const opus_uint8 silk_shell_code_table1[ 152 ] = {
+ 129, 0, 207, 50, 0, 236, 129, 20,
+ 0, 245, 185, 72, 10, 0, 249, 213,
+ 129, 42, 6, 0, 250, 226, 169, 87,
+ 27, 4, 0, 251, 233, 194, 130, 62,
+ 20, 4, 0, 250, 236, 207, 160, 99,
+ 47, 17, 3, 0, 255, 240, 217, 182,
+ 131, 81, 41, 11, 1, 0, 255, 254,
+ 233, 201, 159, 107, 61, 20, 2, 1,
+ 0, 255, 249, 233, 206, 170, 128, 86,
+ 50, 23, 7, 1, 0, 255, 250, 238,
+ 217, 186, 148, 108, 70, 39, 18, 6,
+ 1, 0, 255, 252, 243, 226, 200, 166,
+ 128, 90, 56, 30, 13, 4, 1, 0,
+ 255, 252, 245, 231, 209, 180, 146, 110,
+ 76, 47, 25, 11, 4, 1, 0, 255,
+ 253, 248, 237, 219, 194, 163, 128, 93,
+ 62, 37, 19, 8, 3, 1, 0, 255,
+ 254, 250, 241, 226, 205, 177, 145, 111,
+ 79, 51, 30, 15, 6, 2, 1, 0
+};
+
+const opus_uint8 silk_shell_code_table2[ 152 ] = {
+ 129, 0, 203, 54, 0, 234, 129, 23,
+ 0, 245, 184, 73, 10, 0, 250, 215,
+ 129, 41, 5, 0, 252, 232, 173, 86,
+ 24, 3, 0, 253, 240, 200, 129, 56,
+ 15, 2, 0, 253, 244, 217, 164, 94,
+ 38, 10, 1, 0, 253, 245, 226, 189,
+ 132, 71, 27, 7, 1, 0, 253, 246,
+ 231, 203, 159, 105, 56, 23, 6, 1,
+ 0, 255, 248, 235, 213, 179, 133, 85,
+ 47, 19, 5, 1, 0, 255, 254, 243,
+ 221, 194, 159, 117, 70, 37, 12, 2,
+ 1, 0, 255, 254, 248, 234, 208, 171,
+ 128, 85, 48, 22, 8, 2, 1, 0,
+ 255, 254, 250, 240, 220, 189, 149, 107,
+ 67, 36, 16, 6, 2, 1, 0, 255,
+ 254, 251, 243, 227, 201, 166, 128, 90,
+ 55, 29, 13, 5, 2, 1, 0, 255,
+ 254, 252, 246, 234, 213, 183, 147, 109,
+ 73, 43, 22, 10, 4, 2, 1, 0
+};
+
+const opus_uint8 silk_shell_code_table3[ 152 ] = {
+ 130, 0, 200, 58, 0, 231, 130, 26,
+ 0, 244, 184, 76, 12, 0, 249, 214,
+ 130, 43, 6, 0, 252, 232, 173, 87,
+ 24, 3, 0, 253, 241, 203, 131, 56,
+ 14, 2, 0, 254, 246, 221, 167, 94,
+ 35, 8, 1, 0, 254, 249, 232, 193,
+ 130, 65, 23, 5, 1, 0, 255, 251,
+ 239, 211, 162, 99, 45, 15, 4, 1,
+ 0, 255, 251, 243, 223, 186, 131, 74,
+ 33, 11, 3, 1, 0, 255, 252, 245,
+ 230, 202, 158, 105, 57, 24, 8, 2,
+ 1, 0, 255, 253, 247, 235, 214, 179,
+ 132, 84, 44, 19, 7, 2, 1, 0,
+ 255, 254, 250, 240, 223, 196, 159, 112,
+ 69, 36, 15, 6, 2, 1, 0, 255,
+ 254, 253, 245, 231, 209, 176, 136, 93,
+ 55, 27, 11, 3, 2, 1, 0, 255,
+ 254, 253, 252, 239, 221, 194, 158, 117,
+ 76, 42, 18, 4, 3, 2, 1, 0
+};
+
+const opus_uint8 silk_shell_code_table_offsets[ 17 ] = {
+ 0, 0, 2, 5, 9, 14, 20, 27,
+ 35, 44, 54, 65, 77, 90, 104, 119,
+ 135
+};
+
+const opus_uint8 silk_sign_iCDF[ 42 ] = {
+ 254, 49, 67, 77, 82, 93, 99,
+ 198, 11, 18, 24, 31, 36, 45,
+ 255, 46, 66, 78, 87, 94, 104,
+ 208, 14, 21, 32, 42, 51, 66,
+ 255, 94, 104, 109, 112, 115, 118,
+ 248, 53, 69, 80, 88, 95, 102
+};
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_TUNING_PARAMETERS_H
+#define SILK_TUNING_PARAMETERS_H
+
+/* Decay time for bitreservoir */
+#define BITRESERVOIR_DECAY_TIME_MS 500
+
+/*******************/
+/* Pitch estimator */
+/*******************/
+
+/* Level of noise floor for whitening filter LPC analysis in pitch analysis */
+#define FIND_PITCH_WHITE_NOISE_FRACTION 1e-3f
+
+/* Bandwidth expansion for whitening filter in pitch analysis */
+#define FIND_PITCH_BANDWIDTH_EXPANSION 0.99f
+
+/*********************/
+/* Linear prediction */
+/*********************/
+
+/* LPC analysis regularization */
+#define FIND_LPC_COND_FAC 1e-5f
+
+/* Max cumulative LTP gain */
+#define MAX_SUM_LOG_GAIN_DB 250.0f
+
+/* LTP analysis defines */
+#define LTP_CORR_INV_MAX 0.03f
+
+/***********************/
+/* High pass filtering */
+/***********************/
+
+/* Smoothing parameters for low end of pitch frequency range estimation */
+#define VARIABLE_HP_SMTH_COEF1 0.1f
+#define VARIABLE_HP_SMTH_COEF2 0.015f
+#define VARIABLE_HP_MAX_DELTA_FREQ 0.4f
+
+/* Min and max cut-off frequency values (-3 dB points) */
+#define VARIABLE_HP_MIN_CUTOFF_HZ 60
+#define VARIABLE_HP_MAX_CUTOFF_HZ 100
+
+/***********/
+/* Various */
+/***********/
+
+/* VAD threshold */
+#define SPEECH_ACTIVITY_DTX_THRES 0.05f
+
+/* Speech Activity LBRR enable threshold */
+#define LBRR_SPEECH_ACTIVITY_THRES 0.3f
+
+/*************************/
+/* Perceptual parameters */
+/*************************/
+
+/* reduction in coding SNR during low speech activity */
+#define BG_SNR_DECR_dB 2.0f
+
+/* factor for reducing quantization noise during voiced speech */
+#define HARM_SNR_INCR_dB 2.0f
+
+/* factor for reducing quantization noise for unvoiced sparse signals */
+#define SPARSE_SNR_INCR_dB 2.0f
+
+/* threshold for sparseness measure above which to use lower quantization offset during unvoiced */
+#define ENERGY_VARIATION_THRESHOLD_QNT_OFFSET 0.6f
+
+/* warping control */
+#define WARPING_MULTIPLIER 0.015f
+
+/* fraction added to first autocorrelation value */
+#define SHAPE_WHITE_NOISE_FRACTION 3e-5f
+
+/* noise shaping filter chirp factor */
+#define BANDWIDTH_EXPANSION 0.94f
+
+/* harmonic noise shaping */
+#define HARMONIC_SHAPING 0.3f
+
+/* extra harmonic noise shaping for high bitrates or noisy input */
+#define HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING 0.2f
+
+/* parameter for shaping noise towards higher frequencies */
+#define HP_NOISE_COEF 0.25f
+
+/* parameter for shaping noise even more towards higher frequencies during voiced speech */
+#define HARM_HP_NOISE_COEF 0.35f
+
+/* parameter for applying a high-pass tilt to the input signal */
+#define INPUT_TILT 0.05f
+
+/* parameter for extra high-pass tilt to the input signal at high rates */
+#define HIGH_RATE_INPUT_TILT 0.1f
+
+/* parameter for reducing noise at the very low frequencies */
+#define LOW_FREQ_SHAPING 4.0f
+
+/* less reduction of noise at the very low frequencies for signals with low SNR at low frequencies */
+#define LOW_QUALITY_LOW_FREQ_SHAPING_DECR 0.5f
+
+/* subframe smoothing coefficient for HarmBoost, HarmShapeGain, Tilt (lower -> more smoothing) */
+#define SUBFR_SMTH_COEF 0.4f
+
+/* parameters defining the R/D tradeoff in the residual quantizer */
+#define LAMBDA_OFFSET 1.2f
+#define LAMBDA_SPEECH_ACT -0.2f
+#define LAMBDA_DELAYED_DECISIONS -0.05f
+#define LAMBDA_INPUT_QUALITY -0.1f
+#define LAMBDA_CODING_QUALITY -0.2f
+#define LAMBDA_QUANT_OFFSET 0.8f
+
+/* Compensation in bitrate calculations for 10 ms modes */
+#define REDUCE_BITRATE_10_MS_BPS 2200
+
+/* Maximum time before allowing a bandwidth transition */
+#define MAX_BANDWIDTH_SWITCH_DELAY_MS 5000
+
+#endif /* SILK_TUNING_PARAMETERS_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_TYPEDEF_H
+#define SILK_TYPEDEF_H
+
+#include "opus_types.h"
+#include "opus_defines.h"
+
+#ifndef FIXED_POINT
+# include <float.h>
+# define silk_float float
+# define silk_float_MAX FLT_MAX
+#endif
+
+#define silk_int64_MAX ((opus_int64)0x7FFFFFFFFFFFFFFFLL) /* 2^63 - 1 */
+#define silk_int64_MIN ((opus_int64)0x8000000000000000LL) /* -2^63 */
+#define silk_int32_MAX 0x7FFFFFFF /* 2^31 - 1 = 2147483647 */
+#define silk_int32_MIN ((opus_int32)0x80000000) /* -2^31 = -2147483648 */
+#define silk_int16_MAX 0x7FFF /* 2^15 - 1 = 32767 */
+#define silk_int16_MIN ((opus_int16)0x8000) /* -2^15 = -32768 */
+#define silk_int8_MAX 0x7F /* 2^7 - 1 = 127 */
+#define silk_int8_MIN ((opus_int8)0x80) /* -2^7 = -128 */
+#define silk_uint8_MAX 0xFF /* 2^8 - 1 = 255 */
+
+#define silk_TRUE 1
+#define silk_FALSE 0
+
+/* assertions */
+#if (defined _WIN32 && !defined _WINCE && !defined(__GNUC__) && !defined(NO_ASSERTS))
+# ifndef silk_assert
+# include <crtdbg.h> /* ASSERTE() */
+# define silk_assert(COND) _ASSERTE(COND)
+# endif
+#else
+# ifdef ENABLE_ASSERTIONS
+# include <stdio.h>
+# include <stdlib.h>
+#define silk_fatal(str) _silk_fatal(str, __FILE__, __LINE__);
+#ifdef __GNUC__
+__attribute__((noreturn))
+#endif
+static OPUS_INLINE void _silk_fatal(const char *str, const char *file, int line)
+{
+ fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
+#if defined(_MSC_VER)
+ _set_abort_behavior( 0, _WRITE_ABORT_MSG);
+#endif
+ abort();
+}
+# define silk_assert(COND) {if (!(COND)) {silk_fatal("assertion failed: " #COND);}}
+# else
+# define silk_assert(COND) ((void)(COND))
+# endif
+#endif
+
+#endif /* SILK_TYPEDEF_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SILK_WARPED_AUTOCORRELATION_FIX_ARM_H
+# define SILK_WARPED_AUTOCORRELATION_FIX_ARM_H
+
+# include "celt/arm/armcpu.h"
+
+# if defined(FIXED_POINT)
+
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+void silk_warped_autocorrelation_FIX_neon(
+ opus_int32 *corr, /* O Result [order + 1] */
+ opus_int *scale, /* O Scaling of the correlation vector */
+ const opus_int16 *input, /* I Input data to correlate */
+ const opus_int warping_Q16, /* I Warping coefficient */
+ const opus_int length, /* I Length of input */
+ const opus_int order /* I Correlation order (even) */
+);
+
+# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+# define OVERRIDE_silk_warped_autocorrelation_FIX (1)
+# define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+ ((void)(arch), PRESUME_NEON(silk_warped_autocorrelation_FIX)(corr, scale, input, warping_Q16, length, order))
+# endif
+# endif
+
+# if !defined(OVERRIDE_silk_warped_autocorrelation_FIX)
+/*Is run-time CPU detection enabled on this platform?*/
+# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const SILK_WARPED_AUTOCORRELATION_FIX_IMPL[OPUS_ARCHMASK+1])(opus_int32*, opus_int*, const opus_int16*, const opus_int, const opus_int, const opus_int);
+# define OVERRIDE_silk_warped_autocorrelation_FIX (1)
+# define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+ ((*SILK_WARPED_AUTOCORRELATION_FIX_IMPL[(arch)&OPUS_ARCHMASK])(corr, scale, input, warping_Q16, length, order))
+# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+# define OVERRIDE_silk_warped_autocorrelation_FIX (1)
+# define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+ ((void)(arch), silk_warped_autocorrelation_FIX_neon(corr, scale, input, warping_Q16, length, order))
+# endif
+# endif
+
+# endif /* end FIXED_POINT */
+
+#endif /* end SILK_WARPED_AUTOCORRELATION_FIX_ARM_H */
--- /dev/null
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- 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.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 __WARPED_AUTOCORRELATION_FIX_MIPSR1_H__
+#define __WARPED_AUTOCORRELATION_FIX_MIPSR1_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main_FIX.h"
+
+#if defined (__mips_dsp) && __mips == 32
+
+#define MIPS_MADD __builtin_mips_madd
+#define MIPS_SHILO __builtin_mips_shilo
+
+#define OVERRIDE_silk_warped_autocorrelation_FIX_c
+
+#elif defined (__mips_isa_rev) && __mips == 32
+
+static inline long long MIPS_MADD(long long acc, int a, int b) {
+ return acc + (long long)a * b;
+}
+
+static inline long long MIPS_SHILO(long long acc, int sh) {
+ return (sh >= 0) ? (acc >> sh) : (acc << -sh);
+}
+
+#define OVERRIDE_silk_warped_autocorrelation_FIX_c
+
+#endif
+
+/* Autocorrelations for a warped frequency axis */
+#if defined (OVERRIDE_silk_warped_autocorrelation_FIX_c)
+
+#undef QC
+#define QC 10
+
+#undef QS
+#define QS 14
+
+void silk_warped_autocorrelation_FIX_c(
+ opus_int32 *corr, /* O Result [order + 1] */
+ opus_int *scale, /* O Scaling of the correlation vector */
+ const opus_int16 *input, /* I Input data to correlate */
+ const opus_int warping_Q16, /* I Warping coefficient */
+ const opus_int length, /* I Length of input */
+ const opus_int order /* I Correlation order (even) */
+)
+{
+ opus_int n, i, lsh;
+ opus_int32 tmp1_QS=0, tmp2_QS=0, tmp3_QS=0, tmp4_QS=0, tmp5_QS=0, tmp6_QS=0, tmp7_QS=0, tmp8_QS=0, start_1=0, start_2=0, start_3=0;
+ opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
+ opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
+ opus_int64 temp64;
+
+ opus_int32 val;
+ val = 2 * QS - QC;
+
+ /* Order must be even */
+ silk_assert( ( order & 1 ) == 0 );
+ silk_assert( 2 * QS - QC >= 0 );
+
+ /* Loop over samples */
+ for( n = 0; n < length; n=n+4 ) {
+
+ tmp1_QS = silk_LSHIFT32( (opus_int32)input[ n ], QS );
+ start_1 = tmp1_QS;
+ tmp3_QS = silk_LSHIFT32( (opus_int32)input[ n+1], QS );
+ start_2 = tmp3_QS;
+ tmp5_QS = silk_LSHIFT32( (opus_int32)input[ n+2], QS );
+ start_3 = tmp5_QS;
+ tmp7_QS = silk_LSHIFT32( (opus_int32)input[ n+3], QS );
+
+ /* Loop over allpass sections */
+ for( i = 0; i < order; i += 2 ) {
+ /* Output of allpass section */
+ tmp2_QS = silk_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 );
+ corr_QC[ i ] = MIPS_MADD( corr_QC[ i ], tmp1_QS, start_1);
+
+ tmp4_QS = silk_SMLAWB( tmp1_QS, tmp2_QS - tmp3_QS, warping_Q16 );
+ corr_QC[ i ] = MIPS_MADD( corr_QC[ i ], tmp3_QS, start_2);
+
+ tmp6_QS = silk_SMLAWB( tmp3_QS, tmp4_QS - tmp5_QS, warping_Q16 );
+ corr_QC[ i ] = MIPS_MADD( corr_QC[ i ], tmp5_QS, start_3);
+
+ tmp8_QS = silk_SMLAWB( tmp5_QS, tmp6_QS - tmp7_QS, warping_Q16 );
+ state_QS[ i ] = tmp7_QS;
+ corr_QC[ i ] = MIPS_MADD( corr_QC[ i ], tmp7_QS, state_QS[0]);
+
+ /* Output of allpass section */
+ tmp1_QS = silk_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 );
+ corr_QC[ i+1 ] = MIPS_MADD( corr_QC[ i+1 ], tmp2_QS, start_1);
+
+ tmp3_QS = silk_SMLAWB( tmp2_QS, tmp1_QS - tmp4_QS, warping_Q16 );
+ corr_QC[ i+1 ] = MIPS_MADD( corr_QC[ i+1 ], tmp4_QS, start_2);
+
+ tmp5_QS = silk_SMLAWB( tmp4_QS, tmp3_QS - tmp6_QS, warping_Q16 );
+ corr_QC[ i+1 ] = MIPS_MADD( corr_QC[ i+1 ], tmp6_QS, start_3);
+
+ tmp7_QS = silk_SMLAWB( tmp6_QS, tmp5_QS - tmp8_QS, warping_Q16 );
+ state_QS[ i + 1 ] = tmp8_QS;
+ corr_QC[ i+1 ] = MIPS_MADD( corr_QC[ i+1 ], tmp8_QS, state_QS[ 0 ]);
+
+ }
+ state_QS[ order ] = tmp7_QS;
+
+ corr_QC[ order ] = MIPS_MADD( corr_QC[ order ], tmp1_QS, start_1);
+ corr_QC[ order ] = MIPS_MADD( corr_QC[ order ], tmp3_QS, start_2);
+ corr_QC[ order ] = MIPS_MADD( corr_QC[ order ], tmp5_QS, start_3);
+ corr_QC[ order ] = MIPS_MADD( corr_QC[ order ], tmp7_QS, state_QS[ 0 ]);
+ }
+
+ for(;n< length; n++ ) {
+
+ tmp1_QS = silk_LSHIFT32( (opus_int32)input[ n ], QS );
+
+ /* Loop over allpass sections */
+ for( i = 0; i < order; i += 2 ) {
+
+ /* Output of allpass section */
+ tmp2_QS = silk_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 );
+ state_QS[ i ] = tmp1_QS;
+ corr_QC[ i ] = MIPS_MADD( corr_QC[ i ], tmp1_QS, state_QS[ 0 ]);
+
+ /* Output of allpass section */
+ tmp1_QS = silk_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 );
+ state_QS[ i + 1 ] = tmp2_QS;
+ corr_QC[ i+1 ] = MIPS_MADD( corr_QC[ i+1 ], tmp2_QS, state_QS[ 0 ]);
+ }
+ state_QS[ order ] = tmp1_QS;
+ corr_QC[ order ] = MIPS_MADD( corr_QC[ order ], tmp1_QS, state_QS[ 0 ]);
+ }
+
+ temp64 = corr_QC[ 0 ];
+ temp64 = MIPS_SHILO(temp64, val);
+
+ lsh = silk_CLZ64( temp64 ) - 35;
+ lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC );
+ *scale = -( QC + lsh );
+ silk_assert( *scale >= -30 && *scale <= 12 );
+ if( lsh >= 0 ) {
+ for( i = 0; i < order + 1; i++ ) {
+ temp64 = corr_QC[ i ];
+ //temp64 = MIPS_SHILO(temp64, val);
+ temp64 = (val >= 0) ? (temp64 >> val) : (temp64 << -val);
+ corr[ i ] = (opus_int32)silk_CHECK_FIT32( MIPS_SHILO( temp64, -lsh ) );
+ }
+ } else {
+ for( i = 0; i < order + 1; i++ ) {
+ temp64 = corr_QC[ i ];
+ //temp64 = MIPS_SHILO(temp64, val);
+ temp64 = (val >= 0) ? (temp64 >> val) : (temp64 << -val);
+ corr[ i ] = (opus_int32)silk_CHECK_FIT32( MIPS_SHILO( temp64, -lsh ) );
+ }
+ }
+
+ corr_QC[ 0 ] = MIPS_SHILO(corr_QC[ 0 ], val);
+
+ silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/
+}
+#endif /* OVERRIDE_silk_warped_autocorrelation_FIX_c */
+
+#endif /* __WARPED_AUTOCORRELATION_FIX_MIPSR1_H__ */
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 SIGPROC_FIX_SSE_H
+# define SIGPROC_FIX_SSE_H
+
+# ifdef HAVE_CONFIG_H
+# include "config.h"
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+void silk_burg_modified_sse4_1(
+ opus_int32 *res_nrg, /* O Residual energy */
+ opus_int *res_nrg_Q, /* O Residual energy Q value */
+ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
+ const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */
+ const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */
+ const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */
+ const opus_int nb_subfr, /* I Number of subframes stacked in x */
+ const opus_int D, /* I Order */
+ int arch /* I Run-time architecture */
+);
+
+# if defined(OPUS_X86_PRESUME_SSE4_1)
+
+# define OVERRIDE_silk_burg_modified
+# define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
+ ((void)(arch), silk_burg_modified_sse4_1(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
+
+# elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_BURG_MODIFIED_IMPL[OPUS_ARCHMASK + 1])(
+ opus_int32 *res_nrg, /* O Residual energy */
+ opus_int *res_nrg_Q, /* O Residual energy Q value */
+ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
+ const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */
+ const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */
+ const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */
+ const opus_int nb_subfr, /* I Number of subframes stacked in x */
+ const opus_int D, /* I Order */
+ int arch /* I Run-time architecture */);
+
+# define OVERRIDE_silk_burg_modified
+# define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
+ ((*SILK_BURG_MODIFIED_IMPL[(arch) & OPUS_ARCHMASK])(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
+
+# endif
+
+opus_int64 silk_inner_prod16_sse4_1(
+ const opus_int16 *inVec1,
+ const opus_int16 *inVec2,
+ const opus_int len
+);
+
+
+# if defined(OPUS_X86_PRESUME_SSE4_1)
+
+# define OVERRIDE_silk_inner_prod16
+# define silk_inner_prod16(inVec1, inVec2, len, arch) \
+ ((void)(arch),silk_inner_prod16_sse4_1(inVec1, inVec2, len))
+
+# elif defined(OPUS_HAVE_RTCD)
+
+extern opus_int64 (*const SILK_INNER_PROD16_IMPL[OPUS_ARCHMASK + 1])(
+ const opus_int16 *inVec1,
+ const opus_int16 *inVec2,
+ const opus_int len);
+
+# define OVERRIDE_silk_inner_prod16
+# define silk_inner_prod16(inVec1, inVec2, len, arch) \
+ ((*SILK_INNER_PROD16_IMPL[(arch) & OPUS_ARCHMASK])(inVec1, inVec2, len))
+
+# endif
+# endif
+#endif
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 MAIN_SSE_H
+# define MAIN_SSE_H
+
+# ifdef HAVE_CONFIG_H
+# include "config.h"
+# endif
+
+# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
+
+void silk_VQ_WMat_EC_sse4_1(
+ opus_int8 *ind, /* O index of best codebook vector */
+ opus_int32 *res_nrg_Q15, /* O best residual energy */
+ opus_int32 *rate_dist_Q8, /* O best total bitrate */
+ opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
+ const opus_int32 *XX_Q17, /* I correlation matrix */
+ const opus_int32 *xX_Q17, /* I correlation vector */
+ const opus_int8 *cb_Q7, /* I codebook */
+ const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
+ const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
+ const opus_int subfr_len, /* I number of samples per subframe */
+ const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
+ const opus_int L /* I number of vectors in codebook */
+);
+
+# if defined OPUS_X86_PRESUME_SSE4_1
+
+# define OVERRIDE_silk_VQ_WMat_EC
+# define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+ subfr_len, max_gain_Q7, L, arch) \
+ ((void)(arch),silk_VQ_WMat_EC_sse4_1(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+ subfr_len, max_gain_Q7, L))
+
+# elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_VQ_WMAT_EC_IMPL[OPUS_ARCHMASK + 1])(
+ opus_int8 *ind, /* O index of best codebook vector */
+ opus_int32 *res_nrg_Q15, /* O best residual energy */
+ opus_int32 *rate_dist_Q8, /* O best total bitrate */
+ opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
+ const opus_int32 *XX_Q17, /* I correlation matrix */
+ const opus_int32 *xX_Q17, /* I correlation vector */
+ const opus_int8 *cb_Q7, /* I codebook */
+ const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
+ const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
+ const opus_int subfr_len, /* I number of samples per subframe */
+ const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
+ const opus_int L /* I number of vectors in codebook */
+);
+
+# define OVERRIDE_silk_VQ_WMat_EC
+# define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+ subfr_len, max_gain_Q7, L, arch) \
+ ((*SILK_VQ_WMAT_EC_IMPL[(arch) & OPUS_ARCHMASK])(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, \
+ subfr_len, max_gain_Q7, L))
+
+# endif
+
+void silk_NSQ_sse4_1(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+);
+
+# if defined OPUS_X86_PRESUME_SSE4_1
+
+# define OVERRIDE_silk_NSQ
+# define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+ ((void)(arch),silk_NSQ_sse4_1(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+# elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_NSQ_IMPL[OPUS_ARCHMASK + 1])(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+);
+
+# define OVERRIDE_silk_NSQ
+# define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+ ((*SILK_NSQ_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+# endif
+
+void silk_NSQ_del_dec_sse4_1(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+);
+
+void silk_NSQ_del_dec_avx2(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[MAX_NB_SUBFR], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[MAX_NB_SUBFR], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[MAX_NB_SUBFR], /* I Quantization step sizes */
+ const opus_int32 pitchL[MAX_NB_SUBFR], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+);
+
+# if defined (OPUS_X86_PRESUME_AVX2)
+
+# define OVERRIDE_silk_NSQ_del_dec
+# define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+ ((void)(arch),silk_NSQ_del_dec_avx2(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+# elif defined (OPUS_X86_PRESUME_SSE4_1) && !defined(OPUS_X86_MAY_HAVE_AVX2)
+
+# define OVERRIDE_silk_NSQ_del_dec
+# define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+ ((void)(arch),silk_NSQ_del_dec_sse4_1(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+# elif defined(OPUS_HAVE_RTCD)
+
+extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+);
+
+# define OVERRIDE_silk_NSQ_del_dec
+# define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
+ ((*SILK_NSQ_DEL_DEC_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
+ HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
+
+# endif
+
+void silk_noise_shape_quantizer(
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ opus_int signalType, /* I Signal type */
+ const opus_int32 x_sc_Q10[], /* I */
+ opus_int8 pulses[], /* O */
+ opus_int16 xq[], /* O */
+ opus_int32 sLTP_Q15[], /* I/O LTP state */
+ const opus_int16 a_Q12[], /* I Short term prediction coefs */
+ const opus_int16 b_Q14[], /* I Long term prediction coefs */
+ const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
+ opus_int lag, /* I Pitch lag */
+ opus_int32 HarmShapeFIRPacked_Q14, /* I */
+ opus_int Tilt_Q14, /* I Spectral tilt */
+ opus_int32 LF_shp_Q14, /* I */
+ opus_int32 Gain_Q16, /* I */
+ opus_int Lambda_Q10, /* I */
+ opus_int offset_Q10, /* I */
+ opus_int length, /* I Input length */
+ opus_int shapingLPCOrder, /* I Noise shaping AR filter order */
+ opus_int predictLPCOrder, /* I Prediction filter order */
+ int arch /* I Architecture */
+);
+
+/**************************/
+/* Noise level estimation */
+/**************************/
+void silk_VAD_GetNoiseLevels(
+ const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */
+ silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
+);
+
+opus_int silk_VAD_GetSA_Q8_sse4_1(
+ silk_encoder_state *psEnC,
+ const opus_int16 pIn[]
+);
+
+# if defined(OPUS_X86_PRESUME_SSE4_1)
+
+# define OVERRIDE_silk_VAD_GetSA_Q8
+# define silk_VAD_GetSA_Q8(psEnC, pIn, arch) ((void)(arch),silk_VAD_GetSA_Q8_sse4_1(psEnC, pIn))
+
+# elif defined(OPUS_HAVE_RTCD)
+
+extern opus_int (*const SILK_VAD_GETSA_Q8_IMPL[OPUS_ARCHMASK + 1])(
+ silk_encoder_state *psEnC,
+ const opus_int16 pIn[]);
+
+# define OVERRIDE_silk_VAD_GetSA_Q8
+# define silk_VAD_GetSA_Q8(psEnC, pIn, arch) \
+ ((*SILK_VAD_GETSA_Q8_IMPL[(arch) & OPUS_ARCHMASK])(psEnC, pIn))
+
+# endif
+
+#ifndef FIXED_POINT
+double silk_inner_product_FLP_avx2(
+ const silk_float *data1,
+ const silk_float *data2,
+ opus_int dataSize
+);
+
+#if defined (OPUS_X86_PRESUME_AVX2)
+
+#define OVERRIDE_inner_product_FLP
+#define silk_inner_product_FLP(data1, data2, dataSize, arch) ((void)arch,silk_inner_product_FLP_avx2(data1, data2, dataSize))
+
+#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_X86_MAY_HAVE_AVX2)
+
+#define OVERRIDE_inner_product_FLP
+extern double (*const SILK_INNER_PRODUCT_FLP_IMPL[OPUS_ARCHMASK + 1])(
+ const silk_float *data1,
+ const silk_float *data2,
+ opus_int dataSize
+);
+
+#define silk_inner_product_FLP(data1, data2, dataSize, arch) ((void)arch,(*SILK_INNER_PRODUCT_FLP_IMPL[(arch) & OPUS_ARCHMASK])(data1, data2, dataSize))
+
+#endif
+#endif
+
+# endif
+#endif
--- /dev/null
+/* Copyright (c) 2014, Cisco Systems, INC
+ Written by XiangMingZhu WeiZhou MinPeng YanWang
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include "celt/x86/x86cpu.h"
+#include "structs.h"
+#include "SigProc_FIX.h"
+#ifndef FIXED_POINT
+#include "SigProc_FLP.h"
+#endif
+#include "pitch.h"
+#include "main.h"
+
+#if defined(OPUS_HAVE_RTCD) && !defined(OPUS_X86_PRESUME_AVX2)
+
+#if defined(FIXED_POINT)
+
+#include "fixed/main_FIX.h"
+
+opus_int64 (*const SILK_INNER_PROD16_IMPL[ OPUS_ARCHMASK + 1 ] )(
+ const opus_int16 *inVec1,
+ const opus_int16 *inVec2,
+ const opus_int len
+) = {
+ silk_inner_prod16_c, /* non-sse */
+ silk_inner_prod16_c,
+ silk_inner_prod16_c,
+ MAY_HAVE_SSE4_1( silk_inner_prod16 ), /* sse4.1 */
+ MAY_HAVE_SSE4_1( silk_inner_prod16 ) /* avx */
+};
+
+#endif
+
+opus_int (*const SILK_VAD_GETSA_Q8_IMPL[ OPUS_ARCHMASK + 1 ] )(
+ silk_encoder_state *psEncC,
+ const opus_int16 pIn[]
+) = {
+ silk_VAD_GetSA_Q8_c, /* non-sse */
+ silk_VAD_GetSA_Q8_c,
+ silk_VAD_GetSA_Q8_c,
+ MAY_HAVE_SSE4_1( silk_VAD_GetSA_Q8 ), /* sse4.1 */
+ MAY_HAVE_SSE4_1( silk_VAD_GetSA_Q8 ) /* avx */
+};
+
+void (*const SILK_NSQ_IMPL[ OPUS_ARCHMASK + 1 ] )(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+) = {
+ silk_NSQ_c, /* non-sse */
+ silk_NSQ_c,
+ silk_NSQ_c,
+ MAY_HAVE_SSE4_1( silk_NSQ ), /* sse4.1 */
+ MAY_HAVE_SSE4_1( silk_NSQ ) /* avx */
+};
+
+void (*const SILK_VQ_WMAT_EC_IMPL[ OPUS_ARCHMASK + 1 ] )(
+ opus_int8 *ind, /* O index of best codebook vector */
+ opus_int32 *res_nrg_Q15, /* O best residual energy */
+ opus_int32 *rate_dist_Q8, /* O best total bitrate */
+ opus_int *gain_Q7, /* O sum of absolute LTP coefficients */
+ const opus_int32 *XX_Q17, /* I correlation matrix */
+ const opus_int32 *xX_Q17, /* I correlation vector */
+ const opus_int8 *cb_Q7, /* I codebook */
+ const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */
+ const opus_uint8 *cl_Q5, /* I code length for each codebook vector */
+ const opus_int subfr_len, /* I number of samples per subframe */
+ const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */
+ const opus_int L /* I number of vectors in codebook */
+) = {
+ silk_VQ_WMat_EC_c, /* non-sse */
+ silk_VQ_WMat_EC_c,
+ silk_VQ_WMat_EC_c,
+ MAY_HAVE_SSE4_1( silk_VQ_WMat_EC ), /* sse4.1 */
+ MAY_HAVE_SSE4_1( silk_VQ_WMat_EC ) /* avx */
+};
+
+void (*const SILK_NSQ_DEL_DEC_IMPL[ OPUS_ARCHMASK + 1 ] )(
+ const silk_encoder_state *psEncC, /* I Encoder State */
+ silk_nsq_state *NSQ, /* I/O NSQ state */
+ SideInfoIndices *psIndices, /* I/O Quantization Indices */
+ const opus_int16 x16[], /* I Input */
+ opus_int8 pulses[], /* O Quantized pulse signal */
+ const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */
+ const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
+ const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
+ const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
+ const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
+ const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
+ const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
+ const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
+ const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
+ const opus_int LTP_scale_Q14 /* I LTP state scaling */
+) = {
+ silk_NSQ_del_dec_c, /* non-sse */
+ silk_NSQ_del_dec_c,
+ silk_NSQ_del_dec_c,
+ MAY_HAVE_SSE4_1( silk_NSQ_del_dec ), /* sse4.1 */
+ MAY_HAVE_AVX2( silk_NSQ_del_dec ) /* avx */
+};
+
+#if defined(FIXED_POINT)
+
+void (*const SILK_BURG_MODIFIED_IMPL[ OPUS_ARCHMASK + 1 ] )(
+ opus_int32 *res_nrg, /* O Residual energy */
+ opus_int *res_nrg_Q, /* O Residual energy Q value */
+ opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
+ const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */
+ const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */
+ const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */
+ const opus_int nb_subfr, /* I Number of subframes stacked in x */
+ const opus_int D, /* I Order */
+ int arch /* I Run-time architecture */
+) = {
+ silk_burg_modified_c, /* non-sse */
+ silk_burg_modified_c,
+ silk_burg_modified_c,
+ MAY_HAVE_SSE4_1( silk_burg_modified ), /* sse4.1 */
+ MAY_HAVE_SSE4_1( silk_burg_modified ) /* avx */
+};
+
+#endif
+
+#ifndef FIXED_POINT
+
+double (*const SILK_INNER_PRODUCT_FLP_IMPL[ OPUS_ARCHMASK + 1 ] )(
+ const silk_float *data1,
+ const silk_float *data2,
+ opus_int dataSize
+) = {
+ silk_inner_product_FLP_c, /* non-sse */
+ silk_inner_product_FLP_c,
+ silk_inner_product_FLP_c,
+ silk_inner_product_FLP_c, /* sse4.1 */
+ MAY_HAVE_AVX2( silk_inner_product_FLP ) /* avx */
+};
+
+#endif
+
+#endif
--- /dev/null
+/* Copyright (c) 2007-2008 CSIRO\r
+ Copyright (c) 2007-2009 Xiph.Org Foundation\r
+ Written by Jean-Marc Valin */\r
+/*\r
+ Redistribution and use in source and binary forms, with or without\r
+ modification, are permitted provided that the following conditions\r
+ are met:\r
+\r
+ - Redistributions of source code must retain the above copyright\r
+ notice, this list of conditions and the following disclaimer.\r
+\r
+ - Redistributions in binary form must reproduce the above copyright\r
+ notice, this list of conditions and the following disclaimer in the\r
+ documentation and/or other materials provided with the distribution.\r
+\r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER\r
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*/\r
+\r
+#ifdef HAVE_CONFIG_H\r
+#include "config.h"\r
+#endif\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <stdint.h>\r
+#include "opus.h"\r
+\r
+#include "opus_frame_to_pcm.h"\r
+\r
+#define MAX_PACKET_SIZE 15000\r
+#define MAX_PCM_SAMPLES 5760 /* 120ms at 48kHz */\r
+\r
+int opus_frame_to_pcm_decode_packet(const unsigned char *packet_data, int packet_len,\r
+ int sample_rate, int channels,\r
+ short *out_pcm, int out_pcm_capacity,\r
+ int *out_pcm_samples)\r
+{\r
+ OpusDecoder *decoder = NULL;\r
+ int error = OPUS_OK;\r
+ int decoded_samples = 0;\r
+ int total_samples = 0;\r
+\r
+ if (!packet_data || packet_len <= 0 || !out_pcm || out_pcm_capacity <= 0 || !out_pcm_samples) {\r
+ return 1;\r
+ }\r
+ \r
+ /* Validate packet */\r
+ unsigned char out_toc;\r
+ const unsigned char *frames[48];\r
+ opus_int16 size[48];\r
+ int payload_offset;\r
+ int nb_frames = opus_packet_parse(packet_data, packet_len, &out_toc, frames, size, &payload_offset);\r
+ \r
+ if (nb_frames < 0) {\r
+ return 1;\r
+ }\r
+ \r
+ /* Try to get channel count from packet if not specified */\r
+ if (channels <= 0) {\r
+ int packet_channels = opus_packet_get_nb_channels(packet_data);\r
+ if (packet_channels > 0) {\r
+ channels = packet_channels;\r
+ } else {\r
+ channels = 1; /* Default to mono */\r
+ }\r
+ }\r
+ \r
+ /* Create decoder */\r
+ decoder = opus_decoder_create(sample_rate, channels, &error);\r
+ if (error != OPUS_OK) {\r
+ return 1;\r
+ }\r
+\r
+ /* Decode packet */\r
+ decoded_samples = opus_decode(decoder, packet_data, packet_len, (opus_int16 *)out_pcm, MAX_PCM_SAMPLES, 0);\r
+ if (decoded_samples <= 0) {\r
+ opus_decoder_destroy(decoder);\r
+ return 1;\r
+ }\r
+\r
+ total_samples = decoded_samples * channels;\r
+ if (total_samples > out_pcm_capacity) {\r
+ opus_decoder_destroy(decoder);\r
+ return 1;\r
+ }\r
+ *out_pcm_samples = total_samples;\r
+\r
+ /* Cleanup */\r
+ opus_decoder_destroy(decoder);\r
+ return 0;\r
+}\r
+\r
+/* Decode a single Opus frame file to PCM */\r
+int opus_frame_to_pcm_decode_file(const char *input_file, int sample_rate, int channels,\r
+ const char *output_file)\r
+{\r
+ unsigned char *packet_data = NULL;\r
+ int packet_len = 0;\r
+ opus_int16 *pcm = NULL;\r
+ FILE *fin = NULL;\r
+ FILE *fout = NULL;\r
+ int pcm_samples = 0;\r
+\r
+ if (!input_file) {\r
+ return 1;\r
+ }\r
+\r
+ fin = fopen(input_file, "rb");\r
+ if (!fin) {\r
+ return 1;\r
+ }\r
+\r
+ packet_data = (unsigned char *)malloc(MAX_PACKET_SIZE);\r
+ if (!packet_data) {\r
+ fclose(fin);\r
+ return 1;\r
+ }\r
+\r
+ packet_len = fread(packet_data, 1, MAX_PACKET_SIZE, fin);\r
+ fclose(fin);\r
+ fin = NULL;\r
+ if (packet_len <= 0) {\r
+ free(packet_data);\r
+ return 1;\r
+ }\r
+\r
+ /* worst-case output buffer */\r
+ if (channels <= 0) {\r
+ channels = 2; /* allocate enough; decode_packet will detect actual channels */\r
+ }\r
+ pcm = (opus_int16 *)malloc(MAX_PCM_SAMPLES * channels * sizeof(opus_int16));\r
+ if (!pcm) {\r
+ free(packet_data);\r
+ return 1;\r
+ }\r
+\r
+ if (opus_frame_to_pcm_decode_packet(packet_data, packet_len, sample_rate, channels,\r
+ (short *)pcm, MAX_PCM_SAMPLES * channels, &pcm_samples) != 0) {\r
+ free(pcm);\r
+ free(packet_data);\r
+ return 1;\r
+ }\r
+\r
+ /* Open output file */\r
+ if (output_file) {\r
+ fout = fopen(output_file, "wb");\r
+ if (!fout) {\r
+ free(pcm);\r
+ free(packet_data);\r
+ return 1;\r
+ }\r
+ } else {\r
+ fout = stdout;\r
+ }\r
+\r
+ /* Write PCM data (16-bit little-endian bytes) */\r
+ for (int i = 0; i < pcm_samples; i++) {\r
+ uint16_t sample = (uint16_t)pcm[i];\r
+ uint8_t bytes[2] = { sample & 0xFF, (sample >> 8) & 0xFF };\r
+ if (fwrite(bytes, 1, 2, fout) != 2) {\r
+ if (fout != stdout) fclose(fout);\r
+ free(pcm);\r
+ free(packet_data);\r
+ return 1;\r
+ }\r
+ }\r
+\r
+ if (fout != stdout) {\r
+ fclose(fout);\r
+ }\r
+\r
+ free(pcm);\r
+ free(packet_data);\r
+ return 0;\r
+}\r
--- /dev/null
+/* Copyright (c) 2011 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 ANALYSIS_H
+#define ANALYSIS_H
+
+#include "celt.h"
+#include "opus_private.h"
+#include "mlp.h"
+
+#define NB_FRAMES 8
+#define NB_TBANDS 18
+#define ANALYSIS_BUF_SIZE 720 /* 30 ms at 24 kHz */
+
+/* At that point we can stop counting frames because it no longer matters. */
+#define ANALYSIS_COUNT_MAX 10000
+
+#define DETECT_SIZE 100
+
+/* Uncomment this to print the MLP features on stdout. */
+/*#define MLP_TRAINING*/
+
+typedef struct {
+ int arch;
+ int application;
+ opus_int32 Fs;
+#define TONALITY_ANALYSIS_RESET_START angle
+ float angle[240];
+ float d_angle[240];
+ float d2_angle[240];
+ opus_val32 inmem[ANALYSIS_BUF_SIZE];
+ int mem_fill; /* number of usable samples in the buffer */
+ float prev_band_tonality[NB_TBANDS];
+ float prev_tonality;
+ int prev_bandwidth;
+ float E[NB_FRAMES][NB_TBANDS];
+ float logE[NB_FRAMES][NB_TBANDS];
+ float lowE[NB_TBANDS];
+ float highE[NB_TBANDS];
+ float meanE[NB_TBANDS+1];
+ float mem[32];
+ float cmean[8];
+ float std[9];
+ float Etracker;
+ float lowECount;
+ int E_count;
+ int count;
+ int analysis_offset;
+ int write_pos;
+ int read_pos;
+ int read_subframe;
+ float hp_ener_accum;
+ int initialized;
+ float rnn_state[MAX_NEURONS];
+ opus_val32 downmix_state[3];
+ AnalysisInfo info[DETECT_SIZE];
+} TonalityAnalysisState;
+
+/** Initialize a TonalityAnalysisState struct.
+ *
+ * This performs some possibly slow initialization steps which should
+ * not be repeated every analysis step. No allocated memory is retained
+ * by the state struct, so no cleanup call is required.
+ */
+void tonality_analysis_init(TonalityAnalysisState *analysis, opus_int32 Fs);
+
+/** Reset a TonalityAnalysisState struct.
+ *
+ * Call this when there's a discontinuity in the data.
+ */
+void tonality_analysis_reset(TonalityAnalysisState *analysis);
+
+void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len);
+
+void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm,
+ int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs,
+ int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info);
+
+#endif
--- /dev/null
+/* Copyright (c) 2022 Amazon */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "opus_types.h"
+#include "opus_defines.h"
+#include "arch.h"
+#include "os_support.h"
+#include "opus_private.h"
+
+
+/* Given an extension payload (i.e., excluding the initial ID byte), advance
+ data to the next extension and return the length of the remaining
+ extensions.
+ N.B., a "Repeat These Extensions" extension (ID==2) does not advance past
+ the repeated extension payloads.
+ That requires higher-level logic. */
+static opus_int32 skip_extension_payload(const unsigned char **pdata,
+ opus_int32 len, opus_int32 *pheader_size, int id_byte,
+ opus_int32 trailing_short_len)
+{
+ const unsigned char *data;
+ opus_int32 header_size;
+ int id, L;
+ data = *pdata;
+ header_size = 0;
+ id = id_byte>>1;
+ L = id_byte&1;
+ if ((id == 0 && L == 1) || id == 2)
+ {
+ /* Nothing to do. */
+ } else if (id > 0 && id < 32)
+ {
+ if (len < L)
+ return -1;
+ data += L;
+ len -= L;
+ } else {
+ if (L==0)
+ {
+ if (len < trailing_short_len) return -1;
+ data += len - trailing_short_len;
+ len = trailing_short_len;
+ } else {
+ opus_int32 bytes=0;
+ opus_int32 lacing;
+ do {
+ if (len < 1)
+ return -1;
+ lacing = *data++;
+ bytes += lacing;
+ header_size++;
+ len -= lacing + 1;
+ } while (lacing == 255);
+ if (len < 0)
+ return -1;
+ data += bytes;
+ }
+ }
+ *pdata = data;
+ *pheader_size = header_size;
+ return len;
+}
+
+/* Given an extension, advance data to the next extension and return the
+ length of the remaining extensions.
+ N.B., a "Repeat These Extensions" extension (ID==2) only advances past the
+ extension ID byte.
+ Higher-level logic is required to skip the extension payloads that come
+ after it.*/
+static opus_int32 skip_extension(const unsigned char **pdata, opus_int32 len,
+ opus_int32 *pheader_size)
+{
+ const unsigned char *data;
+ int id_byte;
+ if (len == 0) {
+ *pheader_size = 0;
+ return 0;
+ }
+ if (len < 1)
+ return -1;
+ data = *pdata;
+ id_byte = *data++;
+ len--;
+ len = skip_extension_payload(&data, len, pheader_size, id_byte, 0);
+ if (len >= 0) {
+ *pdata = data;
+ (*pheader_size)++;
+ }
+ return len;
+}
+
+void opus_extension_iterator_init(OpusExtensionIterator *iter,
+ const unsigned char *data, opus_int32 len, opus_int32 nb_frames) {
+ celt_assert(len >= 0);
+ celt_assert(data != NULL || len == 0);
+ celt_assert(nb_frames >= 0 && nb_frames <= 48);
+ iter->repeat_data = iter->curr_data = iter->data = data;
+ iter->last_long = iter->src_data = NULL;
+ iter->curr_len = iter->len = len;
+ iter->repeat_len = iter->src_len = 0;
+ iter->trailing_short_len = 0;
+ iter->frame_max = iter->nb_frames = nb_frames;
+ iter->repeat_frame = iter->curr_frame = 0;
+ iter->repeat_l = 0;
+}
+
+/* Reset the iterator so it can start iterating again from the first
+ extension. */
+void opus_extension_iterator_reset(OpusExtensionIterator *iter) {
+ iter->repeat_data = iter->curr_data = iter->data;
+ iter->last_long = NULL;
+ iter->curr_len = iter->len;
+ iter->repeat_frame = iter->curr_frame = 0;
+ iter->trailing_short_len = 0;
+}
+
+/* Tell the iterator not to return any extensions for frames of index
+ frame_max or larger.
+ This can allow it to stop iterating early if these extensions are not
+ needed. */
+void opus_extension_iterator_set_frame_max(OpusExtensionIterator *iter,
+ int frame_max) {
+ iter->frame_max = frame_max;
+}
+
+/* Return the next repeated extension.
+ The return value is non-zero if one is found, negative on error, or 0 if we
+ have finished repeating extensions. */
+static int opus_extension_iterator_next_repeat(OpusExtensionIterator *iter,
+ opus_extension_data *ext) {
+ opus_int32 header_size;
+ celt_assert(iter->repeat_frame > 0);
+ for (;iter->repeat_frame < iter->nb_frames; iter->repeat_frame++) {
+ while (iter->src_len > 0) {
+ const unsigned char *curr_data0;
+ int repeat_id_byte;
+ repeat_id_byte = *iter->src_data;
+ iter->src_len = skip_extension(&iter->src_data, iter->src_len,
+ &header_size);
+ /* We skipped this extension earlier, so it should not fail now. */
+ celt_assert(iter->src_len >= 0);
+ /* Don't repeat padding or frame separators with a 0 increment. */
+ if (repeat_id_byte <= 3) continue;
+ /* If the "Repeat These Extensions" extension had L == 0 and this
+ is the last repeated long extension, then force decoding the
+ payload with L = 0. */
+ if (iter->repeat_l == 0
+ && iter->repeat_frame + 1 >= iter->nb_frames
+ && iter->src_data == iter->last_long) {
+ repeat_id_byte &= ~1;
+ }
+ curr_data0 = iter->curr_data;
+ iter->curr_len = skip_extension_payload(&iter->curr_data,
+ iter->curr_len, &header_size, repeat_id_byte,
+ iter->trailing_short_len);
+ if (iter->curr_len < 0) {
+ return OPUS_INVALID_PACKET;
+ }
+ celt_assert(iter->curr_data - iter->data
+ == iter->len - iter->curr_len);
+ /* If we were asked to stop at frame_max, skip extensions for later
+ frames. */
+ if (iter->repeat_frame >= iter->frame_max) {
+ continue;
+ }
+ if (ext != NULL) {
+ ext->id = repeat_id_byte >> 1;
+ ext->frame = iter->repeat_frame;
+ ext->data = curr_data0 + header_size;
+ ext->len = iter->curr_data - curr_data0 - header_size;
+ }
+ return 1;
+ }
+ /* We finished repeating the extensions for this frame. */
+ iter->src_data = iter->repeat_data;
+ iter->src_len = iter->repeat_len;
+ }
+ /* We finished repeating extensions. */
+ iter->repeat_data = iter->curr_data;
+ iter->last_long = NULL;
+ /* If L == 0, advance the frame number to handle the case where we did
+ not consume all of the data with an L == 0 long extension. */
+ if (iter->repeat_l == 0) {
+ iter->curr_frame++;
+ /* Ignore additional padding if this was already the last frame. */
+ if (iter->curr_frame >= iter->nb_frames) {
+ iter->curr_len = 0;
+ }
+ }
+ iter->repeat_frame = 0;
+ return 0;
+}
+
+/* Return the next extension (excluding real padding, separators, and repeat
+ indicators, but including the repeated extensions) in bitstream order.
+ Due to the extension repetition mechanism, extensions are not necessarily
+ returned in frame order. */
+int opus_extension_iterator_next(OpusExtensionIterator *iter,
+ opus_extension_data *ext) {
+ opus_int32 header_size;
+ if (iter->curr_len < 0) {
+ return OPUS_INVALID_PACKET;
+ }
+ if (iter->repeat_frame > 0) {
+ int ret;
+ /* We are in the process of repeating some extensions. */
+ ret = opus_extension_iterator_next_repeat(iter, ext);
+ if (ret) return ret;
+ }
+ /* Checking this here allows opus_extension_iterator_set_frame_max() to be
+ called at any point. */
+ if (iter->curr_frame >= iter->frame_max) {
+ return 0;
+ }
+ while (iter->curr_len > 0) {
+ const unsigned char *curr_data0;
+ int id;
+ int L;
+ curr_data0 = iter->curr_data;
+ id = *curr_data0>>1;
+ L = *curr_data0&1;
+ iter->curr_len = skip_extension(&iter->curr_data, iter->curr_len,
+ &header_size);
+ if (iter->curr_len < 0) {
+ return OPUS_INVALID_PACKET;
+ }
+ celt_assert(iter->curr_data - iter->data == iter->len - iter->curr_len);
+ if (id == 1) {
+ if (L == 0) {
+ iter->curr_frame++;
+ }
+ else {
+ /* A frame increment of 0 is a no-op. */
+ if (!curr_data0[1]) continue;
+ iter->curr_frame += curr_data0[1];
+ }
+ if (iter->curr_frame >= iter->nb_frames) {
+ iter->curr_len = -1;
+ return OPUS_INVALID_PACKET;
+ }
+ /* If we were asked to stop at frame_max, skip extensions for later
+ frames. */
+ if (iter->curr_frame >= iter->frame_max) {
+ iter->curr_len = 0;
+ }
+ iter->repeat_data = iter->curr_data;
+ iter->last_long = NULL;
+ iter->trailing_short_len = 0;
+ }
+ else if (id == 2) {
+ int ret;
+ iter->repeat_l = L;
+ iter->repeat_frame = iter->curr_frame + 1;
+ iter->repeat_len = curr_data0 - iter->repeat_data;
+ iter->src_data = iter->repeat_data;
+ iter->src_len = iter->repeat_len;
+ ret = opus_extension_iterator_next_repeat(iter, ext);
+ if (ret) return ret;
+ }
+ else if (id > 2) {
+ /* Update the location of the last long extension.
+ This lets us know when we need to modify the last L flag if we
+ repeat these extensions with L=0. */
+ if (id >= 32) {
+ iter->last_long = iter->curr_data;
+ iter->trailing_short_len = 0;
+ }
+ /* Otherwise, keep track of how many payload bytes follow the last
+ long extension. */
+ else iter->trailing_short_len += L;
+ if (ext != NULL) {
+ ext->id = id;
+ ext->frame = iter->curr_frame;
+ ext->data = curr_data0 + header_size;
+ ext->len = iter->curr_data - curr_data0 - header_size;
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int opus_extension_iterator_find(OpusExtensionIterator *iter,
+ opus_extension_data *ext, int id) {
+ opus_extension_data curr_ext;
+ int ret;
+ for(;;) {
+ ret = opus_extension_iterator_next(iter, &curr_ext);
+ if (ret <= 0) {
+ return ret;
+ }
+ if (curr_ext.id == id) {
+ *ext = curr_ext;
+ return ret;
+ }
+ }
+}
+
+/* Count the number of extensions, excluding real padding, separators, and
+ repeat indicators, but including the repeated extensions. */
+opus_int32 opus_packet_extensions_count(const unsigned char *data,
+ opus_int32 len, int nb_frames)
+{
+ OpusExtensionIterator iter;
+ int count;
+ opus_extension_iterator_init(&iter, data, len, nb_frames);
+ for (count=0; opus_extension_iterator_next(&iter, NULL) > 0; count++);
+ return count;
+}
+
+/* Count the number of extensions for each frame, excluding real padding and
+ separators and repeat indicators, but including the repeated extensions. */
+opus_int32 opus_packet_extensions_count_ext(const unsigned char *data,
+ opus_int32 len, opus_int32 *nb_frame_exts, int nb_frames) {
+ OpusExtensionIterator iter;
+ opus_extension_data ext;
+ int count;
+ opus_extension_iterator_init(&iter, data, len, nb_frames);
+ OPUS_CLEAR(nb_frame_exts, nb_frames);
+ for (count=0; opus_extension_iterator_next(&iter, &ext) > 0; count++) {
+ nb_frame_exts[ext.frame]++;
+ }
+ return count;
+}
+
+/* Extract extensions from Opus padding (excluding real padding, separators,
+ and repeat indicators, but including the repeated extensions) in bitstream
+ order.
+ Due to the extension repetition mechanism, extensions are not necessarily
+ returned in frame order. */
+opus_int32 opus_packet_extensions_parse(const unsigned char *data,
+ opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions,
+ int nb_frames) {
+ OpusExtensionIterator iter;
+ int count;
+ int ret;
+ celt_assert(nb_extensions != NULL);
+ celt_assert(extensions != NULL || *nb_extensions == 0);
+ opus_extension_iterator_init(&iter, data, len, nb_frames);
+ for (count=0;; count++) {
+ opus_extension_data ext;
+ ret = opus_extension_iterator_next(&iter, &ext);
+ if (ret <= 0) break;
+ if (count == *nb_extensions) {
+ return OPUS_BUFFER_TOO_SMALL;
+ }
+ extensions[count] = ext;
+ }
+ *nb_extensions = count;
+ return ret;
+}
+
+/* Extract extensions from Opus padding (excluding real padding, separators,
+ and repeat indicators, but including the repeated extensions) in frame
+ order.
+ nb_frame_exts must be filled with the output of
+ opus_packet_extensions_count_ext(). */
+opus_int32 opus_packet_extensions_parse_ext(const unsigned char *data,
+ opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions,
+ const opus_int32 *nb_frame_exts, int nb_frames) {
+ OpusExtensionIterator iter;
+ opus_extension_data ext;
+ opus_int32 nb_frames_cum[49];
+ int count;
+ int prev_total;
+ int ret;
+ celt_assert(nb_extensions != NULL);
+ celt_assert(extensions != NULL || *nb_extensions == 0);
+ celt_assert(nb_frames <= 48);
+ /* Convert the frame extension count array to a cumulative sum. */
+ prev_total = 0;
+ for (count=0; count<nb_frames; count++) {
+ int total;
+ total = nb_frame_exts[count] + prev_total;
+ nb_frames_cum[count] = prev_total;
+ prev_total = total;
+ }
+ nb_frames_cum[count] = prev_total;
+ opus_extension_iterator_init(&iter, data, len, nb_frames);
+ for (count=0;; count++) {
+ opus_int32 idx;
+ ret = opus_extension_iterator_next(&iter, &ext);
+ if (ret <= 0) break;
+ idx = nb_frames_cum[ext.frame]++;
+ if (idx >= *nb_extensions) {
+ return OPUS_BUFFER_TOO_SMALL;
+ }
+ celt_assert(idx < nb_frames_cum[ext.frame + 1]);
+ extensions[idx] = ext;
+ }
+ *nb_extensions = count;
+ return ret;
+}
+
+static int write_extension_payload(unsigned char *data, opus_int32 len,
+ opus_int32 pos, const opus_extension_data *ext, int last) {
+ celt_assert(ext->id >= 3 && ext->id <= 127);
+ if (ext->id < 32)
+ {
+ if (ext->len < 0 || ext->len > 1)
+ return OPUS_BAD_ARG;
+ if (ext->len > 0) {
+ if (len-pos < ext->len)
+ return OPUS_BUFFER_TOO_SMALL;
+ if (data) data[pos] = ext->data[0];
+ pos++;
+ }
+ } else {
+ opus_int32 length_bytes;
+ if (ext->len < 0)
+ return OPUS_BAD_ARG;
+ length_bytes = 1 + ext->len/255;
+ if (last)
+ length_bytes = 0;
+ if (len-pos < length_bytes + ext->len)
+ return OPUS_BUFFER_TOO_SMALL;
+ if (!last)
+ {
+ opus_int32 j;
+ for (j=0;j<ext->len/255;j++) {
+ if (data) data[pos] = 255;
+ pos++;
+ }
+ if (data) data[pos] = ext->len % 255;
+ pos++;
+ }
+ if (data) OPUS_COPY(&data[pos], ext->data, ext->len);
+ pos += ext->len;
+ }
+ return pos;
+}
+
+static int write_extension(unsigned char *data, opus_int32 len, opus_int32 pos,
+ const opus_extension_data *ext, int last) {
+ if (len-pos < 1)
+ return OPUS_BUFFER_TOO_SMALL;
+ celt_assert(ext->id >= 3 && ext->id <= 127);
+ if (data) data[pos] = (ext->id<<1) + (ext->id < 32 ? ext->len : !last);
+ pos++;
+ return write_extension_payload(data, len, pos, ext, last);
+}
+
+opus_int32 opus_packet_extensions_generate(unsigned char *data, opus_int32 len,
+ const opus_extension_data *extensions, opus_int32 nb_extensions,
+ int nb_frames, int pad)
+{
+ opus_int32 frame_min_idx[48];
+ opus_int32 frame_max_idx[48];
+ opus_int32 frame_repeat_idx[48];
+ opus_int32 i;
+ int f;
+ int curr_frame = 0;
+ opus_int32 pos = 0;
+ opus_int32 written = 0;
+
+ celt_assert(len >= 0);
+ if (nb_frames > 48) return OPUS_BAD_ARG;
+
+ /* Do a little work up-front to make this O(nb_extensions) instead of
+ O(nb_extensions*nb_frames) so long as the extensions are in frame
+ order (without requiring that they be in frame order). */
+ for (f=0;f<nb_frames;f++) frame_min_idx[f] = nb_extensions;
+ OPUS_CLEAR(frame_max_idx, nb_frames);
+ for (i=0;i<nb_extensions;i++)
+ {
+ f = extensions[i].frame;
+ if (f < 0 || f >= nb_frames) return OPUS_BAD_ARG;
+ if (extensions[i].id < 3 || extensions[i].id > 127) return OPUS_BAD_ARG;
+ frame_min_idx[f] = IMIN(frame_min_idx[f], i);
+ frame_max_idx[f] = IMAX(frame_max_idx[f], i+1);
+ }
+ for (f=0;f<nb_frames;f++) frame_repeat_idx[f] = frame_min_idx[f];
+ for (f=0;f<nb_frames;f++)
+ {
+ opus_int32 last_long_idx;
+ int repeat_count;
+ repeat_count = 0;
+ last_long_idx = -1;
+ if (f + 1 < nb_frames)
+ {
+ for (i=frame_min_idx[f];i<frame_max_idx[f];i++)
+ {
+ if (extensions[i].frame == f)
+ {
+ int g;
+ /* Test if we can repeat this extension in future frames. */
+ for (g=f+1;g<nb_frames;g++)
+ {
+ if (frame_repeat_idx[g] >= frame_max_idx[g]) break;
+ celt_assert(extensions[frame_repeat_idx[g]].frame == g);
+ if (extensions[frame_repeat_idx[g]].id != extensions[i].id)
+ {
+ break;
+ }
+ if (extensions[frame_repeat_idx[g]].id < 32
+ && extensions[frame_repeat_idx[g]].len
+ != extensions[i].len)
+ {
+ break;
+ }
+ }
+ if (g < nb_frames) break;
+ /* We can! */
+ /* If this is a long extension, save the index of the last
+ instance, so we can modify its L flag. */
+ if (extensions[i].id >= 32) {
+ last_long_idx = frame_repeat_idx[nb_frames-1];
+ }
+ /* Using the repeat mechanism almost always makes the
+ encoding smaller (or at least no larger).
+ However, there's one case where that might not be true: if
+ the last repeated long extension in the last frame was
+ previously the last extension, but using the repeat
+ mechanism makes that no longer true (because there are other
+ non-repeated extensions in earlier frames that must now be
+ coded after it), and coding its length requires more bytes
+ than the repeat mechanism saves.
+ This can only be true if its length is at least 255 bytes
+ (although sometimes it requires even more).
+ Currently we do not check for that, and just always use the
+ repeat mechanism if we can.
+ See git history for code that does the check. */
+ /* Advance the repeat pointers. */
+ for (g=f+1; g<nb_frames; g++)
+ {
+ int j;
+ for (j=frame_repeat_idx[g]+1; j<frame_max_idx[g]
+ && extensions[j].frame != g; j++);
+ frame_repeat_idx[g] = j;
+ }
+ repeat_count++;
+ /* Point the repeat pointer for this frame to the current
+ extension, so we know when to trigger the repeats. */
+ frame_repeat_idx[f] = i;
+ }
+ }
+ }
+ for (i=frame_min_idx[f];i<frame_max_idx[f];i++)
+ {
+ if (extensions[i].frame == f)
+ {
+ /* Insert separator when needed. */
+ if (f != curr_frame) {
+ int diff = f - curr_frame;
+ if (len-pos < 2)
+ return OPUS_BUFFER_TOO_SMALL;
+ if (diff == 1) {
+ if (data) data[pos] = 0x02;
+ pos++;
+ } else {
+ if (data) data[pos] = 0x03;
+ pos++;
+ if (data) data[pos] = diff;
+ pos++;
+ }
+ curr_frame = f;
+ }
+
+ pos = write_extension(data, len, pos, extensions + i,
+ written == nb_extensions - 1);
+ if (pos < 0) return pos;
+ written++;
+
+ if (repeat_count > 0 && frame_repeat_idx[f] == i) {
+ int nb_repeated;
+ int last;
+ int g;
+ /* Add the repeat indicator. */
+ nb_repeated = repeat_count*(nb_frames - (f + 1));
+ last = written + nb_repeated == nb_extensions
+ || (last_long_idx < 0 && i+1 >= frame_max_idx[f]);
+ if (len-pos < 1)
+ return OPUS_BUFFER_TOO_SMALL;
+ if (data) data[pos] = 0x04 + !last;
+ pos++;
+ for (g=f+1;g<nb_frames;g++)
+ {
+ int j;
+ for (j=frame_min_idx[g];j<frame_repeat_idx[g];j++)
+ {
+ if (extensions[j].frame == g)
+ {
+ pos = write_extension_payload(data, len, pos,
+ extensions + j, last && j == last_long_idx);
+ if (pos < 0) return pos;
+ written++;
+ }
+ }
+ frame_min_idx[g] = j;
+ }
+ if (last) curr_frame++;
+ }
+ }
+ }
+ }
+ celt_assert(written == nb_extensions);
+ /* If we need to pad, just prepend 0x01 bytes. Even better would be to fill the
+ end with zeros, but that requires checking that turning the last extension into
+ an L=1 case still fits. */
+ if (pad && pos < len)
+ {
+ opus_int32 padding = len - pos;
+ if (data) {
+ OPUS_MOVE(data+padding, data, pos);
+ for (i=0;i<padding;i++)
+ data[i] = 0x01;
+ }
+ pos += padding;
+ }
+ return pos;
+}
+
+#if 0
+#include <stdio.h>
+int main()
+{
+ opus_extension_data ext[] = {{2, 0, (const unsigned char *)"a", 1},
+ {32, 10, (const unsigned char *)"DRED", 4},
+ {33, 1, (const unsigned char *)"NOT DRED", 8},
+ {3, 4, (const unsigned char *)NULL, 0}
+ };
+ opus_extension_data ext2[10];
+ int i, len;
+ int nb_ext = 10;
+ unsigned char packet[10000];
+ len = opus_packet_extensions_generate(packet, 32, ext, 4, 1);
+ for (i=0;i<len;i++)
+ {
+ printf("%#04x ", packet[i]);
+ if (i%16 == 15)
+ printf("\n");
+ }
+ printf("\n");
+ printf("count = %d\n", opus_packet_extensions_count(packet, len));
+ opus_packet_extensions_parse(packet, len, ext2, &nb_ext);
+ for (i=0;i<nb_ext;i++)
+ {
+ int j;
+ printf("%d %d {", ext2[i].id, ext2[i].frame);
+ for (j=0;j<ext2[i].len;j++) printf("%#04x ", ext2[i].data[j]);
+ printf("} %d\n", ext2[i].len);
+ }
+}
+#endif
--- /dev/null
+/* Copyright (c) 2017 Google Inc.
+ Written by Andrew Allen */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arch.h"
+#include "float_cast.h"
+#include "opus_private.h"
+#include "opus_defines.h"
+#include "mapping_matrix.h"
+
+#define MATRIX_INDEX(nb_rows, row, col) (nb_rows * col + row)
+
+opus_int32 mapping_matrix_get_size(int rows, int cols)
+{
+ opus_int32 size;
+
+ /* Mapping Matrix must only support up to 255 channels in or out.
+ * Additionally, the total cell count must be <= 65004 octets in order
+ * for the matrix to be stored in an OGG header.
+ */
+ if (rows > 255 || cols > 255)
+ return 0;
+ size = rows * (opus_int32)cols * sizeof(opus_int16);
+ if (size > 65004)
+ return 0;
+
+ return align(sizeof(MappingMatrix)) + align(size);
+}
+
+opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix)
+{
+ /* void* cast avoids clang -Wcast-align warning */
+ return (opus_int16*)(void*)((char*)matrix + align(sizeof(MappingMatrix)));
+}
+
+void mapping_matrix_init(MappingMatrix * const matrix,
+ int rows, int cols, int gain, const opus_int16 *data, opus_int32 data_size)
+{
+ int i;
+ opus_int16 *ptr;
+
+#if !defined(ENABLE_ASSERTIONS)
+ (void)data_size;
+#endif
+ celt_assert(align(data_size) == align(rows * cols * sizeof(opus_int16)));
+
+ matrix->rows = rows;
+ matrix->cols = cols;
+ matrix->gain = gain;
+ ptr = mapping_matrix_get_data(matrix);
+ for (i = 0; i < rows * cols; i++)
+ {
+ ptr[i] = data[i];
+ }
+}
+
+#ifndef DISABLE_FLOAT_API
+void mapping_matrix_multiply_channel_in_float(
+ const MappingMatrix *matrix,
+ const float *input,
+ int input_rows,
+ opus_res *output,
+ int output_row,
+ int output_rows,
+ int frame_size)
+{
+ /* Matrix data is ordered col-wise. */
+ opus_int16* matrix_data;
+ int i, col;
+
+ celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+ matrix_data = mapping_matrix_get_data(matrix);
+
+ for (i = 0; i < frame_size; i++)
+ {
+ float tmp = 0;
+ for (col = 0; col < input_rows; col++)
+ {
+ tmp +=
+ matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+ input[MATRIX_INDEX(input_rows, col, i)];
+ }
+ output[output_rows * i] = FLOAT2RES((1/32768.f)*tmp);
+ }
+}
+
+void mapping_matrix_multiply_channel_out_float(
+ const MappingMatrix *matrix,
+ const opus_res *input,
+ int input_row,
+ int input_rows,
+ float *output,
+ int output_rows,
+ int frame_size
+)
+{
+ /* Matrix data is ordered col-wise. */
+ opus_int16* matrix_data;
+ int i, row;
+ float input_sample;
+
+ celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+ matrix_data = mapping_matrix_get_data(matrix);
+
+ for (i = 0; i < frame_size; i++)
+ {
+ input_sample = RES2FLOAT(input[input_rows * i]);
+ for (row = 0; row < output_rows; row++)
+ {
+ float tmp =
+ (1/32768.f)*matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
+ input_sample;
+ output[MATRIX_INDEX(output_rows, row, i)] += tmp;
+ }
+ }
+}
+#endif /* DISABLE_FLOAT_API */
+
+void mapping_matrix_multiply_channel_in_short(
+ const MappingMatrix *matrix,
+ const opus_int16 *input,
+ int input_rows,
+ opus_res *output,
+ int output_row,
+ int output_rows,
+ int frame_size)
+{
+ /* Matrix data is ordered col-wise. */
+ opus_int16* matrix_data;
+ int i, col;
+
+ celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+ matrix_data = mapping_matrix_get_data(matrix);
+
+ for (i = 0; i < frame_size; i++)
+ {
+ opus_val32 tmp = 0;
+ for (col = 0; col < input_rows; col++)
+ {
+#if defined(FIXED_POINT)
+ tmp +=
+ ((opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+ (opus_int32)input[MATRIX_INDEX(input_rows, col, i)]) >> 8;
+#else
+ tmp +=
+ matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+ input[MATRIX_INDEX(input_rows, col, i)];
+#endif
+ }
+#if defined(FIXED_POINT)
+#ifdef ENABLE_RES24
+ output[output_rows * i] = SHL32(tmp, RES_SHIFT-7);
+#else
+ output[output_rows * i] = SATURATE16((tmp + 64) >> 7);
+#endif
+#else
+ output[output_rows * i] = (1/(32768.f*32768.f))*tmp;
+#endif
+ }
+}
+
+void mapping_matrix_multiply_channel_out_short(
+ const MappingMatrix *matrix,
+ const opus_res *input,
+ int input_row,
+ int input_rows,
+ opus_int16 *output,
+ int output_rows,
+ int frame_size)
+{
+ /* Matrix data is ordered col-wise. */
+ opus_int16* matrix_data;
+ int i, row;
+ opus_int32 input_sample;
+
+ celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+ matrix_data = mapping_matrix_get_data(matrix);
+
+ for (i = 0; i < frame_size; i++)
+ {
+ input_sample = RES2INT16(input[input_rows * i]);
+ for (row = 0; row < output_rows; row++)
+ {
+ opus_int32 tmp =
+ (opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
+ input_sample;
+ output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
+ }
+ }
+}
+
+void mapping_matrix_multiply_channel_in_int24(
+ const MappingMatrix *matrix,
+ const opus_int32 *input,
+ int input_rows,
+ opus_res *output,
+ int output_row,
+ int output_rows,
+ int frame_size)
+{
+ /* Matrix data is ordered col-wise. */
+ opus_int16* matrix_data;
+ int i, col;
+
+ celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+ matrix_data = mapping_matrix_get_data(matrix);
+
+ for (i = 0; i < frame_size; i++)
+ {
+ opus_val64 tmp = 0;
+ for (col = 0; col < input_rows; col++)
+ {
+ tmp +=
+ matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+ (opus_val64)input[MATRIX_INDEX(input_rows, col, i)];
+ }
+#if defined(FIXED_POINT)
+ output[output_rows * i] = INT24TORES((tmp + 16384) >> 15);
+#else
+ output[output_rows * i] = INT24TORES((1/(32768.f))*tmp);
+#endif
+ }
+}
+
+void mapping_matrix_multiply_channel_out_int24(
+ const MappingMatrix *matrix,
+ const opus_res *input,
+ int input_row,
+ int input_rows,
+ opus_int32 *output,
+ int output_rows,
+ int frame_size)
+{
+ /* Matrix data is ordered col-wise. */
+ opus_int16* matrix_data;
+ int i, row;
+ opus_int32 input_sample;
+
+ celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+ matrix_data = mapping_matrix_get_data(matrix);
+
+ for (i = 0; i < frame_size; i++)
+ {
+ input_sample = RES2INT24(input[input_rows * i]);
+ for (row = 0; row < output_rows; row++)
+ {
+ opus_int64 tmp =
+ (opus_int64)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
+ input_sample;
+ output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
+ }
+ }
+}
+
+
+const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 };
+const opus_int16 mapping_matrix_foa_mixing_data[36] = {
+ 16384, 0, -16384, 23170, 0, 0, 16384, 23170,
+ 16384, 0, 0, 0, 16384, 0, -16384, -23170,
+ 0, 0, 16384, -23170, 16384, 0, 0, 0,
+ 0, 0, 0, 0, 32767, 0, 0, 0,
+ 0, 0, 0, 32767
+};
+
+const MappingMatrix mapping_matrix_soa_mixing = { 11, 11, 0 };
+const opus_int16 mapping_matrix_soa_mixing_data[121] = {
+ 10923, 7723, 13377, -13377, 11585, 9459, 7723, -16384,
+ -6689, 0, 0, 10923, 7723, 13377, 13377, -11585,
+ 9459, 7723, 16384, -6689, 0, 0, 10923, -15447,
+ 13377, 0, 0, -18919, 7723, 0, 13377, 0,
+ 0, 10923, 7723, -13377, -13377, 11585, -9459, 7723,
+ 16384, -6689, 0, 0, 10923, -7723, 0, 13377,
+ -16384, 0, -15447, 0, 9459, 0, 0, 10923,
+ -7723, 0, -13377, 16384, 0, -15447, 0, 9459,
+ 0, 0, 10923, 15447, 0, 0, 0, 0,
+ -15447, 0, -18919, 0, 0, 10923, 7723, -13377,
+ 13377, -11585, -9459, 7723, -16384, -6689, 0, 0,
+ 10923, -15447, -13377, 0, 0, 18919, 7723, 0,
+ 13377, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 32767, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 32767
+};
+
+const MappingMatrix mapping_matrix_toa_mixing = { 18, 18, 0 };
+const opus_int16 mapping_matrix_toa_mixing_data[324] = {
+ 8208, 0, -881, 14369, 0, 0, -8192, -4163,
+ 13218, 0, 0, 0, 11095, -8836, -6218, 14833,
+ 0, 0, 8208, -10161, 881, 10161, -13218, -2944,
+ -8192, 2944, 0, -10488, -6218, 6248, -11095, -6248,
+ 0, -10488, 0, 0, 8208, 10161, 881, -10161,
+ -13218, 2944, -8192, -2944, 0, 10488, -6218, -6248,
+ -11095, 6248, 0, 10488, 0, 0, 8176, 5566,
+ -11552, 5566, 9681, -11205, 8192, -11205, 0, 4920,
+ -15158, 9756, -3334, 9756, 0, -4920, 0, 0,
+ 8176, 7871, 11552, 0, 0, 15846, 8192, 0,
+ -9681, -6958, 0, 13797, 3334, 0, -15158, 0,
+ 0, 0, 8176, 0, 11552, 7871, 0, 0,
+ 8192, 15846, 9681, 0, 0, 0, 3334, 13797,
+ 15158, 6958, 0, 0, 8176, 5566, -11552, -5566,
+ -9681, -11205, 8192, 11205, 0, 4920, 15158, 9756,
+ -3334, -9756, 0, 4920, 0, 0, 8208, 14369,
+ -881, 0, 0, -4163, -8192, 0, -13218, -14833,
+ 0, -8836, 11095, 0, 6218, 0, 0, 0,
+ 8208, 10161, 881, 10161, 13218, 2944, -8192, 2944,
+ 0, 10488, 6218, -6248, -11095, -6248, 0, -10488,
+ 0, 0, 8208, -14369, -881, 0, 0, 4163,
+ -8192, 0, -13218, 14833, 0, 8836, 11095, 0,
+ 6218, 0, 0, 0, 8208, 0, -881, -14369,
+ 0, 0, -8192, 4163, 13218, 0, 0, 0,
+ 11095, 8836, -6218, -14833, 0, 0, 8176, -5566,
+ -11552, 5566, -9681, 11205, 8192, -11205, 0, -4920,
+ 15158, -9756, -3334, 9756, 0, -4920, 0, 0,
+ 8176, 0, 11552, -7871, 0, 0, 8192, -15846,
+ 9681, 0, 0, 0, 3334, -13797, 15158, -6958,
+ 0, 0, 8176, -7871, 11552, 0, 0, -15846,
+ 8192, 0, -9681, 6958, 0, -13797, 3334, 0,
+ -15158, 0, 0, 0, 8176, -5566, -11552, -5566,
+ 9681, 11205, 8192, 11205, 0, -4920, -15158, -9756,
+ -3334, -9756, 0, 4920, 0, 0, 8208, -10161,
+ 881, -10161, 13218, -2944, -8192, -2944, 0, -10488,
+ 6218, 6248, -11095, 6248, 0, 10488, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 32767, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 32767
+};
+
+const MappingMatrix mapping_matrix_fourthoa_mixing = { 27, 27, 0 };
+const opus_int16 mapping_matrix_fourthoa_mixing_data[729] = {
+ 9243, 0, 16010, 0, 0, 0, 20669, 0,
+ 0, 0, 0, 0, 24456, 0, 0, 0,
+ 0, 0, 0, 0, 27731, 0, 0, 0,
+ 0, 0, 0, 9243, 0, 10884, 11741, 0,
+ 0, 3995, 17849, 9626, 0, 0, 0, -5727,
+ 14399, 17315, 7625, 0, 0, 0, 0, -11747,
+ 2574, 18637, 15552, 5930, 0, 0, 9243, -14302,
+ -2682, -6677, 13337, 5357, -9464, 2501, -11170, 4770,
+ -5911, 11501, 5858, 5369, 4951, 17901, -19071, -2397,
+ -9281, -9198, 7576, -4294, 7773, -8997, -3399, 0,
+ 0, 9243, 9940, 11991, -3705, -5144, 16647, 7057,
+ -6206, -5941, -2698, -10194, 16781, -1788, -6256, -11772,
+ 4935, 3912, -6062, -13039, 9446, -9758, -3521, -15058,
+ 11089, 565, 0, 0, 9243, -15376, 3720, 2461,
+ -5285, -7989, -8660, 1278, -16087, 15811, -3249, 10500,
+ -7757, -1680, -9890, -8153, 10884, 11022, 2847, 12828,
+ 5137, -2053, 8666, -5684, 14776, 0, 0, 9243,
+ -10577, 10304, -6186, 9139, -15222, 2507, -8902, -5140,
+ -145, 15562, -10596, -7311, -6197, -8753, 8667, -6014,
+ -281, 15033, 938, -11859, 548, -8456, 16735, -3654,
+ 0, 0, 9243, 8974, 4839, -12343, -15472, 6066,
+ -7501, -8343, 5015, 15920, -12374, -4559, -9400, 6271,
+ 4011, 5191, -9932, 14438, 4828, -8768, 1909, 12059,
+ -1565, 4707, -13711, 0, 0, 9243, 15799, 2085,
+ -1534, -3386, 4602, -9808, -447, -17267, -18054, -1167,
+ -13525, -4644, 1313, -5951, 5397, 7485, -7056, 2584,
+ -8120, 8669, 788, 13177, 2109, 18349, 0, 0,
+ 9243, 12371, -10036, 1597, 2760, -17341, 1848, -2239,
+ -10509, -8474, -4577, 11164, 7935, 1441, 17430, -3436,
+ -3713, 15936, 4184, 2647, -11730, 341, -15934, 6462,
+ 6581, 0, 0, 9243, -8963, 2184, 13084, -16381,
+ -2734, -9757, 3991, 6345, -18297, -5912, 7604, -4849,
+ -11100, 2290, -4304, -13305, -7488, 12338, 4805, 8505,
+ -7014, -4779, -1761, -14597, 0, 0, 9243, 1301,
+ -15498, 3799, 690, -2816, 18718, -8223, 889, 255,
+ -1768, 4485, -19951, 13097, -2278, 167, 78, -740,
+ 3324, -6139, 19488, -17925, 4283, -486, 20, 0,
+ 0, 9243, -13470, -6719, 5452, -10257, 12641, -4873,
+ -5116, -10595, 5856, 11389, 1502, 10876, -608, 11765,
+ -13218, 13911, -7373, -2070, -13679, -4154, 5536, -2138,
+ 16643, 451, 0, 0, 9243, 2455, -3679, -15387,
+ -5277, -1261, -8697, 7906, 16112, 8147, 3208, -1690,
+ 7687, 10593, -9796, -15852, -10884, -5616, 2881, 2032,
+ 5246, -12735, -8796, 10928, 14833, 0, 0, 9243,
+ -6849, 2775, -14202, 13586, -2655, -9402, -5505, 10809,
+ -18013, 6231, 5444, -6041, 11288, 4958, -4078, 18799,
+ -9368, -9291, 4535, 7383, 9405, -7391, -2121, -4336,
+ 0, 0, 9243, 6423, -9040, 11548, 10359, -8109,
+ -450, -14580, 6431, 10857, -15475, 3569, 9707, 6416,
+ -9607, 521, 8528, -18391, 11049, 3815, -10423, 6860,
+ 6860, -883, -4221, 0, 0, 9243, 11932, -5968,
+ -8850, -14749, -9946, -6026, 7377, -4472, 5206, 14547,
+ -3406, 10508, 2526, 4411, 14543, 8444, -5822, 347,
+ 12347, -1709, -9158, 105, -16265, -12642, 0, 0,
+ 9243, 13044, -150, 9282, 16910, -274, -10332, -194,
+ -5864, 5428, -420, -12196, 344, -8679, 145, -18554,
+ -12695, -152, -14635, 503, 10389, 358, 5076, 522,
+ -16100, 0, 0, 9243, -8374, -13590, -1221, 1428,
+ 15896, 12005, 2318, -4793, 2590, -3209, -20390, -6256,
+ -2974, 10766, 1202, -876, -6597, 5004, 19896, -1541,
+ 2902, -16788, -3062, 1340, 0, 0, 9243, 9879,
+ 10267, 7300, 10073, 14167, 2416, 10469, -3094, 2899,
+ 17092, 9762, -7400, 7214, -5250, -8238, -3989, 5578,
+ 16392, -1050, -11848, -776, -5034, -15850, -5882, 0,
+ 0, 9243, -4974, -9068, 12221, -8490, 6299, -388,
+ -15478, 8702, -9920, 12723, -2810, 9668, 6905, -13040,
+ 4325, -9456, 16856, -9159, -2909, -10476, 7149, 9387,
+ -7350, 233, 0, 0, 9243, 3627, -13823, -7218,
+ -3656, -7002, 12776, 13935, 2719, 2446, 8352, 9252,
+ -7676, -18413, -6212, -429, -1272, -6335, -13356, -9510,
+ 295, 18926, 9934, 1112, -382, 0, 0, 9243,
+ -6383, -9343, -11326, 10097, 8329, 223, 14780, 6114,
+ -10348, -15590, -4195, 9257, -7445, -9439, -323, 7902,
+ 18117, 12101, -3142, -10944, -5577, 7327, 566, -4133,
+ 0, 0, 9243, 2626, 865, 15769, 5783, 317,
+ -10244, 1905, 16884, 9144, 826, -2420, -1972, -14536,
+ 2413, 16939, 12500, 1482, -4906, -578, 10096, -3476,
+ -14323, 2745, 16105, 0, 0, 9243, -8975, 12086,
+ 5450, -6832, -15149, 7333, 9200, -3550, -362, -13645,
+ -15525, -1391, 9428, -7091, -5442, 3105, -820, -17685,
+ -9175, -9462, 5572, -9191, -12325, -2180, 0, 0,
+ 9243, -114, 11576, -11058, 177, -185, 5875, -17880,
+ 8539, -198, 339, -173, -3411, -16698, 16336, -6369,
+ 193, -430, 408, -75, -10806, -7225, 19670, -13817,
+ 4665, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 32767, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 32767
+};
+
+const MappingMatrix mapping_matrix_fifthoa_mixing = { 38, 38, 0 };
+const opus_int16 mapping_matrix_fifthoa_mixing_data[1444] = {
+ 9243, 0, 16010, 0, 0, 0, 20669, 0,
+ 0, 0, 0, 0, 24456, 0, 0, 0,
+ 0, 0, 0, 0, 27731, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 30657, 0,
+ 0, 0, 0, 0, 0, 0, 9243, 0,
+ -7023, 14387, 0, 0, -4369, -14112, 14455, 0,
+ 0, 0, 10931, -510, -16777, 14031, 0, 0,
+ 0, 0, -5118, 14286, 4343, -18465, 13374, 0,
+ 0, 0, 0, 0, -6494, -12221, 11761, 8513,
+ -19458, 12605, 0, 0, 9243, -14128, 5093, 5547,
+ -10946, -10050, -7197, 3945, -11790, 7142, -9213, 6529,
+ -9701, -2563, -9923, -14846, 16521, 6816, 2764, 14103,
+ 1118, -5537, 2977, -14168, 1228, 4866, 17430, -528,
+ 10639, 2641, 10437, -1037, 11460, 1098, 1296, 15737,
+ 0, 0, 9243, 1128, -14775, 6062, 955, -2329,
+ 16069, -12511, 2477, 579, -2333, 3440, -14197, 18478,
+ -6050, 940, 303, -1604, 4106, -4223, 9829, -22688,
+ 10647, -2604, 334, 145, -927, 3203, -6017, 4507,
+ -3812, 24212, -15600, 5198, -1023, 110, 0, 0,
+ 9243, 1158, 12997, 9277, 1501, 2103, 10097, 16840,
+ 5916, 1402, 3225, 2488, 2929, 19916, 12706, 3585,
+ 1137, 3415, 4698, 2078, -5442, 16634, 18511, 8731,
+ 2095, 850, 3061, 5733, 5225, 960, -11728, 7689,
+ 20588, 14659, 5642, 1187, 0, 0, 9243, -4663,
+ -3081, -15003, 9771, 2007, -9185, 6457, 14199, -14357,
+ -4976, 3554, 6625, 11434, -7231, -11297, 17760, 8291,
+ -6267, -3368, 6712, -10837, -9107, 6524, 6793, -19531,
+ -11338, 7934, 7335, -2205, -9215, -7094, 10659, 6243,
+ -4337, -1250, 0, 0, 9243, -13515, 7679, -3831,
+ 7232, -14496, -3201, -4109, -11731, 8828, 9178, -1901,
+ -10848, -539, -14888, 9626, -10860, 12703, 3824, 12334,
+ -7104, 3496, -6203, 13852, 5461, -2109, -17277, 7837,
+ -4714, 13901, 4097, 3940, 7647, 8546, 8688, -10986,
+ 0, 0, 9243, 8113, -9860, 9657, 10943, -11174,
+ 1426, -13300, 1915, 8178, -17833, 6805, 8309, 8100,
+ -3121, -4742, 2683, -15111, 15688, 2358, -11590, 2807,
+ 2746, 8762, -7430, -2251, -5481, 16370, -4081, -9694,
+ 5872, -11539, -714, -9492, 15177, -6126, 0, 0,
+ 9243, 9933, -9215, -8528, -11831, -12785, -62, 10976,
+ -1811, 5593, 18018, 6100, 9455, -5237, 2758, 8971,
+ 2743, -9659, -13517, 5330, -10737, -4576, -2069, -15491,
+ -8749, -7226, -5237, 9191, -181, -12277, 2815, 10540,
+ -27, 14741, 16703, 3103, 0, 0, 9243, -10067,
+ -8881, -8723, 12265, 12487, -793, 10821, -1762, -6021,
+ -18002, -5072, 9912, -4395, 2587, 9368, -2767, 10021,
+ 12259, -6468, -10113, -5605, -1761, -15590, -9430, 7800,
+ 5092, -8835, 2293, 12314, 1222, 10671, -329, 13745,
+ 17349, 3563, 0, 0, 9243, -6485, 12991, -6743,
+ 6108, -11768, 10080, -12236, 238, -2883, 13115, -13907,
+ 2900, -14460, 511, 2564, 186, -7019, 19094, -11597,
+ -5472, -12058, 744, 6243, -2384, 930, 501, -11778,
+ 21214, -5330, -11746, -5542, 827, 10475, -6418, 1132,
+ 0, 0, 9243, 3862, 5238, -14627, -7891, 2826,
+ -7015, -10701, 13900, 11410, -6831, -1679, -9861, 6359,
+ 12032, -11660, -14041, 11199, 1713, -3895, 657, 14749,
+ -3017, -11445, 8380, 15575, -15236, -346, 7690, -923,
+ 10317, 3498, -13545, 354, 9093, -4476, 0, 0,
+ 9243, -8417, 13183, 3418, -4018, -15498, 10685, 6294,
+ -4132, 1419, -8755, -18818, 3926, 7642, -9001, -3235,
+ 2125, 3506, -13037, -16570, -4337, 6729, -13404, -7991,
+ 59, 443, 5804, 6005, -15011, -9060, -11044, 3679,
+ -15434, -13685, 161, 1185, 0, 0, 9243, -5288,
+ 6773, -13508, 9977, -5002, -4784, -12780, 10790, -12942,
+ 11168, 519, -10890, 1326, 12078, -6274, 13780, -16427,
+ 2186, 5352, -4328, 13671, 2364, -7963, 1080, -12568,
+ 19336, -6557, -8574, 4084, 7277, 10433, -9273, -3178,
+ 1516, 3817, 0, 0, 9243, 9660, 7817, 10093,
+ 13619, 10548, -2942, 11021, 597, 9663, 17594, 1736,
+ -10794, 1814, 771, -8469, 1041, 14155, 7891, -8597,
+ -7498, -8982, 346, -12407, -11848, -6809, 1686, 9181,
+ -8306, -10247, 3538, -10706, -364, -8047, -19188, -8493,
+ 0, 0, 9243, -7163, -1020, 14282, -14289, 1021,
+ -10208, -2036, 10660, -18919, 2410, 6564, 2323, -13088,
+ -1798, 3365, -19498, 3619, 12022, -1858, 9978, 3705,
+ -8969, -643, -5794, -15523, 4123, 15113, -3949, -6265,
+ -3596, 12490, 2946, -2688, 1225, -14570, 0, 0,
+ 9243, -12187, 772, -10354, 17623, -1314, -10262, -1117,
+ -2885, -9937, 2249, 11267, -1763, 9572, -368, 16506,
+ -6510, -1438, -15014, 2402, 10157, 2041, 2458, 2389,
+ -19346, 19860, -1041, 8067, -3704, -10931, 2743, -9286,
+ 606, -13399, -3095, 7924, 0, 0, 9243, 15545,
+ -2367, -3011, -6538, -5139, -9657, 995, -16242, -15706,
+ 2557, -12952, 5226, 2508, 6353, 10156, 13593, 6966,
+ 4795, 8960, 8183, -1735, 11914, -4504, 14149, 11727,
+ -6665, 10460, -3962, 10145, -7648, -1965, -9845, -6764,
+ -6938, -16633, 0, 0, 9243, 3098, 12983, -8841,
+ -3826, 5618, 10053, -16031, 4787, 3283, -8209, 6632,
+ 2856, -18922, 10272, -2055, -2344, 7987, -11939, 5516,
+ -5520, -15739, 14940, -5001, 530, 1465, -6306, 13388,
+ -13243, 2513, -11772, -7170, 16572, -8384, 1426, 168,
+ 0, 0, 9243, -15767, -2008, -1916, 4220, 4422,
+ -9846, 537, -17105, 17650, -1400, 13589, 4481, 1651,
+ 5677, 6701, -9241, -6642, -3252, -7827, 8792, -951,
+ 13182, -2522, 17586, -17005, 3845, -12562, 2213, -11472,
+ -6688, -1394, -8970, -4769, -7316, -11753, 0, 0,
+ 9243, -13344, -3829, 7975, -14863, 7136, -8561, -4265,
+ -7992, -801, 9405, 8912, 7937, -5326, 5057, -17681,
+ 15207, 575, 7717, -11360, 4847, 6789, 4150, 12686,
+ -10050, 16730, -12063, 322, -12920, -3313, -10267, 1980,
+ -6948, 7112, 7972, 8042, 0, 0, 9243, 7791,
+ -1021, 13949, 15180, -1111, -10208, -1989, 9348, 19199,
+ -2561, -7140, 2323, -12782, -1577, 817, 18164, -3673,
+ -12771, 2022, 9978, 3620, -7865, -156, -9155, 11924,
+ -3842, -15336, 4196, 6814, -3596, 12199, 2583, -652,
+ 1936, -17637, 0, 0, 9243, -4810, -15144, -1958,
+ 1315, 10175, 17406, 4142, -1348, 263, -3292, -15632,
+ -17046, -6363, 3374, 605, -227, -748, 5997, 20334,
+ 14481, 8277, -6146, -1717, 5, 27, 712, 1542,
+ -9197, -23572, -10163, -9595, 9425, 3539, -17, -72,
+ 0, 0, 9243, -7366, 8261, 11568, -11901, -8499,
+ -2079, 13347, 5556, -12049, -16247, -2282, -10529, 3584,
+ 7585, -1577, -8464, -18652, -8902, 5913, -8688, -9287,
+ 4156, -2442, -7089, -2993, -14485, -13949, 5422, 8459,
+ 1638, -13285, -2531, -1826, -12132, -9456, 0, 0,
+ 9243, 11716, 698, -10889, -17818, 1143, -10275, -1062,
+ -1305, 12057, -2057, -10855, -1595, 10088, -150, 15043,
+ 2978, 1578, 15225, -2090, 10201, 1943, 1115, 1969,
+ -20211, -17636, 430, -9826, 3391, 10572, 2485, -9826,
+ 248, -12259, -2924, 12131, 0, 0, 9243, 4361,
+ -4594, -14703, -8956, -2798, -7781, 9434, 13769, 12936,
+ 6800, -2400, 9082, 8091, -10453, -11023, -15786, -11136,
+ 3285, 4153, 2658, -14002, -5051, 9489, 7000, 17206,
+ 15024, -2777, -8491, -42, -10626, 141, 13053, 2366,
+ -6662, -2231, 0, 0, 9243, -752, -11933, -10646,
+ 1119, 1254, 6890, 17745, 7875, -1203, -2207, -1251,
+ 2024, -17706, -15532, -5600, 1128, 2691, 2800, 683,
+ -9927, 9661, 19706, 12522, 3889, -978, -2789, -3992,
+ -2440, 206, 12695, 2921, -17173, -18575, -9616, -2657,
+ 0, 0, 9243, 4791, -15001, -2887, -1931, -10037,
+ 16885, 6048, -1020, 46, 4789, 15191, -15922, -9154,
+ 2530, 823, 252, -130, -8608, -19335, 12613, 11651,
+ -4549, -2314, -172, -101, -784, 265, 12975, 21741,
+ -7551, -13101, 6856, 4710, 535, -46, 0, 0,
+ 9243, -12153, -10395, 754, -1281, 17644, 2735, -1095,
+ -10274, 8359, 2200, -12593, 7083, 782, 17650, -1573,
+ 1685, -16282, -2164, -530, -11878, 32, -17359, 3065,
+ 6651, -5212, -3628, 19365, 965, 13180, 8243, -818,
+ 7746, -3645, -14323, 1670, 0, 0, 9243, -6961,
+ -11198, 9081, -8829, 10887, 4833, -14202, 2374, -6524,
+ 16339, -9417, 4737, 12284, -4394, -2691, -2683, 13690,
+ -18539, 2830, -11438, -3692, 4985, 5648, -4628, 514,
+ 6225, -18409, 12672, 5311, 11170, -6928, -3407, -7595,
+ 10737, -3977, 0, 0, 9243, 12099, -10405, 1294,
+ 2187, -17582, 2760, -1880, -10105, -8058, -3760, 12583,
+ 7058, 1346, 17376, -2667, -2829, 15710, 3705, 468,
+ -11880, 50, -17123, 5201, 6230, 4698, 6098, -18716,
+ -1665, -13088, 8285, -1400, 7696, -6196, -13429, 2770,
+ 0, 0, 9243, 8602, 13392, 1722, 2070, 16090,
+ 11359, 3222, -4960, -2638, 4581, 20106, 5099, 4026,
+ -10978, -1778, -1314, -6620, 6988, 18701, -2965, 3745,
+ -16745, -4461, 1300, 584, -3646, -11588, 8350, 11847,
+ -10050, 2372, -20010, -7809, 3608, 887, 0, 0,
+ 9243, 14252, -1958, 7026, 13986, -3899, -9870, -1922,
+ -10736, -3693, -4527, -12333, 4376, -6080, 3475, -18537,
+ -19222, 1355, -10843, 6913, 8869, 3408, 8323, 6804,
+ -5141, -13648, 7800, 2649, 7171, 10505, -6548, 5179,
+ -5505, 13299, 2086, 15579, 0, 0, 9243, 11323,
+ 9021, -6835, -10810, 14267, -489, -8613, -5689, 639,
+ -16117, 6224, -9731, -3757, -8482, 10882, 7873, 1080,
+ -11447, -6791, -10388, 4099, -6025, 18396, -5407, -7536,
+ 14714, 984, 1267, -13940, -1889, 8416, 666, 16762,
+ -10106, -3418, 0, 0, 9243, 871, 4833, 15238,
+ 1855, 588, -7508, 10287, 16162, 2857, 1481, -443,
+ -9392, -7758, 12910, 16506, 3837, 2588, -581, -851,
+ 1928, -14879, -5066, 14950, 16498, 4773, 3842, -425,
+ -1785, -82, 10578, -1435, -15554, -2459, 16520, 16250,
+ 0, 0, 9243, 14762, 5967, 1673, 3450, 12303,
+ -6027, 1394, -15022, -14571, 3402, -4217, -10507, -478,
+ -14813, -5131, -6634, -16293, -82, -15276, -1705, -1731,
+ 358, -5738, 13681, 12503, -8200, -3023, -3290, -7384,
+ 9272, -837, 14328, -1064, 16913, 7915, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 32767, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 32767
+};
+
+const MappingMatrix mapping_matrix_foa_demixing = { 6, 6, 0 };
+const opus_int16 mapping_matrix_foa_demixing_data[36] = {
+ 16384, 16384, 16384, 16384, 0, 0, 0, 23170,
+ 0, -23170, 0, 0, -16384, 16384, -16384, 16384,
+ 0, 0, 23170, 0, -23170, 0, 0, 0,
+ 0, 0, 0, 0, 32767, 0, 0, 0,
+ 0, 0, 0, 32767
+};
+
+const MappingMatrix mapping_matrix_soa_demixing = { 11, 11, 3050 };
+const opus_int16 mapping_matrix_soa_demixing_data[121] = {
+ 2771, 2771, 2771, 2771, 2771, 2771, 2771, 2771,
+ 2771, 0, 0, 10033, 10033, -20066, 10033, 14189,
+ 14189, -28378, 10033, -20066, 0, 0, 3393, 3393,
+ 3393, -3393, 0, 0, 0, -3393, -3393, 0,
+ 0, -17378, 17378, 0, -17378, -24576, 24576, 0,
+ 17378, 0, 0, 0, -14189, 14189, 0, -14189,
+ -28378, 28378, 0, 14189, 0, 0, 0, 2399,
+ 2399, -4799, -2399, 0, 0, 0, -2399, 4799,
+ 0, 0, 1959, 1959, 1959, 1959, -3918, -3918,
+ -3918, 1959, 1959, 0, 0, -4156, 4156, 0,
+ 4156, 0, 0, 0, -4156, 0, 0, 0,
+ 8192, 8192, -16384, 8192, 16384, 16384, -32768, 8192,
+ -16384, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 8312, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 8312
+};
+
+const MappingMatrix mapping_matrix_toa_demixing = { 18, 18, 0 };
+const opus_int16 mapping_matrix_toa_demixing_data[324] = {
+ 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
+ 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
+ 0, 0, 0, -9779, 9779, 6263, 8857, 0,
+ 6263, 13829, 9779, -13829, 0, -6263, 0, -8857,
+ -6263, -9779, 0, 0, -3413, 3413, 3413, -11359,
+ 11359, 11359, -11359, -3413, 3413, -3413, -3413, -11359,
+ 11359, 11359, -11359, 3413, 0, 0, 13829, 9779,
+ -9779, 6263, 0, 8857, -6263, 0, 9779, 0,
+ -13829, 6263, -8857, 0, -6263, -9779, 0, 0,
+ 0, -15617, -15617, 6406, 0, 0, -6406, 0,
+ 15617, 0, 0, -6406, 0, 0, 6406, 15617,
+ 0, 0, 0, -5003, 5003, -10664, 15081, 0,
+ -10664, -7075, 5003, 7075, 0, 10664, 0, -15081,
+ 10664, -5003, 0, 0, -8176, -8176, -8176, 8208,
+ 8208, 8208, 8208, -8176, -8176, -8176, -8176, 8208,
+ 8208, 8208, 8208, -8176, 0, 0, -7075, 5003,
+ -5003, -10664, 0, 15081, 10664, 0, 5003, 0,
+ 7075, -10664, -15081, 0, 10664, -5003, 0, 0,
+ 15617, 0, 0, 0, -6406, 6406, 0, -15617,
+ 0, -15617, 15617, 0, 6406, -6406, 0, 0,
+ 0, 0, 0, -11393, 11393, 2993, -4233, 0,
+ 2993, -16112, 11393, 16112, 0, -2993, 0, 4233,
+ -2993, -11393, 0, 0, 0, -9974, -9974, -13617,
+ 0, 0, 13617, 0, 9974, 0, 0, 13617,
+ 0, 0, -13617, 9974, 0, 0, 0, 5579,
+ -5579, 10185, 14403, 0, 10185, -7890, -5579, 7890,
+ 0, -10185, 0, -14403, -10185, 5579, 0, 0,
+ 11826, -11826, -11826, -901, 901, 901, -901, 11826,
+ -11826, 11826, 11826, -901, 901, 901, -901, -11826,
+ 0, 0, -7890, -5579, 5579, 10185, 0, 14403,
+ -10185, 0, -5579, 0, 7890, 10185, -14403, 0,
+ -10185, 5579, 0, 0, -9974, 0, 0, 0,
+ -13617, 13617, 0, 9974, 0, 9974, -9974, 0,
+ 13617, -13617, 0, 0, 0, 0, 16112, -11393,
+ 11393, -2993, 0, 4233, 2993, 0, -11393, 0,
+ -16112, -2993, -4233, 0, 2993, 11393, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 32767, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 32767
+};
+
+const MappingMatrix mapping_matrix_fourthoa_demixing = { 27, 27, 0 };
+const opus_int16 mapping_matrix_fourthoa_demixing_data[729] = {
+ 4870, 4484, 4870, 4347, 4440, 4726, 4683, 4821,
+ 4883, 4842, 4603, 4484, 4683, 4698, 4234, 4368,
+ 4603, 4783, 4783, 4820, 4821, 4347, 4820, 4440,
+ 4698, 0, 0, 101, 84, -7818, 4640, -7178,
+ -5492, 4629, 8384, 6547, -4966, 617, -6345, 1061,
+ -3241, 2939, 5549, 6390, -4434, 4994, -2610, 1993,
+ -2873, 1547, -4356, -164, 0, 0, 8797, 5074,
+ -1553, 5383, 1906, 5297, 2722, 1158, -5226, 1311,
+ -7760, -3327, -1940, 1586, -4093, -2951, -214, -6873,
+ 5450, -4875, -7193, -4438, 558, 5593, 5607, 0,
+ 0, -26, 5761, -3723, -1460, 1195, -3065, -6357,
+ -1175, 608, 6965, 2310, 2759, -8023, -7138, 5162,
+ -3624, 5006, -809, 3592, 6209, -4159, -4968, 8150,
+ 2513, -5702, 0, 0, 301, 109, 7161, -2462,
+ -2443, 5044, -7125, -2256, 1967, -9107, 259, -4928,
+ -2592, 6514, 4111, -7236, 8695, 635, 5009, -4025,
+ -1937, 4794, 3420, -3507, -400, 0, 0, -134,
+ 85, 2771, 7842, -3649, -8225, 2866, 2586, -9200,
+ -1945, -1563, 6155, -720, -1061, -3494, -4513, -487,
+ 8389, 7317, 3348, -3721, 3806, 371, -6896, 70,
+ 0, 0, 10919, 2072, -4867, 3472, -4429, 1721,
+ -4066, -5193, 1032, -5253, 9501, -2017, -3971, -5261,
+ -306, -2737, -5137, 5713, 1237, -8, 6387, 364,
+ -5423, 3364, 2888, 0, 0, -48, 8946, 1048,
+ -2691, 602, -4332, -4302, -514, -1730, 2459, -4328,
+ -2156, 3335, -2748, -6029, 4023, 155, 897, 5268,
+ -8380, 7625, 7395, 508, 3945, -8951, 0, 0,
+ 39, 4151, -5965, -3398, -7006, -3534, 2697, -8989,
+ -5237, 2913, 46, -5540, 8196, 5766, 2711, -2520,
+ -3043, -2146, -948, 4965, 1806, 2472, 8988, -1266,
+ 4840, 0, 0, -407, -189, 2179, -1627, 6516,
+ 259, 7196, -9449, -4905, -9766, 561, 4021, 3371,
+ -8650, 5032, 3329, 2534, 641, 2224, -5747, 1047,
+ -4074, 5252, -24, 674, 0, 0, 664, 237,
+ -2837, -4072, -1205, 8252, -5875, -1670, -2743, -3984,
+ 381, 5059, 1765, 2666, -8295, 7403, 1154, -2086,
+ 7622, 7105, 3677, -6943, 1050, -6632, -694, 0,
+ 0, 382, -133, 5699, 7650, 5154, -5713, -1645,
+ -6902, 6181, 4450, 1151, 410, -993, 3829, 2444,
+ -2405, -6618, -9514, 5366, -1896, 5844, -2886, -1524,
+ -7321, -1007, 0, 0, 12767, -2530, 3183, -1409,
+ -4015, -2894, -5155, -1710, 3841, -2107, -10274, 5119,
+ 3979, -4010, 5550, 4822, -746, -2507, -3080, 4289,
+ -3675, 4333, -1416, -1230, -1122, 0, 0, 17,
+ 8048, 2398, -2167, -73, -3606, 3125, 398, 731,
+ -5973, 5705, -1032, 4679, 7305, 3134, 1301, -3858,
+ -89, 2938, 4359, -9155, -4805, -8407, 3673, -8645,
+ 0, 0, 187, 7355, 3145, -6719, -4432, -5939,
+ 2541, -2810, 9723, 778, -1105, 5687, -4174, 2534,
+ -4461, 1017, -244, 5481, -1655, -6765, -3350, -4894,
+ 1592, -2318, 8827, 0, 0, 196, 3588, 9631,
+ 3063, -4564, 6043, 2683, 2595, -2488, -2186, 173,
+ -6059, -8270, -2386, 409, 7441, -8608, 376, -4364,
+ 2321, -280, 97, 8331, -3022, -4721, 0, 0,
+ 117, -748, -10833, 1533, 4200, -2875, -997, -109,
+ -3661, -6119, 4454, 8808, -9189, 8294, 1521, 7265,
+ -2348, -5094, -948, -5400, -3193, 8914, 5763, 1716,
+ -1070, 0, 0, 2497, 399, -5201, -2038, 7843,
+ -376, 7567, -5073, 7616, -5537, 2086, -3453, -5544,
+ -56, -11648, -1314, 3546, -3432, -117, 8694, -4245,
+ 9621, 3098, -2582, -2351, 0, 0, 4386, -3104,
+ -3132, -10512, 566, 5217, 5128, 4967, 1348, 7035,
+ -1470, 91, -125, -3548, 8244, -3029, -10033, 2186,
+ 9745, -6440, -2074, 3638, -1477, -7045, -562, 0,
+ 0, 2154, 8116, -6102, 6570, 12998, -712, -4126,
+ -4996, 30, 1571, -6393, -12794, 425, 5036, 1190,
+ 5763, 5653, 12933, -6671, 5197, -2964, -3316, -6354,
+ -10554, -2652, 0, 0, 12618, -3737, 93, -5901,
+ 4262, -3364, 4444, 3103, -2767, 3403, 4925, -2584,
+ -989, 4977, -3714, -1965, 3076, 326, -2946, -2568,
+ 1026, -2980, 3362, -6132, -5966, 0, 0, 6001,
+ 48, -1979, -7275, 3476, -2096, 10591, 3793, 2629,
+ -447, -14747, -3689, -5525, 8358, 6883, -9703, -4556,
+ 7471, 2965, 4056, 13221, -7327, -3073, -2353, -6720,
+ 0, 0, 621, 11034, -44, -2828, 5978, -1850,
+ -1772, 3894, -7471, -1397, 945, -2028, -2928, -2240,
+ 3172, 2222, 4544, -4243, -5645, 3745, 2573, 3511,
+ -8206, -7286, 5700, 0, 0, 321, 10818, -4982,
+ 7813, -749, 9907, 1360, -1443, 568, -1103, 2305,
+ 6045, 2270, -1063, -1920, -3073, 5893, -3476, -11346,
+ -1657, -588, 2957, -2287, -8527, -8041, 0, 0,
+ 119, -268, 2372, -3040, 4979, -3789, -5630, 10619,
+ 5900, -5109, -4585, -3862, 10467, -3527, -385, -10034,
+ -9991, 4860, 984, 2362, 2311, -6804, 6324, 433,
+ 5291, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 32767, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 32767
+};
+
+const MappingMatrix mapping_matrix_fifthoa_demixing = { 38, 38, 0 };
+const opus_int16 mapping_matrix_fifthoa_demixing_data[1444] = {
+ 3188, 3247, 3268, 3368, 3368, 3138, 3268, 3099,
+ 3211, 3368, 3099, 3247, 3211, 3368, 3368, 3368,
+ 3149, 3268, 3247, 3211, 3099, 3188, 3138, 3149,
+ 3099, 3188, 3368, 3149, 3188, 3247, 3268, 3138,
+ 3211, 3368, 3138, 3149, 0, 0, 118, -47,
+ -5011, 282, 333, -1497, -4584, 2908, 3388, -3647,
+ -2493, 1139, -2882, -1719, 3604, -2543, -4328, 5443,
+ 1286, -5498, -4583, 2510, -1743, -2556, 4168, 1446,
+ -290, 1812, -4074, -2377, 4152, 2847, 4991, 3980,
+ 393, 5072, 0, 0, 5489, -2235, 1507, -5326,
+ 4609, -1096, 2926, -3427, -3301, -3078, 4226, 1730,
+ 4627, 2561, 2966, -592, 143, -677, 4617, -755,
+ -956, -433, -5138, 3037, 157, -1394, -4498, -4984,
+ -3661, -4112, -3756, 4628, -570, 3356, 1605, 1803,
+ 0, 0, -162, 5162, 2132, 2392, 3556, -5141,
+ -1536, 2975, -3001, -3350, -2231, -5230, 1294, -4965,
+ 3494, 5230, -3292, -1359, -2945, -773, 2670, 4867,
+ -660, 3720, -3415, -5112, -3700, -1211, 407, 3013,
+ 763, 591, 2481, -2657, 5210, 784, 0, 0,
+ -156, 338, -4246, 510, 462, 3296, 2846, 3333,
+ -4292, 4574, 1940, -2986, -1275, 3701, 5022, -5250,
+ 5780, -2676, -1180, 1516, -4852, 4877, 342, -3923,
+ -5703, -2920, 379, -657, -361, -3346, 1044, 795,
+ 5257, -4004, 698, 1115, 0, 0, 47, -140,
+ -3292, -1097, 652, 855, -5260, -3691, -4470, 4521,
+ -3863, 1093, -5552, -2016, 3831, 334, -456, -1532,
+ 2068, 1788, 2054, -295, 3668, -2820, 328, -994,
+ 295, -3301, 5770, 4282, -6353, 5632, -1371, 5005,
+ 238, 4041, 0, 0, 6764, -1659, -2730, 5726,
+ 3715, -3216, -933, 531, -52, -345, 3022, -2818,
+ 4005, -1617, -1189, -3748, -3403, -3592, 4040, -3553,
+ -2806, -3444, 6023, -711, -3298, -2503, 2548, 5564,
+ 940, 1848, 1207, 4010, -3488, -358, -2511, -1966,
+ 0, 0, -64, -5039, 1403, -4455, 6240, 2189,
+ -1716, -4348, 4183, 3951, -4042, -3606, 2399, -4563,
+ 4050, -612, -395, 348, -5791, 391, -1440, -735,
+ 1398, 4359, -518, 2969, 6556, 1951, -518, -4993,
+ -925, 998, -569, -2934, 3460, 420, 0, 0,
+ 16, 5482, -4122, 770, 2082, 5020, -3961, 485,
+ -584, -793, 3, 5222, -1416, 3673, 78, 3549,
+ -937, -5723, 1673, -6162, -2540, 3082, -355, 1838,
+ -615, 4601, 2832, -359, -3346, 668, -3393, -1583,
+ -3774, -2206, 5754, -4961, 0, 0, -328, 299,
+ 2470, 317, 525, -4494, 2805, 2617, 2383, -2363,
+ -1037, 4085, 895, -4622, 3218, -6607, -3381, -5933,
+ 1397, 6394, -446, 5694, 14, -4510, 4329, 3690,
+ -334, 0, 2932, -2478, -2944, -577, -599, -230,
+ 1553, -4736, 0, 0, -324, 142, -3252, -867,
+ 1111, -1882, 3378, -6055, 6502, -6840, 4280, -2694,
+ -2876, 4190, 6454, 655, 1061, 626, -2669, -798,
+ 3192, -985, -898, -5482, -548, 2315, -558, 1302,
+ 900, 5747, -1325, 1599, -1384, -5749, 624, 1110,
+ 0, 0, 321, 312, 2188, 1322, 237, 708,
+ -304, 2463, 1500, -1094, -5112, -1010, -6799, 646,
+ 992, 1969, 3423, -3996, 2628, 4451, 3432, -2833,
+ -6101, -330, -3768, -3, -707, 5961, -4037, -3736,
+ 4080, 7254, -4113, 2151, 54, -2150, 0, 0,
+ 7735, 4064, -3884, -5240, 577, 2229, -3947, 2914,
+ 3555, 4011, 774, -3519, 1985, -3701, -3824, 330,
+ -905, 2085, 1155, 2176, 3006, 340, -5533, -3264,
+ -902, 3114, 344, -5060, 1524, 1805, 1926, 2350,
+ 1905, -3203, -2762, -4162, 0, 0, 193, -151,
+ -1434, 6289, 7354, 4234, 169, 2868, -1977, -1375,
+ -4987, 2345, 2742, 599, 939, -4837, 2688, 991,
+ -6907, 716, -1542, -4346, -1833, 1493, 3134, 2903,
+ -7019, -2835, 93, 4395, 621, 870, -2357, -975,
+ -2933, -127, 0, 0, -616, -5968, -3479, -1651,
+ 4932, -2445, -5512, -1451, 691, 739, 479, 4227,
+ -2886, 3853, 8, -501, 188, 1990, 3842, 2270,
+ 1662, -174, 1290, 2456, 67, -3267, -5535, 483,
+ 5721, -1642, 6501, -3432, 1184, -3246, 4101, -4880,
+ 0, 0, -465, 5264, -4812, 682, 1683, -4539,
+ 2916, -1985, 2899, 3324, 1060, -4398, -745, -2137,
+ -3827, 1044, 6225, 3609, -532, 1980, -6001, 564,
+ -209, -1299, 5336, -3605, -1484, 37, 19, -1295,
+ -665, -385, -6773, 3651, 6153, -1291, 0, 0,
+ 193, -415, 5166, -110, 626, 6743, -2860, 1425,
+ 1101, -1341, 80, -4533, 249, 4231, -119, -6009,
+ -2970, 5170, -822, -2610, 4527, 5948, 182, -2589,
+ 837, -5471, 371, -43, 373, -665, -1233, -626,
+ -7353, 2606, 1339, -1398, 0, 0, -533, 147,
+ 2075, -672, 1043, 3503, 4402, -4971, -3287, 3731,
+ -2606, 3817, 1972, -5603, 5114, 1185, -1318, 1906,
+ 3018, -1999, 343, -1943, 207, -6744, 913, -4060,
+ 645, -349, -5667, 4766, 5575, -1733, 1116, 160,
+ 1534, -5690, 0, 0, -137, -36, 1556, 1325,
+ 1553, -2230, 1188, 5296, -5104, 4673, 6295, 498,
+ -4723, 933, 2994, 4067, -4700, 1758, -4116, -1252,
+ 2444, -4092, 1653, -2802, 5069, 1133, 790, -2355,
+ -934, -6304, 1642, 2045, -4259, -3873, -213, 215,
+ 0, 0, -364, 423, 4888, -1316, 118, -950,
+ 4027, 114, 2961, -3136, -3012, -883, -6192, 1340,
+ -3210, -1193, 1376, 3128, 1596, -2994, -3194, 533,
+ 8502, 2487, -1485, 1032, 301, -8007, -577, 887,
+ 297, 7778, 3121, -1901, -94, -6401, 0, 0,
+ 9260, -1845, 668, 2787, -2255, 2699, -2512, -3737,
+ -3675, -3601, -1803, 210, -1701, -1442, -2700, 3457,
+ 2868, 2079, -2113, 3178, 1277, 3578, 5240, -2482,
+ 3324, 1020, -4027, 3835, -3758, -3633, -3170, -1310,
+ 2509, -3110, 713, 174, 0, 0, -399, 4969,
+ -2321, -7744, 6494, -3776, 1478, 758, -1794, -2233,
+ -4059, 4932, 2770, 4761, -3475, 1243, 829, -651,
+ -5358, -436, 2381, 1360, 2561, -3118, 858, -4366,
+ 3933, 3646, -43, -1310, -16, 924, 1197, 1415,
+ -5036, -376, 0, 0, 100, 1410, 1290, 3199,
+ 7091, -3638, -2641, 1118, 45, -441, 794, -974,
+ -5033, 889, 438, -3102, 895, 3555, 4672, 4795,
+ 1129, -2408, -2153, 1742, 159, -2040, 7578, -2006,
+ -5737, 1986, -5568, -6413, 2428, -1387, -2441, 667,
+ 0, 0, -37, -6031, -4434, -904, 3290, 1806,
+ 4736, 2516, -5905, -5927, 1754, -4300, -2468, -2203,
+ -4836, -672, 1444, -1591, -1631, -1789, 4311, -153,
+ -688, -1222, 1058, 3139, 4659, -353, 1543, 1838,
+ 2180, -1448, 2432, 6277, 5304, -1692, 0, 0,
+ -280, 4506, 807, -477, 823, 3550, 1427, -1856,
+ -3003, -3501, -1203, 2679, 933, 778, -4954, -1977,
+ -7458, 4687, 435, 7045, -4053, -3130, 257, -3917,
+ -6165, 1889, 927, 235, 1889, -1097, 1985, 630,
+ -2172, -2130, 7080, 4810, 0, 0, -300, 496,
+ 2808, 279, 667, -7179, -2661, -526, -2832, 1751,
+ 2849, 4829, -906, -4151, -1124, -3062, 8166, 5361,
+ -1656, -6017, 3265, 2551, -864, -432, -6966, 6295,
+ -168, 901, 442, -582, 269, 236, -3574, 799,
+ 472, 565, 0, 0, 805, -2466, 6208, -4592,
+ -170, -6701, -5610, 3678, -4242, 4561, -724, -5534,
+ 2415, 7354, 2761, 2699, -349, 3822, -2372, 1756,
+ -5523, -3445, -588, -5749, -3986, 9804, -3871, 5375,
+ -2308, 5504, -2766, -1651, 1472, 6832, 2705, -5104,
+ 0, 0, -700, -1179, 4402, 400, 1383, 939,
+ -1342, 6013, 2577, -3472, 472, 2883, 1450, -3917,
+ 2849, 5084, 4990, 5392, 342, -4925, -3329, -5372,
+ -2674, -6035, -5072, -836, 179, 2506, 7987, -3647,
+ -8202, -1437, 1891, 2400, 1607, -3611, 0, 0,
+ -4706, -4003, 9928, -379, 5557, 3738, -8789, 685,
+ 1937, -5157, 13388, 7995, -4119, -9909, -5079, 4804,
+ 5586, 774, -5430, 299, -9943, 3264, -3690, -3901,
+ -1133, -6199, 3182, 1544, 5467, 3686, -2639, 4068,
+ 1163, -185, -1299, -506, 0, 0, 843, 1005,
+ -1059, 467, -1279, -2259, 6057, -1694, -5885, 5342,
+ -5160, -3748, -1382, 4420, -697, -2000, -3808, 3100,
+ 2685, -4073, 531, 318, -7822, 2414, 2901, 3399,
+ -1340, 8449, 3685, 463, -3341, 2423, 2304, -2723,
+ 84, -2622, 0, 0, 12088, -265, 2562, -435,
+ -4348, -2426, 3538, 1552, 1279, 883, -4166, 2634,
+ -6130, 2994, 3729, -1570, -601, -1753, -5124, -2788,
+ -2096, -1920, -2649, 2793, -1079, -1952, 2983, -1530,
+ 2499, 1769, 1492, -6757, -2108, 2841, 1466, 2597,
+ 0, 0, -3830, -4093, 2448, 12720, 7737, -665,
+ -832, -9257, 2971, -2400, 791, 1873, 1072, -587,
+ -7440, 8055, 1531, -4736, 616, -1782, -2982, 9663,
+ -5057, -5926, 1610, -4489, 7033, -8658, 6010, -5673,
+ 5648, 812, -271, -1802, -4500, 4392, 0, 0,
+ -888, -327, 3373, -1084, 7959, 2430, 1898, -2360,
+ -1820, -1377, -1090, -4436, -3422, -1106, -3230, 3876,
+ -41, -5128, 6375, -1848, -3824, 5844, 617, -1957,
+ 4232, 1345, -1439, -83, 3046, -214, 5458, -5566,
+ -4387, -3738, -5740, 8657, 0, 0, 6978, 6239,
+ -3686, -981, -2854, 78, 5859, -357, 4618, 7391,
+ -138, 971, -5799, 2135, 4478, -7004, -5949, 1668,
+ -6933, -1163, 7010, -5624, 2990, 6192, -8075, 3567,
+ -8308, 2236, -5098, -2120, -4355, -4238, 4955, 10230,
+ 692, -5606, 0, 0, -1348, -7069, -12, -4927,
+ 1211, 651, 1360, 7744, 3404, 5069, -2438, -105,
+ 2332, 1494, -4686, 1336, -3628, -881, 2474, 1736,
+ -26, -257, 2135, -4452, 446, -641, -4704, 2605,
+ -6436, 6662, -4939, 990, -1100, -3782, 5028, 4753,
+ 0, 0, -2875, 6410, 3518, 3950, 1271, 869,
+ -2842, -5837, 1532, -2899, 1140, -597, 1712, -1988,
+ -4819, -4783, 4773, -8796, 2240, -4596, 3565, -4853,
+ -556, -3974, 7366, -4370, 3113, -3548, 3552, -5450,
+ 3869, 2514, 6736, -4570, 6074, 3151, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 32767, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 32767
+};
--- /dev/null
+/* Copyright (c) 2017 Google Inc.
+ Written by Andrew Allen */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+/**
+ * @file mapping_matrix.h
+ * @brief Opus reference implementation mapping matrix API
+ */
+
+#ifndef MAPPING_MATRIX_H
+#define MAPPING_MATRIX_H
+
+#include "opus_types.h"
+#include "opus_projection.h"
+
+typedef struct MappingMatrix
+{
+ int rows; /* number of channels outputted from matrix. */
+ int cols; /* number of channels inputted to matrix. */
+ int gain; /* in dB. S7.8-format. */
+ /* Matrix cell data goes here using col-wise ordering. */
+} MappingMatrix;
+
+opus_int32 mapping_matrix_get_size(int rows, int cols);
+
+opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix);
+
+void mapping_matrix_init(
+ MappingMatrix * const matrix,
+ int rows,
+ int cols,
+ int gain,
+ const opus_int16 *data,
+ opus_int32 data_size
+);
+
+#ifndef DISABLE_FLOAT_API
+void mapping_matrix_multiply_channel_in_float(
+ const MappingMatrix *matrix,
+ const float *input,
+ int input_rows,
+ opus_res *output,
+ int output_row,
+ int output_rows,
+ int frame_size
+);
+
+void mapping_matrix_multiply_channel_out_float(
+ const MappingMatrix *matrix,
+ const opus_res *input,
+ int input_row,
+ int input_rows,
+ float *output,
+ int output_rows,
+ int frame_size
+);
+#endif /* DISABLE_FLOAT_API */
+
+void mapping_matrix_multiply_channel_in_short(
+ const MappingMatrix *matrix,
+ const opus_int16 *input,
+ int input_rows,
+ opus_res *output,
+ int output_row,
+ int output_rows,
+ int frame_size
+);
+
+void mapping_matrix_multiply_channel_out_short(
+ const MappingMatrix *matrix,
+ const opus_res *input,
+ int input_row,
+ int input_rows,
+ opus_int16 *output,
+ int output_rows,
+ int frame_size
+);
+
+
+void mapping_matrix_multiply_channel_in_int24(
+ const MappingMatrix *matrix,
+ const opus_int32 *input,
+ int input_rows,
+ opus_res *output,
+ int output_row,
+ int output_rows,
+ int frame_size
+);
+
+void mapping_matrix_multiply_channel_out_int24(
+ const MappingMatrix *matrix,
+ const opus_res *input,
+ int input_row,
+ int input_rows,
+ opus_int32 *output,
+ int output_rows,
+ int frame_size
+);
+/* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics.
+ * foa: first-order ambisonics
+ * soa: second-order ambisonics
+ * toa: third-order ambisonics
+ */
+extern const MappingMatrix mapping_matrix_foa_mixing;
+extern const opus_int16 mapping_matrix_foa_mixing_data[36];
+
+extern const MappingMatrix mapping_matrix_soa_mixing;
+extern const opus_int16 mapping_matrix_soa_mixing_data[121];
+
+extern const MappingMatrix mapping_matrix_toa_mixing;
+extern const opus_int16 mapping_matrix_toa_mixing_data[324];
+
+extern const MappingMatrix mapping_matrix_fourthoa_mixing;
+extern const opus_int16 mapping_matrix_fourthoa_mixing_data[729];
+
+extern const MappingMatrix mapping_matrix_fifthoa_mixing;
+extern const opus_int16 mapping_matrix_fifthoa_mixing_data[1444];
+
+extern const MappingMatrix mapping_matrix_foa_demixing;
+extern const opus_int16 mapping_matrix_foa_demixing_data[36];
+
+extern const MappingMatrix mapping_matrix_soa_demixing;
+extern const opus_int16 mapping_matrix_soa_demixing_data[121];
+
+extern const MappingMatrix mapping_matrix_toa_demixing;
+extern const opus_int16 mapping_matrix_toa_demixing_data[324];
+
+extern const MappingMatrix mapping_matrix_fourthoa_demixing;
+extern const opus_int16 mapping_matrix_fourthoa_demixing_data[729];
+
+extern const MappingMatrix mapping_matrix_fifthoa_demixing;
+extern const opus_int16 mapping_matrix_fifthoa_demixing_data[1444];
+
+#endif /* MAPPING_MATRIX_H */
--- /dev/null
+/* Copyright (c) 2017 Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 MLP_H_
+#define MLP_H_
+
+#include "opus_types.h"
+
+#define WEIGHTS_SCALE (1.f/128)
+
+#define MAX_NEURONS 32
+
+typedef struct {
+ const opus_int8 *bias;
+ const opus_int8 *input_weights;
+ int nb_inputs;
+ int nb_neurons;
+ int sigmoid;
+} AnalysisDenseLayer;
+
+typedef struct {
+ const opus_int8 *bias;
+ const opus_int8 *input_weights;
+ const opus_int8 *recurrent_weights;
+ int nb_inputs;
+ int nb_neurons;
+} AnalysisGRULayer;
+
+extern const AnalysisDenseLayer layer0;
+extern const AnalysisGRULayer layer1;
+extern const AnalysisDenseLayer layer2;
+
+void analysis_compute_dense(const AnalysisDenseLayer *layer, float *output, const float *input);
+
+void analysis_compute_gru(const AnalysisGRULayer *gru, float *state, const float *input);
+
+#endif /* MLP_H_ */
--- /dev/null
+/* Copyright (c) 2011 Xiph.Org Foundation, Skype Limited
+ Copyright (c) 2024 Arm Limited
+ Written by Jean-Marc Valin and Koen Vos */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "opus.h"
+#include "mathops.h"
+#include "opus_private.h"
+
+#ifndef DISABLE_FLOAT_API
+
+void opus_pcm_soft_clip_impl(float *_x, int N, int C, float *declip_mem, int arch)
+{
+ int c;
+ int i;
+ float *x;
+ int all_within_neg1pos1;
+
+ if (C<1 || N<1 || !_x || !declip_mem) return;
+
+ /* Clamp everything within the range [-2, +2] which is the domain of the soft
+ clipping non-linearity. Outside the defined range the derivative will be zero,
+ therefore there is no discontinuity introduced here. The implementation
+ might provide a hint if all input samples are within the [-1, +1] range.
+
+ `opus_limit2_checkwithin1()`:
+ - Clamps all samples within the valid range [-2, +2].
+ - Generic C implementation:
+ * Does not attempt early detection whether samples are within hinted range.
+ * Always returns 0.
+ - Architecture specific implementation:
+ * Uses SIMD instructions to efficiently detect if all samples are
+ within the hinted range [-1, +1].
+ * Returns 1 if no samples exceed the hinted range, 0 otherwise.
+
+ `all_within_neg1pos1`:
+ - Optimization hint to skip per-sample out-of-bound checks.
+ If true, the check can be skipped. */
+ all_within_neg1pos1 = opus_limit2_checkwithin1(_x, N*C, arch);
+
+ for (c=0;c<C;c++)
+ {
+ float a;
+ float x0;
+ int curr;
+
+ x = _x+c;
+ a = declip_mem[c];
+ /* Continue applying the non-linearity from the previous frame to avoid
+ any discontinuity. */
+ for (i=0;i<N;i++)
+ {
+ if (x[i*C]*a>=0)
+ break;
+ x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
+ }
+
+ curr=0;
+ x0 = x[0];
+ while(1)
+ {
+ int start, end;
+ float maxval;
+ int special=0;
+ int peak_pos;
+ /* Detection for early exit can be skipped if hinted by `all_within_neg1pos1` */
+ if (all_within_neg1pos1)
+ {
+ i = N;
+ } else {
+ for (i=curr;i<N;i++)
+ {
+ if (x[i*C]>1 || x[i*C]<-1)
+ break;
+ }
+ }
+ if (i==N)
+ {
+ a=0;
+ break;
+ }
+ peak_pos = i;
+ start=end=i;
+ maxval=ABS16(x[i*C]);
+ /* Look for first zero crossing before clipping */
+ while (start>0 && x[i*C]*x[(start-1)*C]>=0)
+ start--;
+ /* Look for first zero crossing after clipping */
+ while (end<N && x[i*C]*x[end*C]>=0)
+ {
+ /* Look for other peaks until the next zero-crossing. */
+ if (ABS16(x[end*C])>maxval)
+ {
+ maxval = ABS16(x[end*C]);
+ peak_pos = end;
+ }
+ end++;
+ }
+ /* Detect the special case where we clip before the first zero crossing */
+ special = (start==0 && x[i*C]*x[0]>=0);
+
+ /* Compute a such that maxval + a*maxval^2 = 1 */
+ a=(maxval-1)/(maxval*maxval);
+ /* Slightly boost "a" by 2^-22. This is just enough to ensure -ffast-math
+ does not cause output values larger than +/-1, but small enough not
+ to matter even for 24-bit output. */
+ a += a*2.4e-7f;
+ if (x[i*C]>0)
+ a = -a;
+ /* Apply soft clipping */
+ for (i=start;i<end;i++)
+ x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
+
+ if (special && peak_pos>=2)
+ {
+ /* Add a linear ramp from the first sample to the signal peak.
+ This avoids a discontinuity at the beginning of the frame. */
+ float delta;
+ float offset = x0-x[0];
+ delta = offset / peak_pos;
+ for (i=curr;i<peak_pos;i++)
+ {
+ offset -= delta;
+ x[i*C] += offset;
+ x[i*C] = MAX16(-1.f, MIN16(1.f, x[i*C]));
+ }
+ }
+ curr = end;
+ if (curr==N)
+ break;
+ }
+ declip_mem[c] = a;
+ }
+}
+
+OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
+{
+ opus_pcm_soft_clip_impl(_x, N, C, declip_mem, 0);
+}
+
+#endif
+
+int encode_size(int size, unsigned char *data)
+{
+ if (size < 252)
+ {
+ data[0] = size;
+ return 1;
+ } else {
+ data[0] = 252+(size&0x3);
+ data[1] = (size-(int)data[0])>>2;
+ return 2;
+ }
+}
+
+static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size)
+{
+ if (len<1)
+ {
+ *size = -1;
+ return -1;
+ } else if (data[0]<252)
+ {
+ *size = data[0];
+ return 1;
+ } else if (len<2)
+ {
+ *size = -1;
+ return -1;
+ } else {
+ *size = 4*data[1] + data[0];
+ return 2;
+ }
+}
+
+int opus_packet_get_samples_per_frame(const unsigned char *data,
+ opus_int32 Fs)
+{
+ int audiosize;
+ if (data[0]&0x80)
+ {
+ audiosize = ((data[0]>>3)&0x3);
+ audiosize = (Fs<<audiosize)/400;
+ } else if ((data[0]&0x60) == 0x60)
+ {
+ audiosize = (data[0]&0x08) ? Fs/50 : Fs/100;
+ } else {
+ audiosize = ((data[0]>>3)&0x3);
+ if (audiosize == 3)
+ audiosize = Fs*60/1000;
+ else
+ audiosize = (Fs<<audiosize)/100;
+ }
+ return audiosize;
+}
+
+int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
+ int self_delimited, unsigned char *out_toc,
+ const unsigned char *frames[48], opus_int16 size[48],
+ int *payload_offset, opus_int32 *packet_offset,
+ const unsigned char **padding, opus_int32 *padding_len)
+{
+ int i, bytes;
+ int count;
+ int cbr;
+ unsigned char ch, toc;
+ int framesize;
+ opus_int32 last_size;
+ opus_int32 pad = 0;
+ const unsigned char *data0 = data;
+
+ /* Make sure we return NULL/0 on error. */
+ if (padding != NULL)
+ {
+ *padding = NULL;
+ *padding_len = 0;
+ }
+
+ if (size==NULL || len<0)
+ return OPUS_BAD_ARG;
+ if (len==0)
+ return OPUS_INVALID_PACKET;
+
+ framesize = opus_packet_get_samples_per_frame(data, 48000);
+
+ cbr = 0;
+ toc = *data++;
+ len--;
+ last_size = len;
+ switch (toc&0x3)
+ {
+ /* One frame */
+ case 0:
+ count=1;
+ break;
+ /* Two CBR frames */
+ case 1:
+ count=2;
+ cbr = 1;
+ if (!self_delimited)
+ {
+ if (len&0x1)
+ return OPUS_INVALID_PACKET;
+ last_size = len/2;
+ /* If last_size doesn't fit in size[0], we'll catch it later */
+ size[0] = (opus_int16)last_size;
+ }
+ break;
+ /* Two VBR frames */
+ case 2:
+ count = 2;
+ bytes = parse_size(data, len, size);
+ len -= bytes;
+ if (size[0]<0 || size[0] > len)
+ return OPUS_INVALID_PACKET;
+ data += bytes;
+ last_size = len-size[0];
+ break;
+ /* Multiple CBR/VBR frames (from 0 to 120 ms) */
+ default: /*case 3:*/
+ if (len<1)
+ return OPUS_INVALID_PACKET;
+ /* Number of frames encoded in bits 0 to 5 */
+ ch = *data++;
+ count = ch&0x3F;
+ if (count <= 0 || framesize*(opus_int32)count > 5760)
+ return OPUS_INVALID_PACKET;
+ len--;
+ /* Padding flag is bit 6 */
+ if (ch&0x40)
+ {
+ int p;
+ do {
+ int tmp;
+ if (len<=0)
+ return OPUS_INVALID_PACKET;
+ p = *data++;
+ len--;
+ tmp = p==255 ? 254: p;
+ len -= tmp;
+ pad += tmp;
+ } while (p==255);
+ }
+ if (len<0)
+ return OPUS_INVALID_PACKET;
+ /* VBR flag is bit 7 */
+ cbr = !(ch&0x80);
+ if (!cbr)
+ {
+ /* VBR case */
+ last_size = len;
+ for (i=0;i<count-1;i++)
+ {
+ bytes = parse_size(data, len, size+i);
+ len -= bytes;
+ if (size[i]<0 || size[i] > len)
+ return OPUS_INVALID_PACKET;
+ data += bytes;
+ last_size -= bytes+size[i];
+ }
+ if (last_size<0)
+ return OPUS_INVALID_PACKET;
+ } else if (!self_delimited)
+ {
+ /* CBR case */
+ last_size = len/count;
+ if (last_size*count!=len)
+ return OPUS_INVALID_PACKET;
+ for (i=0;i<count-1;i++)
+ size[i] = (opus_int16)last_size;
+ }
+ break;
+ }
+ /* Self-delimited framing has an extra size for the last frame. */
+ if (self_delimited)
+ {
+ bytes = parse_size(data, len, size+count-1);
+ len -= bytes;
+ if (size[count-1]<0 || size[count-1] > len)
+ return OPUS_INVALID_PACKET;
+ data += bytes;
+ /* For CBR packets, apply the size to all the frames. */
+ if (cbr)
+ {
+ if (size[count-1]*count > len)
+ return OPUS_INVALID_PACKET;
+ for (i=0;i<count-1;i++)
+ size[i] = size[count-1];
+ } else if (bytes+size[count-1] > last_size)
+ return OPUS_INVALID_PACKET;
+ } else
+ {
+ /* Because it's not encoded explicitly, it's possible the size of the
+ last packet (or all the packets, for the CBR case) is larger than
+ 1275. Reject them here.*/
+ if (last_size > 1275)
+ return OPUS_INVALID_PACKET;
+ size[count-1] = (opus_int16)last_size;
+ }
+
+ if (payload_offset)
+ *payload_offset = (int)(data-data0);
+
+ for (i=0;i<count;i++)
+ {
+ if (frames)
+ frames[i] = data;
+ data += size[i];
+ }
+
+ if (padding != NULL)
+ {
+ *padding = data;
+ *padding_len = pad;
+ }
+ if (packet_offset)
+ *packet_offset = pad+(opus_int32)(data-data0);
+
+ if (out_toc)
+ *out_toc = toc;
+
+ return count;
+}
+
+int opus_packet_parse(const unsigned char *data, opus_int32 len,
+ unsigned char *out_toc, const unsigned char *frames[48],
+ opus_int16 size[48], int *payload_offset)
+{
+ return opus_packet_parse_impl(data, len, 0, out_toc,
+ frames, size, payload_offset, NULL, NULL, NULL);
+}
--- /dev/null
+/* Copyright (c) 2010 Xiph.Org Foundation, Skype Limited
+ Copyright (c) 2024 Arm Limited
+ Written by Jean-Marc Valin and Koen Vos */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifndef OPUS_BUILD
+# error "OPUS_BUILD _MUST_ be defined to build Opus. This probably means you need other defines as well, as in a config.h. See the included build files for details."
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ >= 2) && !defined(__OPTIMIZE__) && !defined(OPUS_WILL_BE_SLOW)
+# pragma message "You appear to be compiling without optimization, if so opus will be very slow."
+#endif
+
+#include <stdarg.h>
+#include "celt.h"
+#include "opus.h"
+#include "entdec.h"
+#include "modes.h"
+#include "API.h"
+#include "stack_alloc.h"
+#include "float_cast.h"
+#include "opus_private.h"
+#include "os_support.h"
+#include "structs.h"
+#include "define.h"
+#include "mathops.h"
+#include "cpu_support.h"
+
+#ifdef ENABLE_DEEP_PLC
+#include "dred_rdovae_dec_data.h"
+#include "dred_rdovae_dec.h"
+#endif
+
+#ifdef ENABLE_OSCE
+#include "osce.h"
+#endif
+
+struct OpusDecoder {
+ int celt_dec_offset;
+ int silk_dec_offset;
+ int channels;
+ opus_int32 Fs; /** Sampling rate (at the API level) */
+ silk_DecControlStruct DecControl;
+ int decode_gain;
+ int complexity;
+ int ignore_extensions;
+ int arch;
+#ifdef ENABLE_DEEP_PLC
+ LPCNetPLCState lpcnet;
+#endif
+
+ /* Everything beyond this point gets cleared on a reset */
+#define OPUS_DECODER_RESET_START stream_channels
+ int stream_channels;
+
+ int bandwidth;
+ int mode;
+ int prev_mode;
+ int frame_size;
+ int prev_redundancy;
+ int last_packet_duration;
+#ifndef FIXED_POINT
+ opus_val16 softclip_mem[2];
+#endif
+
+ opus_uint32 rangeFinal;
+};
+
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+static void validate_opus_decoder(OpusDecoder *st)
+{
+ celt_assert(st->channels == 1 || st->channels == 2);
+#ifdef ENABLE_QEXT
+ celt_assert(st->Fs == 96000 || st->Fs == 48000 || st->Fs == 24000 || st->Fs == 16000 || st->Fs == 12000 || st->Fs == 8000);
+#else
+ celt_assert(st->Fs == 48000 || st->Fs == 24000 || st->Fs == 16000 || st->Fs == 12000 || st->Fs == 8000);
+#endif
+ celt_assert(st->DecControl.API_sampleRate == st->Fs);
+ celt_assert(st->DecControl.internalSampleRate == 0 || st->DecControl.internalSampleRate == 16000 || st->DecControl.internalSampleRate == 12000 || st->DecControl.internalSampleRate == 8000);
+ celt_assert(st->DecControl.nChannelsAPI == st->channels);
+ celt_assert(st->DecControl.nChannelsInternal == 0 || st->DecControl.nChannelsInternal == 1 || st->DecControl.nChannelsInternal == 2);
+ celt_assert(st->DecControl.payloadSize_ms == 0 || st->DecControl.payloadSize_ms == 10 || st->DecControl.payloadSize_ms == 20 || st->DecControl.payloadSize_ms == 40 || st->DecControl.payloadSize_ms == 60);
+#ifdef OPUS_ARCHMASK
+ celt_assert(st->arch >= 0);
+ celt_assert(st->arch <= OPUS_ARCHMASK);
+#endif
+ celt_assert(st->stream_channels == 1 || st->stream_channels == 2);
+}
+#define VALIDATE_OPUS_DECODER(st) validate_opus_decoder(st)
+#else
+#define VALIDATE_OPUS_DECODER(st)
+#endif
+
+int opus_decoder_get_size(int channels)
+{
+ int silkDecSizeBytes, celtDecSizeBytes;
+ int ret;
+ if (channels<1 || channels > 2)
+ return 0;
+ ret = silk_Get_Decoder_Size( &silkDecSizeBytes );
+ if(ret)
+ return 0;
+ silkDecSizeBytes = align(silkDecSizeBytes);
+ celtDecSizeBytes = celt_decoder_get_size(channels);
+ return align(sizeof(OpusDecoder))+silkDecSizeBytes+celtDecSizeBytes;
+}
+
+int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels)
+{
+ void *silk_dec;
+ CELTDecoder *celt_dec;
+ int ret, silkDecSizeBytes;
+
+ if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000
+#ifdef ENABLE_QEXT
+ &&Fs!=96000
+#endif
+ )
+ || (channels!=1&&channels!=2))
+ return OPUS_BAD_ARG;
+
+ OPUS_CLEAR((char*)st, opus_decoder_get_size(channels));
+ /* Initialize SILK decoder */
+ ret = silk_Get_Decoder_Size(&silkDecSizeBytes);
+ if (ret)
+ return OPUS_INTERNAL_ERROR;
+
+ silkDecSizeBytes = align(silkDecSizeBytes);
+ st->silk_dec_offset = align(sizeof(OpusDecoder));
+ st->celt_dec_offset = st->silk_dec_offset+silkDecSizeBytes;
+ silk_dec = (char*)st+st->silk_dec_offset;
+ celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
+ st->stream_channels = st->channels = channels;
+ st->complexity = 0;
+
+ st->Fs = Fs;
+ st->DecControl.API_sampleRate = st->Fs;
+ st->DecControl.nChannelsAPI = st->channels;
+
+ /* Reset decoder */
+ ret = silk_InitDecoder( silk_dec );
+ if(ret)return OPUS_INTERNAL_ERROR;
+
+ /* Initialize CELT decoder */
+ ret = celt_decoder_init(celt_dec, Fs, channels);
+ if(ret!=OPUS_OK)return OPUS_INTERNAL_ERROR;
+
+ celt_decoder_ctl(celt_dec, CELT_SET_SIGNALLING(0));
+
+ st->prev_mode = 0;
+ st->frame_size = Fs/400;
+#ifdef ENABLE_DEEP_PLC
+ lpcnet_plc_init( &st->lpcnet);
+#endif
+ st->arch = opus_select_arch();
+ return OPUS_OK;
+}
+
+OpusDecoder *opus_decoder_create(opus_int32 Fs, int channels, int *error)
+{
+ int ret;
+ OpusDecoder *st;
+ if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000
+#ifdef ENABLE_QEXT
+ &&Fs!=96000
+#endif
+ )
+ || (channels!=1&&channels!=2))
+ {
+ if (error)
+ *error = OPUS_BAD_ARG;
+ return NULL;
+ }
+ st = (OpusDecoder *)opus_alloc(opus_decoder_get_size(channels));
+ if (st == NULL)
+ {
+ if (error)
+ *error = OPUS_ALLOC_FAIL;
+ return NULL;
+ }
+ ret = opus_decoder_init(st, Fs, channels);
+ if (error)
+ *error = ret;
+ if (ret != OPUS_OK)
+ {
+ opus_free(st);
+ st = NULL;
+ }
+ return st;
+}
+
+#ifdef ENABLE_RES24
+static void smooth_fade(const opus_res *in1, const opus_res *in2,
+ opus_res *out, int overlap, int channels,
+ const celt_coef *window, opus_int32 Fs)
+{
+ int i, c;
+ int inc = 48000/Fs;
+ for (c=0;c<channels;c++)
+ {
+ for (i=0;i<overlap;i++)
+ {
+ celt_coef w = MULT_COEF(window[i*inc], window[i*inc]);
+ out[i*channels+c] = ADD32(MULT_COEF_32(w,in2[i*channels+c]),
+ MULT_COEF_32(COEF_ONE-w, in1[i*channels+c]));
+ }
+ }
+}
+#else
+static void smooth_fade(const opus_res *in1, const opus_res *in2,
+ opus_res *out, int overlap, int channels,
+ const celt_coef *window, opus_int32 Fs)
+{
+ int i, c;
+ int inc = 48000/Fs;
+ for (c=0;c<channels;c++)
+ {
+ for (i=0;i<overlap;i++)
+ {
+ opus_val16 w = COEF2VAL16(window[i*inc]);
+ w = MULT16_16_Q15(w, w);
+ out[i*channels+c] = SHR32(MAC16_16(MULT16_16(w,in2[i*channels+c]),
+ Q15ONE-w, in1[i*channels+c]), 15);
+ }
+ }
+}
+#endif
+
+static int opus_packet_get_mode(const unsigned char *data)
+{
+ int mode;
+ if (data[0]&0x80)
+ {
+ mode = MODE_CELT_ONLY;
+ } else if ((data[0]&0x60) == 0x60)
+ {
+ mode = MODE_HYBRID;
+ } else {
+ mode = MODE_SILK_ONLY;
+ }
+ return mode;
+}
+
+static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
+ opus_int32 len, opus_res *pcm, int frame_size, int decode_fec ARG_QEXT(opus_extension_data *ext))
+{
+ void *silk_dec;
+ CELTDecoder *celt_dec;
+ int i, silk_ret=0, celt_ret=0;
+ ec_dec dec;
+ opus_int32 silk_frame_size;
+ int pcm_transition_silk_size;
+ VARDECL(opus_res, pcm_transition_silk);
+ int pcm_transition_celt_size;
+ VARDECL(opus_res, pcm_transition_celt);
+ opus_res *pcm_transition=NULL;
+ int redundant_audio_size;
+ VARDECL(opus_res, redundant_audio);
+
+ int audiosize;
+ int mode;
+ int bandwidth;
+ int transition=0;
+ int start_band;
+ int redundancy=0;
+ int redundancy_bytes = 0;
+ int celt_to_silk=0;
+ int c;
+ int F2_5, F5, F10, F20;
+ const celt_coef *window;
+ opus_uint32 redundant_rng = 0;
+ int celt_accum;
+ ALLOC_STACK;
+
+ silk_dec = (char*)st+st->silk_dec_offset;
+ celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
+ F20 = st->Fs/50;
+ F10 = F20>>1;
+ F5 = F10>>1;
+ F2_5 = F5>>1;
+ if (frame_size < F2_5)
+ {
+ RESTORE_STACK;
+ return OPUS_BUFFER_TOO_SMALL;
+ }
+ /* Limit frame_size to avoid excessive stack allocations. */
+ frame_size = IMIN(frame_size, st->Fs/25*3);
+ /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
+ if (len<=1)
+ {
+ data = NULL;
+ /* In that case, don't conceal more than what the ToC says */
+ frame_size = IMIN(frame_size, st->frame_size);
+ }
+ if (data != NULL)
+ {
+ audiosize = st->frame_size;
+ mode = st->mode;
+ bandwidth = st->bandwidth;
+ ec_dec_init(&dec,(unsigned char*)data,len);
+ } else {
+ audiosize = frame_size;
+ /* Run PLC using last used mode (CELT if we ended with CELT redundancy) */
+ mode = st->prev_redundancy ? MODE_CELT_ONLY : st->prev_mode;
+ bandwidth = 0;
+
+ if (mode == 0)
+ {
+ /* If we haven't got any packet yet, all we can do is return zeros */
+ for (i=0;i<audiosize*st->channels;i++)
+ pcm[i] = 0;
+ RESTORE_STACK;
+ return audiosize;
+ }
+
+ /* Avoids trying to run the PLC on sizes other than 2.5 (CELT), 5 (CELT),
+ 10, or 20 (e.g. 12.5 or 30 ms). */
+ if (audiosize > F20)
+ {
+ do {
+ int ret = opus_decode_frame(st, NULL, 0, pcm, IMIN(audiosize, F20), 0 ARG_QEXT(NULL));
+ if (ret<0)
+ {
+ RESTORE_STACK;
+ return ret;
+ }
+ pcm += ret*st->channels;
+ audiosize -= ret;
+ } while (audiosize > 0);
+ RESTORE_STACK;
+ return frame_size;
+ } else if (audiosize < F20)
+ {
+ if (audiosize > F10)
+ audiosize = F10;
+ else if (mode != MODE_SILK_ONLY && audiosize > F5 && audiosize < F10)
+ audiosize = F5;
+ }
+ }
+
+ /* In fixed-point, we can tell CELT to do the accumulation on top of the
+ SILK PCM buffer. This saves some stack space. */
+ celt_accum = (mode != MODE_CELT_ONLY);
+
+ pcm_transition_silk_size = ALLOC_NONE;
+ pcm_transition_celt_size = ALLOC_NONE;
+ if (data!=NULL && st->prev_mode > 0 && (
+ (mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy)
+ || (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) )
+ )
+ {
+ transition = 1;
+ /* Decide where to allocate the stack memory for pcm_transition */
+ if (mode == MODE_CELT_ONLY)
+ pcm_transition_celt_size = F5*st->channels;
+ else
+ pcm_transition_silk_size = F5*st->channels;
+ }
+ ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_res);
+ if (transition && mode == MODE_CELT_ONLY)
+ {
+ pcm_transition = pcm_transition_celt;
+ opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0 ARG_QEXT(NULL));
+ }
+ if (audiosize > frame_size)
+ {
+ /*fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);*/
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ } else {
+ frame_size = audiosize;
+ }
+
+ /* SILK processing */
+ if (mode != MODE_CELT_ONLY)
+ {
+ int lost_flag, decoded_samples;
+ opus_res *pcm_ptr;
+ int pcm_too_small;
+ int pcm_silk_size = ALLOC_NONE;
+ VARDECL(opus_res, pcm_silk);
+ pcm_too_small = (frame_size < F10);
+ if (pcm_too_small)
+ pcm_silk_size = F10*st->channels;
+ ALLOC(pcm_silk, pcm_silk_size, opus_res);
+ if (pcm_too_small)
+ pcm_ptr = pcm_silk;
+ else
+ pcm_ptr = pcm;
+
+ if (st->prev_mode==MODE_CELT_ONLY)
+ silk_ResetDecoder( silk_dec );
+
+ /* The SILK PLC cannot produce frames of less than 10 ms */
+ st->DecControl.payloadSize_ms = IMAX(10, 1000 * audiosize / st->Fs);
+
+ if (data != NULL)
+ {
+ st->DecControl.nChannelsInternal = st->stream_channels;
+ if( mode == MODE_SILK_ONLY ) {
+ if( bandwidth == OPUS_BANDWIDTH_NARROWBAND ) {
+ st->DecControl.internalSampleRate = 8000;
+ } else if( bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) {
+ st->DecControl.internalSampleRate = 12000;
+ } else if( bandwidth == OPUS_BANDWIDTH_WIDEBAND ) {
+ st->DecControl.internalSampleRate = 16000;
+ } else {
+ st->DecControl.internalSampleRate = 16000;
+ celt_assert( 0 );
+ }
+ } else {
+ /* Hybrid mode */
+ st->DecControl.internalSampleRate = 16000;
+ }
+ }
+ st->DecControl.enable_deep_plc = st->complexity >= 5;
+#ifdef ENABLE_OSCE
+ st->DecControl.osce_method = OSCE_METHOD_NONE;
+#ifndef DISABLE_LACE
+ if (st->complexity >= 6) {st->DecControl.osce_method = OSCE_METHOD_LACE;}
+#endif
+#ifndef DISABLE_NOLACE
+ if (st->complexity >= 7) {st->DecControl.osce_method = OSCE_METHOD_NOLACE;}
+#endif
+#ifdef ENABLE_OSCE_BWE
+ if (st->complexity >= 4 && st->DecControl.enable_osce_bwe &&
+ st->Fs == 48000 && st->DecControl.internalSampleRate == 16000 &&
+ ((mode == MODE_SILK_ONLY) || (data == NULL))) {
+ /* request WB -> FB signal extension */
+ st->DecControl.osce_extended_mode = OSCE_MODE_SILK_BBWE;
+ } else {
+ /* at this point, mode can only be MODE_SILK_ONLY or MODE_HYBRID */
+ st->DecControl.osce_extended_mode = mode == MODE_SILK_ONLY ? OSCE_MODE_SILK_ONLY : OSCE_MODE_HYBRID;
+ }
+ if (st->prev_mode == MODE_CELT_ONLY) {
+ /* Update extended mode for CELT->SILK transition */
+ st->DecControl.prev_osce_extended_mode = OSCE_MODE_CELT_ONLY;
+ }
+#endif
+#endif
+
+ lost_flag = data == NULL ? 1 : 2 * !!decode_fec;
+ decoded_samples = 0;
+ do {
+ /* Call SILK decoder */
+ int first_frame = decoded_samples == 0;
+ silk_ret = silk_Decode( silk_dec, &st->DecControl,
+ lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size,
+#ifdef ENABLE_DEEP_PLC
+ &st->lpcnet,
+#endif
+ st->arch );
+ if( silk_ret ) {
+ if (lost_flag) {
+ /* PLC failure should not be fatal */
+ silk_frame_size = frame_size;
+ for (i=0;i<frame_size*st->channels;i++)
+ pcm_ptr[i] = 0;
+ } else {
+ RESTORE_STACK;
+ return OPUS_INTERNAL_ERROR;
+ }
+ }
+ pcm_ptr += silk_frame_size * st->channels;
+ decoded_samples += silk_frame_size;
+ } while( decoded_samples < frame_size );
+ if (pcm_too_small) {
+ OPUS_COPY(pcm, pcm_silk, frame_size*st->channels);
+ }
+ }
+
+ start_band = 0;
+ if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL
+ && ec_tell(&dec)+17+20*(mode == MODE_HYBRID) <= 8*len)
+ {
+ /* Check if we have a redundant 0-8 kHz band */
+ if (mode == MODE_HYBRID)
+ redundancy = ec_dec_bit_logp(&dec, 12);
+ else
+ redundancy = 1;
+ if (redundancy)
+ {
+ celt_to_silk = ec_dec_bit_logp(&dec, 1);
+ /* redundancy_bytes will be at least two, in the non-hybrid
+ case due to the ec_tell() check above */
+ redundancy_bytes = mode==MODE_HYBRID ?
+ (opus_int32)ec_dec_uint(&dec, 256)+2 :
+ len-((ec_tell(&dec)+7)>>3);
+ len -= redundancy_bytes;
+ /* This is a sanity check. It should never happen for a valid
+ packet, so the exact behaviour is not normative. */
+ if (len*8 < ec_tell(&dec))
+ {
+ len = 0;
+ redundancy_bytes = 0;
+ redundancy = 0;
+ }
+ /* Shrink decoder because of raw bits */
+ dec.storage -= redundancy_bytes;
+ }
+ }
+ if (mode != MODE_CELT_ONLY)
+ start_band = 17;
+
+ if (redundancy)
+ {
+ transition = 0;
+ pcm_transition_silk_size=ALLOC_NONE;
+ }
+
+ ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_res);
+
+ if (transition && mode != MODE_CELT_ONLY)
+ {
+ pcm_transition = pcm_transition_silk;
+ opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0 ARG_QEXT(NULL));
+ }
+
+
+ if (bandwidth)
+ {
+ int endband=21;
+
+ switch(bandwidth)
+ {
+ case OPUS_BANDWIDTH_NARROWBAND:
+ endband = 13;
+ break;
+ case OPUS_BANDWIDTH_MEDIUMBAND:
+ case OPUS_BANDWIDTH_WIDEBAND:
+ endband = 17;
+ break;
+ case OPUS_BANDWIDTH_SUPERWIDEBAND:
+ endband = 19;
+ break;
+ case OPUS_BANDWIDTH_FULLBAND:
+ endband = 21;
+ break;
+ default:
+ celt_assert(0);
+ break;
+ }
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband)));
+ }
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels)));
+
+ /* Only allocation memory for redundancy if/when needed */
+ redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE;
+ ALLOC(redundant_audio, redundant_audio_size, opus_res);
+
+ /* 5 ms redundant frame for CELT->SILK*/
+ if (redundancy && celt_to_silk)
+ {
+ /* If the previous frame did not use CELT (the first redundancy frame in
+ a transition from SILK may have been lost) then the CELT decoder is
+ stale at this point and the redundancy audio is not useful, however
+ the final range is still needed (for testing), so the redundancy is
+ always decoded but the decoded audio may not be used */
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
+ celt_decode_with_ec(celt_dec, data+len, redundancy_bytes,
+ redundant_audio, F5, NULL, 0);
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)));
+ }
+
+ /* MUST be after PLC */
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band)));
+
+#ifdef ENABLE_OSCE_BWE
+ if (mode != MODE_SILK_ONLY && st->DecControl.osce_extended_mode != OSCE_MODE_SILK_BBWE)
+#else
+ if (mode != MODE_SILK_ONLY)
+#endif
+ {
+ int celt_frame_size = IMIN(F20, frame_size);
+ /* Make sure to discard any previous CELT state */
+ if (mode != st->prev_mode && st->prev_mode > 0 && !st->prev_redundancy)
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_RESET_STATE));
+ /* Decode CELT */
+ celt_ret = celt_decode_with_ec_dred(celt_dec, decode_fec ? NULL : data,
+ len, pcm, celt_frame_size, &dec, celt_accum
+#ifdef ENABLE_DEEP_PLC
+ , &st->lpcnet
+#endif
+ ARG_QEXT(ext ? ext->data : NULL) ARG_QEXT(ext ? ext->len : 0));
+ celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&st->rangeFinal));
+ } else {
+ unsigned char silence[2] = {0xFF, 0xFF};
+ if (!celt_accum)
+ {
+ for (i=0;i<frame_size*st->channels;i++)
+ pcm[i] = 0;
+ }
+ /* For hybrid -> SILK transitions, we let the CELT MDCT
+ do a fade-out by decoding a silence frame */
+ if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) )
+ {
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
+ celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL, celt_accum);
+ }
+ st->rangeFinal = dec.rng;
+ }
+
+ {
+ const CELTMode *celt_mode;
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode)));
+ window = celt_mode->window;
+ }
+
+ /* 5 ms redundant frame for SILK->CELT */
+ if (redundancy && !celt_to_silk)
+ {
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_RESET_STATE));
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
+
+ celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL, 0);
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)));
+ smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5,
+ pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs);
+ }
+ /* 5ms redundant frame for CELT->SILK; ignore if the previous frame did not
+ use CELT (the first redundancy frame in a transition from SILK may have
+ been lost) */
+ if (redundancy && celt_to_silk && (st->prev_mode != MODE_SILK_ONLY || st->prev_redundancy))
+ {
+ for (c=0;c<st->channels;c++)
+ {
+ for (i=0;i<F2_5;i++)
+ pcm[st->channels*i+c] = redundant_audio[st->channels*i+c];
+ }
+ smooth_fade(redundant_audio+st->channels*F2_5, pcm+st->channels*F2_5,
+ pcm+st->channels*F2_5, F2_5, st->channels, window, st->Fs);
+ }
+ if (transition)
+ {
+ if (audiosize >= F5)
+ {
+ for (i=0;i<st->channels*F2_5;i++)
+ pcm[i] = pcm_transition[i];
+ smooth_fade(pcm_transition+st->channels*F2_5, pcm+st->channels*F2_5,
+ pcm+st->channels*F2_5, F2_5,
+ st->channels, window, st->Fs);
+ } else {
+ /* Not enough time to do a clean transition, but we do it anyway
+ This will not preserve amplitude perfectly and may introduce
+ a bit of temporal aliasing, but it shouldn't be too bad and
+ that's pretty much the best we can do. In any case, generating this
+ transition it pretty silly in the first place */
+ smooth_fade(pcm_transition, pcm,
+ pcm, F2_5,
+ st->channels, window, st->Fs);
+ }
+ }
+
+ if(st->decode_gain)
+ {
+ opus_val32 gain;
+ gain = celt_exp2(MULT16_16_P15(QCONST16(6.48814081e-4f, 25), st->decode_gain));
+ for (i=0;i<frame_size*st->channels;i++)
+ {
+ opus_val32 x;
+#ifdef ENABLE_RES24
+ x = MULT32_32_Q16(pcm[i],gain);
+#else
+ x = MULT16_32_P16(pcm[i],gain);
+#endif
+ pcm[i] = SATURATE(x, 32767);
+ }
+ }
+
+ if (len <= 1)
+ st->rangeFinal = 0;
+ else
+ st->rangeFinal ^= redundant_rng;
+
+ st->prev_mode = mode;
+ st->prev_redundancy = redundancy && !celt_to_silk;
+
+ if (celt_ret>=0)
+ {
+ if (OPUS_CHECK_ARRAY(pcm, audiosize*st->channels))
+ OPUS_PRINT_INT(audiosize);
+ }
+
+ RESTORE_STACK;
+ return celt_ret < 0 ? celt_ret : audiosize;
+
+}
+
+int opus_decode_native(OpusDecoder *st, const unsigned char *data,
+ opus_int32 len, opus_res *pcm, int frame_size, int decode_fec,
+ int self_delimited, opus_int32 *packet_offset, int soft_clip, const OpusDRED *dred, opus_int32 dred_offset)
+{
+ int i, nb_samples;
+ int count, offset;
+ unsigned char toc;
+ int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels;
+ /* 48 x 2.5 ms = 120 ms */
+ opus_int16 size[48];
+ const unsigned char *padding;
+ opus_int32 padding_len;
+ OpusExtensionIterator iter;
+ VALIDATE_OPUS_DECODER(st);
+ if (decode_fec<0 || decode_fec>1)
+ return OPUS_BAD_ARG;
+ /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */
+ if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0)
+ return OPUS_BAD_ARG;
+#ifdef ENABLE_DRED
+ if (dred != NULL && dred->process_stage == 2) {
+ int F10;
+ int features_per_frame;
+ int needed_feature_frames;
+ int init_frames;
+ lpcnet_plc_fec_clear(&st->lpcnet);
+ F10 = st->Fs/100;
+ /* if blend==0, the last PLC call was "update" and we need to feed two extra 10-ms frames. */
+ init_frames = (st->lpcnet.blend == 0) ? 2 : 0;
+ features_per_frame = IMAX(1, frame_size/F10);
+ needed_feature_frames = init_frames + features_per_frame;
+ for (i=0;i<needed_feature_frames;i++) {
+ int feature_offset;
+ /* We floor instead of rounding because 5-ms overlap compensates for the missing 0.5 rounding offset. */
+ feature_offset = init_frames - i - 2 + (int)floor(((float)dred_offset + dred->dred_offset*F10/4)/F10);
+ if (feature_offset <= 4*dred->nb_latents-1 && feature_offset >= 0) {
+ lpcnet_plc_fec_add(&st->lpcnet, dred->fec_features+feature_offset*DRED_NUM_FEATURES);
+ } else {
+ if (feature_offset >= 0) lpcnet_plc_fec_add(&st->lpcnet, NULL);
+ }
+
+ }
+ }
+#else
+ (void)dred;
+ (void)dred_offset;
+#endif
+ if (len==0 || data==NULL)
+ {
+ int pcm_count=0;
+ do {
+ int ret;
+ ret = opus_decode_frame(st, NULL, 0, pcm+pcm_count*st->channels, frame_size-pcm_count, 0 ARG_QEXT(NULL));
+ if (ret<0)
+ return ret;
+ pcm_count += ret;
+ } while (pcm_count < frame_size);
+ celt_assert(pcm_count == frame_size);
+ if (OPUS_CHECK_ARRAY(pcm, pcm_count*st->channels))
+ OPUS_PRINT_INT(pcm_count);
+ st->last_packet_duration = pcm_count;
+ return pcm_count;
+ } else if (len<0)
+ return OPUS_BAD_ARG;
+
+ packet_mode = opus_packet_get_mode(data);
+ packet_bandwidth = opus_packet_get_bandwidth(data);
+ packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs);
+ packet_stream_channels = opus_packet_get_nb_channels(data);
+
+ count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
+ size, &offset, packet_offset, &padding, &padding_len);
+ if (st->ignore_extensions) {
+ padding = NULL;
+ padding_len = 0;
+ }
+ if (count<0)
+ return count;
+ opus_extension_iterator_init(&iter, padding, padding_len, count);
+
+ data += offset;
+
+ if (decode_fec)
+ {
+ int duration_copy;
+ int ret;
+ /* If no FEC can be present, run the PLC (recursive call) */
+ if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY)
+ return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, soft_clip, NULL, 0);
+ /* Otherwise, run the PLC on everything except the size for which we might have FEC */
+ duration_copy = st->last_packet_duration;
+ if (frame_size-packet_frame_size!=0)
+ {
+ ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL, soft_clip, NULL, 0);
+ if (ret<0)
+ {
+ st->last_packet_duration = duration_copy;
+ return ret;
+ }
+ celt_assert(ret==frame_size-packet_frame_size);
+ }
+ /* Complete with FEC */
+ st->mode = packet_mode;
+ st->bandwidth = packet_bandwidth;
+ st->frame_size = packet_frame_size;
+ st->stream_channels = packet_stream_channels;
+ ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size),
+ packet_frame_size, 1 ARG_QEXT(NULL));
+ if (ret<0)
+ return ret;
+ else {
+ if (OPUS_CHECK_ARRAY(pcm, frame_size*st->channels))
+ OPUS_PRINT_INT(frame_size);
+ st->last_packet_duration = frame_size;
+ return frame_size;
+ }
+ }
+
+ if (count*packet_frame_size > frame_size)
+ return OPUS_BUFFER_TOO_SMALL;
+
+ /* Update the state as the last step to avoid updating it on an invalid packet */
+ st->mode = packet_mode;
+ st->bandwidth = packet_bandwidth;
+ st->frame_size = packet_frame_size;
+ st->stream_channels = packet_stream_channels;
+
+ nb_samples=0;
+ for (i=0;i<count;i++)
+ {
+ int ret;
+#ifdef ENABLE_QEXT
+ opus_extension_data ext;
+ ext.frame = -1;
+ ext.data = NULL;
+ ext.len = 0;
+ ext.id = -1;
+ while (ext.frame < i) {
+ OpusExtensionIterator iter_copy;
+ iter_copy = iter;
+ ret = opus_extension_iterator_find(&iter, &ext, QEXT_EXTENSION_ID);
+ if (ret <= 0) break;
+ if (ext.frame > i) iter = iter_copy;
+ }
+ if (ext.frame != i) ext.data = NULL;
+#endif
+ ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0 ARG_QEXT(&ext));
+ if (ret<0)
+ return ret;
+ celt_assert(ret==packet_frame_size);
+ data += size[i];
+ nb_samples += ret;
+ }
+ st->last_packet_duration = nb_samples;
+ if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels))
+ OPUS_PRINT_INT(nb_samples);
+#ifndef FIXED_POINT
+ if (soft_clip)
+ opus_pcm_soft_clip_impl(pcm, nb_samples, st->channels, st->softclip_mem, st->arch);
+ else
+ st->softclip_mem[0]=st->softclip_mem[1]=0;
+#endif
+ return nb_samples;
+}
+
+#ifdef FIXED_POINT
+#define OPTIONAL_CLIP 0
+#else
+#define OPTIONAL_CLIP 1
+#endif
+
+#if defined(FIXED_POINT) && !defined(ENABLE_RES24)
+int opus_decode(OpusDecoder *st, const unsigned char *data,
+ opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
+{
+ if(frame_size<=0)
+ return OPUS_BAD_ARG;
+ return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
+}
+#else
+int opus_decode(OpusDecoder *st, const unsigned char *data,
+ opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
+{
+ VARDECL(opus_res, out);
+ int ret;
+ int nb_samples;
+ ALLOC_STACK;
+
+ if(frame_size<=0)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+ if (data != NULL && len > 0 && !decode_fec)
+ {
+ nb_samples = opus_decoder_get_nb_samples(st, data, len);
+ if (nb_samples>0)
+ frame_size = IMIN(frame_size, nb_samples);
+ else
+ return OPUS_INVALID_PACKET;
+ }
+ celt_assert(st->channels == 1 || st->channels == 2);
+ ALLOC(out, frame_size*st->channels, opus_res);
+
+ ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, OPTIONAL_CLIP, NULL, 0);
+ if (ret > 0)
+ {
+# if defined(FIXED_POINT)
+ int i;
+ for (i=0;i<ret*st->channels;i++)
+ pcm[i] = RES2INT16(out[i]);
+# else
+ celt_float2int16(out, pcm, ret*st->channels, st->arch);
+# endif
+ }
+ RESTORE_STACK;
+ return ret;
+}
+#endif
+
+#if defined(FIXED_POINT) && defined(ENABLE_RES24)
+int opus_decode24(OpusDecoder *st, const unsigned char *data,
+ opus_int32 len, opus_int32 *pcm, int frame_size, int decode_fec)
+{
+ if(frame_size<=0)
+ return OPUS_BAD_ARG;
+ return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
+}
+#else
+int opus_decode24(OpusDecoder *st, const unsigned char *data,
+ opus_int32 len, opus_int32 *pcm, int frame_size, int decode_fec)
+{
+ VARDECL(opus_res, out);
+ int ret, i;
+ int nb_samples;
+ ALLOC_STACK;
+
+ if(frame_size<=0)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+ if (data != NULL && len > 0 && !decode_fec)
+ {
+ nb_samples = opus_decoder_get_nb_samples(st, data, len);
+ if (nb_samples>0)
+ frame_size = IMIN(frame_size, nb_samples);
+ else
+ return OPUS_INVALID_PACKET;
+ }
+ celt_assert(st->channels == 1 || st->channels == 2);
+ ALLOC(out, frame_size*st->channels, opus_res);
+
+ ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
+ if (ret > 0)
+ {
+ nb_samples = ret*st->channels;
+ for (i=0;i<nb_samples;i++)
+ pcm[i] = RES2INT24(out[i]);
+ }
+ RESTORE_STACK;
+ return ret;
+}
+#endif
+
+
+#ifndef DISABLE_FLOAT_API
+
+# if !defined(FIXED_POINT)
+int opus_decode_float(OpusDecoder *st, const unsigned char *data,
+ opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
+{
+ if(frame_size<=0)
+ return OPUS_BAD_ARG;
+ return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
+}
+# else
+int opus_decode_float(OpusDecoder *st, const unsigned char *data,
+ opus_int32 len, float *pcm, int frame_size, int decode_fec)
+{
+ VARDECL(opus_res, out);
+ int ret, i;
+ int nb_samples;
+ ALLOC_STACK;
+
+ if(frame_size<=0)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+ if (data != NULL && len > 0 && !decode_fec)
+ {
+ nb_samples = opus_decoder_get_nb_samples(st, data, len);
+ if (nb_samples>0)
+ frame_size = IMIN(frame_size, nb_samples);
+ else
+ return OPUS_INVALID_PACKET;
+ }
+ celt_assert(st->channels == 1 || st->channels == 2);
+ ALLOC(out, frame_size*st->channels, opus_res);
+
+ ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
+ if (ret > 0)
+ {
+ for (i=0;i<ret*st->channels;i++)
+ pcm[i] = RES2FLOAT(out[i]);
+ }
+ RESTORE_STACK;
+ return ret;
+}
+# endif
+
+#endif
+
+
+int opus_decoder_ctl(OpusDecoder *st, int request, ...)
+{
+ int ret = OPUS_OK;
+ va_list ap;
+ void *silk_dec;
+ CELTDecoder *celt_dec;
+
+ silk_dec = (char*)st+st->silk_dec_offset;
+ celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
+
+
+ va_start(ap, request);
+
+ switch (request)
+ {
+ case OPUS_GET_BANDWIDTH_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = st->bandwidth;
+ }
+ break;
+ case OPUS_SET_COMPLEXITY_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ if(value<0 || value>10)
+ {
+ goto bad_arg;
+ }
+ st->complexity = value;
+ celt_decoder_ctl(celt_dec, OPUS_SET_COMPLEXITY(value));
+ }
+ break;
+ case OPUS_GET_COMPLEXITY_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = st->complexity;
+ }
+ break;
+#ifdef ENABLE_OSCE_BWE
+ case OPUS_SET_OSCE_BWE_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ if(value<0 || value>1)
+ { goto bad_arg;
+ }
+ st->DecControl.enable_osce_bwe = value;
+
+ }
+ break;
+ case OPUS_GET_OSCE_BWE_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = st->DecControl.enable_osce_bwe;
+ }
+ break;
+#endif
+ case OPUS_GET_FINAL_RANGE_REQUEST:
+ {
+ opus_uint32 *value = va_arg(ap, opus_uint32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = st->rangeFinal;
+ }
+ break;
+ case OPUS_RESET_STATE:
+ {
+ OPUS_CLEAR((char*)&st->OPUS_DECODER_RESET_START,
+ sizeof(OpusDecoder)-
+ ((char*)&st->OPUS_DECODER_RESET_START - (char*)st));
+
+ celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
+ silk_ResetDecoder( silk_dec );
+ st->stream_channels = st->channels;
+ st->frame_size = st->Fs/400;
+#ifdef ENABLE_DEEP_PLC
+ lpcnet_plc_reset( &st->lpcnet );
+#endif
+ }
+ break;
+ case OPUS_GET_SAMPLE_RATE_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = st->Fs;
+ }
+ break;
+ case OPUS_GET_PITCH_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ if (st->prev_mode == MODE_CELT_ONLY)
+ ret = celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
+ else
+ *value = st->DecControl.prevPitchLag;
+ }
+ break;
+ case OPUS_GET_GAIN_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = st->decode_gain;
+ }
+ break;
+ case OPUS_SET_GAIN_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ if (value<-32768 || value>32767)
+ {
+ goto bad_arg;
+ }
+ st->decode_gain = value;
+ }
+ break;
+ case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = st->last_packet_duration;
+ }
+ break;
+ case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ if(value<0 || value>1)
+ {
+ goto bad_arg;
+ }
+ ret = celt_decoder_ctl(celt_dec, OPUS_SET_PHASE_INVERSION_DISABLED(value));
+ }
+ break;
+ case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ ret = celt_decoder_ctl(celt_dec, OPUS_GET_PHASE_INVERSION_DISABLED(value));
+ }
+ break;
+ case OPUS_SET_IGNORE_EXTENSIONS_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ if(value<0 || value>1)
+ {
+ goto bad_arg;
+ }
+ st->ignore_extensions = value;
+ }
+ break;
+ case OPUS_GET_IGNORE_EXTENSIONS_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = st->ignore_extensions;
+ }
+ break;
+#ifdef USE_WEIGHTS_FILE
+ case OPUS_SET_DNN_BLOB_REQUEST:
+ {
+ const unsigned char *data = va_arg(ap, const unsigned char *);
+ opus_int32 len = va_arg(ap, opus_int32);
+ if(len<0 || data == NULL)
+ {
+ goto bad_arg;
+ }
+ ret = lpcnet_plc_load_model(&st->lpcnet, data, len);
+ ret = silk_LoadOSCEModels(silk_dec, data, len) || ret;
+ }
+ break;
+#endif
+ default:
+ /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
+ ret = OPUS_UNIMPLEMENTED;
+ break;
+ }
+
+ va_end(ap);
+ return ret;
+bad_arg:
+ va_end(ap);
+ return OPUS_BAD_ARG;
+}
+
+void opus_decoder_destroy(OpusDecoder *st)
+{
+ opus_free(st);
+}
+
+
+int opus_packet_get_bandwidth(const unsigned char *data)
+{
+ int bandwidth;
+ if (data[0]&0x80)
+ {
+ bandwidth = OPUS_BANDWIDTH_MEDIUMBAND + ((data[0]>>5)&0x3);
+ if (bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
+ bandwidth = OPUS_BANDWIDTH_NARROWBAND;
+ } else if ((data[0]&0x60) == 0x60)
+ {
+ bandwidth = (data[0]&0x10) ? OPUS_BANDWIDTH_FULLBAND :
+ OPUS_BANDWIDTH_SUPERWIDEBAND;
+ } else {
+ bandwidth = OPUS_BANDWIDTH_NARROWBAND + ((data[0]>>5)&0x3);
+ }
+ return bandwidth;
+}
+
+int opus_packet_get_nb_channels(const unsigned char *data)
+{
+ return (data[0]&0x4) ? 2 : 1;
+}
+
+int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len)
+{
+ int count;
+ if (len<1)
+ return OPUS_BAD_ARG;
+ count = packet[0]&0x3;
+ if (count==0)
+ return 1;
+ else if (count!=3)
+ return 2;
+ else if (len<2)
+ return OPUS_INVALID_PACKET;
+ else
+ return packet[1]&0x3F;
+}
+
+int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len,
+ opus_int32 Fs)
+{
+ int samples;
+ int count = opus_packet_get_nb_frames(packet, len);
+
+ if (count<0)
+ return count;
+
+ samples = count*opus_packet_get_samples_per_frame(packet, Fs);
+ /* Can't have more than 120 ms */
+ if (samples*25 > Fs*3)
+ return OPUS_INVALID_PACKET;
+ else
+ return samples;
+}
+
+int opus_packet_has_lbrr(const unsigned char packet[], opus_int32 len)
+{
+ int ret;
+ const unsigned char *frames[48];
+ opus_int16 size[48];
+ int packet_mode, packet_frame_size, packet_stream_channels;
+ int nb_frames=1;
+ int lbrr;
+
+ packet_mode = opus_packet_get_mode(packet);
+ if (packet_mode == MODE_CELT_ONLY)
+ return 0;
+ packet_frame_size = opus_packet_get_samples_per_frame(packet, 48000);
+ if (packet_frame_size > 960)
+ nb_frames = packet_frame_size/960;
+ packet_stream_channels = opus_packet_get_nb_channels(packet);
+ ret = opus_packet_parse(packet, len, NULL, frames, size, NULL);
+ if (ret <= 0)
+ return ret;
+ if (size[0] == 0)
+ return 0;
+ lbrr = (frames[0][0] >> (7-nb_frames)) & 0x1;
+ if (packet_stream_channels == 2)
+ lbrr = lbrr || ((frames[0][0] >> (6-2*nb_frames)) & 0x1);
+ return lbrr;
+}
+
+int opus_decoder_get_nb_samples(const OpusDecoder *dec,
+ const unsigned char packet[], opus_int32 len)
+{
+ return opus_packet_get_nb_samples(packet, len, dec->Fs);
+}
+
+struct OpusDREDDecoder {
+#ifdef ENABLE_DRED
+ RDOVAEDec model;
+#endif
+ int loaded;
+ int arch;
+ opus_uint32 magic;
+};
+
+#if defined(ENABLE_DRED) && (defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS))
+static void validate_dred_decoder(OpusDREDDecoder *st)
+{
+ celt_assert(st->magic == 0xD8EDDEC0);
+#ifdef OPUS_ARCHMASK
+ celt_assert(st->arch >= 0);
+ celt_assert(st->arch <= OPUS_ARCHMASK);
+#endif
+}
+#define VALIDATE_DRED_DECODER(st) validate_dred_decoder(st)
+#else
+#define VALIDATE_DRED_DECODER(st)
+#endif
+
+
+int opus_dred_decoder_get_size(void)
+{
+ return sizeof(OpusDREDDecoder);
+}
+
+#ifdef ENABLE_DRED
+int dred_decoder_load_model(OpusDREDDecoder *dec, const unsigned char *data, int len)
+{
+ WeightArray *list;
+ int ret;
+ parse_weights(&list, data, len);
+ ret = init_rdovaedec(&dec->model, list);
+ opus_free(list);
+ if (ret == 0) dec->loaded = 1;
+ return (ret == 0) ? OPUS_OK : OPUS_BAD_ARG;
+}
+#endif
+
+int opus_dred_decoder_init(OpusDREDDecoder *dec)
+{
+ int ret = 0;
+ dec->loaded = 0;
+#if defined(ENABLE_DRED) && !defined(USE_WEIGHTS_FILE)
+ ret = init_rdovaedec(&dec->model, rdovaedec_arrays);
+ if (ret == 0) dec->loaded = 1;
+#endif
+ dec->arch = opus_select_arch();
+ /* To make sure nobody forgets to init, use a magic number. */
+ dec->magic = 0xD8EDDEC0;
+ return (ret == 0) ? OPUS_OK : OPUS_UNIMPLEMENTED;
+}
+
+OpusDREDDecoder *opus_dred_decoder_create(int *error)
+{
+ int ret;
+ OpusDREDDecoder *dec;
+ dec = (OpusDREDDecoder *)opus_alloc(opus_dred_decoder_get_size());
+ if (dec == NULL)
+ {
+ if (error)
+ *error = OPUS_ALLOC_FAIL;
+ return NULL;
+ }
+ ret = opus_dred_decoder_init(dec);
+ if (error)
+ *error = ret;
+ if (ret != OPUS_OK)
+ {
+ opus_free(dec);
+ dec = NULL;
+ }
+ return dec;
+}
+
+void opus_dred_decoder_destroy(OpusDREDDecoder *dec)
+{
+ if (dec) dec->magic = 0xDE57801D;
+ opus_free(dec);
+}
+
+int opus_dred_decoder_ctl(OpusDREDDecoder *dred_dec, int request, ...)
+{
+#ifdef ENABLE_DRED
+ int ret = OPUS_OK;
+ va_list ap;
+
+ va_start(ap, request);
+ (void)dred_dec;
+ switch (request)
+ {
+# ifdef USE_WEIGHTS_FILE
+ case OPUS_SET_DNN_BLOB_REQUEST:
+ {
+ const unsigned char *data = va_arg(ap, const unsigned char *);
+ opus_int32 len = va_arg(ap, opus_int32);
+ if(len<0 || data == NULL)
+ {
+ goto bad_arg;
+ }
+ return dred_decoder_load_model(dred_dec, data, len);
+ }
+ break;
+# endif
+ default:
+ /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
+ ret = OPUS_UNIMPLEMENTED;
+ break;
+ }
+ va_end(ap);
+ return ret;
+# ifdef USE_WEIGHTS_FILE
+bad_arg:
+ va_end(ap);
+ return OPUS_BAD_ARG;
+# endif
+#else
+ (void)dred_dec;
+ (void)request;
+ return OPUS_UNIMPLEMENTED;
+#endif
+}
+
+#ifdef ENABLE_DRED
+static int dred_find_payload(const unsigned char *data, opus_int32 len, const unsigned char **payload, int *dred_frame_offset)
+{
+ OpusExtensionIterator iter;
+ opus_extension_data ext;
+ const unsigned char *padding;
+ opus_int32 padding_len;
+ int nb_frames;
+ const unsigned char *frames[48];
+ opus_int16 size[48];
+ int frame_size;
+ int ret;
+
+ *payload = NULL;
+ /* Get the padding section of the packet. */
+ ret = opus_packet_parse_impl(data, len, 0, NULL, frames, size, NULL, NULL,
+ &padding, &padding_len);
+ if (ret < 0)
+ return ret;
+ nb_frames = ret;
+ frame_size = opus_packet_get_samples_per_frame(data, 48000);
+ opus_extension_iterator_init(&iter, padding, padding_len, nb_frames);
+ for (;;) {
+ ret = opus_extension_iterator_find(&iter, &ext, DRED_EXTENSION_ID);
+ if (ret <= 0)
+ return ret;
+ /* DRED position in the packet, in units of 2.5 ms like for the signaled DRED offset. */
+ *dred_frame_offset = ext.frame*frame_size/120;
+#ifdef DRED_EXPERIMENTAL_VERSION
+ /* Check that temporary extension type and version match.
+ This check will be removed once extension is finalized. */
+ if (ext.len > DRED_EXPERIMENTAL_BYTES && ext.data[0] == 'D'
+ && ext.data[1] == DRED_EXPERIMENTAL_VERSION) {
+ *payload = ext.data+2;
+ return ext.len-2;
+ }
+#else
+ if (ext.len > 0) {
+ *payload = ext.data;
+ return ext.len;
+ }
+#endif
+ }
+}
+#endif
+
+int opus_dred_get_size(void)
+{
+#ifdef ENABLE_DRED
+ return sizeof(OpusDRED);
+#else
+ return 0;
+#endif
+}
+
+OpusDRED *opus_dred_alloc(int *error)
+{
+#ifdef ENABLE_DRED
+ OpusDRED *dec;
+ dec = (OpusDRED *)opus_alloc(opus_dred_get_size());
+ if (dec == NULL)
+ {
+ if (error)
+ *error = OPUS_ALLOC_FAIL;
+ return NULL;
+ }
+ return dec;
+#else
+ if (error)
+ *error = OPUS_UNIMPLEMENTED;
+ return NULL;
+#endif
+}
+
+void opus_dred_free(OpusDRED *dec)
+{
+#ifdef ENABLE_DRED
+ opus_free(dec);
+#else
+ (void)dec;
+#endif
+}
+
+int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const unsigned char *data, opus_int32 len, opus_int32 max_dred_samples, opus_int32 sampling_rate, int *dred_end, int defer_processing)
+{
+#ifdef ENABLE_DRED
+ const unsigned char *payload;
+ opus_int32 payload_len;
+ int dred_frame_offset=0;
+ VALIDATE_DRED_DECODER(dred_dec);
+ if (!dred_dec->loaded) return OPUS_UNIMPLEMENTED;
+ dred->process_stage = -1;
+ payload_len = dred_find_payload(data, len, &payload, &dred_frame_offset);
+ if (payload_len < 0)
+ return payload_len;
+ if (payload != NULL)
+ {
+ int offset;
+ int min_feature_frames;
+ offset = 100*max_dred_samples/sampling_rate;
+ min_feature_frames = IMIN(2 + offset, 2*DRED_NUM_REDUNDANCY_FRAMES);
+ dred_ec_decode(dred, payload, payload_len, min_feature_frames, dred_frame_offset);
+ if (!defer_processing)
+ opus_dred_process(dred_dec, dred, dred);
+ if (dred_end) *dred_end = IMAX(0, -dred->dred_offset*sampling_rate/400);
+ return IMAX(0, dred->nb_latents*sampling_rate/25 - dred->dred_offset* sampling_rate/400);
+ }
+ if (dred_end) *dred_end = 0;
+ return 0;
+#else
+ (void)dred_dec;
+ (void)dred;
+ (void)data;
+ (void)len;
+ (void)max_dred_samples;
+ (void)sampling_rate;
+ (void)defer_processing;
+ (void)dred_end;
+ return OPUS_UNIMPLEMENTED;
+#endif
+}
+
+int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src, OpusDRED *dst)
+{
+#ifdef ENABLE_DRED
+ if (dred_dec == NULL || src == NULL || dst == NULL || (src->process_stage != 1 && src->process_stage != 2))
+ return OPUS_BAD_ARG;
+ VALIDATE_DRED_DECODER(dred_dec);
+ if (!dred_dec->loaded) return OPUS_UNIMPLEMENTED;
+ if (src != dst)
+ OPUS_COPY(dst, src, 1);
+ if (dst->process_stage == 2)
+ return OPUS_OK;
+ DRED_rdovae_decode_all(&dred_dec->model, dst->fec_features, dst->state, dst->latents, dst->nb_latents, dred_dec->arch);
+ dst->process_stage = 2;
+ return OPUS_OK;
+#else
+ (void)dred_dec;
+ (void)src;
+ (void)dst;
+ return OPUS_UNIMPLEMENTED;
+#endif
+}
+
+int opus_decoder_dred_decode(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int16 *pcm, opus_int32 frame_size)
+{
+#ifdef ENABLE_DRED
+ VARDECL(float, out);
+ int ret, i;
+ ALLOC_STACK;
+
+ if(frame_size<=0)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+
+ celt_assert(st->channels == 1 || st->channels == 2);
+ ALLOC(out, frame_size*st->channels, float);
+
+ ret = opus_decode_native(st, NULL, 0, out, frame_size, 0, 0, NULL, 1, dred, dred_offset);
+ if (ret > 0)
+ {
+ for (i=0;i<ret*st->channels;i++)
+ pcm[i] = RES2INT16(out[i]);
+ }
+ RESTORE_STACK;
+ return ret;
+#else
+ (void)st;
+ (void)dred;
+ (void)dred_offset;
+ (void)pcm;
+ (void)frame_size;
+ return OPUS_UNIMPLEMENTED;
+#endif
+}
+
+int opus_decoder_dred_decode24(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int32 *pcm, opus_int32 frame_size)
+{
+#ifdef ENABLE_DRED
+ VARDECL(float, out);
+ int ret, i;
+ ALLOC_STACK;
+
+ if(frame_size<=0)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+
+ celt_assert(st->channels == 1 || st->channels == 2);
+ ALLOC(out, frame_size*st->channels, float);
+
+ ret = opus_decode_native(st, NULL, 0, out, frame_size, 0, 0, NULL, 1, dred, dred_offset);
+ if (ret > 0)
+ {
+ for (i=0;i<ret*st->channels;i++)
+ pcm[i] = RES2INT24(out[i]);
+ }
+ RESTORE_STACK;
+ return ret;
+#else
+ (void)st;
+ (void)dred;
+ (void)dred_offset;
+ (void)pcm;
+ (void)frame_size;
+ return OPUS_UNIMPLEMENTED;
+#endif
+}
+
+int opus_decoder_dred_decode_float(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, float *pcm, opus_int32 frame_size)
+{
+#ifdef ENABLE_DRED
+ if(frame_size<=0)
+ return OPUS_BAD_ARG;
+ return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, 0, dred, dred_offset);
+#else
+ (void)st;
+ (void)dred;
+ (void)dred_offset;
+ (void)pcm;
+ (void)frame_size;
+ return OPUS_UNIMPLEMENTED;
+#endif
+}
--- /dev/null
+/* Copyright (c) 2011 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "opus_multistream.h"
+#include "opus.h"
+#include "opus_private.h"
+#include "stack_alloc.h"
+#include <stdarg.h>
+#include "float_cast.h"
+#include "os_support.h"
+
+/* DECODER */
+
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+static void validate_ms_decoder(OpusMSDecoder *st)
+{
+ validate_layout(&st->layout);
+}
+#define VALIDATE_MS_DECODER(st) validate_ms_decoder(st)
+#else
+#define VALIDATE_MS_DECODER(st)
+#endif
+
+
+opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
+{
+ int coupled_size;
+ int mono_size;
+
+ if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
+ coupled_size = opus_decoder_get_size(2);
+ mono_size = opus_decoder_get_size(1);
+ return align(sizeof(OpusMSDecoder))
+ + nb_coupled_streams * align(coupled_size)
+ + (nb_streams-nb_coupled_streams) * align(mono_size);
+}
+
+int opus_multistream_decoder_init(
+ OpusMSDecoder *st,
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ const unsigned char *mapping
+)
+{
+ int coupled_size;
+ int mono_size;
+ int i, ret;
+ char *ptr;
+
+ if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
+ (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
+ return OPUS_BAD_ARG;
+
+ st->layout.nb_channels = channels;
+ st->layout.nb_streams = streams;
+ st->layout.nb_coupled_streams = coupled_streams;
+
+ for (i=0;i<st->layout.nb_channels;i++)
+ st->layout.mapping[i] = mapping[i];
+ if (!validate_layout(&st->layout))
+ return OPUS_BAD_ARG;
+
+ ptr = (char*)st + align(sizeof(OpusMSDecoder));
+ coupled_size = opus_decoder_get_size(2);
+ mono_size = opus_decoder_get_size(1);
+
+ for (i=0;i<st->layout.nb_coupled_streams;i++)
+ {
+ ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
+ if(ret!=OPUS_OK)return ret;
+ ptr += align(coupled_size);
+ }
+ for (;i<st->layout.nb_streams;i++)
+ {
+ ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
+ if(ret!=OPUS_OK)return ret;
+ ptr += align(mono_size);
+ }
+ return OPUS_OK;
+}
+
+
+OpusMSDecoder *opus_multistream_decoder_create(
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ const unsigned char *mapping,
+ int *error
+)
+{
+ int ret;
+ OpusMSDecoder *st;
+ if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
+ (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
+ {
+ if (error)
+ *error = OPUS_BAD_ARG;
+ return NULL;
+ }
+ st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
+ if (st==NULL)
+ {
+ if (error)
+ *error = OPUS_ALLOC_FAIL;
+ return NULL;
+ }
+ ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
+ if (error)
+ *error = ret;
+ if (ret != OPUS_OK)
+ {
+ opus_free(st);
+ st = NULL;
+ }
+ return st;
+}
+
+static int opus_multistream_packet_validate(const unsigned char *data,
+ opus_int32 len, int nb_streams, opus_int32 Fs)
+{
+ int s;
+ int count;
+ unsigned char toc;
+ opus_int16 size[48];
+ int samples=0;
+ opus_int32 packet_offset;
+
+ for (s=0;s<nb_streams;s++)
+ {
+ int tmp_samples;
+ if (len<=0)
+ return OPUS_INVALID_PACKET;
+ count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL,
+ size, NULL, &packet_offset, NULL, NULL);
+ if (count<0)
+ return count;
+ tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs);
+ if (s!=0 && samples != tmp_samples)
+ return OPUS_INVALID_PACKET;
+ samples = tmp_samples;
+ data += packet_offset;
+ len -= packet_offset;
+ }
+ return samples;
+}
+
+int opus_multistream_decode_native(
+ OpusMSDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ void *pcm,
+ opus_copy_channel_out_func copy_channel_out,
+ int frame_size,
+ int decode_fec,
+ int soft_clip,
+ void *user_data
+)
+{
+ opus_int32 Fs;
+ int coupled_size;
+ int mono_size;
+ int s, c;
+ char *ptr;
+ int do_plc=0;
+ VARDECL(opus_res, buf);
+ ALLOC_STACK;
+
+ VALIDATE_MS_DECODER(st);
+ if (frame_size <= 0)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+ /* Limit frame_size to avoid excessive stack allocations. */
+ MUST_SUCCEED(opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)));
+ frame_size = IMIN(frame_size, Fs/25*3);
+ ALLOC(buf, 2*frame_size, opus_res);
+ ptr = (char*)st + align(sizeof(OpusMSDecoder));
+ coupled_size = opus_decoder_get_size(2);
+ mono_size = opus_decoder_get_size(1);
+
+ if (len==0)
+ do_plc = 1;
+ if (len < 0)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+ if (!do_plc && len < 2*st->layout.nb_streams-1)
+ {
+ RESTORE_STACK;
+ return OPUS_INVALID_PACKET;
+ }
+ if (!do_plc)
+ {
+ int ret = opus_multistream_packet_validate(data, len, st->layout.nb_streams, Fs);
+ if (ret < 0)
+ {
+ RESTORE_STACK;
+ return ret;
+ } else if (ret > frame_size)
+ {
+ RESTORE_STACK;
+ return OPUS_BUFFER_TOO_SMALL;
+ }
+ }
+ for (s=0;s<st->layout.nb_streams;s++)
+ {
+ OpusDecoder *dec;
+ opus_int32 packet_offset;
+ int ret;
+
+ dec = (OpusDecoder*)ptr;
+ ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
+
+ if (!do_plc && len<=0)
+ {
+ RESTORE_STACK;
+ return OPUS_INTERNAL_ERROR;
+ }
+ packet_offset = 0;
+ ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip, NULL, 0);
+ if (!do_plc)
+ {
+ data += packet_offset;
+ len -= packet_offset;
+ }
+ if (ret <= 0)
+ {
+ RESTORE_STACK;
+ return ret;
+ }
+ frame_size = ret;
+ if (s < st->layout.nb_coupled_streams)
+ {
+ int chan, prev;
+ prev = -1;
+ /* Copy "left" audio to the channel(s) where it belongs */
+ while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
+ {
+ (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
+ buf, 2, frame_size, user_data);
+ prev = chan;
+ }
+ prev = -1;
+ /* Copy "right" audio to the channel(s) where it belongs */
+ while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
+ {
+ (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
+ buf+1, 2, frame_size, user_data);
+ prev = chan;
+ }
+ } else {
+ int chan, prev;
+ prev = -1;
+ /* Copy audio to the channel(s) where it belongs */
+ while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
+ {
+ (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
+ buf, 1, frame_size, user_data);
+ prev = chan;
+ }
+ }
+ }
+ /* Handle muted channels */
+ for (c=0;c<st->layout.nb_channels;c++)
+ {
+ if (st->layout.mapping[c] == 255)
+ {
+ (*copy_channel_out)(pcm, st->layout.nb_channels, c,
+ NULL, 0, frame_size, user_data);
+ }
+ }
+ RESTORE_STACK;
+ return frame_size;
+}
+
+#if !defined(DISABLE_FLOAT_API)
+static void opus_copy_channel_out_float(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_res *src,
+ int src_stride,
+ int frame_size,
+ void *user_data
+)
+{
+ float *float_dst;
+ opus_int32 i;
+ (void)user_data;
+ float_dst = (float*)dst;
+ if (src != NULL)
+ {
+ for (i=0;i<frame_size;i++)
+ float_dst[i*dst_stride+dst_channel] = RES2FLOAT(src[i*src_stride]);
+ }
+ else
+ {
+ for (i=0;i<frame_size;i++)
+ float_dst[i*dst_stride+dst_channel] = 0;
+ }
+}
+#endif
+
+static void opus_copy_channel_out_short(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_res *src,
+ int src_stride,
+ int frame_size,
+ void *user_data
+)
+{
+ opus_int16 *short_dst;
+ opus_int32 i;
+ (void)user_data;
+ short_dst = (opus_int16*)dst;
+ if (src != NULL)
+ {
+ for (i=0;i<frame_size;i++)
+ short_dst[i*dst_stride+dst_channel] = RES2INT16(src[i*src_stride]);
+ }
+ else
+ {
+ for (i=0;i<frame_size;i++)
+ short_dst[i*dst_stride+dst_channel] = 0;
+ }
+}
+
+static void opus_copy_channel_out_int24(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_res *src,
+ int src_stride,
+ int frame_size,
+ void *user_data
+)
+{
+ opus_int32 *short_dst;
+ opus_int32 i;
+ (void)user_data;
+ short_dst = (opus_int32*)dst;
+ if (src != NULL)
+ {
+ for (i=0;i<frame_size;i++)
+ short_dst[i*dst_stride+dst_channel] = RES2INT24(src[i*src_stride]);
+ }
+ else
+ {
+ for (i=0;i<frame_size;i++)
+ short_dst[i*dst_stride+dst_channel] = 0;
+ }
+}
+
+#ifdef FIXED_POINT
+#define OPTIONAL_CLIP 0
+#else
+#define OPTIONAL_CLIP 1
+#endif
+
+int opus_multistream_decode(
+ OpusMSDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ opus_int16 *pcm,
+ int frame_size,
+ int decode_fec
+)
+{
+ return opus_multistream_decode_native(st, data, len,
+ pcm, opus_copy_channel_out_short, frame_size, decode_fec, OPTIONAL_CLIP, NULL);
+}
+
+int opus_multistream_decode24(
+ OpusMSDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ opus_int32 *pcm,
+ int frame_size,
+ int decode_fec
+)
+{
+ return opus_multistream_decode_native(st, data, len,
+ pcm, opus_copy_channel_out_int24, frame_size, decode_fec, 0, NULL);
+}
+
+#ifndef DISABLE_FLOAT_API
+int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
+ opus_int32 len, float *pcm, int frame_size, int decode_fec)
+{
+ return opus_multistream_decode_native(st, data, len,
+ pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
+}
+#endif
+
+int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
+ va_list ap)
+{
+ int coupled_size, mono_size;
+ char *ptr;
+ int ret = OPUS_OK;
+
+ coupled_size = opus_decoder_get_size(2);
+ mono_size = opus_decoder_get_size(1);
+ ptr = (char*)st + align(sizeof(OpusMSDecoder));
+ switch (request)
+ {
+ case OPUS_GET_BANDWIDTH_REQUEST:
+ case OPUS_GET_SAMPLE_RATE_REQUEST:
+ case OPUS_GET_GAIN_REQUEST:
+ case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
+ case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+ case OPUS_GET_COMPLEXITY_REQUEST:
+ {
+ OpusDecoder *dec;
+ /* For int32* GET params, just query the first stream */
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ dec = (OpusDecoder*)ptr;
+ ret = opus_decoder_ctl(dec, request, value);
+ }
+ break;
+ case OPUS_GET_FINAL_RANGE_REQUEST:
+ {
+ int s;
+ opus_uint32 *value = va_arg(ap, opus_uint32*);
+ opus_uint32 tmp;
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = 0;
+ for (s=0;s<st->layout.nb_streams;s++)
+ {
+ OpusDecoder *dec;
+ dec = (OpusDecoder*)ptr;
+ if (s < st->layout.nb_coupled_streams)
+ ptr += align(coupled_size);
+ else
+ ptr += align(mono_size);
+ ret = opus_decoder_ctl(dec, request, &tmp);
+ if (ret != OPUS_OK) break;
+ *value ^= tmp;
+ }
+ }
+ break;
+ case OPUS_RESET_STATE:
+ {
+ int s;
+ for (s=0;s<st->layout.nb_streams;s++)
+ {
+ OpusDecoder *dec;
+
+ dec = (OpusDecoder*)ptr;
+ if (s < st->layout.nb_coupled_streams)
+ ptr += align(coupled_size);
+ else
+ ptr += align(mono_size);
+ ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
+ if (ret != OPUS_OK)
+ break;
+ }
+ }
+ break;
+ case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
+ {
+ int s;
+ opus_int32 stream_id;
+ OpusDecoder **value;
+ stream_id = va_arg(ap, opus_int32);
+ if (stream_id<0 || stream_id >= st->layout.nb_streams)
+ goto bad_arg;
+ value = va_arg(ap, OpusDecoder**);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ for (s=0;s<stream_id;s++)
+ {
+ if (s < st->layout.nb_coupled_streams)
+ ptr += align(coupled_size);
+ else
+ ptr += align(mono_size);
+ }
+ *value = (OpusDecoder*)ptr;
+ }
+ break;
+ case OPUS_SET_GAIN_REQUEST:
+ case OPUS_SET_COMPLEXITY_REQUEST:
+ case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+ {
+ int s;
+ /* This works for int32 params */
+ opus_int32 value = va_arg(ap, opus_int32);
+ for (s=0;s<st->layout.nb_streams;s++)
+ {
+ OpusDecoder *dec;
+
+ dec = (OpusDecoder*)ptr;
+ if (s < st->layout.nb_coupled_streams)
+ ptr += align(coupled_size);
+ else
+ ptr += align(mono_size);
+ ret = opus_decoder_ctl(dec, request, value);
+ if (ret != OPUS_OK)
+ break;
+ }
+ }
+ break;
+ default:
+ ret = OPUS_UNIMPLEMENTED;
+ break;
+ }
+ return ret;
+bad_arg:
+ return OPUS_BAD_ARG;
+}
+
+int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, request);
+ ret = opus_multistream_decoder_ctl_va_list(st, request, ap);
+ va_end(ap);
+ return ret;
+}
+
+void opus_multistream_decoder_destroy(OpusMSDecoder *st)
+{
+ opus_free(st);
+}
--- /dev/null
+/* Copyright (c) 2012 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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 OPUS_PRIVATE_H
+#define OPUS_PRIVATE_H
+
+#include "arch.h"
+#include "opus.h"
+#include "celt.h"
+
+#include <stdarg.h> /* va_list */
+#include <stddef.h> /* offsetof */
+
+struct OpusRepacketizer {
+ unsigned char toc;
+ int nb_frames;
+ const unsigned char *frames[48];
+ opus_int16 len[48];
+ int framesize;
+ const unsigned char *paddings[48];
+ opus_int32 padding_len[48];
+ unsigned char padding_nb_frames[48];
+};
+
+typedef struct OpusExtensionIterator {
+ const unsigned char *data;
+ const unsigned char *curr_data;
+ const unsigned char *repeat_data;
+ const unsigned char *last_long;
+ const unsigned char *src_data;
+ opus_int32 len;
+ opus_int32 curr_len;
+ opus_int32 repeat_len;
+ opus_int32 src_len;
+ opus_int32 trailing_short_len;
+ int nb_frames;
+ int frame_max;
+ int curr_frame;
+ int repeat_frame;
+ unsigned char repeat_l;
+} OpusExtensionIterator;
+
+typedef struct {
+ int id;
+ int frame;
+ const unsigned char *data;
+ opus_int32 len;
+} opus_extension_data;
+
+void opus_extension_iterator_init(OpusExtensionIterator *iter,
+ const unsigned char *data, opus_int32 len, opus_int32 nb_frames);
+
+void opus_extension_iterator_reset(OpusExtensionIterator *iter);
+void opus_extension_iterator_set_frame_max(OpusExtensionIterator *iter,
+ int frame_max);
+int opus_extension_iterator_next(OpusExtensionIterator *iter,
+ opus_extension_data *ext);
+int opus_extension_iterator_find(OpusExtensionIterator *iter,
+ opus_extension_data *ext, int id);
+
+typedef struct ChannelLayout {
+ int nb_channels;
+ int nb_streams;
+ int nb_coupled_streams;
+ unsigned char mapping[256];
+} ChannelLayout;
+
+typedef enum {
+ MAPPING_TYPE_NONE,
+ MAPPING_TYPE_SURROUND,
+ MAPPING_TYPE_AMBISONICS
+} MappingType;
+
+struct OpusMSEncoder {
+ ChannelLayout layout;
+ int arch;
+ int lfe_stream;
+ int application;
+ opus_int32 Fs;
+ int variable_duration;
+ MappingType mapping_type;
+ opus_int32 bitrate_bps;
+ /* Encoder states go here */
+ /* then opus_val32 window_mem[channels*120]; */
+ /* then opus_val32 preemph_mem[channels]; */
+};
+
+struct OpusMSDecoder {
+ ChannelLayout layout;
+ /* Decoder states go here */
+};
+
+int opus_multistream_encoder_ctl_va_list(struct OpusMSEncoder *st, int request,
+ va_list ap);
+int opus_multistream_decoder_ctl_va_list(struct OpusMSDecoder *st, int request,
+ va_list ap);
+
+int validate_layout(const ChannelLayout *layout);
+int get_left_channel(const ChannelLayout *layout, int stream_id, int prev);
+int get_right_channel(const ChannelLayout *layout, int stream_id, int prev);
+int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev);
+
+typedef void (*opus_copy_channel_in_func)(
+ opus_res *dst,
+ int dst_stride,
+ const void *src,
+ int src_stride,
+ int src_channel,
+ int frame_size,
+ void *user_data
+);
+
+typedef void (*opus_copy_channel_out_func)(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_res *src,
+ int src_stride,
+ int frame_size,
+ void *user_data
+);
+
+#define MODE_SILK_ONLY 1000
+#define MODE_HYBRID 1001
+#define MODE_CELT_ONLY 1002
+
+#define OPUS_SET_VOICE_RATIO_REQUEST 11018
+#define OPUS_GET_VOICE_RATIO_REQUEST 11019
+
+/** Configures the encoder's expected percentage of voice
+ * opposed to music or other signals.
+ *
+ * @note This interface is currently more aspiration than actuality. It's
+ * ultimately expected to bias an automatic signal classifier, but it currently
+ * just shifts the static bitrate to mode mapping around a little bit.
+ *
+ * @param[in] x <tt>int</tt>: Voice percentage in the range 0-100, inclusive.
+ * @hideinitializer */
+#define OPUS_SET_VOICE_RATIO(x) OPUS_SET_VOICE_RATIO_REQUEST, opus_check_int(x)
+/** Gets the encoder's configured voice ratio value, @see OPUS_SET_VOICE_RATIO
+ *
+ * @param[out] x <tt>int*</tt>: Voice percentage in the range 0-100, inclusive.
+ * @hideinitializer */
+#define OPUS_GET_VOICE_RATIO(x) OPUS_GET_VOICE_RATIO_REQUEST, opus_check_int_ptr(x)
+
+
+#define OPUS_SET_FORCE_MODE_REQUEST 11002
+#define OPUS_SET_FORCE_MODE(x) OPUS_SET_FORCE_MODE_REQUEST, opus_check_int(x)
+
+typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int);
+void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
+void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
+void downmix_int24(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
+int is_digital_silence(const opus_res* pcm, int frame_size, int channels, int lsb_depth);
+
+void opus_pcm_soft_clip_impl(float *_x, int N, int C, float *declip_mem, int arch);
+
+int encode_size(int size, unsigned char *data);
+
+opus_int32 frame_size_select(int application, opus_int32 frame_size, int variable_duration, opus_int32 Fs);
+
+opus_int32 opus_encode_native(OpusEncoder *st, const opus_res *pcm, int frame_size,
+ unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
+ const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
+ int analysis_channels, downmix_func downmix, int float_api);
+
+int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len,
+ opus_res *pcm, int frame_size, int decode_fec, int self_delimited,
+ opus_int32 *packet_offset, int soft_clip, const OpusDRED *dred, opus_int32 dred_offset);
+
+/* Make sure everything is properly aligned. */
+static OPUS_INLINE int align(int i)
+{
+ struct foo {char c; union { void* p; opus_int32 i; opus_val32 v; } u;};
+
+ unsigned int alignment = offsetof(struct foo, u);
+
+ /* Optimizing compilers should optimize div and multiply into and
+ for all sensible alignment values. */
+ return ((i + alignment - 1) / alignment) * alignment;
+}
+
+int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
+ int self_delimited, unsigned char *out_toc,
+ const unsigned char *frames[48], opus_int16 size[48],
+ int *payload_offset, opus_int32 *packet_offset,
+ const unsigned char **padding, opus_int32 *padding_len);
+
+opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end,
+ unsigned char *data, opus_int32 maxlen, int self_delimited, int pad,
+ const opus_extension_data *extensions, int nb_extensions);
+
+int pad_frame(unsigned char *data, opus_int32 len, opus_int32 new_len);
+
+int opus_multistream_encode_native
+(
+ struct OpusMSEncoder *st,
+ opus_copy_channel_in_func copy_channel_in,
+ const void *pcm,
+ int analysis_frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes,
+ int lsb_depth,
+ downmix_func downmix,
+ int float_api,
+ void *user_data
+);
+
+int opus_multistream_decode_native(
+ struct OpusMSDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ void *pcm,
+ opus_copy_channel_out_func copy_channel_out,
+ int frame_size,
+ int decode_fec,
+ int soft_clip,
+ void *user_data
+);
+
+opus_int32 opus_packet_extensions_parse(const unsigned char *data,
+ opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions,
+ int nb_frames);
+
+opus_int32 opus_packet_extensions_parse_ext(const unsigned char *data,
+ opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions,
+ const opus_int32 *nb_frame_exts, int nb_frames);
+
+opus_int32 opus_packet_extensions_generate(unsigned char *data, opus_int32 len,
+ const opus_extension_data *extensions, opus_int32 nb_extensions,
+ int nb_frames, int pad);
+
+opus_int32 opus_packet_extensions_count(const unsigned char *data,
+ opus_int32 len, int nb_frames);
+
+opus_int32 opus_packet_extensions_count_ext(const unsigned char *data,
+ opus_int32 len, opus_int32 *nb_frame_exts, int nb_frames);
+
+opus_int32 opus_packet_pad_impl(unsigned char *data, opus_int32 len, opus_int32 new_len, int pad, const opus_extension_data *extensions, int nb_extensions);
+
+#endif /* OPUS_PRIVATE_H */
--- /dev/null
+/* Copyright (c) 2017 Google Inc.
+ Written by Andrew Allen */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mathops.h"
+#include "os_support.h"
+#include "opus_private.h"
+#include "opus_defines.h"
+#include "opus_projection.h"
+#include "opus_multistream.h"
+#include "mapping_matrix.h"
+#include "stack_alloc.h"
+
+struct OpusProjectionDecoder
+{
+ opus_int32 demixing_matrix_size_in_bytes;
+ /* Encoder states go here */
+};
+
+#if !defined(DISABLE_FLOAT_API)
+static void opus_projection_copy_channel_out_float(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_res *src,
+ int src_stride,
+ int frame_size,
+ void *user_data)
+{
+ float *float_dst;
+ const MappingMatrix *matrix;
+ float_dst = (float *)dst;
+ matrix = (const MappingMatrix *)user_data;
+
+ if (dst_channel == 0)
+ OPUS_CLEAR(float_dst, frame_size * dst_stride);
+
+ if (src != NULL)
+ mapping_matrix_multiply_channel_out_float(matrix, src, dst_channel,
+ src_stride, float_dst, dst_stride, frame_size);
+}
+#endif
+
+static void opus_projection_copy_channel_out_short(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_res *src,
+ int src_stride,
+ int frame_size,
+ void *user_data)
+{
+ opus_int16 *short_dst;
+ const MappingMatrix *matrix;
+ short_dst = (opus_int16 *)dst;
+ matrix = (const MappingMatrix *)user_data;
+ if (dst_channel == 0)
+ OPUS_CLEAR(short_dst, frame_size * dst_stride);
+
+ if (src != NULL)
+ mapping_matrix_multiply_channel_out_short(matrix, src, dst_channel,
+ src_stride, short_dst, dst_stride, frame_size);
+}
+
+static void opus_projection_copy_channel_out_int24(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_res *src,
+ int src_stride,
+ int frame_size,
+ void *user_data)
+{
+ opus_int32 *short_dst;
+ const MappingMatrix *matrix;
+ short_dst = (opus_int32 *)dst;
+ matrix = (const MappingMatrix *)user_data;
+ if (dst_channel == 0)
+ OPUS_CLEAR(short_dst, frame_size * dst_stride);
+
+ if (src != NULL)
+ mapping_matrix_multiply_channel_out_int24(matrix, src, dst_channel,
+ src_stride, short_dst, dst_stride, frame_size);
+}
+
+static MappingMatrix *get_dec_demixing_matrix(OpusProjectionDecoder *st)
+{
+ /* void* cast avoids clang -Wcast-align warning */
+ return (MappingMatrix*)(void*)((char*)st +
+ align(sizeof(OpusProjectionDecoder)));
+}
+
+static OpusMSDecoder *get_multistream_decoder(OpusProjectionDecoder *st)
+{
+ /* void* cast avoids clang -Wcast-align warning */
+ return (OpusMSDecoder*)(void*)((char*)st +
+ align(sizeof(OpusProjectionDecoder) +
+ st->demixing_matrix_size_in_bytes));
+}
+
+opus_int32 opus_projection_decoder_get_size(int channels, int streams,
+ int coupled_streams)
+{
+ opus_int32 matrix_size;
+ opus_int32 decoder_size;
+
+ matrix_size =
+ mapping_matrix_get_size(streams + coupled_streams, channels);
+ if (!matrix_size)
+ return 0;
+
+ decoder_size = opus_multistream_decoder_get_size(streams, coupled_streams);
+ if (!decoder_size)
+ return 0;
+
+ return align(sizeof(OpusProjectionDecoder)) + matrix_size + decoder_size;
+}
+
+int opus_projection_decoder_init(OpusProjectionDecoder *st, opus_int32 Fs,
+ int channels, int streams, int coupled_streams,
+ unsigned char *demixing_matrix, opus_int32 demixing_matrix_size)
+{
+ int nb_input_streams;
+ opus_int32 expected_matrix_size;
+ int i, ret;
+ unsigned char mapping[255];
+ VARDECL(opus_int16, buf);
+ ALLOC_STACK;
+
+ /* Verify supplied matrix size. */
+ nb_input_streams = streams + coupled_streams;
+ expected_matrix_size = nb_input_streams * channels * sizeof(opus_int16);
+ if (expected_matrix_size != demixing_matrix_size)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+
+ /* Convert demixing matrix input into internal format. */
+ ALLOC(buf, nb_input_streams * channels, opus_int16);
+ for (i = 0; i < nb_input_streams * channels; i++)
+ {
+ int s = demixing_matrix[2*i + 1] << 8 | demixing_matrix[2*i];
+ s = ((s & 0xFFFF) ^ 0x8000) - 0x8000;
+ buf[i] = (opus_int16)s;
+ }
+
+ /* Assign demixing matrix. */
+ st->demixing_matrix_size_in_bytes =
+ mapping_matrix_get_size(channels, nb_input_streams);
+ if (!st->demixing_matrix_size_in_bytes)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+
+ mapping_matrix_init(get_dec_demixing_matrix(st), channels, nb_input_streams, 0,
+ buf, demixing_matrix_size);
+
+ /* Set trivial mapping so each input channel pairs with a matrix column. */
+ for (i = 0; i < channels; i++)
+ mapping[i] = i;
+
+ ret = opus_multistream_decoder_init(
+ get_multistream_decoder(st), Fs, channels, streams, coupled_streams, mapping);
+ RESTORE_STACK;
+ return ret;
+}
+
+OpusProjectionDecoder *opus_projection_decoder_create(
+ opus_int32 Fs, int channels, int streams, int coupled_streams,
+ unsigned char *demixing_matrix, opus_int32 demixing_matrix_size, int *error)
+{
+ int size;
+ int ret;
+ OpusProjectionDecoder *st;
+
+ /* Allocate space for the projection decoder. */
+ size = opus_projection_decoder_get_size(channels, streams, coupled_streams);
+ if (!size) {
+ if (error)
+ *error = OPUS_ALLOC_FAIL;
+ return NULL;
+ }
+ st = (OpusProjectionDecoder *)opus_alloc(size);
+ if (!st)
+ {
+ if (error)
+ *error = OPUS_ALLOC_FAIL;
+ return NULL;
+ }
+
+ /* Initialize projection decoder with provided settings. */
+ ret = opus_projection_decoder_init(st, Fs, channels, streams, coupled_streams,
+ demixing_matrix, demixing_matrix_size);
+ if (ret != OPUS_OK)
+ {
+ opus_free(st);
+ st = NULL;
+ }
+ if (error)
+ *error = ret;
+ return st;
+}
+
+#ifdef FIXED_POINT
+#define OPTIONAL_CLIP 0
+#else
+#define OPTIONAL_CLIP 1
+#endif
+
+int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
+ opus_int32 len, opus_int16 *pcm, int frame_size,
+ int decode_fec)
+{
+ return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
+ pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, OPTIONAL_CLIP,
+ get_dec_demixing_matrix(st));
+}
+
+int opus_projection_decode24(OpusProjectionDecoder *st, const unsigned char *data,
+ opus_int32 len, opus_int32 *pcm, int frame_size,
+ int decode_fec)
+{
+ return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
+ pcm, opus_projection_copy_channel_out_int24, frame_size, decode_fec, 0,
+ get_dec_demixing_matrix(st));
+}
+
+#ifndef DISABLE_FLOAT_API
+int opus_projection_decode_float(OpusProjectionDecoder *st, const unsigned char *data,
+ opus_int32 len, float *pcm, int frame_size, int decode_fec)
+{
+ return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
+ pcm, opus_projection_copy_channel_out_float, frame_size, decode_fec, 0,
+ get_dec_demixing_matrix(st));
+}
+#endif
+
+int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...)
+{
+ va_list ap;
+ int ret = OPUS_OK;
+
+ va_start(ap, request);
+ ret = opus_multistream_decoder_ctl_va_list(get_multistream_decoder(st),
+ request, ap);
+ va_end(ap);
+ return ret;
+}
+
+void opus_projection_decoder_destroy(OpusProjectionDecoder *st)
+{
+ opus_free(st);
+}
--- /dev/null
+/* Copyright (c) 2011 Xiph.Org Foundation
+ Written by Jean-Marc Valin */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - 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.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``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 COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "opus.h"
+#include "opus_private.h"
+#include "os_support.h"
+#include "stack_alloc.h"
+
+
+int opus_repacketizer_get_size(void)
+{
+ return sizeof(OpusRepacketizer);
+}
+
+OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp)
+{
+ rp->nb_frames = 0;
+ return rp;
+}
+
+OpusRepacketizer *opus_repacketizer_create(void)
+{
+ OpusRepacketizer *rp;
+ rp=(OpusRepacketizer *)opus_alloc(opus_repacketizer_get_size());
+ if(rp==NULL)return NULL;
+ return opus_repacketizer_init(rp);
+}
+
+void opus_repacketizer_destroy(OpusRepacketizer *rp)
+{
+ opus_free(rp);
+}
+
+static int opus_repacketizer_cat_impl(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len, int self_delimited)
+{
+ unsigned char tmp_toc;
+ int curr_nb_frames,ret;
+ /* Set of check ToC */
+ if (len<1) return OPUS_INVALID_PACKET;
+ if (rp->nb_frames == 0)
+ {
+ rp->toc = data[0];
+ rp->framesize = opus_packet_get_samples_per_frame(data, 8000);
+ } else if ((rp->toc&0xFC) != (data[0]&0xFC))
+ {
+ /*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp->toc, data[0]);*/
+ return OPUS_INVALID_PACKET;
+ }
+ curr_nb_frames = opus_packet_get_nb_frames(data, len);
+ if(curr_nb_frames<1) return OPUS_INVALID_PACKET;
+
+ /* Check the 120 ms maximum packet size */
+ if ((curr_nb_frames+rp->nb_frames)*rp->framesize > 960)
+ {
+ return OPUS_INVALID_PACKET;
+ }
+
+ ret=opus_packet_parse_impl(data, len, self_delimited, &tmp_toc, &rp->frames[rp->nb_frames], &rp->len[rp->nb_frames],
+ NULL, NULL, &rp->paddings[rp->nb_frames], &rp->padding_len[rp->nb_frames]);
+ if(ret<1)return ret;
+ rp->padding_nb_frames[rp->nb_frames]=ret;
+
+ /* set padding length to zero for all but the first frame */
+ while (curr_nb_frames > 1)
+ {
+ rp->nb_frames++;
+ rp->padding_len[rp->nb_frames] = 0;
+ rp->padding_nb_frames[rp->nb_frames] = 0;
+ rp->paddings[rp->nb_frames] = NULL;
+ curr_nb_frames--;
+ }
+ rp->nb_frames++;
+ return OPUS_OK;
+}
+
+int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len)
+{
+ return opus_repacketizer_cat_impl(rp, data, len, 0);
+}
+
+int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp)
+{
+ return rp->nb_frames;
+}
+
+opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end,
+ unsigned char *data, opus_int32 maxlen, int self_delimited, int pad, const opus_extension_data *extensions, int nb_extensions)
+{
+ int i, count;
+ opus_int32 tot_size;
+ opus_int16 *len;
+ const unsigned char **frames;
+ unsigned char * ptr;
+ int ones_begin=0, ones_end=0;
+ int ext_begin=0, ext_len=0;
+ int ext_count, total_ext_count;
+ VARDECL(opus_extension_data, all_extensions);
+ SAVE_STACK;
+
+ if (begin<0 || begin>=end || end>rp->nb_frames)
+ {
+ /*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+ count = end-begin;
+
+ len = rp->len+begin;
+ frames = rp->frames+begin;
+ if (self_delimited)
+ tot_size = 1 + (len[count-1]>=252);
+ else
+ tot_size = 0;
+
+ /* figure out total number of extensions */
+ total_ext_count = nb_extensions;
+ for (i=begin;i<end;i++)
+ {
+ int n = opus_packet_extensions_count(rp->paddings[i], rp->padding_len[i],
+ rp->padding_nb_frames[i]);
+ if (n > 0) total_ext_count += n;
+ }
+ ALLOC(all_extensions, total_ext_count ? total_ext_count : ALLOC_NONE, opus_extension_data);
+ /* copy over any extensions that were passed in */
+ for (ext_count=0;ext_count<nb_extensions;ext_count++)
+ {
+ all_extensions[ext_count] = extensions[ext_count];
+ }
+
+ /* incorporate any extensions from the repacketizer padding */
+ for (i=begin;i<end;i++)
+ {
+ int j, ret;
+ opus_int32 frame_ext_count;
+ frame_ext_count = total_ext_count - ext_count;
+ ret = opus_packet_extensions_parse(rp->paddings[i], rp->padding_len[i],
+ &all_extensions[ext_count], &frame_ext_count, rp->padding_nb_frames[i]);
+ if (ret<0)
+ {
+ RESTORE_STACK;
+ return OPUS_INTERNAL_ERROR;
+ }
+ /* renumber the extension frame numbers */
+ for (j=0;j<frame_ext_count;j++)
+ {
+ all_extensions[ext_count+j].frame += i-begin;
+ }
+ ext_count += frame_ext_count;
+ }
+
+ ptr = data;
+ if (count==1)
+ {
+ /* Code 0 */
+ tot_size += len[0]+1;
+ if (tot_size > maxlen)
+ {
+ RESTORE_STACK;
+ return OPUS_BUFFER_TOO_SMALL;
+ }
+ *ptr++ = rp->toc&0xFC;
+ } else if (count==2)
+ {
+ if (len[1] == len[0])
+ {
+ /* Code 1 */
+ tot_size += 2*len[0]+1;
+ if (tot_size > maxlen)
+ {
+ RESTORE_STACK;
+ return OPUS_BUFFER_TOO_SMALL;
+ }
+ *ptr++ = (rp->toc&0xFC) | 0x1;
+ } else {
+ /* Code 2 */
+ tot_size += len[0]+len[1]+2+(len[0]>=252);
+ if (tot_size > maxlen)
+ {
+ RESTORE_STACK;
+ return OPUS_BUFFER_TOO_SMALL;
+ }
+ *ptr++ = (rp->toc&0xFC) | 0x2;
+ ptr += encode_size(len[0], ptr);
+ }
+ }
+ if (count > 2 || (pad && tot_size < maxlen) || ext_count > 0)
+ {
+ /* Code 3 */
+ int vbr;
+ int pad_amount=0;
+
+ /* Restart the process for the padding case */
+ ptr = data;
+ if (self_delimited)
+ tot_size = 1 + (len[count-1]>=252);
+ else
+ tot_size = 0;
+ vbr = 0;
+ for (i=1;i<count;i++)
+ {
+ if (len[i] != len[0])
+ {
+ vbr=1;
+ break;
+ }
+ }
+ if (vbr)
+ {
+ tot_size += 2;
+ for (i=0;i<count-1;i++)
+ tot_size += 1 + (len[i]>=252) + len[i];
+ tot_size += len[count-1];
+
+ if (tot_size > maxlen)
+ {
+ RESTORE_STACK;
+ return OPUS_BUFFER_TOO_SMALL;
+ }
+ *ptr++ = (rp->toc&0xFC) | 0x3;
+ *ptr++ = count | 0x80;
+ } else {
+ tot_size += count*len[0]+2;
+ if (tot_size > maxlen)
+ {
+ RESTORE_STACK;
+ return OPUS_BUFFER_TOO_SMALL;
+ }
+ *ptr++ = (rp->toc&0xFC) | 0x3;
+ *ptr++ = count;
+ }
+ pad_amount = pad ? (maxlen-tot_size) : 0;
+ if (ext_count>0)
+ {
+ /* figure out how much space we need for the extensions */
+ ext_len = opus_packet_extensions_generate(NULL, maxlen-tot_size,
+ all_extensions, ext_count, count, 0);
+ if (ext_len < 0) return ext_len;
+ if (!pad)
+ pad_amount = ext_len + (ext_len ? (ext_len+253)/254 : 1);
+ }
+ if (pad_amount != 0)
+ {
+ int nb_255s;
+ data[1] |= 0x40;
+ nb_255s = (pad_amount-1)/255;
+ if (tot_size + ext_len + nb_255s + 1 > maxlen)
+ {
+ RESTORE_STACK;
+ return OPUS_BUFFER_TOO_SMALL;
+ }
+ ext_begin = tot_size+pad_amount-ext_len;
+ /* Prepend 0x01 padding */
+ ones_begin = tot_size+nb_255s+1;
+ ones_end = tot_size+pad_amount-ext_len;
+ for (i=0;i<nb_255s;i++)
+ *ptr++ = 255;
+ *ptr++ = pad_amount-255*nb_255s-1;
+ tot_size += pad_amount;
+ }
+ if (vbr)
+ {
+ for (i=0;i<count-1;i++)
+ ptr += encode_size(len[i], ptr);
+ }
+ }
+ if (self_delimited) {
+ int sdlen = encode_size(len[count-1], ptr);
+ ptr += sdlen;
+ }
+ /* Copy the actual data */
+ for (i=0;i<count;i++)
+ {
+ /* Using OPUS_MOVE() instead of OPUS_COPY() in case we're doing in-place
+ padding from opus_packet_pad or opus_packet_unpad(). */
+ /* assert disabled because it's not valid in C. */
+ /* celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]); */
+ OPUS_MOVE(ptr, frames[i], len[i]);
+ ptr += len[i];
+ }
+ if (ext_len > 0) {
+ int ret = opus_packet_extensions_generate(&data[ext_begin], ext_len,
+ all_extensions, ext_count, count, 0);
+ celt_assert(ret == ext_len);
+ }
+ for (i=ones_begin;i<ones_end;i++)
+ data[i] = 0x01;
+ if (pad && ext_count==0)
+ {
+ /* Fill padding with zeros. */
+ while (ptr<data+maxlen)
+ *ptr++=0;
+ }
+ RESTORE_STACK;
+ return tot_size;
+}
+
+opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen)
+{
+ return opus_repacketizer_out_range_impl(rp, begin, end, data, maxlen, 0, 0, NULL, 0);
+}
+
+opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen)
+{
+ return opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, maxlen, 0, 0, NULL, 0);
+}
+
+opus_int32 opus_packet_pad_impl(unsigned char *data, opus_int32 len, opus_int32 new_len, int pad, const opus_extension_data *extensions, int nb_extensions)
+{
+ OpusRepacketizer rp;
+ opus_int32 ret;
+ VARDECL(unsigned char, copy);
+ SAVE_STACK;
+ if (len < 1)
+ return OPUS_BAD_ARG;
+ if (len==new_len)
+ return OPUS_OK;
+ else if (len > new_len)
+ return OPUS_BAD_ARG;
+ ALLOC(copy, len, unsigned char);
+ opus_repacketizer_init(&rp);
+ /* Moving payload to the end of the packet so we can do in-place padding */
+ OPUS_COPY(copy, data, len);
+ ret = opus_repacketizer_cat(&rp, copy, len);
+ if (ret != OPUS_OK)
+ return ret;
+ ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, pad, extensions, nb_extensions);
+ RESTORE_STACK;
+ return ret;
+}
+
+int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len)
+{
+ opus_int32 ret;
+ ALLOC_STACK;
+ ret = opus_packet_pad_impl(data, len, new_len, 1, NULL, 0);
+ RESTORE_STACK;
+ if (ret > 0)
+ return OPUS_OK;
+ else
+ return ret;
+}
+
+opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len)
+{
+ OpusRepacketizer rp;
+ opus_int32 ret;
+ int i;
+ if (len < 1)
+ return OPUS_BAD_ARG;
+ opus_repacketizer_init(&rp);
+ ret = opus_repacketizer_cat(&rp, data, len);
+ if (ret < 0)
+ return ret;
+ /* Discard all padding and extensions. */
+ for (i=0;i<rp.nb_frames;i++) {
+ rp.padding_len[i] = 0;
+ rp.paddings[i] = NULL;
+ }
+ ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 0, NULL, 0);
+ celt_assert(ret > 0 && ret <= len);
+ return ret;
+}
+
+int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams)
+{
+ int s;
+ int count;
+ unsigned char toc;
+ opus_int16 size[48];
+ opus_int32 packet_offset;
+ opus_int32 amount;
+
+ if (len < 1)
+ return OPUS_BAD_ARG;
+ if (len==new_len)
+ return OPUS_OK;
+ else if (len > new_len)
+ return OPUS_BAD_ARG;
+ amount = new_len - len;
+ /* Seek to last stream */
+ for (s=0;s<nb_streams-1;s++)
+ {
+ if (len<=0)
+ return OPUS_INVALID_PACKET;
+ count = opus_packet_parse_impl(data, len, 1, &toc, NULL,
+ size, NULL, &packet_offset, NULL, NULL);
+ if (count<0)
+ return count;
+ data += packet_offset;
+ len -= packet_offset;
+ }
+ return opus_packet_pad(data, len, len+amount);
+}
+
+opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams)
+{
+ int s;
+ unsigned char toc;
+ opus_int16 size[48];
+ opus_int32 packet_offset;
+ OpusRepacketizer rp;
+ unsigned char *dst;
+ opus_int32 dst_len;
+
+ if (len < 1)
+ return OPUS_BAD_ARG;
+ dst = data;
+ dst_len = 0;
+ /* Unpad all frames */
+ for (s=0;s<nb_streams;s++)
+ {
+ opus_int32 ret;
+ int i;
+ int self_delimited = s!=nb_streams-1;
+ if (len<=0)
+ return OPUS_INVALID_PACKET;
+ opus_repacketizer_init(&rp);
+ ret = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
+ size, NULL, &packet_offset, NULL, NULL);
+ if (ret<0)
+ return ret;
+ ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited);
+ if (ret < 0)
+ return ret;
+ /* Discard all padding and extensions. */
+ for (i=0;i<rp.nb_frames;i++) {
+ rp.padding_len[i] = 0;
+ rp.paddings[i] = NULL;
+ }
+ ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, dst, len, self_delimited, 0, NULL, 0);
+ if (ret < 0)
+ return ret;
+ else
+ dst_len += ret;
+ dst += ret;
+ data += packet_offset;
+ len -= packet_offset;
+ }
+ return dst_len;
+}