| /****************************************************************************** |
| * |
| * Copyright (C) 2003-2012 Broadcom 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. |
| * |
| ******************************************************************************/ |
| |
| /****************************************************************************** |
| * |
| * This file contains the down sampling utility to convert PCM samples in |
| * 16k/32k/48k/44.1k/22050/11025 sampling rate into 8K/16bits samples |
| * required for SCO channel format. One API function isprovided and only |
| * possible to be used when transmitting SCO data is sent via HCI |
| * interface. |
| * |
| ******************************************************************************/ |
| #include <string.h> |
| #include "bta_api.h" |
| #include "bta_sys.h" |
| |
| #if (BTM_SCO_HCI_INCLUDED == TRUE) |
| |
| #ifndef BTA_DM_SCO_DEBUG |
| #define BTA_DM_SCO_DEBUG FALSE |
| #endif |
| /***************************************************************************** |
| ** Constants |
| *****************************************************************************/ |
| |
| #define BTA_DM_PCM_OVERLAP_SIZE 48 |
| |
| #define BTA_DM_PCM_SMPL_RATE_44100 44100 |
| #define BTA_DM_PCM_SMPL_RATE_22050 22050 |
| #define BTA_DM_PCM_SMPL_RATE_11025 11025 |
| |
| /***************************************************************************** |
| ** Data types for PCM Resampling utility |
| *****************************************************************************/ |
| |
| typedef INT32 (*PCONVERT_TO_BT_FILTERED) (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples, |
| UINT32 dwSrcSps,INT32 *pLastCurPos, UINT8 *pOverlapArea); |
| typedef INT32 (*PCONVERT_TO_BT_NOFILTER) (void *pSrc, void *pDst, UINT32 dwSrcSamples, |
| UINT32 dwSrcSps); |
| typedef struct |
| { |
| UINT8 overlap_area[BTA_DM_PCM_OVERLAP_SIZE * 4]; |
| UINT32 cur_pos; /* current position */ |
| UINT32 src_sps; /* samples per second (source audio data) */ |
| PCONVERT_TO_BT_FILTERED filter; /* the action function to do the |
| conversion 44100, 22050, 11025*/ |
| PCONVERT_TO_BT_NOFILTER nofilter; /* the action function to do |
| the conversion 48000, 32000, 16000*/ |
| UINT32 bits; /* number of bits per pcm sample */ |
| UINT32 n_channels; /* number of channels (i.e. mono(1), stereo(2)...) */ |
| UINT32 sample_size; |
| UINT32 can_be_filtered; |
| UINT32 divisor; |
| } tBTA_DM_PCM_RESAMPLE_CB; |
| |
| tBTA_DM_PCM_RESAMPLE_CB bta_dm_pcm_cb; |
| |
| /***************************************************************************** |
| ** Macro Definition |
| *****************************************************************************/ |
| |
| |
| #define CHECK_SATURATION16(x) \ |
| if (x > 32767) \ |
| x = 32767; \ |
| else if (x < -32768) \ |
| x = -32768; |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // |
| #define CONVERT_44100_TO_BLUETOOTH(pStart, pEnd) \ |
| { \ |
| INT32 out1, out2, out3, out4, out5; \ |
| SRC_TYPE *pS = (SRC_TYPE *)pStart; \ |
| SRC_TYPE *pSEnd = (SRC_TYPE *)pEnd; \ |
| \ |
| while (pS < pSEnd) \ |
| { \ |
| CurrentPos -= 8000; \ |
| \ |
| if (CurrentPos >= 0) \ |
| { \ |
| pS += SRC_CHANNELS; \ |
| continue; \ |
| } \ |
| CurrentPos += dwSrcSps; \ |
| \ |
| out1 = (SRC_SAMPLE(0) * 1587) \ |
| + ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 1522) \ |
| + ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1337) \ |
| + ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 1058); \ |
| \ |
| out1 = out1 / 30000; \ |
| \ |
| out2 = ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 725) \ |
| + ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 384) \ |
| + ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 79); \ |
| \ |
| out2 = out2 / 30000; \ |
| \ |
| out3 = ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 156) \ |
| + ((SRC_SAMPLE(8) + SRC_SAMPLE(-8)) * 298) \ |
| + ((SRC_SAMPLE(9) + SRC_SAMPLE(-9)) * 345); \ |
| \ |
| out3 = out3 / 30000; \ |
| \ |
| out4 = ((SRC_SAMPLE(10) + SRC_SAMPLE(-10)) * 306) \ |
| + ((SRC_SAMPLE(11) + SRC_SAMPLE(-11)) * 207) \ |
| + ((SRC_SAMPLE(12) + SRC_SAMPLE(-12)) * 78); \ |
| \ |
| out4 = out4 / 30000; \ |
| \ |
| out5 = out1 + out2 - out3 - out4; \ |
| \ |
| CHECK_SATURATION16(out5); \ |
| *psBtOut++ = (INT16)out5; \ |
| \ |
| pS += SRC_CHANNELS; \ |
| } \ |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // |
| #define CONVERT_22050_TO_BLUETOOTH(pStart, pEnd) \ |
| { \ |
| INT32 out1, out2, out3, out4, out5; \ |
| SRC_TYPE *pS = (SRC_TYPE *)pStart; \ |
| SRC_TYPE *pSEnd = (SRC_TYPE *)pEnd; \ |
| \ |
| while (pS < pSEnd) \ |
| { \ |
| CurrentPos -= 8000; \ |
| \ |
| if (CurrentPos >= 0) \ |
| { \ |
| pS += SRC_CHANNELS; \ |
| continue; \ |
| } \ |
| CurrentPos += dwSrcSps; \ |
| \ |
| out1 = (SRC_SAMPLE(0) * 2993) \ |
| + ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 2568) \ |
| + ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1509) \ |
| + ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 331); \ |
| \ |
| out1 = out1 / 30000; \ |
| \ |
| out2 = ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 454) \ |
| + ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 620) \ |
| + ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 305); \ |
| \ |
| out2 = out2 / 30000; \ |
| \ |
| out3 = ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 127) \ |
| + ((SRC_SAMPLE(8) + SRC_SAMPLE(-8)) * 350) \ |
| + ((SRC_SAMPLE(9) + SRC_SAMPLE(-9)) * 265) \ |
| + ((SRC_SAMPLE(10) + SRC_SAMPLE(-10)) * 6); \ |
| \ |
| out3 = out3 / 30000; \ |
| \ |
| out4 = ((SRC_SAMPLE(11) + SRC_SAMPLE(-11)) * 201); \ |
| \ |
| out4 = out4 / 30000; \ |
| \ |
| out5 = out1 - out2 + out3 - out4; \ |
| \ |
| CHECK_SATURATION16(out5); \ |
| *psBtOut++ = (INT16)out5; \ |
| \ |
| pS += SRC_CHANNELS; \ |
| } \ |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // |
| #define CONVERT_11025_TO_BLUETOOTH(pStart, pEnd) \ |
| { \ |
| INT32 out1; \ |
| SRC_TYPE *pS = (SRC_TYPE *)pStart; \ |
| SRC_TYPE *pSEnd = (SRC_TYPE *)pEnd; \ |
| \ |
| while (pS < pSEnd) \ |
| { \ |
| CurrentPos -= 8000; \ |
| \ |
| if (CurrentPos >= 0) \ |
| { \ |
| pS += SRC_CHANNELS; \ |
| continue; \ |
| } \ |
| CurrentPos += dwSrcSps; \ |
| \ |
| out1 = (SRC_SAMPLE(0) * 6349) \ |
| + ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 2874) \ |
| - ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1148) \ |
| - ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 287) \ |
| + ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 675) \ |
| - ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 258) \ |
| - ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 206) \ |
| + ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 266); \ |
| \ |
| out1 = out1 / 30000; \ |
| \ |
| CHECK_SATURATION16(out1); \ |
| *psBtOut++ = (INT16)out1; \ |
| \ |
| pS += SRC_CHANNELS; \ |
| } \ |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // |
| #undef SRC_CHANNELS |
| #undef SRC_SAMPLE |
| #undef SRC_TYPE |
| |
| #define SRC_TYPE UINT8 |
| #define SRC_CHANNELS 1 |
| #define SRC_SAMPLE(x) ((pS[x] - 0x80) << 8) |
| |
| /***************************************************************************** |
| ** Local Function |
| *****************************************************************************/ |
| INT32 Convert_8M_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples, |
| UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea) |
| { |
| INT32 CurrentPos = *pLastCurPos; |
| SRC_TYPE *pIn, *pInEnd; |
| SRC_TYPE *pOv, *pOvEnd; |
| INT16 *psBtOut = (INT16 *)pDst; |
| #if BTA_DM_SCO_DEBUG |
| APPL_TRACE_DEBUG1("Convert_8M_ToBT_Filtered, CurrentPos %d\n", CurrentPos); |
| #endif |
| memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2); |
| |
| pOv = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE); |
| pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3)); |
| |
| pIn = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE); |
| pInEnd = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \ |
| BTA_DM_PCM_OVERLAP_SIZE); |
| |
| if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100) |
| { |
| CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd); |
| CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd); |
| } |
| else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050) |
| { |
| CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd); |
| CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd); |
| } |
| else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025) |
| { |
| CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd); |
| CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd); |
| } |
| |
| memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \ |
| (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2); |
| |
| *pLastCurPos = CurrentPos; |
| |
| return (psBtOut - (INT16 *)pDst); |
| } |
| |
| INT32 Convert_8M_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps) |
| { |
| INT32 CurrentPos; |
| UINT8 *pbSrc = (UINT8 *)pSrc; |
| INT16 *psDst = (INT16 *)pDst; |
| INT16 sWorker; |
| |
| // start at dwSpsSrc / 2, decrement by 8000 |
| // |
| CurrentPos = (dwSrcSps >> 1); |
| |
| while (dwSrcSamples--) |
| { |
| CurrentPos -= 8000; |
| |
| if (CurrentPos >= 0) |
| pbSrc++; |
| else |
| { |
| sWorker = *pbSrc++; |
| sWorker -= 0x80; |
| sWorker <<= 8; |
| |
| *psDst++ = sWorker; |
| |
| CurrentPos += dwSrcSps; |
| } |
| } |
| |
| return (psDst - (INT16 *)pDst); |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // |
| #undef SRC_CHANNELS |
| #undef SRC_SAMPLE |
| #undef SRC_TYPE |
| |
| #define SRC_TYPE INT16 |
| #define SRC_CHANNELS 1 |
| #define SRC_SAMPLE(x) pS[x] |
| |
| INT32 Convert_16M_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples, |
| UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea) |
| { |
| INT32 CurrentPos = *pLastCurPos; |
| SRC_TYPE *pIn, *pInEnd; |
| SRC_TYPE *pOv, *pOvEnd; |
| INT16 *psBtOut = (INT16 *)pDst; |
| |
| memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2); |
| |
| pOv = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE); |
| pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3)); |
| |
| pIn = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE); |
| pInEnd = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - BTA_DM_PCM_OVERLAP_SIZE); |
| |
| if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100) |
| { |
| CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd); |
| CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd); |
| } |
| else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050) |
| { |
| CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd); |
| CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd); |
| } |
| else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025) |
| { |
| CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd); |
| CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd); |
| } |
| |
| memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \ |
| (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2); |
| |
| *pLastCurPos = CurrentPos; |
| |
| return (psBtOut - (INT16 *)pDst); |
| } |
| |
| INT32 Convert_16M_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps) |
| { |
| INT32 CurrentPos; |
| INT16 *psSrc = (INT16 *)pSrc; |
| INT16 *psDst = (INT16 *)pDst; |
| |
| // start at dwSpsSrc / 2, decrement by 8000 |
| // |
| CurrentPos = (dwSrcSps >> 1); |
| |
| while (dwSrcSamples--) |
| { |
| CurrentPos -= 8000; |
| |
| if (CurrentPos >= 0) |
| psSrc++; |
| else |
| { |
| *psDst++ = *psSrc++; |
| |
| CurrentPos += dwSrcSps; |
| } |
| } |
| |
| return (psDst - (INT16 *)pDst); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // |
| #undef SRC_CHANNELS |
| #undef SRC_SAMPLE |
| #undef SRC_TYPE |
| |
| #define SRC_TYPE UINT8 |
| #define SRC_CHANNELS 2 |
| #define SRC_SAMPLE(x) ((((pS[x * 2] - 0x80) << 8) + ((pS[(x * 2) + 1] - 0x80) << 8)) >> 1) |
| |
| INT32 Convert_8S_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples, |
| UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea) |
| { |
| INT32 CurrentPos = *pLastCurPos; |
| SRC_TYPE *pIn, *pInEnd; |
| SRC_TYPE *pOv, *pOvEnd; |
| INT16 *psBtOut = (INT16 *)pDst; |
| |
| #if BTA_DM_SCO_DEBUG |
| APPL_TRACE_DEBUG5("Convert_8S_ToBT_Filtered CurrentPos %d, SRC_TYPE %d, SRC_CHANNELS %d, \ |
| dwSrcSamples %d, dwSrcSps %d", CurrentPos, sizeof (SRC_TYPE), SRC_CHANNELS, \ |
| dwSrcSamples, dwSrcSps); |
| #endif |
| memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2); |
| |
| pOv = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE); |
| pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3)); |
| |
| pIn = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE); |
| pInEnd = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - BTA_DM_PCM_OVERLAP_SIZE); |
| |
| if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100) |
| { |
| CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd); |
| CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd); |
| } |
| else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050) |
| { |
| CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd); |
| CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd); |
| } |
| else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025) |
| { |
| CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd); |
| CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd); |
| } |
| |
| memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \ |
| (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2); |
| |
| *pLastCurPos = CurrentPos; |
| |
| return (psBtOut - (INT16 *)pDst); |
| } |
| |
| INT32 Convert_8S_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps) |
| { |
| INT32 CurrentPos; |
| UINT8 *pbSrc = (UINT8 *)pSrc; |
| INT16 *psDst = (INT16 *)pDst; |
| INT16 sWorker, sWorker2; |
| |
| // start at dwSpsSrc / 2, decrement by 8000 |
| // |
| CurrentPos = (dwSrcSps >> 1); |
| |
| while (dwSrcSamples--) |
| { |
| CurrentPos -= 8000; |
| |
| if (CurrentPos >= 0) |
| pbSrc += 2; |
| else |
| { |
| sWorker = *(unsigned char *)pbSrc; |
| sWorker -= 0x80; |
| sWorker <<= 8; |
| pbSrc++; |
| |
| sWorker2 = *(unsigned char *)pbSrc; |
| sWorker2 -= 0x80; |
| sWorker2 <<= 8; |
| pbSrc++; |
| |
| sWorker += sWorker2; |
| sWorker >>= 1; |
| |
| *psDst++ = sWorker; |
| |
| CurrentPos += dwSrcSps; |
| } |
| } |
| |
| return (psDst - (INT16 *)pDst); |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // |
| #undef SRC_CHANNELS |
| #undef SRC_SAMPLE |
| #undef SRC_TYPE |
| |
| #define SRC_TYPE INT16 |
| #define SRC_CHANNELS 2 |
| #define SRC_SAMPLE(x) ((pS[x * 2] + pS[(x * 2) + 1]) >> 1) |
| |
| INT32 Convert_16S_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples, |
| UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea) |
| { |
| INT32 CurrentPos = *pLastCurPos; |
| SRC_TYPE *pIn, *pInEnd; |
| SRC_TYPE *pOv, *pOvEnd; |
| INT16 *psBtOut = (INT16 *)pDst; |
| |
| memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2); |
| |
| pOv = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE); |
| pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3)); |
| |
| pIn = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE); |
| pInEnd = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - BTA_DM_PCM_OVERLAP_SIZE); |
| |
| if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100) |
| { |
| CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd); |
| CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd); |
| } |
| else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050) |
| { |
| CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd); |
| CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd); |
| } |
| else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025) |
| { |
| CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd); |
| CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd); |
| } |
| |
| memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \ |
| (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2); |
| |
| *pLastCurPos = CurrentPos; |
| |
| return (psBtOut - (INT16 *)pDst); |
| } |
| |
| INT32 Convert_16S_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps) |
| { |
| INT32 CurrentPos; |
| INT16 *psSrc = (INT16 *)pSrc; |
| INT16 *psDst = (INT16 *)pDst; |
| INT16 sWorker; |
| |
| // start at dwSpsSrc / 2, decrement by 8000 |
| // |
| CurrentPos = (dwSrcSps >> 1); |
| |
| while (dwSrcSamples--) |
| { |
| CurrentPos -= 8000; |
| |
| if (CurrentPos >= 0) |
| psSrc += 2; |
| else |
| { |
| /* CR 82894, to avoid overflow, divide before add */ |
| sWorker = ((*psSrc) >> 1 ); |
| psSrc++; |
| sWorker += ((*psSrc) >> 1 ); |
| psSrc++; |
| |
| *psDst++ = sWorker; |
| |
| CurrentPos += dwSrcSps; |
| } |
| } |
| |
| return (psDst - (INT16 *)pDst); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function BTA_DmPcmInitSamples |
| ** |
| ** Description initialize the down sample converter. |
| ** |
| ** src_sps: original samples per second (source audio data) |
| ** (ex. 44100, 48000) |
| ** bits: number of bits per pcm sample (16) |
| ** n_channels: number of channels (i.e. mono(1), stereo(2)...) |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void BTA_DmPcmInitSamples (UINT32 src_sps, UINT32 bits, UINT32 n_channels) |
| { |
| tBTA_DM_PCM_RESAMPLE_CB *p_cb = &bta_dm_pcm_cb; |
| |
| p_cb->cur_pos = src_sps / 2; |
| p_cb->src_sps = src_sps; |
| p_cb->bits = bits; |
| p_cb->n_channels = n_channels; |
| p_cb->sample_size = 2; |
| p_cb->divisor = 2; |
| |
| memset(p_cb->overlap_area, 0, sizeof(p_cb->overlap_area) ); |
| |
| if ((src_sps == BTA_DM_PCM_SMPL_RATE_44100) || |
| (src_sps == BTA_DM_PCM_SMPL_RATE_22050) || |
| (src_sps == BTA_DM_PCM_SMPL_RATE_11025)) |
| p_cb->can_be_filtered = 1; |
| else |
| p_cb->can_be_filtered = 0; |
| |
| #if BTA_DM_SCO_DEBUG |
| APPL_TRACE_DEBUG2("bta_dm_pcm_init_samples: n_channels = %d bits = %d", n_channels, bits); |
| #endif |
| if(n_channels == 1) |
| { |
| /* mono */ |
| if(bits == 8) |
| { |
| p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_8M_ToBT_Filtered; |
| p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_8M_ToBT_NoFilter; |
| p_cb->divisor = 1; |
| } |
| else |
| { |
| p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_16M_ToBT_Filtered; |
| p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_16M_ToBT_NoFilter; |
| } |
| } |
| else |
| { |
| /* stereo */ |
| if(bits == 8) |
| { |
| p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_8S_ToBT_Filtered; |
| p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_8S_ToBT_NoFilter; |
| } |
| else |
| { |
| p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_16S_ToBT_Filtered; |
| p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_16S_ToBT_NoFilter; |
| p_cb->divisor = 4; |
| } |
| } |
| |
| #if BTA_DM_SCO_DEBUG |
| APPL_TRACE_DEBUG2("bta_pcm_init_dwn_sample: cur_pos %d, src_sps %d", \ |
| p_cb->cur_pos, p_cb->src_sps); |
| APPL_TRACE_DEBUG3("bta_pcm_init_dwn_sample: bits %d, n_channels %d, sample_size %d, ", \ |
| p_cb->bits, p_cb->n_channels, p_cb->sample_size); |
| APPL_TRACE_DEBUG3("bta_pcm_init_dwn_sample: can_be_filtered %d, n_channels: %d, \ |
| divisor %d", p_cb->can_be_filtered, p_cb->n_channels, p_cb->divisor); |
| #endif |
| |
| } |
| |
| /************************************************************************************** |
| ** Function BTA_DmPcmResample |
| ** |
| ** Description Down sampling utility to convert higher sampling rate into 8K/16bits |
| ** PCM samples. |
| ** |
| ** Parameters p_src: pointer to the buffer where the original sampling PCM |
| ** are stored. |
| ** in_bytes: Length of the input PCM sample buffer in byte. |
| ** p_dst: pointer to the buffer which is to be used to store |
| ** the converted PCM samples. |
| ** |
| ** |
| ** Returns INT32: number of samples converted. |
| ** |
| **************************************************************************************/ |
| INT32 BTA_DmPcmResample (void *p_src, UINT32 in_bytes, void *p_dst) |
| { |
| UINT32 out_sample; |
| |
| #if BTA_DM_SCO_DEBUG |
| APPL_TRACE_DEBUG1("bta_pcm_resample : insamples %d", (in_bytes / bta_dm_pcm_cb.divisor)); |
| #endif |
| if(bta_dm_pcm_cb.can_be_filtered) |
| { |
| out_sample = (*bta_dm_pcm_cb.filter) (p_src, p_dst, (in_bytes / bta_dm_pcm_cb.divisor), |
| bta_dm_pcm_cb.src_sps, (INT32 *) &bta_dm_pcm_cb.cur_pos, bta_dm_pcm_cb.overlap_area); |
| } |
| else |
| { |
| out_sample = (*bta_dm_pcm_cb.nofilter) (p_src, p_dst, |
| (in_bytes / bta_dm_pcm_cb.divisor), bta_dm_pcm_cb.src_sps); |
| } |
| |
| #if BTA_DM_SCO_DEBUG |
| APPL_TRACE_DEBUG1("bta_pcm_resample : outsamples %d", out_sample); |
| #endif |
| |
| return (out_sample * bta_dm_pcm_cb.sample_size); |
| } |
| #endif |