blob: 85ac76efeeddc89697952ccbd38ce25c9c2b744f [file] [log] [blame]
/*****************************************************************************
* Copyright Statement:
* --------------------
* This software is protected by Copyright and the information contained
* herein is confidential. The software may not be copied and the information
* contained herein may not be used or disclosed except with the written
* permission of MediaTek Inc. (C) 2005
*
* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
*
* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*
* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
*
*****************************************************************************/
/*****************************************************************************
*
* Filename:
* ---------
* snd_effect.c
*
* Project:
* --------
* Maui_sw
*
* Description:
* ------------
* Streaming Background Sound Playback.
* Play 8kHz mono linear PCM in TCH or idle mode.
*
* Author:
* -------
* -------
*============================================================================
* HISTORY
* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
*------------------------------------------------------------------------------
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
* removed!
*
*
*------------------------------------------------------------------------------
* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
*============================================================================
****************************************************************************/
#include "kal_public_api.h"
#include "kal_general_types.h"
#include "sync_data.h"
#include "kal_trace.h"
#include "l1sp_trc.h"
#include "am.h"
//#include "speech_def.h"
#include "afe_def.h" // for output device setting
#include "sp_drv.h"
#include "sal_exp.h"
#define DSP_BGS_UP_DOWN_INT_SEPERATE
/************************** Constants ***************************************/
// #define DP_BUFFER_DEFAULT_LEN 4096 /* The frame size of DSP. */
#define DSP_BUFFER_LEN_NB 160 //unit is sample (16bit)
#define DSP_BUFFER_LEN_WB 320 //unit is sample (16bit)
#define DSP_BUFFER_LEN_MAX 320 //unit is sample (16bit)
/* DSP Sound Effect State */
#define DP_BGSND_STATE_IDLE 0 /* MCU: 0 -> 1 */
#define DP_BGSND_STATE_READY 1 /* DSP: 1 -> 2 */
#define DP_BGSND_STATE_PLAYING 2 /* MCU: 2 -> 3 */
#define DP_BGSND_STATE_STOP 3 /* DSP: 3 -> 0 */
//#define SND_CHECK_DATA
#define SND_GAIN_CONFIG 1 /* 0: right shamt, 1: multiplier */
#define BGSND_BUF_SIZE 2560 // using in 16 bit
#define BGSND_BUF_PTR_DIFF 2
typedef enum {
BGSND_STATE_IDLE = 0,
BGSND_STATE_RUN,
BGSND_STATE_STOP,
BGSND_STATE_CLOSE,
}BGSND_STATE_TYPE;
/*********** Structure *******************************************************/
typedef struct{
BGSND_STATE_TYPE state;
kal_bool fULSPH;
kal_bool fDLSPH;
kal_bool isDlHisrCome;
kal_bool isUlHisrCome;
void (*bgSnd_hisrHandler)(void);
void (*bgSnd_offHandler)(void);
kal_uint16 aud_id;
kal_timerid timer;
kal_uint16 endCount;
kal_uint16 ULGain;
kal_uint16 DLGain;
kal_uint16 dspLastSample;
kal_uint16 *pBuf;
kal_int32 bufSize; // unit is 16 bit (sample)
kal_int32 bufWrite; // unit is 16 bit
kal_int32 bufRead; // unit is 16 bit
}BGSND_T;
/*********** variable ********************************************************/
static BGSND_T bgSnd;
static kal_uint16 bgSndBuf[BGSND_BUF_SIZE];
/*********** internal fucntion **********************************************/
static void bgsndUpdateMixer()
{
if ( AM_IsSpeechOn() ) {
SAL_Bgsnd_Config(bgSnd.ULGain, bgSnd.DLGain, bgSnd.fULSPH, bgSnd.fDLSPH);
} else {
SAL_Bgsnd_Config(bgSnd.ULGain, bgSnd.DLGain, 0, 0);
}
}
/**
@return: size is 16-bit, available PCM size
*/
static int32 bgsndGetDataCount(void)
{
int32 count;
// int32 count = (int32)ihdl->mh.rbInfo.write - (int32)ihdl->mh.rbInfo.read;
if(bgSnd.bufWrite<bgSnd.bufRead){
count = (bgSnd.bufSize - BGSND_BUF_PTR_DIFF)+bgSnd.bufWrite - bgSnd.bufRead;
} else {
count = bgSnd.bufWrite - bgSnd.bufRead;
}
if( count > BGSND_BUF_PTR_DIFF) {
count -= BGSND_BUF_PTR_DIFF;
} else {
count = 0;
}
if(count&1){
count = count -1;
}
return count;
/*
int32 count = bgSnd.bufWrite - bgSnd.bufRead;
if( count < 0 )
count += (bgSnd.bufSize - BGSND_BUF_PTR_DIFF );
else if( count > 2)
count -= BGSND_BUF_PTR_DIFF;
else
count = 0;
return count;
*/
}
/*
static kal_int16 tone1k_16kSR[320] = {
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
0x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
0x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05
};
*/
static void bgsnd_WriteToDSP(void)
{
uint16 dsp_buf_len, dsp_buf_len_Ul;
uint16 *dataPtr;
volatile uint16 *toPtr;
volatile uint16 *toPtr_Ul;
int32 count, segment, i;
bool isWb, isWb_Ul;
/*
¡VSph_Band_Flag
¡EBit 0: Sch band (0/1 : Nb/Wb)
¡EBit 1: Cod band (0/1 : Nb/Wb)
¡EBit 2: VBI band (0/1 : Nb/Wb)
¡EBit 3: BT band (0/1 : Nb/Wb)
MT6280 0x2FBF
MT6589 0x32F1
dm5
*/
// get current buffer data length in two sample alight. (16k sampling rate)
count = bgsndGetDataCount();
//set up the DSP address and pointers
dsp_buf_len = SAL_Bgsnd_GetDataLen_DL();
#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
dsp_buf_len_Ul = SAL_Bgsnd_GetDataLen_UL();
#else
dsp_buf_len_Ul = dsp_buf_len;
#endif
if(dsp_buf_len == DSP_BUFFER_LEN_WB)
isWb = true;
else if(dsp_buf_len == DSP_BUFFER_LEN_NB){
isWb = false;
// count >>= 1;
}
else {
ASSERT_REBOOT(0);
isWb = false;
}
if(dsp_buf_len_Ul == DSP_BUFFER_LEN_WB)
isWb_Ul= true;
else if(dsp_buf_len_Ul == DSP_BUFFER_LEN_NB){
isWb_Ul= false;
}
else {
ASSERT_REBOOT(0);
isWb_Ul = false;
}
toPtr = SAL_Bgsnd_GetBuf_DL();
#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
toPtr_Ul = SAL_Bgsnd_GetBuf_UL();
#else
toPtr_Ul = toPtr;
#endif
MD_TRC_L1SND_DSP_BUFFER_INFO(count, toPtr, dsp_buf_len);
#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
MD_TRC_L1SND_DSP_BUFFER_INFO(-1, toPtr_Ul, dsp_buf_len_Ul);
#else
MD_TRC_L1SND_DSP_BUFFER_INFO(count, toPtr_Ul, dsp_buf_len_Ul);
#endif
if (count > DSP_BUFFER_LEN_MAX)
count = DSP_BUFFER_LEN_MAX;
if(count > 0) {
/* First Segemnt */
if(bgSnd.bufWrite < bgSnd.bufRead) {
segment = (bgSnd.bufSize - bgSnd.bufRead);
} else {
segment = (bgSnd.bufWrite - bgSnd.bufRead);
}
if(segment&1){ // keep two sample alight
segment =segment - 1;
}
/*
if(isNb){ // 8k
if (segment > (count<<1))
segment = (count<<1);
}else { // 16 k
if (segment > count)
segment = count;
}
*/
if (segment > count)
segment = count;
if (segment > 0) {
// kal_dev_trace(TRACE_STATE, L1SND_FILLBUFFER, segment);
dataPtr = &(bgSnd.pBuf[bgSnd.bufRead]);
for (i=segment; i>0; (i-=2)) {
// first sample
*toPtr++ = *dataPtr;
*toPtr_Ul++ = *dataPtr++;
// second sample
if(isWb) {
*toPtr++ = *dataPtr;
}
if(isWb_Ul) {
*toPtr_Ul++ = *dataPtr;
}
dataPtr++;
}
Data_Sync_Barrier();
bgSnd.dspLastSample = *(toPtr-1);
bgSnd.bufRead += segment;
if (bgSnd.bufRead >= bgSnd.bufSize)
bgSnd.bufRead = (bgSnd.bufRead-bgSnd.bufSize);
MD_TRC_L1SND_FILLBUFFER(1, segment, bgSnd.bufRead, bgSnd.bufWrite);
}
/* Second Segment */
/*
if(isNb){ // 8k
segment = (count<<1) - segment;
} else {
segment = count - segment;
}
*/
segment = count - segment;
if (segment > 0) {
// kal_dev_trace(TRACE_STATE, L1SND_FILLBUFFER, segment);
// dataPtr = bgSnd.pBuf;
dataPtr = &(bgSnd.pBuf[bgSnd.bufRead]);
for (i=segment; i>0; (i-=2)) {
// first sample
*toPtr++ = *dataPtr;
*toPtr_Ul++ = *dataPtr++;
// second sample
if(isWb) {
*toPtr++ = *dataPtr;
}
if(isWb_Ul) {
*toPtr_Ul++ = *dataPtr;
}
dataPtr++;
}
Data_Sync_Barrier();
bgSnd.dspLastSample = *(toPtr-1);
bgSnd.bufRead += segment;
if (bgSnd.bufRead >= bgSnd.bufSize)
bgSnd.bufRead = (bgSnd.bufRead-bgSnd.bufSize);
MD_TRC_L1SND_FILLBUFFER(2, segment, bgSnd.bufRead, bgSnd.bufWrite);
}
}
/* Put silence (last sample) if MCU buffer is empty */
if (count < DSP_BUFFER_LEN_MAX) {
kal_uint16 last_sample;
last_sample = bgSnd.dspLastSample;
// segment = dsp_buf_len - count;
segment = DSP_BUFFER_LEN_MAX - count;
MD_TRC_L1SND_PUT_SILENCE(segment, last_sample);
/*
for (i=segment; i>0; i--) {
*toPtr++ = last_sample;
}
*/
for (i=segment; i>0; (i-=2)) {
// first sample
*toPtr++ = last_sample;
*toPtr_Ul++ = last_sample;
// second sample
if(isWb) {
*toPtr++ = last_sample;
}
if(isWb_Ul) {
*toPtr_Ul++ = last_sample;
}
}
Data_Sync_Barrier();
}
}
void bgsndHisr( void *pram )
{
// gain and setting update
bgsndUpdateMixer();
// handle extra notify and closing state
if ((BGSND_STATE_RUN != bgSnd.state) && (BGSND_STATE_STOP !=bgSnd.state))
return;
// if ( ihdl->end_status != MEDIA_NONE )
// return;
if(!SAL_Bgsnd_IsRunning())
return;
bgsnd_WriteToDSP();
if( bgSnd.bgSnd_hisrHandler != NULL) {
bgSnd.bgSnd_hisrHandler();
}
}
#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
void bgsndDlHisr( void * param)
{
if(true == bgSnd.isDlHisrCome) {
MD_TRC_L1SND_REENTER_HISR(bgSnd.isDlHisrCome, bgSnd.isUlHisrCome);
} else {
bgSnd.isDlHisrCome = true;
if(bgSnd.isUlHisrCome == bgSnd.isDlHisrCome) {
bgsndHisr(param);
bgSnd.isUlHisrCome = false;
bgSnd.isDlHisrCome = false;
}
}
}
void bgsndUlHisr( void * param)
{
if(true == bgSnd.isUlHisrCome) {
MD_TRC_L1SND_REENTER_HISR(bgSnd.isDlHisrCome, bgSnd.isUlHisrCome);
} else {
bgSnd.isUlHisrCome = true;
if(bgSnd.isUlHisrCome == bgSnd.isDlHisrCome) {
bgsndHisr(param);
bgSnd.isUlHisrCome = false;
bgSnd.isDlHisrCome = false;
}
}
}
#endif // DSP_BGS_UP_DOWN_INT_SEPERATE
void bgsndOnHandler(void)
{
AM_SND_PlaybackOn();
SAL_Bgsnd_SetInit();
//*DSP_SOUND_EFFECT_CTRL = DP_BGSND_STATE_READY;
{
uint32 I;
for( I = 0; ; I++ ) {
//if( *DSP_SOUND_EFFECT_CTRL == DP_BGSND_STATE_PLAYING)
if(SAL_Bgsnd_IsRunning())
break;
ASSERT_REBOOT( I < 20 );
kal_sleep_task( AUD_1TICK(2) );
}
}
}
void bgsndOffHandler(void)
{
if(BGSND_STATE_STOP != bgSnd.state) {
return;
}
uint32 I;
if(SAL_Bgsnd_IsRunning())
SAL_Bgsnd_SetFinal();
for ( I = 0; ; I++ ) {
if ( SAL_Bgsnd_IsIdle()) /* DSP returns to idle state */
break;
ASSERT_REBOOT( I < 20 );
kal_sleep_task( AUD_1TICK(2) );
}
AM_SND_PlaybackOff( true );
}
void bgsndTimerCallback(void)
{
L1Audio_SetEvent(bgSnd.aud_id, NULL);
}
/**
Run on AUDIO task
*/
void bgsndEventHandler(void)
{
MD_TRC_L1SND_ENTER_EVENT_HANDLER(bgSnd.state);
switch (bgSnd.state)
{
case BGSND_STATE_STOP:
{
// int32 I = 0;
// Flush and Disable DSP.
//while( I++ >= 0 ){
while(bgSnd.endCount++ >=0){
int32 count = bgsndGetDataCount();
// if( I >=40 ){
if(bgSnd.endCount >=20) {
MD_TRC_L1SND_STOP_FLUSH_LEAVE(count);
break;
}
if( count > BGSND_BUF_PTR_DIFF ){
MD_TRC_L1SND_STOP_FLUSH_COUNT(count);
// kal_sleep_task( AUD_1TICK(1) );
kal_set_timer(bgSnd.timer, (kal_timer_func_ptr)(bgsndTimerCallback), NULL, AUD_1TICK(2), AUD_1TICK(0));
return;
}
}
//if ( *DSP_SOUND_EFFECT_CTRL == DP_BGSND_STATE_PLAYING ) {
// *DSP_SOUND_EFFECT_CTRL = DP_BGSND_STATE_STOP; /* give ABORT command to the DSP */
//}
kal_cancel_timer(bgSnd.timer);
bgsndOffHandler();
if(NULL != bgSnd.bgSnd_offHandler){
bgSnd.bgSnd_offHandler();
}
}
break;
default:
break;
}
}
/*===========================================================================*/
/**
@srcBuf:
@bufLen: unit is byte
*/
void BGSND_WriteData(kal_uint8 *srcBuf, kal_int32 bufLen)
{
int32 freeLen;
int32 srcBufLen = bufLen >> 1; // unit i s word
int32 currentRead = bgSnd.bufRead;
if(currentRead > bgSnd.bufWrite || currentRead < BGSND_BUF_PTR_DIFF) { // one segment
if(currentRead > bgSnd.bufWrite){
freeLen=currentRead - bgSnd.bufWrite-BGSND_BUF_PTR_DIFF;
}else {
freeLen=bgSnd.bufSize - bgSnd.bufWrite-BGSND_BUF_PTR_DIFF;
}
MD_TRC_L1SND_WRITE_DATA(1, srcBufLen, freeLen, bgSnd.bufRead, bgSnd.bufWrite+srcBufLen); /* using write information which is after memory copy*/
ASSERT(srcBufLen <= freeLen); // unit is 2 byte
memcpy(bgSnd.pBuf+bgSnd.bufWrite, srcBuf, srcBufLen*sizeof(uint16));
bgSnd.bufWrite += srcBufLen;
//kal_prompt_trace(MOD_L1SP, "[pDebug]BGSND_WriteData1, bgSnd.bufRead=%d, bgSnd.bufWrite=%d", bgSnd.bufRead, bgSnd.bufWrite);
} else { // two segment
int32 segment;
kal_uint8 *p2SrcBuf;
freeLen= currentRead + bgSnd.bufSize - bgSnd.bufWrite-BGSND_BUF_PTR_DIFF;
MD_TRC_L1SND_WRITE_DATA(2, srcBufLen, freeLen, 0, 0);
ASSERT(srcBufLen <= freeLen);
p2SrcBuf = srcBuf;
segment = bgSnd.bufSize - bgSnd.bufWrite; // bug
if(segment > srcBufLen){
segment = srcBufLen;
}
if(segment>0) { //first segment
// kal_prompt_trace(MOD_L1SP, "xbgs temp3: bgSnd.pBuf+bgSnd.bufWrite=%x, p2SrcBuf=%x, segment*sizeof(kal_uint16)=%x",
// bgSnd.pBuf+bgSnd.bufWrite, p2SrcBuf, segment*sizeof(kal_uint16));
memcpy(bgSnd.pBuf+bgSnd.bufWrite, p2SrcBuf, segment*sizeof(kal_uint16));
//update pointer
p2SrcBuf = srcBuf + segment*sizeof(kal_uint16);
bgSnd.bufWrite += segment;
if(bgSnd.bufWrite>=bgSnd.bufSize){
bgSnd.bufWrite = 0;
}
// kal_prompt_trace(MOD_L1SP, "[pDebug]BGSND_WriteData2-1, bgSnd.bufRead=%d, bgSnd.bufWrite=%d", bgSnd.bufRead, bgSnd.bufWrite);
MD_TRC_L1SND_WRITE_DATA(3, 0, 0, bgSnd.bufRead, bgSnd.bufWrite);
segment = srcBufLen - segment;
}
if(segment>0) { //second segement
// kal_prompt_trace(MOD_L1SP, "xbgs temp5: bgSnd.pBuf=%x, p2SrcBuf=%x, segment*sizeof(kal_uint16=%x)",
// bgSnd.pBuf, p2SrcBuf, segment*sizeof(kal_uint16));
memcpy(bgSnd.pBuf, p2SrcBuf, segment*sizeof(kal_uint16));
bgSnd.bufWrite = segment;
// kal_prompt_trace(MOD_L1SP, "[pDebug]BGSND_WriteData2-2, bgSnd.bufRead=%d, bgSnd.bufWrite=%d", bgSnd.bufRead, bgSnd.bufWrite);
MD_TRC_L1SND_WRITE_DATA(4, 0, 0, bgSnd.bufRead, bgSnd.bufWrite);
}
}
/*
freeLen=bgSnd.bufRead - bgSnd.bufWrite-1;
if(freeLen<0){ // two segment
int32 segment;
kal_uint8 *p2SrcBuf;
freeLen += bgSnd.bufSize;
p2SrcBuf = srcBuf;
segment = bgSnd.bufSize - bgSnd.bufWrite;
memcpy(bgSnd.pBuf+bgSnd.bufWrite, p2SrcBuf, segment*sizeof(kal_uint16));
//update pointer
p2SrcBuf = srcBuf + (segment<<1);
bgSnd.bufWrite = 0;
segment = srcBufLen - segment;
memcpy(bgSnd.pBuf+bgSnd.bufWrite, p2SrcBuf, segment*sizeof(kal_uint16));
bgSnd.bufWrite = segment;
} else { // one segment
ASSERT(bufLen <= freeLen);
memcpy(bgSnd.pBuf+bgSnd.bufWrite, srcBuf, bufLen);
// for debug
kal_prompt_trace(MOD_L1SP, "bgs temp: bgSnd.pBuf=%x, bgSnd.bufWrite=%x, bgSnd.pBuf+bgSnd.bufWrite = %x",
bgSnd.pBuf, bgSnd.bufWrite, bgSnd.pBuf+bgSnd.bufWrite);
bgSnd.bufWrite += (bufLen>>1);
// for debg
kal_prompt_trace(MOD_L1SP, "bgs temp2: new bgSnd.bufWrite = %x", bgSnd.bufWrite);
}
*/
}
/**
@return: size is 16-bit (2byte)
*/
int32 BGSND_GetFreeSpace(void)
{
int32 count;
count = bgSnd.bufSize + bgSnd.bufRead - bgSnd.bufWrite-BGSND_BUF_PTR_DIFF; // (int32)ihdl->mh.rbInfo.read - (int32)ihdl->mh.rbInfo.write - 1;
if( count > bgSnd.bufSize )
count = count - bgSnd.bufSize;
return count;
}
/**
The function sets the playback mode.
@bULSPHFlag: Mixer switch for uplink speech, 1 for SPH+background Sound, 0 for background sound only
@ULSNDGain: Sound effect gain for uplink mixer
*/
void BGSND_ConfigULMixer(kal_bool bULSPHFlag, kal_int8 ULSNDGain )
{
#if defined(__ENABLE_SPEECH_DVT__)
ULSNDGain = 7;
#endif // defined(__ENABLE_SPEECH_DVT__)
MD_TRC_L1SND_CONFIG_ULMIXER(bULSPHFlag, ULSNDGain);
ASSERT(ULSNDGain>=0 && ULSNDGain<=7);
if( ULSNDGain == 0 )
bgSnd.ULGain = 0;
else {
bgSnd.ULGain = (kal_int16)(32767 >> (7 - ULSNDGain));
}
bgSnd.fULSPH = bULSPHFlag;
}
/**
The function sets the playback mode.
@bDLSPHFlag: Mixer switch for downlink speech, 1 for SPH+background Sound, 0 for background sound only
@DLSNDGain: Sound effect gain for downlink mixer
*/
void BGSND_ConfigDLMixer(kal_bool bDLSPHFlag, kal_int8 DLSNDGain )
{
#if defined(__ENABLE_SPEECH_DVT__)
DLSNDGain = 7;
#endif // defined(__ENABLE_SPEECH_DVT__)
MD_TRC_L1SND_CONFIG_DLMIXER(bDLSPHFlag, DLSNDGain);
ASSERT(DLSNDGain>=0 && DLSNDGain<=7);
if( DLSNDGain == 0)
bgSnd.DLGain = 0;
else {
bgSnd.DLGain = (kal_int16)(32767 >> (7 - DLSNDGain));
}
bgSnd.fDLSPH = bDLSPHFlag;
}
/**
The function starts the background sound playback of the media handle.
@bgSnd_hdlr: handler
@ULGainLevel: uplink gain level, from 0~7
@DLGainLevel: downlink gain level, from 0~7
*/
void BGSND_Start(void (*bgSnd_hisrHandler)(void), void (*bgSnd_offHandler)(void),
kal_uint8 ULGainLevel , kal_uint8 DLGainLevel)
{
MD_TRC_L1SND_ENTER_BGSND_START();
// clean up
bgSnd.dspLastSample = 0;
bgSnd.endCount = 0;
// buffer reset
memset(bgSndBuf, 0, sizeof(kal_uint16)*BGSND_BUF_SIZE);
bgSnd.pBuf = bgSndBuf;
bgSnd.bufSize = BGSND_BUF_SIZE;
bgSnd.bufRead = 0;
bgSnd.bufWrite = BGSND_BUF_PTR_DIFF;
// clear hisr flag
bgSnd.isDlHisrCome = false;
bgSnd.isUlHisrCome = false;
// lock DSP for sherif writing.
L1Audio_SetFlag( bgSnd.aud_id ); // REIMIND: Before Locking SleepMode, to access DSP sherrif tasks much time. So access DSP must be after SetFlag1
// L1Audio_SetEventHandler(bgSnd.aud_id, BGSND_eventHandler );
bgSnd.bgSnd_hisrHandler = bgSnd_hisrHandler;
#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
L1Audio_HookHisrHandler(D2C_SOUND_EFFECT_INT_ID_DL, bgsndDlHisr, 0);
L1Audio_HookHisrHandler(D2C_SOUND_EFFECT_INT_ID_UL, bgsndUlHisr, 0);
#else
L1Audio_HookHisrHandler(D2C_SOUND_EFFECT_INT_ID_DL, bgsndHisr, 0);
#endif
bgSnd.bgSnd_offHandler = bgSnd_offHandler;
// gain setting and update
if(AM_IsSpeechOn()){
BGSND_ConfigULMixer(KAL_TRUE, ULGainLevel);
BGSND_ConfigDLMixer(KAL_TRUE, DLGainLevel);
} else {
BGSND_ConfigULMixer(KAL_FALSE, ULGainLevel);
BGSND_ConfigDLMixer(KAL_FALSE, DLGainLevel);
}
bgsndUpdateMixer();
// Before dynamic download, all application should be off.
// But background sound do not need to dynamic download, so the following is unnecessary.
// KT_StopAndWait();
// turn on.
bgsndOnHandler();
// L1SP_Register_BgsService(bgsndOnHandler, bgsndOffHandler);
bgSnd.state = BGSND_STATE_RUN;
}
/*
* Description
* ---------
* The function stops the background sound playback of the media handle.
*
* Syntax
* ---------
* void BGSND_Stop();
*
* where
* hdl The media handle
*
* Return Value
* ---------
* None
*/
void BGSND_Stop(void)
{
MD_TRC_L1SND_ENTER_BGSND_STOP();
/*
if ( !L1Audio_CheckFlag( bgSnd.aud_id ) )
return;
*/
// unregister service
// L1SP_UnRegister_BgsService();
bgSnd.state = BGSND_STATE_STOP;
// set event to trigger close process
L1Audio_SetEvent(bgSnd.aud_id, NULL);
}
void BGSND_Close(void)
{
L1Audio_ClearFlag( bgSnd.aud_id );
#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
L1Audio_UnhookHisrHandler(D2C_SOUND_EFFECT_INT_ID_DL);
L1Audio_UnhookHisrHandler(D2C_SOUND_EFFECT_INT_ID_UL);
#else
L1Audio_UnhookHisrHandler(D2C_SOUND_EFFECT_INT_ID_DL);
#endif
// reset the pointer
bgSnd.pBuf = NULL;
bgSnd.bufSize = 0;
bgSnd.bgSnd_hisrHandler = NULL;
bgSnd.state = BGSND_STATE_IDLE;
}
/*
* Description
* ---------
* The function sets the output device.
*
* Syntax
* ---------
* void BGSND_SetOutputDevice( kal_uint8 device );
*
* where
* device The output device (L1SP_SPEAKER1, L1SP_SPEAKER2, L1SP_LOUD_SPEAKER)
*
* Return Value
* ---------
* None
void BGSND_SetOutputDevice( kal_uint8 device )
{
//if( !AM_IsSpeechOn() )
#ifdef ANALOG_AFE_PATH_EXIST
AFE_SetOutputDevice( L1SP_SND_EFFECT, device );
#endif
}
*/
void BGSND_INIT()
{
memset(&bgSnd, 0, sizeof(BGSND_T));
// get audio ID
bgSnd.aud_id = L1Audio_GetAudioID();
L1Audio_SetEventHandler( bgSnd.aud_id, (L1Audio_EventHandler)bgsndEventHandler );
bgSnd.timer = kal_create_timer("bgSnd");
}