1df25739fSMilanka Ringwald /****************************************************************************** 2df25739fSMilanka Ringwald * 3df25739fSMilanka Ringwald * Copyright (C) 2014 The Android Open Source Project 4df25739fSMilanka Ringwald * Copyright 2006 Open Interface North America, Inc. All rights reserved. 5df25739fSMilanka Ringwald * 6df25739fSMilanka Ringwald * Licensed under the Apache License, Version 2.0 (the "License"); 7df25739fSMilanka Ringwald * you may not use this file except in compliance with the License. 8df25739fSMilanka Ringwald * You may obtain a copy of the License at: 9df25739fSMilanka Ringwald * 10df25739fSMilanka Ringwald * http://www.apache.org/licenses/LICENSE-2.0 11df25739fSMilanka Ringwald * 12df25739fSMilanka Ringwald * Unless required by applicable law or agreed to in writing, software 13df25739fSMilanka Ringwald * distributed under the License is distributed on an "AS IS" BASIS, 14df25739fSMilanka Ringwald * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15df25739fSMilanka Ringwald * See the License for the specific language governing permissions and 16df25739fSMilanka Ringwald * limitations under the License. 17df25739fSMilanka Ringwald * 18df25739fSMilanka Ringwald ******************************************************************************/ 19df25739fSMilanka Ringwald 20df25739fSMilanka Ringwald /********************************************************************************** 21df25739fSMilanka Ringwald $Revision: #1 $ 22df25739fSMilanka Ringwald ***********************************************************************************/ 23df25739fSMilanka Ringwald 24df25739fSMilanka Ringwald /** @file 25df25739fSMilanka Ringwald @ingroup codec_internal 26df25739fSMilanka Ringwald */ 27df25739fSMilanka Ringwald 28df25739fSMilanka Ringwald /**@addtogroup codec_internal */ 29df25739fSMilanka Ringwald /**@{*/ 30df25739fSMilanka Ringwald 31df25739fSMilanka Ringwald #include "oi_codec_sbc_private.h" 32df25739fSMilanka Ringwald #include "oi_bitstream.h" 33df25739fSMilanka Ringwald 34df25739fSMilanka Ringwald #define SPECIALIZE_READ_SAMPLES_JOINT 35df25739fSMilanka Ringwald 36df25739fSMilanka Ringwald /** 37df25739fSMilanka Ringwald * Scans through a buffer looking for a codec syncword. If the decoder has been 38df25739fSMilanka Ringwald * set for enhanced operation using OI_CODEC_SBC_DecoderReset(), it will search 39df25739fSMilanka Ringwald * for both a standard and an enhanced syncword. 40df25739fSMilanka Ringwald */ 41df25739fSMilanka Ringwald PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context, 42df25739fSMilanka Ringwald const OI_BYTE **frameData, 4308b456cdSMilanka Ringwald OI_UINT32 *frameBytes); 4408b456cdSMilanka Ringwald PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context, 4508b456cdSMilanka Ringwald const OI_BYTE **frameData, 46df25739fSMilanka Ringwald OI_UINT32 *frameBytes) 47df25739fSMilanka Ringwald { 48df25739fSMilanka Ringwald #ifdef SBC_ENHANCED 49df25739fSMilanka Ringwald OI_BYTE search1 = OI_SBC_SYNCWORD; 50df25739fSMilanka Ringwald OI_BYTE search2 = OI_SBC_ENHANCED_SYNCWORD; 51df25739fSMilanka Ringwald #endif // SBC_ENHANCED 52df25739fSMilanka Ringwald 53df25739fSMilanka Ringwald if (*frameBytes == 0) { 54df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; 55df25739fSMilanka Ringwald } 56df25739fSMilanka Ringwald 57df25739fSMilanka Ringwald #ifdef SBC_ENHANCED 58df25739fSMilanka Ringwald if (context->limitFrameFormat && context->enhancedEnabled){ 59df25739fSMilanka Ringwald /* If the context is restricted, only search for specified SYNCWORD */ 60df25739fSMilanka Ringwald search1 = search2; 61df25739fSMilanka Ringwald } else if (context->enhancedEnabled == FALSE) { 62df25739fSMilanka Ringwald /* If enhanced is not enabled, only search for classic SBC SYNCWORD*/ 63df25739fSMilanka Ringwald search2 = search1; 64df25739fSMilanka Ringwald } 65df25739fSMilanka Ringwald while (*frameBytes && (**frameData != search1) && (**frameData != search2)) { 66df25739fSMilanka Ringwald (*frameBytes)--; 67df25739fSMilanka Ringwald (*frameData)++; 68df25739fSMilanka Ringwald } 69df25739fSMilanka Ringwald if (*frameBytes) { 70df25739fSMilanka Ringwald /* Syncword found, *frameData points to it, and *frameBytes correctly 71df25739fSMilanka Ringwald * reflects the number of bytes available to read, including the 72df25739fSMilanka Ringwald * syncword. */ 73df25739fSMilanka Ringwald context->common.frameInfo.enhanced = (**frameData == OI_SBC_ENHANCED_SYNCWORD); 74df25739fSMilanka Ringwald return OI_OK; 75df25739fSMilanka Ringwald } else { 76df25739fSMilanka Ringwald /* No syncword was found anywhere in the provided input data. 77df25739fSMilanka Ringwald * *frameData points past the end of the original input, and 78df25739fSMilanka Ringwald * *frameBytes is 0. */ 79df25739fSMilanka Ringwald return OI_CODEC_SBC_NO_SYNCWORD; 80df25739fSMilanka Ringwald } 81df25739fSMilanka Ringwald #else // SBC_ENHANCED 82435e3c4eSMilanka Ringwald /* BK4BTSTACK_CHANGE START */ 83435e3c4eSMilanka Ringwald OI_UINT8 syncword = OI_SBC_SYNCWORD; 84fcb08cdbSMilanka Ringwald if (context->common.frameInfo.mSBCEnabled){ 85435e3c4eSMilanka Ringwald syncword = OI_mSBC_SYNCWORD; 86435e3c4eSMilanka Ringwald } 872831fb0aSMilanka Ringwald //printf("search %x\n", syncword); 88435e3c4eSMilanka Ringwald /* BK4BTSTACK_CHANGE END */ 89435e3c4eSMilanka Ringwald while (*frameBytes && (**frameData != syncword)) { 902831fb0aSMilanka Ringwald // printf("%c ", **frameData); 91df25739fSMilanka Ringwald (*frameBytes)--; 92df25739fSMilanka Ringwald (*frameData)++; 93df25739fSMilanka Ringwald } 942831fb0aSMilanka Ringwald //printf("\n\n"); 95df25739fSMilanka Ringwald if (*frameBytes) { 96df25739fSMilanka Ringwald /* Syncword found, *frameData points to it, and *frameBytes correctly 97df25739fSMilanka Ringwald * reflects the number of bytes available to read, including the 98df25739fSMilanka Ringwald * syncword. */ 99df25739fSMilanka Ringwald context->common.frameInfo.enhanced = FALSE; 100df25739fSMilanka Ringwald return OI_OK; 101df25739fSMilanka Ringwald } else { 102df25739fSMilanka Ringwald /* No syncword was found anywhere in the provided input data. 103df25739fSMilanka Ringwald * *frameData points past the end of the original input, and 104df25739fSMilanka Ringwald * *frameBytes is 0. */ 105df25739fSMilanka Ringwald return OI_CODEC_SBC_NO_SYNCWORD; 106df25739fSMilanka Ringwald } 107df25739fSMilanka Ringwald #endif // SBC_ENHANCED 108df25739fSMilanka Ringwald } 109df25739fSMilanka Ringwald 110df25739fSMilanka Ringwald 111df25739fSMilanka Ringwald static OI_STATUS DecodeBody(OI_CODEC_SBC_DECODER_CONTEXT *context, 112df25739fSMilanka Ringwald const OI_BYTE *bodyData, 113df25739fSMilanka Ringwald OI_INT16 *pcmData, 114df25739fSMilanka Ringwald OI_UINT32 *pcmBytes, 115df25739fSMilanka Ringwald OI_BOOL allowPartial) 116df25739fSMilanka Ringwald { 117df25739fSMilanka Ringwald OI_BITSTREAM bs; 118df25739fSMilanka Ringwald OI_UINT frameSamples = context->common.frameInfo.nrof_blocks * context->common.frameInfo.nrof_subbands; 119df25739fSMilanka Ringwald OI_UINT decode_block_count; 120df25739fSMilanka Ringwald 121df25739fSMilanka Ringwald /* 122df25739fSMilanka Ringwald * Based on the header data, make sure that there is enough room to write the output samples. 123df25739fSMilanka Ringwald */ 124df25739fSMilanka Ringwald if (*pcmBytes < (sizeof(OI_INT16) * frameSamples * context->common.pcmStride) && !allowPartial) { 125df25739fSMilanka Ringwald /* If we're not allowing partial decodes, we need room for the entire 126df25739fSMilanka Ringwald * codec frame */ 127df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA")); 128df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA; 129df25739fSMilanka Ringwald } else if (*pcmBytes < sizeof (OI_INT16) * context->common.frameInfo.nrof_subbands * context->common.pcmStride) { 130df25739fSMilanka Ringwald /* Even if we're allowing partials, we can still only decode on a frame 131df25739fSMilanka Ringwald * boundary */ 132df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA; 133df25739fSMilanka Ringwald } 134df25739fSMilanka Ringwald 135df25739fSMilanka Ringwald if (context->bufferedBlocks == 0) { 136df25739fSMilanka Ringwald TRACE(("Reading scalefactors")); 137df25739fSMilanka Ringwald OI_SBC_ReadScalefactors(&context->common, bodyData, &bs); 138df25739fSMilanka Ringwald 139df25739fSMilanka Ringwald TRACE(("Computing bit allocation")); 140df25739fSMilanka Ringwald OI_SBC_ComputeBitAllocation(&context->common); 141df25739fSMilanka Ringwald 142df25739fSMilanka Ringwald TRACE(("Reading samples")); 143df25739fSMilanka Ringwald if (context->common.frameInfo.mode == SBC_JOINT_STEREO) { 144df25739fSMilanka Ringwald OI_SBC_ReadSamplesJoint(context, &bs); 145df25739fSMilanka Ringwald } else { 146df25739fSMilanka Ringwald OI_SBC_ReadSamples(context, &bs); 147df25739fSMilanka Ringwald } 148df25739fSMilanka Ringwald 149df25739fSMilanka Ringwald context->bufferedBlocks = context->common.frameInfo.nrof_blocks; 150df25739fSMilanka Ringwald } 151df25739fSMilanka Ringwald 152df25739fSMilanka Ringwald if (allowPartial) { 153df25739fSMilanka Ringwald decode_block_count = *pcmBytes / sizeof(OI_INT16) / context->common.pcmStride / context->common.frameInfo.nrof_subbands; 154df25739fSMilanka Ringwald 155df25739fSMilanka Ringwald if (decode_block_count > context->bufferedBlocks) { 156df25739fSMilanka Ringwald decode_block_count = context->bufferedBlocks; 157df25739fSMilanka Ringwald } 158df25739fSMilanka Ringwald 159df25739fSMilanka Ringwald } else { 160df25739fSMilanka Ringwald decode_block_count = context->common.frameInfo.nrof_blocks; 161df25739fSMilanka Ringwald } 162df25739fSMilanka Ringwald 163df25739fSMilanka Ringwald TRACE(("Synthesizing frame")); 164df25739fSMilanka Ringwald { 165df25739fSMilanka Ringwald OI_UINT start_block = context->common.frameInfo.nrof_blocks - context->bufferedBlocks; 166df25739fSMilanka Ringwald OI_SBC_SynthFrame(context, pcmData, start_block, decode_block_count); 167df25739fSMilanka Ringwald } 168df25739fSMilanka Ringwald 169df25739fSMilanka Ringwald OI_ASSERT(context->bufferedBlocks >= decode_block_count); 170df25739fSMilanka Ringwald context->bufferedBlocks -= decode_block_count; 171df25739fSMilanka Ringwald 172df25739fSMilanka Ringwald frameSamples = decode_block_count * context->common.frameInfo.nrof_subbands; 173df25739fSMilanka Ringwald 174df25739fSMilanka Ringwald /* 175df25739fSMilanka Ringwald * When decoding mono into a stride-2 array, copy pcm data to second channel 176df25739fSMilanka Ringwald */ 177*c1ab6cc1SMatthias Ringwald if ((context->common.frameInfo.nrof_channels == 1) && (context->common.pcmStride == 2)) { 178df25739fSMilanka Ringwald OI_UINT i; 179df25739fSMilanka Ringwald for (i = 0; i < frameSamples; ++i) { 180*c1ab6cc1SMatthias Ringwald pcmData[(2*i)+1] = pcmData[2*i]; 181df25739fSMilanka Ringwald } 182df25739fSMilanka Ringwald } 183df25739fSMilanka Ringwald 184df25739fSMilanka Ringwald /* 185df25739fSMilanka Ringwald * Return number of pcm bytes generated by the decode operation. 186df25739fSMilanka Ringwald */ 187df25739fSMilanka Ringwald *pcmBytes = frameSamples * sizeof(OI_INT16) * context->common.pcmStride; 188df25739fSMilanka Ringwald 189df25739fSMilanka Ringwald if (context->bufferedBlocks > 0) { 190df25739fSMilanka Ringwald return OI_CODEC_SBC_PARTIAL_DECODE; 191df25739fSMilanka Ringwald } else { 192df25739fSMilanka Ringwald return OI_OK; 193df25739fSMilanka Ringwald } 194df25739fSMilanka Ringwald } 195df25739fSMilanka Ringwald 196df25739fSMilanka Ringwald PRIVATE OI_STATUS internal_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context, 197df25739fSMilanka Ringwald OI_UINT8 bitpool, 198df25739fSMilanka Ringwald const OI_BYTE **frameData, 199df25739fSMilanka Ringwald OI_UINT32 *frameBytes, 200df25739fSMilanka Ringwald OI_INT16 *pcmData, 201df25739fSMilanka Ringwald OI_UINT32 *pcmBytes) 202df25739fSMilanka Ringwald { 203df25739fSMilanka Ringwald OI_STATUS status; 204df25739fSMilanka Ringwald OI_UINT bodyLen; 205df25739fSMilanka Ringwald 206df25739fSMilanka Ringwald TRACE(("+OI_CODEC_SBC_DecodeRaw")); 207df25739fSMilanka Ringwald 208df25739fSMilanka Ringwald if (context->bufferedBlocks == 0) { 209df25739fSMilanka Ringwald /* 210df25739fSMilanka Ringwald * The bitallocator needs to know the bitpool value. 211df25739fSMilanka Ringwald */ 212df25739fSMilanka Ringwald context->common.frameInfo.bitpool = bitpool; 213df25739fSMilanka Ringwald /* 214df25739fSMilanka Ringwald * Compute the frame length and check we have enough frame data to proceed 215df25739fSMilanka Ringwald */ 216df25739fSMilanka Ringwald bodyLen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo) - SBC_HEADER_LEN; 217df25739fSMilanka Ringwald if (*frameBytes < bodyLen) { 218df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA")); 219df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA; 220df25739fSMilanka Ringwald } 221df25739fSMilanka Ringwald } else { 222df25739fSMilanka Ringwald bodyLen = 0; 223df25739fSMilanka Ringwald } 224df25739fSMilanka Ringwald /* 225df25739fSMilanka Ringwald * Decode the SBC data. Pass TRUE to DecodeBody to allow partial decoding of 226df25739fSMilanka Ringwald * tones. 227df25739fSMilanka Ringwald */ 228df25739fSMilanka Ringwald status = DecodeBody(context, *frameData, pcmData, pcmBytes, TRUE); 229*c1ab6cc1SMatthias Ringwald if (OI_SUCCESS(status) || (status == OI_CODEC_SBC_PARTIAL_DECODE)) { 230df25739fSMilanka Ringwald *frameData += bodyLen; 231df25739fSMilanka Ringwald *frameBytes -= bodyLen; 232df25739fSMilanka Ringwald } 233df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_DecodeRaw: %d", status)); 234df25739fSMilanka Ringwald return status; 235df25739fSMilanka Ringwald } 236df25739fSMilanka Ringwald 237435e3c4eSMilanka Ringwald 238df25739fSMilanka Ringwald OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, 239df25739fSMilanka Ringwald OI_UINT32 *decoderData, 240df25739fSMilanka Ringwald OI_UINT32 decoderDataBytes, 241df25739fSMilanka Ringwald OI_UINT8 maxChannels, 242df25739fSMilanka Ringwald OI_UINT8 pcmStride, 243df25739fSMilanka Ringwald OI_BOOL enhanced) 244df25739fSMilanka Ringwald { 245df25739fSMilanka Ringwald return internal_DecoderReset(context, decoderData, decoderDataBytes, maxChannels, pcmStride, enhanced); 246df25739fSMilanka Ringwald } 247df25739fSMilanka Ringwald 248435e3c4eSMilanka Ringwald /* BK4BTSTACK_CHANGE START */ 249435e3c4eSMilanka Ringwald OI_STATUS OI_CODEC_mSBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, 250435e3c4eSMilanka Ringwald OI_UINT32 *decoderData, 251435e3c4eSMilanka Ringwald OI_UINT32 decoderDataBytes) 252435e3c4eSMilanka Ringwald { 253435e3c4eSMilanka Ringwald OI_STATUS status = OI_CODEC_SBC_DecoderReset(context, decoderData, decoderDataBytes, 1, 1, FALSE); 254fcb08cdbSMilanka Ringwald context->common.frameInfo.mSBCEnabled = TRUE; 255435e3c4eSMilanka Ringwald return status; 256435e3c4eSMilanka Ringwald } 257435e3c4eSMilanka Ringwald /* BK4BTSTACK_CHANGE END */ 258435e3c4eSMilanka Ringwald 259df25739fSMilanka Ringwald OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, 260df25739fSMilanka Ringwald const OI_BYTE **frameData, 261df25739fSMilanka Ringwald OI_UINT32 *frameBytes, 262df25739fSMilanka Ringwald OI_INT16 *pcmData, 263df25739fSMilanka Ringwald OI_UINT32 *pcmBytes) 264df25739fSMilanka Ringwald { 265df25739fSMilanka Ringwald OI_STATUS status; 266df25739fSMilanka Ringwald OI_UINT framelen; 267df25739fSMilanka Ringwald OI_UINT8 crc; 268df25739fSMilanka Ringwald 269df25739fSMilanka Ringwald TRACE(("+OI_CODEC_SBC_DecodeFrame")); 270df25739fSMilanka Ringwald 271df25739fSMilanka Ringwald TRACE(("Finding syncword")); 2722831fb0aSMilanka Ringwald //printf("OI_CODEC_SBC_DecodeFrame frameBytes %d\n", frameBytes); 273df25739fSMilanka Ringwald status = FindSyncword(context, frameData, frameBytes); 274df25739fSMilanka Ringwald if (!OI_SUCCESS(status)) { 275df25739fSMilanka Ringwald return status; 276df25739fSMilanka Ringwald } 277df25739fSMilanka Ringwald /* Make sure enough data remains to read the header. */ 278df25739fSMilanka Ringwald if (*frameBytes < SBC_HEADER_LEN) { 279df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA")); 280df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; 281df25739fSMilanka Ringwald } 282df25739fSMilanka Ringwald 283df25739fSMilanka Ringwald TRACE(("Reading Header")); 284fcb08cdbSMilanka Ringwald if (context->common.frameInfo.mSBCEnabled){ 285fcb08cdbSMilanka Ringwald OI_SBC_ReadHeader_mSBC(&context->common, *frameData); 286fcb08cdbSMilanka Ringwald } else { 287df25739fSMilanka Ringwald OI_SBC_ReadHeader(&context->common, *frameData); 288fcb08cdbSMilanka Ringwald } 289df25739fSMilanka Ringwald 290df25739fSMilanka Ringwald /* 291df25739fSMilanka Ringwald * Some implementations load the decoder into RAM and use overlays for 4 vs 8 subbands. We need 292df25739fSMilanka Ringwald * to ensure that the SBC parameters for this frame are compatible with the restrictions imposed 293df25739fSMilanka Ringwald * by the loaded overlays. 294df25739fSMilanka Ringwald */ 295df25739fSMilanka Ringwald if (context->limitFrameFormat && (context->common.frameInfo.subbands != context->restrictSubbands)) { 296df25739fSMilanka Ringwald ERROR(("SBC parameters incompatible with loaded overlay")); 297df25739fSMilanka Ringwald return OI_STATUS_INVALID_PARAMETERS; 298df25739fSMilanka Ringwald } 299df25739fSMilanka Ringwald TRACE(("Frame: ")); 300df25739fSMilanka Ringwald 301df25739fSMilanka Ringwald if (context->common.frameInfo.nrof_channels > context->common.maxChannels) { 302df25739fSMilanka Ringwald ERROR(("SBC parameters incompatible with number of channels specified during reset")); 303df25739fSMilanka Ringwald return OI_STATUS_INVALID_PARAMETERS; 304df25739fSMilanka Ringwald } 305df25739fSMilanka Ringwald 306*c1ab6cc1SMatthias Ringwald if ((context->common.pcmStride < 1) || (context->common.pcmStride > 2)) { 307df25739fSMilanka Ringwald ERROR(("PCM stride not set correctly during reset")); 308df25739fSMilanka Ringwald return OI_STATUS_INVALID_PARAMETERS; 309df25739fSMilanka Ringwald } 310df25739fSMilanka Ringwald 311df25739fSMilanka Ringwald /* 312df25739fSMilanka Ringwald * At this point a header has been read. However, it's possible that we found a false syncword, 313df25739fSMilanka Ringwald * so the header data might be invalid. Make sure we have enough bytes to read in the 314df25739fSMilanka Ringwald * CRC-protected header, but don't require we have the whole frame. That way, if it turns out 315df25739fSMilanka Ringwald * that we're acting on bogus header data, we don't stall the decoding process by waiting for 316df25739fSMilanka Ringwald * data that we don't actually need. 317df25739fSMilanka Ringwald */ 318df25739fSMilanka Ringwald framelen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo); 319df25739fSMilanka Ringwald if (*frameBytes < framelen) { 320df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA")); 321df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA; 322df25739fSMilanka Ringwald } 323df25739fSMilanka Ringwald TRACE(("frame len %d\n", framelen)); 324df25739fSMilanka Ringwald 325df25739fSMilanka Ringwald TRACE(("Calculating checksum")); 326fcb08cdbSMilanka Ringwald if (context->common.frameInfo.mSBCEnabled){ 327fcb08cdbSMilanka Ringwald crc = OI_SBC_CalculateChecksum_mSBC(&context->common.frameInfo, *frameData); 328fcb08cdbSMilanka Ringwald } else { 329df25739fSMilanka Ringwald crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData); 330fcb08cdbSMilanka Ringwald } 331fcb08cdbSMilanka Ringwald 332df25739fSMilanka Ringwald if (crc != context->common.frameInfo.crc) { 333df25739fSMilanka Ringwald TRACE(("CRC Mismatch: calc=%02x read=%02x\n", crc, context->common.frameInfo.crc)); 334df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_CHECKSUM_MISMATCH")); 335df25739fSMilanka Ringwald return OI_CODEC_SBC_CHECKSUM_MISMATCH; 336df25739fSMilanka Ringwald } 337df25739fSMilanka Ringwald 338df25739fSMilanka Ringwald #ifdef OI_DEBUG 339df25739fSMilanka Ringwald /* 340df25739fSMilanka Ringwald * Make sure the bitpool values are sane. 341df25739fSMilanka Ringwald */ 342df25739fSMilanka Ringwald if ((context->common.frameInfo.bitpool < SBC_MIN_BITPOOL) && !context->common.frameInfo.enhanced) { 343df25739fSMilanka Ringwald ERROR(("Bitpool too small: %d (must be >= 2)", context->common.frameInfo.bitpool)); 344df25739fSMilanka Ringwald return OI_STATUS_INVALID_PARAMETERS; 345df25739fSMilanka Ringwald } 346df25739fSMilanka Ringwald if (context->common.frameInfo.bitpool > OI_SBC_MaxBitpool(&context->common.frameInfo)) { 347df25739fSMilanka Ringwald ERROR(("Bitpool too large: %d (must be <= %ld)", context->common.frameInfo.bitpool, OI_SBC_MaxBitpool(&context->common.frameInfo))); 348df25739fSMilanka Ringwald return OI_STATUS_INVALID_PARAMETERS; 349df25739fSMilanka Ringwald } 350df25739fSMilanka Ringwald #endif 351df25739fSMilanka Ringwald 352df25739fSMilanka Ringwald /* 353df25739fSMilanka Ringwald * Now decode the SBC data. Partial decode is not yet implemented for an SBC 354df25739fSMilanka Ringwald * stream, so pass FALSE to decode body to have it enforce the old rule that 355df25739fSMilanka Ringwald * you have to decode a whole packet at a time. 356df25739fSMilanka Ringwald */ 357df25739fSMilanka Ringwald status = DecodeBody(context, *frameData + SBC_HEADER_LEN, pcmData, pcmBytes, FALSE); 358df25739fSMilanka Ringwald if (OI_SUCCESS(status)) { 359df25739fSMilanka Ringwald *frameData += framelen; 360df25739fSMilanka Ringwald *frameBytes -= framelen; 361df25739fSMilanka Ringwald } 362df25739fSMilanka Ringwald TRACE(("-OI_CODEC_SBC_DecodeFrame: %d", status)); 363df25739fSMilanka Ringwald 364df25739fSMilanka Ringwald return status; 365df25739fSMilanka Ringwald } 366df25739fSMilanka Ringwald 367df25739fSMilanka Ringwald OI_STATUS OI_CODEC_SBC_SkipFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, 368df25739fSMilanka Ringwald const OI_BYTE **frameData, 369df25739fSMilanka Ringwald OI_UINT32 *frameBytes) 370df25739fSMilanka Ringwald { 371df25739fSMilanka Ringwald OI_STATUS status; 372df25739fSMilanka Ringwald OI_UINT framelen; 373df25739fSMilanka Ringwald OI_UINT headerlen; 374df25739fSMilanka Ringwald OI_UINT8 crc; 375df25739fSMilanka Ringwald 376df25739fSMilanka Ringwald status = FindSyncword(context, frameData, frameBytes); 377df25739fSMilanka Ringwald if (!OI_SUCCESS(status)) { 378df25739fSMilanka Ringwald return status; 379df25739fSMilanka Ringwald } 380df25739fSMilanka Ringwald if (*frameBytes < SBC_HEADER_LEN) { 381df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; 382df25739fSMilanka Ringwald } 383df25739fSMilanka Ringwald OI_SBC_ReadHeader(&context->common, *frameData); 384df25739fSMilanka Ringwald framelen = OI_SBC_CalculateFrameAndHeaderlen(&context->common.frameInfo, &headerlen); 385df25739fSMilanka Ringwald if (*frameBytes < headerlen) { 386df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA; 387df25739fSMilanka Ringwald } 388df25739fSMilanka Ringwald crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData); 389df25739fSMilanka Ringwald if (crc != context->common.frameInfo.crc) { 390df25739fSMilanka Ringwald return OI_CODEC_SBC_CHECKSUM_MISMATCH; 391df25739fSMilanka Ringwald } 392df25739fSMilanka Ringwald if (*frameBytes < framelen) { 393df25739fSMilanka Ringwald return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA; 394df25739fSMilanka Ringwald } 395df25739fSMilanka Ringwald context->bufferedBlocks = 0; 396df25739fSMilanka Ringwald *frameData += framelen; 397df25739fSMilanka Ringwald *frameBytes -= framelen; 398df25739fSMilanka Ringwald return OI_OK; 399df25739fSMilanka Ringwald } 400df25739fSMilanka Ringwald 401df25739fSMilanka Ringwald OI_UINT8 OI_CODEC_SBC_FrameCount(OI_BYTE *frameData, 402df25739fSMilanka Ringwald OI_UINT32 frameBytes) 403df25739fSMilanka Ringwald { 404df25739fSMilanka Ringwald OI_UINT8 mode; 405df25739fSMilanka Ringwald OI_UINT8 blocks; 406df25739fSMilanka Ringwald OI_UINT8 subbands; 407df25739fSMilanka Ringwald OI_UINT8 frameCount = 0; 408df25739fSMilanka Ringwald OI_UINT frameLen; 409df25739fSMilanka Ringwald 410df25739fSMilanka Ringwald while (frameBytes){ 411df25739fSMilanka Ringwald while (frameBytes && ((frameData[0] & 0xFE) != 0x9C)){ 412df25739fSMilanka Ringwald frameData++; 413df25739fSMilanka Ringwald frameBytes--; 414df25739fSMilanka Ringwald } 415df25739fSMilanka Ringwald 416df25739fSMilanka Ringwald if (frameBytes < SBC_HEADER_LEN) { 417df25739fSMilanka Ringwald return frameCount; 418df25739fSMilanka Ringwald } 419df25739fSMilanka Ringwald 420df25739fSMilanka Ringwald /* Extract and translate required fields from Header */ 421df25739fSMilanka Ringwald subbands = mode = blocks = frameData[1];; 422df25739fSMilanka Ringwald mode = (mode & (BIT3 | BIT2)) >> 2; 423df25739fSMilanka Ringwald blocks = block_values[(blocks & (BIT5 | BIT4)) >> 4]; 424df25739fSMilanka Ringwald subbands = band_values[(subbands & BIT0)]; 425df25739fSMilanka Ringwald 426df25739fSMilanka Ringwald /* Inline logic to avoid corrupting context */ 427df25739fSMilanka Ringwald frameLen = blocks * frameData[2]; 428df25739fSMilanka Ringwald switch (mode){ 429df25739fSMilanka Ringwald case SBC_JOINT_STEREO: 430df25739fSMilanka Ringwald frameLen += subbands + (8 * subbands); 431df25739fSMilanka Ringwald break; 432df25739fSMilanka Ringwald 433df25739fSMilanka Ringwald case SBC_DUAL_CHANNEL: 434df25739fSMilanka Ringwald frameLen *= 2; 435df25739fSMilanka Ringwald /* fall through */ 436df25739fSMilanka Ringwald 437df25739fSMilanka Ringwald default: 438df25739fSMilanka Ringwald if (mode == SBC_MONO){ 439df25739fSMilanka Ringwald frameLen += 4*subbands; 440df25739fSMilanka Ringwald } else { 441df25739fSMilanka Ringwald frameLen += 8*subbands; 442df25739fSMilanka Ringwald } 443df25739fSMilanka Ringwald } 444df25739fSMilanka Ringwald 445df25739fSMilanka Ringwald frameCount++; 446*c1ab6cc1SMatthias Ringwald frameLen = SBC_HEADER_LEN + ((frameLen + 7) / 8); 447df25739fSMilanka Ringwald if (frameBytes > frameLen){ 448df25739fSMilanka Ringwald frameBytes -= frameLen; 449df25739fSMilanka Ringwald frameData += frameLen; 450df25739fSMilanka Ringwald } else { 451df25739fSMilanka Ringwald frameBytes = 0; 452df25739fSMilanka Ringwald } 453df25739fSMilanka Ringwald } 454df25739fSMilanka Ringwald return frameCount; 455df25739fSMilanka Ringwald } 456df25739fSMilanka Ringwald 457df25739fSMilanka Ringwald /** Read quantized subband samples from the input bitstream and expand them. */ 458df25739fSMilanka Ringwald 459df25739fSMilanka Ringwald #ifdef SPECIALIZE_READ_SAMPLES_JOINT 460df25739fSMilanka Ringwald 46108b456cdSMilanka Ringwald PRIVATE void OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs); 462df25739fSMilanka Ringwald PRIVATE void OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs) 463df25739fSMilanka Ringwald { 464df25739fSMilanka Ringwald #define NROF_SUBBANDS 4 465df25739fSMilanka Ringwald #include "readsamplesjoint.inc" 466df25739fSMilanka Ringwald #undef NROF_SUBBANDS 467df25739fSMilanka Ringwald } 468df25739fSMilanka Ringwald 46908b456cdSMilanka Ringwald PRIVATE void OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs); 470df25739fSMilanka Ringwald PRIVATE void OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs) 471df25739fSMilanka Ringwald { 472df25739fSMilanka Ringwald #define NROF_SUBBANDS 8 473df25739fSMilanka Ringwald #include "readsamplesjoint.inc" 474df25739fSMilanka Ringwald #undef NROF_SUBBANDS 475df25739fSMilanka Ringwald } 476df25739fSMilanka Ringwald 477df25739fSMilanka Ringwald typedef void (*READ_SAMPLES)(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs); 478df25739fSMilanka Ringwald 479df25739fSMilanka Ringwald static const READ_SAMPLES SpecializedReadSamples[] = { 480df25739fSMilanka Ringwald OI_SBC_ReadSamplesJoint4, 481df25739fSMilanka Ringwald OI_SBC_ReadSamplesJoint8 482df25739fSMilanka Ringwald }; 483df25739fSMilanka Ringwald 484df25739fSMilanka Ringwald #endif /* SPECIALIZE_READ_SAMPLES_JOINT */ 485df25739fSMilanka Ringwald 486df25739fSMilanka Ringwald 487df25739fSMilanka Ringwald PRIVATE void OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs) 488df25739fSMilanka Ringwald { 489df25739fSMilanka Ringwald OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common; 490df25739fSMilanka Ringwald OI_UINT nrof_subbands = common->frameInfo.nrof_subbands; 491df25739fSMilanka Ringwald #ifdef SPECIALIZE_READ_SAMPLES_JOINT 492df25739fSMilanka Ringwald OI_ASSERT((nrof_subbands >> 3u) <= 1u); 493df25739fSMilanka Ringwald SpecializedReadSamples[nrof_subbands >> 3](context, global_bs); 494df25739fSMilanka Ringwald #else 495df25739fSMilanka Ringwald 496df25739fSMilanka Ringwald #define NROF_SUBBANDS nrof_subbands 497df25739fSMilanka Ringwald #include "readsamplesjoint.inc" 498df25739fSMilanka Ringwald #undef NROF_SUBBANDS 499df25739fSMilanka Ringwald #endif /* SPECIALIZE_READ_SAMPLES_JOINT */ 500df25739fSMilanka Ringwald } 501df25739fSMilanka Ringwald 502df25739fSMilanka Ringwald /**@}*/ 503df25739fSMilanka Ringwald 504