/******************************************************************************
*
* 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