You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
667 lines
25 KiB
667 lines
25 KiB
/****************************************************************************** |
|
* |
|
* 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_t (*PCONVERT_TO_BT_FILTERED)(uint8_t* pSrc, void* pDst, |
|
uint32_t dwSrcSamples, |
|
uint32_t dwSrcSps, |
|
int32_t* pLastCurPos, |
|
uint8_t* pOverlapArea); |
|
typedef int32_t (*PCONVERT_TO_BT_NOFILTER)(void* pSrc, void* pDst, |
|
uint32_t dwSrcSamples, |
|
uint32_t dwSrcSps); |
|
typedef struct { |
|
uint8_t overlap_area[BTA_DM_PCM_OVERLAP_SIZE * 4]; |
|
uint32_t cur_pos; /* current position */ |
|
uint32_t 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_t bits; /* number of bits per pcm sample */ |
|
uint32_t n_channels; /* number of channels (i.e. mono(1), stereo(2)...) */ |
|
uint32_t sample_size; |
|
uint32_t can_be_filtered; |
|
uint32_t divisor; |
|
} tBTA_DM_PCM_RESAMPLE_CB; |
|
|
|
tBTA_DM_PCM_RESAMPLE_CB bta_dm_pcm_cb; |
|
|
|
/***************************************************************************** |
|
* Macro Definition |
|
****************************************************************************/ |
|
|
|
#define CHECK_SATURATION16(x) \ |
|
do { \ |
|
if ((x) > 32767) \ |
|
(x) = 32767; \ |
|
else if ((x) < -32768) \ |
|
(x) = -32768; \ |
|
} while (0) |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// |
|
#define CONVERT_44100_TO_BLUETOOTH(pStart, pEnd) \ |
|
do { \ |
|
int32_t 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_t)out5; \ |
|
\ |
|
pS += SRC_CHANNELS; \ |
|
} \ |
|
} while (0) |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// |
|
#define CONVERT_22050_TO_BLUETOOTH(pStart, pEnd) \ |
|
do { \ |
|
int32_t 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_t)out5; \ |
|
\ |
|
pS += SRC_CHANNELS; \ |
|
} \ |
|
} while (0) |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// |
|
#define CONVERT_11025_TO_BLUETOOTH(pStart, pEnd) \ |
|
do { \ |
|
int32_t 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_t)out1; \ |
|
\ |
|
pS += SRC_CHANNELS; \ |
|
} \ |
|
} while (0) |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// |
|
#undef SRC_CHANNELS |
|
#undef SRC_SAMPLE |
|
#undef SRC_TYPE |
|
|
|
#define SRC_TYPE uint8_t |
|
#define SRC_CHANNELS 1 |
|
#define SRC_SAMPLE(x) ((pS[x] - 0x80) << 8) |
|
|
|
/***************************************************************************** |
|
* Local Function |
|
****************************************************************************/ |
|
int32_t Convert_8M_ToBT_Filtered(uint8_t* pSrc, void* pDst, |
|
uint32_t dwSrcSamples, uint32_t dwSrcSps, |
|
int32_t* pLastCurPos, uint8_t* pOverlapArea) { |
|
int32_t CurrentPos = *pLastCurPos; |
|
SRC_TYPE *pIn, *pInEnd; |
|
SRC_TYPE *pOv, *pOvEnd; |
|
int16_t* psBtOut = (int16_t*)pDst; |
|
#if (BTA_DM_SCO_DEBUG == TRUE) |
|
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_t*)pDst); |
|
} |
|
|
|
int32_t Convert_8M_ToBT_NoFilter(void* pSrc, void* pDst, uint32_t dwSrcSamples, |
|
uint32_t dwSrcSps) { |
|
int32_t CurrentPos; |
|
uint8_t* pbSrc = (uint8_t*)pSrc; |
|
int16_t* psDst = (int16_t*)pDst; |
|
int16_t 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_t*)pDst); |
|
} |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// |
|
#undef SRC_CHANNELS |
|
#undef SRC_SAMPLE |
|
#undef SRC_TYPE |
|
|
|
#define SRC_TYPE int16_t |
|
#define SRC_CHANNELS 1 |
|
#define SRC_SAMPLE(x) pS[x] |
|
|
|
int32_t Convert_16M_ToBT_Filtered(uint8_t* pSrc, void* pDst, |
|
uint32_t dwSrcSamples, uint32_t dwSrcSps, |
|
int32_t* pLastCurPos, uint8_t* pOverlapArea) { |
|
int32_t CurrentPos = *pLastCurPos; |
|
SRC_TYPE *pIn, *pInEnd; |
|
SRC_TYPE *pOv, *pOvEnd; |
|
int16_t* psBtOut = (int16_t*)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_t*)pDst); |
|
} |
|
|
|
int32_t Convert_16M_ToBT_NoFilter(void* pSrc, void* pDst, uint32_t dwSrcSamples, |
|
uint32_t dwSrcSps) { |
|
int32_t CurrentPos; |
|
int16_t* psSrc = (int16_t*)pSrc; |
|
int16_t* psDst = (int16_t*)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_t*)pDst); |
|
} |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// |
|
#undef SRC_CHANNELS |
|
#undef SRC_SAMPLE |
|
#undef SRC_TYPE |
|
|
|
#define SRC_TYPE uint8_t |
|
#define SRC_CHANNELS 2 |
|
#define SRC_SAMPLE(x) \ |
|
((((pS[x * 2] - 0x80) << 8) + ((pS[(x * 2) + 1] - 0x80) << 8)) >> 1) |
|
|
|
int32_t Convert_8S_ToBT_Filtered(uint8_t* pSrc, void* pDst, |
|
uint32_t dwSrcSamples, uint32_t dwSrcSps, |
|
int32_t* pLastCurPos, uint8_t* pOverlapArea) { |
|
int32_t CurrentPos = *pLastCurPos; |
|
SRC_TYPE *pIn, *pInEnd; |
|
SRC_TYPE *pOv, *pOvEnd; |
|
int16_t* psBtOut = (int16_t*)pDst; |
|
|
|
#if (BTA_DM_SCO_DEBUG == TRUE) |
|
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_t*)pDst); |
|
} |
|
|
|
int32_t Convert_8S_ToBT_NoFilter(void* pSrc, void* pDst, uint32_t dwSrcSamples, |
|
uint32_t dwSrcSps) { |
|
int32_t CurrentPos; |
|
uint8_t* pbSrc = (uint8_t*)pSrc; |
|
int16_t* psDst = (int16_t*)pDst; |
|
int16_t 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_t*)pDst); |
|
} |
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
// |
|
#undef SRC_CHANNELS |
|
#undef SRC_SAMPLE |
|
#undef SRC_TYPE |
|
|
|
#define SRC_TYPE int16_t |
|
#define SRC_CHANNELS 2 |
|
#define SRC_SAMPLE(x) ((pS[x * 2] + pS[(x * 2) + 1]) >> 1) |
|
|
|
int32_t Convert_16S_ToBT_Filtered(uint8_t* pSrc, void* pDst, |
|
uint32_t dwSrcSamples, uint32_t dwSrcSps, |
|
int32_t* pLastCurPos, uint8_t* pOverlapArea) { |
|
int32_t CurrentPos = *pLastCurPos; |
|
SRC_TYPE *pIn, *pInEnd; |
|
SRC_TYPE *pOv, *pOvEnd; |
|
int16_t* psBtOut = (int16_t*)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_t*)pDst); |
|
} |
|
|
|
int32_t Convert_16S_ToBT_NoFilter(void* pSrc, void* pDst, uint32_t dwSrcSamples, |
|
uint32_t dwSrcSps) { |
|
int32_t CurrentPos; |
|
int16_t* psSrc = (int16_t*)pSrc; |
|
int16_t* psDst = (int16_t*)pDst; |
|
int16_t 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_t*)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_t src_sps, uint32_t bits, |
|
uint32_t 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 == TRUE) |
|
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 == TRUE) |
|
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_t: number of samples converted. |
|
* |
|
******************************************************************************/ |
|
int32_t BTA_DmPcmResample(void* p_src, uint32_t in_bytes, void* p_dst) { |
|
uint32_t out_sample; |
|
|
|
#if (BTA_DM_SCO_DEBUG == TRUE) |
|
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_t*)&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 == TRUE) |
|
APPL_TRACE_DEBUG("bta_pcm_resample : outsamples %d", out_sample); |
|
#endif |
|
|
|
return (out_sample * bta_dm_pcm_cb.sample_size); |
|
} |
|
#endif
|
|
|