/** * Copyright (C) 2022 The Android Open Source Project * * 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. */ /*------------------------------------------------------------------------------ * * All declarations relevant for the SyncInserter class. This class exposes a * public interface that lets a client supply two aptX encoder objects (left * and right stereo channel) and have the current quantised codes adjusted to * bury an autosync bit. * *----------------------------------------------------------------------------*/ #ifndef SYNCINSERTER_H #define SYNCINSERTER_H #ifdef _GCC #pragma GCC visibility push(hidden) #endif #include "AptxParameters.h" /* Function to insert sync information into one of the 8 quantised codes * spread across 2 aptX codewords (1 codeword per channel) */ XBT_INLINE_ void xbtEncinsertSync(Encoder_data* leftChannelEncoder, Encoder_data* rightChannelEncoder, uint32_t* syncWordPhase) { /* Currently using 0x1 as the 8-bit sync pattern */ static const uint32_t syncWord = 0x1; uint32_t tmp_var; uint32_t i; /* Variable to hold the XOR of all the quantised code lsbs */ uint32_t xorCodeLsbs; /* Variable to point to the quantiser with the minimum calculated distance * penalty. */ Quantiser_data* minPenaltyQuantiser; /* Get the vector of quantiser pointers from the left and right encoders */ Quantiser_data* leftQuant[4]; Quantiser_data* rightQuant[4]; leftQuant[0] = &leftChannelEncoder->m_qdata[0]; leftQuant[1] = &leftChannelEncoder->m_qdata[1]; leftQuant[2] = &leftChannelEncoder->m_qdata[2]; leftQuant[3] = &leftChannelEncoder->m_qdata[3]; rightQuant[0] = &rightChannelEncoder->m_qdata[0]; rightQuant[1] = &rightChannelEncoder->m_qdata[1]; rightQuant[2] = &rightChannelEncoder->m_qdata[2]; rightQuant[3] = &rightChannelEncoder->m_qdata[3]; /* Starting quantiser traversal with the LL quantiser from the left channel. * Initialise the pointer to the minimum penalty quantiser with the details * of the left LL quantiser. Initialise the code lsbs XOR variable with the * left LL quantised code lsbs and also XOR in the left and right random * dither bit generated by the 2 encoders. */ xorCodeLsbs = ((rightQuant[LL]->qCode) & 0x1) ^ leftChannelEncoder->m_dithSyncRandBit ^ rightChannelEncoder->m_dithSyncRandBit; minPenaltyQuantiser = rightQuant[LH]; /* Traverse across the LH, HL and HH quantisers from the right channel */ for (i = LH; i <= HH; i++) { /* XOR in the lsb of the quantised code currently examined */ xorCodeLsbs ^= (rightQuant[i]->qCode) & 0x1; } /* If the distance penalty associated with a quantiser is less than the * current minimum, then make that quantiser the minimum penalty * quantiser. */ if (rightQuant[HL]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = rightQuant[HL]; } if (rightQuant[LL]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = rightQuant[LL]; } if (rightQuant[HH]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = rightQuant[HH]; } /* Traverse across all quantisers from the left channel */ for (i = LL; i <= HH; i++) { /* XOR in the lsb of the quantised code currently examined */ xorCodeLsbs ^= (leftQuant[i]->qCode) & 0x1; } /* If the distance penalty associated with a quantiser is less than the * current minimum, then make that quantiser the minimum penalty * quantiser. */ if (leftQuant[LH]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = leftQuant[LH]; } if (leftQuant[HL]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = leftQuant[HL]; } if (leftQuant[LL]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = leftQuant[LL]; } if (leftQuant[HH]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = leftQuant[HH]; } /* If the lsbs of all 8 quantised codes don't happen to equal the desired * sync bit to embed, then force them to be by replacing the optimum code * with the alternate code in the minimum penalty quantiser (changes the lsb * of the code in this quantiser) */ if (xorCodeLsbs != ((syncWord >> (*syncWordPhase)) & 0x1)) { minPenaltyQuantiser->qCode = minPenaltyQuantiser->altQcode; } /* Decrement the selected sync word bit modulo 8 for the next pass. */ tmp_var = --(*syncWordPhase); (*syncWordPhase) = tmp_var & 0x7; } XBT_INLINE_ void xbtEncinsertSyncDualMono(Encoder_data* leftChannelEncoder, Encoder_data* rightChannelEncoder, uint32_t* syncWordPhase) { /* Currently using 0x1 as the 8-bit sync pattern */ static const uint32_t syncWord = 0x1; uint32_t tmp_var; uint32_t i; /* Variable to hold the XOR of all the quantised code lsbs */ uint32_t xorCodeLsbs; /* Variable to point to the quantiser with the minimum calculated distance * penalty. */ Quantiser_data* minPenaltyQuantiser; /* Get the vector of quantiser pointers from the left and right encoders */ Quantiser_data* leftQuant[4]; Quantiser_data* rightQuant[4]; leftQuant[0] = &leftChannelEncoder->m_qdata[0]; leftQuant[1] = &leftChannelEncoder->m_qdata[1]; leftQuant[2] = &leftChannelEncoder->m_qdata[2]; leftQuant[3] = &leftChannelEncoder->m_qdata[3]; rightQuant[0] = &rightChannelEncoder->m_qdata[0]; rightQuant[1] = &rightChannelEncoder->m_qdata[1]; rightQuant[2] = &rightChannelEncoder->m_qdata[2]; rightQuant[3] = &rightChannelEncoder->m_qdata[3]; /* Starting quantiser traversal with the LL quantiser from the left channel. * Initialise the pointer to the minimum penalty quantiser with the details * of the left LL quantiser. Initialise the code lsbs XOR variable with the * left LL quantised code lsbs */ xorCodeLsbs = leftChannelEncoder->m_dithSyncRandBit; minPenaltyQuantiser = leftQuant[LH]; /* Traverse across all the quantisers from the left channel */ for (i = LL; i <= HH; i++) { /* XOR in the lsb of the quantised code currently examined */ xorCodeLsbs ^= (leftQuant[i]->qCode) & 0x1; } /* If the distance penalty associated with a quantiser is less than the * current minimum, then make that quantiser the minimum penalty * quantiser. */ if (leftQuant[LH]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = leftQuant[LH]; } if (leftQuant[HL]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = leftQuant[HL]; } if (leftQuant[LL]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = leftQuant[LL]; } if (leftQuant[HH]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = leftQuant[HH]; } /* If the lsbs of all 4 quantised codes don't happen to equal the desired * sync bit to embed, then force them to be by replacing the optimum code * with the alternate code in the minimum penalty quantiser (changes the lsb * of the code in this quantiser) */ if (xorCodeLsbs != ((syncWord >> (*syncWordPhase)) & 0x1)) { minPenaltyQuantiser->qCode = minPenaltyQuantiser->altQcode; } /**** Insert sync on the Right channel ****/ xorCodeLsbs = rightChannelEncoder->m_dithSyncRandBit; minPenaltyQuantiser = rightQuant[LH]; /* Traverse across all quantisers from the right channel */ for (i = LL; i <= HH; i++) { /* XOR in the lsb of the quantised code currently examined */ xorCodeLsbs ^= (rightQuant[i]->qCode) & 0x1; } /* If the distance penalty associated with a quantiser is less than the * current minimum, then make that quantiser the minimum penalty * quantiser. */ if (rightQuant[LH]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = rightQuant[LH]; } if (rightQuant[HL]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = rightQuant[HL]; } if (rightQuant[LL]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = rightQuant[LL]; } if (rightQuant[HH]->distPenalty < minPenaltyQuantiser->distPenalty) { minPenaltyQuantiser = rightQuant[HH]; } /* If the lsbs of all 4 quantised codes don't happen to equal the desired * sync bit to embed, then force them to be by replacing the optimum code * with the alternate code in the minimum penalty quantiser (changes the lsb * of the code in this quantiser) */ if (xorCodeLsbs != ((syncWord >> (*syncWordPhase)) & 0x1)) { minPenaltyQuantiser->qCode = minPenaltyQuantiser->altQcode; } /* End of Right channel autosync insert*/ /* Decrement the selected sync word bit modulo 8 for the next pass. */ tmp_var = --(*syncWordPhase); (*syncWordPhase) = tmp_var & 0x7; } #ifdef _GCC #pragma GCC visibility pop #endif #endif // SYNCINSERTER_H