summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChisato Kenmochi <Chisato.Kenmochi@sony.com>2017-03-28 05:10:23 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-03-28 05:10:23 +0000
commit147d610ad346a9895c0e5776fd5169780c98ab9f (patch)
tree8c841292dbdb5f6b5e611b971cff0808cd062a9d
parent9e776a0f9f9524932a6e15a16c7de72920a17c56 (diff)
parentb4f70c5b723ddd3e7b4785e81cb0120d5d8fd861 (diff)
downloadlibldac-147d610ad346a9895c0e5776fd5169780c98ab9f.tar.gz
Contribution of LDAC Adaptive Bit Rate am: 878aad2a83
am: b4f70c5b72 Change-Id: Ia9a0cbf958274082652dd0f2e60accb91b8f964c
-rw-r--r--Android.bp13
-rw-r--r--abr/inc/ldacBT_abr.h163
-rw-r--r--abr/src/ldacBT_abr.c355
-rw-r--r--src/ldaclib_api.c15
4 files changed, 546 insertions, 0 deletions
diff --git a/Android.bp b/Android.bp
index 86d3b14..e159c7f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,3 +14,16 @@ cc_library_shared {
// unit such as ARM Cortex-R series or external 32-bit DSPs.
cflags: ["-O2", "-Werror", "-Wall", "-Wextra"],
}
+
+cc_library_shared {
+ name: "libldacBT_abr",
+ arch: {
+ arm: {
+ instruction_set: "arm",
+ },
+ },
+ export_include_dirs: ["abr/inc"],
+ srcs: ["abr/src/ldacBT_abr.c"],
+ shared_libs: ["libldacBT_enc"],
+ cflags: ["-O2", "-Werror", "-Wall", "-Wextra"]
+}
diff --git a/abr/inc/ldacBT_abr.h b/abr/inc/ldacBT_abr.h
new file mode 100644
index 0000000..135238f
--- /dev/null
+++ b/abr/inc/ldacBT_abr.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2014 - 2017 Sony Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LDACBT_ABR_H_
+#define _LDACBT_ABR_H_
+
+/* This file contains the definitions, declarations and macros for an implementation of
+ * LDAC Adaptive Bit Rate (hereinafter ABR) processing.
+ *
+ * The basic flow of the ABR processing is as follows:
+ * - The program creates a handle of LDAC ABR API using ldac_ABR_get_handle().
+ * - The program initializes the handle by setting the ldac_ABR_Proc() call interval to
+ * ldac_ABR_Init().
+ * The interval shall be as short as possible at the timing without accumulation
+ * of packet in the buffer if propagation environment is fine.
+ * - The program reinitializes the handle by calling ldac_ABR_Init() again when the
+ * state of the TX queue changes greatly, such as clearing the queue.
+ * - If the program demands to control the thresholds, then ldac_ABR_set_thresholds()
+ * should be called.
+ * - The program sets flagEnable to "1" when allowing LDAC encode bitrate to be
+ * adjusted by ABR, and sets it to "0" if it is not allowed.
+ * - The program calls ldac_ABR_Proc() at the interval set to ldac_ABR_Init() even if
+ * flagEnable is "0".
+ * The program passes TxQueueDepth and flagEnable to ldac_ABR_Proc() at this call,
+ * LDAC encode bitrate is adjusted only when flagEnable is "1".
+ * Otherwise, the internal parameters are updated and analyzed then returned.
+ * The ABR handle adjusts eqmid based on TxQueueDepth which is passed from the program.
+ * The ABR handle calls LDAC encode API ldacBT_alter_eqmid_priority() to adjust eqmid.
+ * The ABR handle calls LDAC encode API ldacBT_get_eqmid() to get current eqmid.
+ * - The handle may be released with ldac_ABR_free_handle().
+ *
+ * Notes on debugging LDAC ABR:
+ * The meaning of "works fine" is that the bit rate will be low in case of bad radio situation
+ * and high in case of good radio situation.
+ *
+ * The bit rate transition can be debug by checking logcat messages from LDAC ABR library which
+ * built with the following changes in Android.bp:
+ * - Adding "liblog" to shared_libs.
+ * - Adding "-DLOCAL_DEBUG" to cflags.
+ * The messages are formated as follows:
+ * [LDAC ABR] - abrQualityModeID : 0 -- eqmid : 0 -- TxQue : 0
+ * where abrQualityModeID and eqmid related to the current bit rate and TxQue shows the depth
+ * of current Tx queue.
+ * The relationship between abrQualityModeID, eqmid and the bit rate is described in
+ * "ldacBT_abr.c".
+ *
+ * The bit rate transition can be estimated/debug by listening to the audio played on the SNK
+ * device. This method cannot use to confirm the details of the bit rate transition, but useful
+ * to know how LDAC ABR algorithm works in a field test without checking the log.
+ * To try this method, rebuilding of the "libldacBT_enc" library with the following change in
+ * Android.bp is required:
+ * - Adding "-DUSE_LDAC_ENC_SETTING_FOR_ABR_DEBUG" to cflags.
+ * By defining the above macro, the lower the bit rate, the greatly lower the bandwidth of the audio
+ * played on the SNK device. Therefore, the audio played on the SNK device will sounds like a
+ * low-pass filtered sound when the bit rate is low and will sounds as usual when the bit rate is
+ * enough high. It is recommend using sound such as white noise to hear those changes for the first
+ * time.
+ *
+ * IMPORTANT:
+ * These libraries modified as described above shall be used only to confirm the bit rate transition
+ * and SHALL NOT BE USED FOR FINAL PRODUCTS.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LDAC_ABR_API
+#define LDAC_ABR_API
+#endif /* LDAC_ABR_API */
+
+#include <ldacBT.h> /* HANDLE_LDAC_BT */
+
+/* LDAC ABR handle type*/
+typedef struct _ldacbt_abr_param * HANDLE_LDAC_ABR;
+
+/* Allocation of LDAC ABR handle.
+ * Format
+ * HANDLE_LDAC_ABR ldacBT_get_handle( void );
+ * Arguments
+ * None.
+ * Return value
+ * HANDLE_LDAC_ABR for success, NULL for failure.
+ */
+LDAC_ABR_API HANDLE_LDAC_ABR ldac_ABR_get_handle(void);
+
+/* Release of LDAC ABR handle.
+ * Format
+ * void ldac_ABR_free_handle( HANDLE_LDAC_ABR );
+ * Arguments
+ * hLdacAbr HANDLE_LDAC_ABR LDAC ABR handle.
+ * Return value
+ * None.
+ */
+LDAC_ABR_API void ldac_ABR_free_handle(HANDLE_LDAC_ABR hLdacAbr);
+
+/* Initialize LDAC ABR.
+ * Format
+ * int ldac_ABR_Init( HANDLE_LDAC_ABR, unsigned int );
+ * Arguments
+ * hLdacAbr HANDLE_LDAC_ABR LDAC ABR handle.
+ * interval_ms unsigned int interval in ms for calling ldac_ABR_Proc().
+ * interval of 1ms to 500ms is valid.
+ * Return value
+ * int: 0 for success, -1 for failure.
+ */
+LDAC_ABR_API int ldac_ABR_Init(HANDLE_LDAC_ABR hLdacAbr, unsigned int interval_ms);
+
+/* Setup thresholds for LDAC ABR.
+ * Format
+ * int ldac_ABR_set_thresholds( HANDLE_LDAC_ABR, unsigned int, unsigned int, unsigned int );
+ * Arguments
+ * hLdacAbr HANDLE_LDAC_ABR LDAC ABR handle.
+ * thCritical unsigned int threshold for critical TxQueueDepth status.
+ * thDangerousTrend unsigned int threshold for dangerous trend of TxQueueDepth.
+ * thSafety4HQSQ unsigned int safety threshold for LDACBT_EQMID_HQ and
+ * LDACBT_EQMID_SQ.
+ * Return value
+ * int: 0 for success, -1 for failure.
+ * Remarks
+ * Those thresholds should be the number of packets stored in the TX queue and should be
+ * greater than 0.
+ * The thCritical and thDangerousTrend are used for all eqmid and thSafety4HQSQ is used
+ * only for LDACBT_EQMID_HQ and LDACBT_EQMID_SQ. Therefore, those thresholds must satisfy
+ * the following releationship:
+ * thCritical >= thDangerousTrend >= thSafety4HQSQ
+ */
+LDAC_ABR_API int ldac_ABR_set_thresholds(HANDLE_LDAC_ABR hLdacAbr, unsigned int thCritical,
+ unsigned int thDangerousTrend, unsigned int thSafety4HQSQ);
+
+/* LDAC ABR main process.
+ * Format
+ * int ldac_ABR_Proc( HANDLE_LDAC_BT, HANDLE_LDAC_ABR, unsigned int, unsigned int );
+ * Arguments
+ * hLdacBt HANDLE_LDAC_BT LDAC handle.
+ * hLdacAbr HANDLE_LDAC_ABR LDAC ABR handle.
+ * TxQueueDepth unsigned int depth of TX queue.
+ * flagEnable unsigned int flag indicating whether ABR is allowed to adjust LDAC
+ * encode bitrate
+ * Return value
+ * int: updated Encode Quality Mode Index for success, -1 for failure.
+ */
+LDAC_ABR_API int ldac_ABR_Proc(HANDLE_LDAC_BT hLdacBt, HANDLE_LDAC_ABR hLdacAbr,
+ unsigned int TxQueueDepth, unsigned int flagEnable);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LDACBT_ABR_H_ */
+
diff --git a/abr/src/ldacBT_abr.c b/abr/src/ldacBT_abr.c
new file mode 100644
index 0000000..b9bf4be
--- /dev/null
+++ b/abr/src/ldacBT_abr.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2014 - 2017 Sony Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ldacBT_abr.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define LDAC_ABR_OBSERVING_TIME_MS 500 /* [ms] the time length for storing Tx Queue Depth */
+#define LDAC_ABR_PENALTY_MAX 4
+
+/* Number of observing count to judge whether EQMID may be increase.
+ * Those count can convert in time by following formula:
+ * Time [ms] = (Count - abrQualityModeID) * LDAC_ABR_OBSERVING_TIME_MS
+ * where abrQualityModeID is the value which converted EQMID by aEqmidToAbrQualityModeID[].
+ * Therefore, using the default value of 12, the observation time in each abrQualityModeID is
+ * as follows:
+ * ----------------------------------------------------
+ * | abrQualityModeID | 0 | 1 | 2 | 3 | 4 |
+ * | observation time [s] | 6 | 5 | 4 | 3 | 2 |
+ * ----------------------------------------------------
+ */
+#define LDAC_ABR_OBSERVING_COUNT_TO_JUDGE_INC_QUALITY 12
+#define LDAC_ABR_OBSERVING_COUNT_FOR_INIT 6 /* = 3sec. keep same EQMID in first 3sec */
+/* Default value for thresholds */
+#define LDAC_ABR_THRESHOLD_CRITICAL_DEFAULT 6
+#define LDAC_ABR_THRESHOLD_DANGEROUSTREND_DEFAULT 4
+#define LDAC_ABR_THRESHOLD_SAFETY_FOR_HQSQ_DEFAULT 2
+/* Number of steady state count to judge */
+#define LDAC_ABR_NUM_STEADY_STATE_TO_JUDGE_STEADY 3
+/* Number of steady state count to reset for LDACBT_EQMID_HQ */
+#define LDAC_ABR_NUM_STEADY_STATE_TO_RESET_PENALTY_FOR_HQ 60
+
+
+typedef struct _tx_queue_param
+{
+ unsigned char *pHist;
+ unsigned int szHist;
+ int sum;
+ unsigned int cnt;
+ unsigned int idx;
+} TxQ_INFO;
+
+typedef struct _ldacbt_abr_param
+{
+ TxQ_INFO TxQD_Info;
+ int cntToIncQuality;
+ int nSteadyState;
+ int nPenalty;
+ int abrQualityModeIdSteady;
+ unsigned int numToEvaluate;
+ /* thresholds */
+ unsigned int thCritical;
+ unsigned int thDangerousTrend;
+ unsigned int thSafety4HQSQ;
+} LDAC_ABR_PARAMS;
+
+#define clear_data(ptr, n) memset(ptr, 0, n)
+
+#ifdef LOCAL_DEBUG
+#include <android/log.h>
+#define ABRDBG(fmt, ... ) \
+ __android_log_print( ANDROID_LOG_INFO, "******** LDAC ABR ********",\
+ "%s@%s:%d::"fmt, __func__, __FILE__, __LINE__, ## __VA_ARGS__ )
+#else
+#define ABRDBG(fmt, ...)
+#endif /* LOCAL_DEBUG */
+
+/* A table for converting EQMID to abrQualityModeID which is sorted in descending order by bit rate.
+ * The relationship between EQMID, bit rate and abrQualityModeID when the sampling frequency is
+ * 96 kHz is as follows:
+ * ----------------------------------------------------
+ * | EQMID | 0 | 1 | 2 | 3 | 4 |
+ * | bit rate [kbps] | 990 | 660 | 330 | 492 | 396 |
+ * | abrQualityModeID | 0 | 1 | 4 | 2 | 3 |
+ * ----------------------------------------------------
+ */
+static const int aEqmidToAbrQualityModeID[]={ 0, 1, 4, 2, 3};
+static const int sizeOfEqmidToBitrateSortedIdTable = (int)(sizeof(aEqmidToAbrQualityModeID)
+ / sizeof(aEqmidToAbrQualityModeID[0]));
+
+/* Get LDAC ABR handle */
+HANDLE_LDAC_ABR ldac_ABR_get_handle(void)
+{
+ HANDLE_LDAC_ABR hLdacAbr;
+ ABRDBG( "" );
+ if ((hLdacAbr = (HANDLE_LDAC_ABR)malloc(sizeof(LDAC_ABR_PARAMS))) == NULL) {
+ ABRDBG( "[ERR] Failed to allocate memory for handle." );
+ return NULL;
+ }
+ hLdacAbr->TxQD_Info.pHist = NULL;
+ return hLdacAbr;
+}
+
+/* Free LDAC ABR handle */
+void ldac_ABR_free_handle(HANDLE_LDAC_ABR hLdacAbr)
+{
+ ABRDBG( "" );
+ if (hLdacAbr != NULL) {
+ if (hLdacAbr->TxQD_Info.pHist) {
+ free(hLdacAbr->TxQD_Info.pHist);
+ }
+ free(hLdacAbr);
+ }
+}
+
+/* Initialize LDAC ABR */
+int ldac_ABR_Init( HANDLE_LDAC_ABR hLdacAbr, unsigned int interval_ms )
+{
+ ABRDBG( "hLdacAbr:0x%x, interval_ms:%u", (unsigned int)hLdacAbr, interval_ms );
+ if (hLdacAbr == NULL) return -1;
+ if (interval_ms == 0) return -1;
+ if (interval_ms > LDAC_ABR_OBSERVING_TIME_MS) return -1;
+
+ hLdacAbr->numToEvaluate = LDAC_ABR_OBSERVING_TIME_MS / interval_ms;
+ hLdacAbr->TxQD_Info.sum = 0;
+ hLdacAbr->TxQD_Info.cnt = 0;
+ hLdacAbr->TxQD_Info.idx = 0;
+ hLdacAbr->TxQD_Info.szHist = hLdacAbr->numToEvaluate + 1;
+ if (hLdacAbr->TxQD_Info.pHist) free(hLdacAbr->TxQD_Info.pHist);
+ if ((hLdacAbr->TxQD_Info.pHist =
+ (unsigned char*)malloc(hLdacAbr->TxQD_Info.szHist * sizeof(unsigned char))) == NULL){
+ return -1;
+ }
+ clear_data(hLdacAbr->TxQD_Info.pHist, hLdacAbr->TxQD_Info.szHist * sizeof(unsigned char));
+
+ hLdacAbr->nSteadyState = 0;
+ hLdacAbr->nPenalty = 1;
+ hLdacAbr->abrQualityModeIdSteady = aEqmidToAbrQualityModeID[LDACBT_EQMID_HQ];
+ hLdacAbr->cntToIncQuality = LDAC_ABR_OBSERVING_COUNT_FOR_INIT;
+ /* thresholds */
+ hLdacAbr->thCritical = LDAC_ABR_THRESHOLD_CRITICAL_DEFAULT;
+ hLdacAbr->thDangerousTrend = LDAC_ABR_THRESHOLD_DANGEROUSTREND_DEFAULT;
+ hLdacAbr->thSafety4HQSQ = LDAC_ABR_THRESHOLD_SAFETY_FOR_HQSQ_DEFAULT;
+
+ return 0;
+}
+
+/* Setup thresholds for LDAC ABR */
+int ldac_ABR_set_thresholds( HANDLE_LDAC_ABR hLdacAbr, unsigned int thCritical,
+ unsigned int thDangerousTrend, unsigned int thSafety4HQSQ )
+{
+ ABRDBG( "thCritical=%u, thDangerousTrend=%u, thSafety4HQSQ=%u",
+ thCritical, thDangerousTrend, thSafety4HQSQ);
+ if (hLdacAbr == NULL) return -1;
+ if (thCritical < thDangerousTrend) return -1;
+ if (thDangerousTrend < thSafety4HQSQ) return -1;
+ hLdacAbr->thCritical = thCritical;
+ hLdacAbr->thDangerousTrend = thDangerousTrend;
+ hLdacAbr->thSafety4HQSQ = thSafety4HQSQ;
+ return 0;
+}
+
+/* LDAC ABR main process */
+int ldac_ABR_Proc( HANDLE_LDAC_BT hLDAC, HANDLE_LDAC_ABR hLdacAbr,
+ unsigned int TxQueueDepth, unsigned int flagEnable)
+{
+ int nStepsToChangeEQMID, abrQualityModeID, eqmid, i;
+ unsigned int TxQD_curr, TxQD_prev;
+#ifdef LOCAL_DEBUG
+ int qd, TxQ; // for debug
+#endif
+
+ if (hLDAC == NULL) return -1;
+ if (hLdacAbr == NULL) return -1;
+
+ eqmid = ldacBT_get_eqmid(hLDAC);
+ abrQualityModeID = -1;
+ if ((LDACBT_EQMID_HQ <= eqmid) && (eqmid < sizeOfEqmidToBitrateSortedIdTable)) {
+ abrQualityModeID = aEqmidToAbrQualityModeID[eqmid];
+ }
+#ifdef LOCAL_DEBUG
+ ABRDBG( "[LDAC ABR] - abrQualityModeID : %d -- eqmid : %d -- TxQue : %d --------------",
+ abrQualityModeID, eqmid, TxQueueDepth);
+#endif
+ /* check for the situation when unsupported eqmid was return from ldacBT_get_eqmid(). */
+ if (abrQualityModeID < 0) return eqmid; /* return current eqmid. */
+
+ /* update */
+ TxQD_curr = TxQueueDepth;
+ if ((i = hLdacAbr->TxQD_Info.idx - 1) < 0 ) i = hLdacAbr->TxQD_Info.szHist - 1;
+ TxQD_prev = hLdacAbr->TxQD_Info.pHist[i];
+
+ hLdacAbr->TxQD_Info.sum -= hLdacAbr->TxQD_Info.pHist[hLdacAbr->TxQD_Info.idx];
+ hLdacAbr->TxQD_Info.pHist[hLdacAbr->TxQD_Info.idx] = (unsigned char)TxQD_curr;
+ if (++hLdacAbr->TxQD_Info.idx >= hLdacAbr->TxQD_Info.szHist) hLdacAbr->TxQD_Info.idx = 0;
+
+ hLdacAbr->TxQD_Info.sum += TxQD_curr;
+ ++hLdacAbr->TxQD_Info.cnt;
+
+#ifdef LOCAL_DEBUG
+ qd = (abrQualityModeID * 100000000);
+ qd += (hLdacAbr->nPenalty * 1000000);
+ qd += (hLdacAbr->cntToIncQuality *1000);
+ qd += (hLdacAbr->nSteadyState);
+ TxQ = TxQD_prev * 100 + TxQD_curr;
+#endif
+
+ /* judge */
+ nStepsToChangeEQMID = 0;
+ if (TxQD_curr >= hLdacAbr->thCritical) {
+ /* for Critical situation */
+ ABRDBG("Critical: %d, %d", TxQ, qd);
+ nStepsToChangeEQMID = -1;
+ if ((eqmid == LDACBT_EQMID_HQ) || (eqmid == LDACBT_EQMID_SQ)) {
+ nStepsToChangeEQMID = -2;
+ }
+ }
+ else if ((TxQD_curr > hLdacAbr->thDangerousTrend) && (TxQD_curr > TxQD_prev)) {
+ ABRDBG("Dangerous: %d, %d", TxQ, qd);
+ nStepsToChangeEQMID = -1;
+ }
+ else if ((TxQD_curr > hLdacAbr->thSafety4HQSQ) &&
+ ((eqmid == LDACBT_EQMID_HQ) || (eqmid == LDACBT_EQMID_SQ))) {
+ ABRDBG("Safety4HQSQ: %d, %d", TxQ, qd);
+ nStepsToChangeEQMID = -1;
+ }
+ else if (hLdacAbr->TxQD_Info.cnt >= hLdacAbr->numToEvaluate) {
+ int ave10;
+ hLdacAbr->TxQD_Info.cnt = hLdacAbr->numToEvaluate;
+ /* eanble average process */
+ ave10 = (hLdacAbr->TxQD_Info.sum * 10) / hLdacAbr->TxQD_Info.cnt;
+
+ if (ave10 > 15) { /* if average of TxQue_Count in 0.5[s] was larger than 1.5 */
+ ABRDBG("ave: %d, %d, %d", TxQ, qd, ave10);
+ nStepsToChangeEQMID = -1;
+ }
+ else {
+ ++hLdacAbr->nSteadyState;
+#ifdef LOCAL_DEBUG
+ qd = (abrQualityModeID * 100000000);
+ qd += (hLdacAbr->nPenalty * 1000000);
+ qd += (hLdacAbr->cntToIncQuality *1000);
+ qd += (hLdacAbr->nSteadyState);
+#endif
+
+ if (hLdacAbr->TxQD_Info.sum == 0) {
+ if (--hLdacAbr->cntToIncQuality <= 0) {
+ ABRDBG("inc1: %d, %d, %d", TxQ, qd, ave10);
+ nStepsToChangeEQMID = 1;
+ }
+ else {
+ ABRDBG("reset: %d, %d, %d", TxQ, qd, ave10);
+ hLdacAbr->TxQD_Info.cnt = 0; // reset the number of sample for average proc.
+ }
+ }
+ else {
+ ABRDBG( "reset cntToIncQuality, %d,%d, %d", TxQ,qd, ave10);
+ hLdacAbr->cntToIncQuality = LDAC_ABR_OBSERVING_COUNT_TO_JUDGE_INC_QUALITY
+ - 2 * abrQualityModeID;
+ if (abrQualityModeID >= hLdacAbr->abrQualityModeIdSteady) {
+ hLdacAbr->cntToIncQuality *= hLdacAbr->nPenalty;
+ }
+ }
+ }
+ }
+#ifdef LOCAL_DEBUG
+ else {
+ ABRDBG("Nothing %d, hLdacAbr->TxQD_Info.cnt %u", TxQ, hLdacAbr->TxQD_Info.cnt);
+ }
+#endif
+ if (flagEnable) {
+ if (nStepsToChangeEQMID) {
+ int abrQualityModeIDNew;
+ if (nStepsToChangeEQMID < 0) {
+ for (i = 0; i > nStepsToChangeEQMID; --i) {
+ if (ldacBT_alter_eqmid_priority(hLDAC, LDACBT_EQMID_INC_CONNECTION)) {
+#ifdef LOCAL_DEBUG
+ int err;
+ err = ldacBT_get_error_code(hLDAC);
+ ABRDBG("Info@%d : %d ,%d, %d", __LINE__,
+ LDACBT_API_ERR(err), LDACBT_HANDLE_ERR(err), LDACBT_BLOCK_ERR(err));
+#endif
+ break;// EQMID was already the ID of the highest connectivity.
+ }
+ }
+
+ eqmid = ldacBT_get_eqmid(hLDAC);
+ abrQualityModeIDNew = abrQualityModeID;
+ if (eqmid >= 0) {
+ if (eqmid < sizeOfEqmidToBitrateSortedIdTable) {
+ abrQualityModeIDNew = aEqmidToAbrQualityModeID[eqmid];
+ }
+ }
+
+ if (hLdacAbr->nSteadyState < LDAC_ABR_NUM_STEADY_STATE_TO_JUDGE_STEADY) {
+ hLdacAbr->abrQualityModeIdSteady = abrQualityModeIDNew - 1;
+ if (hLdacAbr->abrQualityModeIdSteady < 0) hLdacAbr->abrQualityModeIdSteady = 0;
+ hLdacAbr->nPenalty *= 2;
+ if(hLdacAbr->nPenalty > LDAC_ABR_PENALTY_MAX) {
+ hLdacAbr->nPenalty = LDAC_ABR_PENALTY_MAX; // MAX PENALTY
+ }
+ }
+ }
+ else {
+ if (ldacBT_alter_eqmid_priority( hLDAC, LDACBT_EQMID_INC_QUALITY )) {
+#ifdef LOCAL_DEBUG
+ int err;
+ err = ldacBT_get_error_code(hLDAC);
+ ABRDBG("Info@%d : %d ,%d, %d", __LINE__,
+ LDACBT_API_ERR(err), LDACBT_HANDLE_ERR(err), LDACBT_BLOCK_ERR(err));
+#endif
+ ;// EQMID was already the ID of the highest sound quality.
+ }
+ eqmid = ldacBT_get_eqmid(hLDAC);
+ abrQualityModeIDNew = abrQualityModeID;
+ if (eqmid >= 0) {
+ if (eqmid < sizeOfEqmidToBitrateSortedIdTable) {
+ abrQualityModeIDNew = aEqmidToAbrQualityModeID[eqmid];
+ }
+ }
+ if (abrQualityModeIDNew < hLdacAbr->abrQualityModeIdSteady) {
+ hLdacAbr->nPenalty = 1;
+ }
+ if (abrQualityModeIDNew == aEqmidToAbrQualityModeID[0]) { /* for HQ */
+ if (hLdacAbr->nSteadyState > LDAC_ABR_NUM_STEADY_STATE_TO_RESET_PENALTY_FOR_HQ) {
+ hLdacAbr->nPenalty = 1;
+ }
+ }
+ }
+
+ hLdacAbr->nSteadyState = 0;
+ // reset the number of sample for average proc.
+ hLdacAbr->TxQD_Info.cnt = 0;
+ hLdacAbr->cntToIncQuality = LDAC_ABR_OBSERVING_COUNT_TO_JUDGE_INC_QUALITY
+ - 2 * abrQualityModeIDNew;
+ if (hLdacAbr->cntToIncQuality <= 0) {
+ // set minimum value. e1 f == 0.5[s]
+ hLdacAbr->cntToIncQuality = 1;
+ }
+ hLdacAbr->cntToIncQuality *= hLdacAbr->nPenalty;
+ ABRDBG("EQMID NOW %d", eqmid);
+ }
+ }
+#ifdef LOCAL_DEBUG
+ else if (TxQueueDepth) {
+ ABRDBG("flagEnable false: %d ,%d", TxQ, qd);
+ }
+#endif
+
+ return eqmid;
+}
diff --git a/src/ldaclib_api.c b/src/ldaclib_api.c
index d15cae2..4c54407 100644
--- a/src/ldaclib_api.c
+++ b/src/ldaclib_api.c
@@ -456,6 +456,20 @@ int frame_status)
static const int saa_encode_setting_ldac[LDAC_ENC_NSETTING][LDAC_ENC_NPROPERTY] = {
{0, 512, 17, 0, 28, 44, 8, 24, 0},
{0, 256, 17, 0, 28, 44, 6, 22, 0},
+#ifdef MODIFY_LDAC_ENC_SETTING_FOR_ABR_DEBUG // See file "ldacBT_abr.h" for description
+ {0, 164, 16, 0, 18, 32, 7, 23, 0},
+ {0, 110, 8, 0, 16, 32, 10, 31, 0},
+ {0, 82, 6, 0, 16, 32, 12, 31, 0},
+ {0, 66, 4, 0, 14, 26, 12, 31, 0},
+ {0, 54, 2, 0, 14, 26, 12, 31, 0},
+ {0, 46, 2, 1, 10, 26, 12, 31, 0},
+ {0, 40, 2, 2, 10, 26, 12, 31, 0},
+ {0, 36, 2, 2, 8, 26, 12, 31, 0},
+ {0, 32, 2, 2, 8, 26, 16, 31, 0},
+ {0, 30, 2, 2, 4, 26, 16, 31, 0},
+ {0, 26, 2, 3, 4, 26, 16, 31, 0},
+ {0, 24, 2, 3, 4, 26, 16, 31, 0},
+#else
{0, 164, 16, 0, 18, 32, 7, 23, 0},
{0, 110, 13, 0, 16, 32, 10, 31, 0},
{0, 82, 12, 0, 16, 32, 12, 31, 0},
@@ -468,6 +482,7 @@ static const int saa_encode_setting_ldac[LDAC_ENC_NSETTING][LDAC_ENC_NPROPERTY]
{0, 30, 5, 2, 4, 26, 16, 31, 0},
{0, 26, 4, 3, 4, 26, 16, 31, 0},
{0, 24, 3, 3, 4, 26, 16, 31, 0},
+#endif
{0, 22, 2, 3, 4, 26, 16, 31, 0},
};