/****************************************************************************** * * 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_DEBUG("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_DEBUG("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_DEBUG("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_DEBUG("bta_pcm_init_dwn_sample: cur_pos %d, src_sps %d", \ p_cb->cur_pos, p_cb->src_sps); APPL_TRACE_DEBUG("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_DEBUG("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_DEBUG("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_DEBUG("bta_pcm_resample : outsamples %d", out_sample); #endif return (out_sample * bta_dm_pcm_cb.sample_size); } #endif