blob: 85ac76efeeddc89697952ccbd38ce25c9c2b744f [file] [log] [blame]
yu.dongc33b3072024-08-21 23:14:49 -07001/*****************************************************************************
2* Copyright Statement:
3* --------------------
4* This software is protected by Copyright and the information contained
5* herein is confidential. The software may not be copied and the information
6* contained herein may not be used or disclosed except with the written
7* permission of MediaTek Inc. (C) 2005
8*
9* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
10* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
11* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
12* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
13* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
14* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
15* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
16* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
17* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
18* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
19* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
20* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
21*
22* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
23* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
24* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
25* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
26* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
27*
28* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
29* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
30* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
31* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
32* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
33*
34*****************************************************************************/
35
36/*****************************************************************************
37 *
38 * Filename:
39 * ---------
40 * snd_effect.c
41 *
42 * Project:
43 * --------
44 * Maui_sw
45 *
46 * Description:
47 * ------------
48 * Streaming Background Sound Playback.
49 * Play 8kHz mono linear PCM in TCH or idle mode.
50 *
51 * Author:
52 * -------
53 * -------
54 *============================================================================
55 * HISTORY
56 * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
57 *------------------------------------------------------------------------------
58 * removed!
59 * removed!
60 * removed!
61 *
62 * removed!
63 * removed!
64 * removed!
65 *
66 * removed!
67 * removed!
68 *
69 * removed!
70 * removed!
71 * removed!
72 * removed!
73 *
74 * removed!
75 * removed!
76 * removed!
77 *
78 * removed!
79 * removed!
80 * removed!
81 *
82 * removed!
83 * removed!
84 * removed!
85 *
86 * removed!
87 * removed!
88 * removed!
89 * removed!
90 * removed!
91 * removed!
92 * removed!
93 * removed!
94 * removed!
95 * removed!
96 * removed!
97 *
98 * removed!
99 * removed!
100 *
101 * removed!
102 * removed!
103 * removed!
104 *
105 * removed!
106 * removed!
107 * removed!
108 *
109 * removed!
110 * removed!
111 * removed!
112 *
113 * removed!
114 * removed!
115 * removed!
116 * removed!
117 * removed!
118 * removed!
119 *
120 * removed!
121 * removed!
122 * removed!
123 * removed!
124 * removed!
125 * removed!
126 * removed!
127 *
128 * removed!
129 * removed!
130 * removed!
131 *
132 * removed!
133 * removed!
134 * removed!
135 * removed!
136 * removed!
137 * removed!
138 * removed!
139 * removed!
140 * removed!
141 * removed!
142 * removed!
143 * removed!
144 * removed!
145 * removed!
146 * removed!
147 * removed!
148 * removed!
149 * removed!
150 * removed!
151 * removed!
152 * removed!
153 * removed!
154 * removed!
155 * removed!
156 * removed!
157 * removed!
158 * removed!
159 * removed!
160 * removed!
161 * removed!
162 * removed!
163 * removed!
164 * removed!
165 * removed!
166 * removed!
167 * removed!
168 * removed!
169 * removed!
170 * removed!
171 *
172 *
173 *------------------------------------------------------------------------------
174 * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
175 *============================================================================
176 ****************************************************************************/
177
178#include "kal_public_api.h"
179#include "kal_general_types.h"
180#include "sync_data.h"
181
182#include "kal_trace.h"
183#include "l1sp_trc.h"
184
185
186#include "am.h"
187//#include "speech_def.h"
188#include "afe_def.h" // for output device setting
189#include "sp_drv.h"
190
191#include "sal_exp.h"
192
193#define DSP_BGS_UP_DOWN_INT_SEPERATE
194
195/************************** Constants ***************************************/
196// #define DP_BUFFER_DEFAULT_LEN 4096 /* The frame size of DSP. */
197#define DSP_BUFFER_LEN_NB 160 //unit is sample (16bit)
198#define DSP_BUFFER_LEN_WB 320 //unit is sample (16bit)
199#define DSP_BUFFER_LEN_MAX 320 //unit is sample (16bit)
200
201/* DSP Sound Effect State */
202#define DP_BGSND_STATE_IDLE 0 /* MCU: 0 -> 1 */
203#define DP_BGSND_STATE_READY 1 /* DSP: 1 -> 2 */
204#define DP_BGSND_STATE_PLAYING 2 /* MCU: 2 -> 3 */
205#define DP_BGSND_STATE_STOP 3 /* DSP: 3 -> 0 */
206
207//#define SND_CHECK_DATA
208
209#define SND_GAIN_CONFIG 1 /* 0: right shamt, 1: multiplier */
210
211#define BGSND_BUF_SIZE 2560 // using in 16 bit
212#define BGSND_BUF_PTR_DIFF 2
213
214typedef enum {
215 BGSND_STATE_IDLE = 0,
216 BGSND_STATE_RUN,
217 BGSND_STATE_STOP,
218 BGSND_STATE_CLOSE,
219}BGSND_STATE_TYPE;
220
221/*********** Structure *******************************************************/
222
223typedef struct{
224
225 BGSND_STATE_TYPE state;
226
227 kal_bool fULSPH;
228 kal_bool fDLSPH;
229
230 kal_bool isDlHisrCome;
231 kal_bool isUlHisrCome;
232
233 void (*bgSnd_hisrHandler)(void);
234 void (*bgSnd_offHandler)(void);
235
236 kal_uint16 aud_id;
237 kal_timerid timer;
238 kal_uint16 endCount;
239
240 kal_uint16 ULGain;
241 kal_uint16 DLGain;
242 kal_uint16 dspLastSample;
243
244 kal_uint16 *pBuf;
245
246
247 kal_int32 bufSize; // unit is 16 bit (sample)
248 kal_int32 bufWrite; // unit is 16 bit
249 kal_int32 bufRead; // unit is 16 bit
250}BGSND_T;
251
252/*********** variable ********************************************************/
253
254static BGSND_T bgSnd;
255
256static kal_uint16 bgSndBuf[BGSND_BUF_SIZE];
257
258/*********** internal fucntion **********************************************/
259
260static void bgsndUpdateMixer()
261{
262 if ( AM_IsSpeechOn() ) {
263 SAL_Bgsnd_Config(bgSnd.ULGain, bgSnd.DLGain, bgSnd.fULSPH, bgSnd.fDLSPH);
264 } else {
265 SAL_Bgsnd_Config(bgSnd.ULGain, bgSnd.DLGain, 0, 0);
266 }
267
268}
269
270/**
271 @return: size is 16-bit, available PCM size
272*/
273static int32 bgsndGetDataCount(void)
274{
275 int32 count;
276 // int32 count = (int32)ihdl->mh.rbInfo.write - (int32)ihdl->mh.rbInfo.read;
277 if(bgSnd.bufWrite<bgSnd.bufRead){
278 count = (bgSnd.bufSize - BGSND_BUF_PTR_DIFF)+bgSnd.bufWrite - bgSnd.bufRead;
279 } else {
280 count = bgSnd.bufWrite - bgSnd.bufRead;
281 }
282
283 if( count > BGSND_BUF_PTR_DIFF) {
284 count -= BGSND_BUF_PTR_DIFF;
285 } else {
286 count = 0;
287 }
288
289 if(count&1){
290 count = count -1;
291 }
292 return count;
293 /*
294 int32 count = bgSnd.bufWrite - bgSnd.bufRead;
295 if( count < 0 )
296 count += (bgSnd.bufSize - BGSND_BUF_PTR_DIFF );
297 else if( count > 2)
298 count -= BGSND_BUF_PTR_DIFF;
299 else
300 count = 0;
301 return count;
302 */
303}
304/*
305static kal_int16 tone1k_16kSR[320] = {
3060x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3070x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3080x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3090x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3100x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3110x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3120x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3130x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3140x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3150x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3160x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3170x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3180x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3190x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3200x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3210x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3220x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3230x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3240x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3250x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3260x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3270x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3280x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3290x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3300x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3310x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3320x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3330x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3340x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3350x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3360x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3370x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3380x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3390x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3400x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3410x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3420x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3430x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05,
3440x0000, 0x30FC, 0x5A82, 0x7641, 0x7FFF, 0x7641, 0x5A82, 0x30FB,
3450x0001, 0xCF05, 0xA57E, 0x89C0, 0x8001, 0x89BF, 0xA57E, 0xCF05
346};
347
348*/
349static void bgsnd_WriteToDSP(void)
350{
351 uint16 dsp_buf_len, dsp_buf_len_Ul;
352 uint16 *dataPtr;
353 volatile uint16 *toPtr;
354 volatile uint16 *toPtr_Ul;
355 int32 count, segment, i;
356 bool isWb, isWb_Ul;
357
358/*
359 ¡VSph_Band_Flag
360 ¡EBit 0: Sch band (0/1 : Nb/Wb)
361 ¡EBit 1: Cod band (0/1 : Nb/Wb)
362 ¡EBit 2: VBI band (0/1 : Nb/Wb)
363 ¡EBit 3: BT band (0/1 : Nb/Wb)
364 MT6280 0x2FBF
365 MT6589 0x32F1
366 dm5
367*/
368
369 // get current buffer data length in two sample alight. (16k sampling rate)
370 count = bgsndGetDataCount();
371
372 //set up the DSP address and pointers
373 dsp_buf_len = SAL_Bgsnd_GetDataLen_DL();
374#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
375 dsp_buf_len_Ul = SAL_Bgsnd_GetDataLen_UL();
376#else
377 dsp_buf_len_Ul = dsp_buf_len;
378#endif
379
380 if(dsp_buf_len == DSP_BUFFER_LEN_WB)
381 isWb = true;
382 else if(dsp_buf_len == DSP_BUFFER_LEN_NB){
383 isWb = false;
384// count >>= 1;
385 }
386 else {
387 ASSERT_REBOOT(0);
388 isWb = false;
389 }
390
391 if(dsp_buf_len_Ul == DSP_BUFFER_LEN_WB)
392 isWb_Ul= true;
393 else if(dsp_buf_len_Ul == DSP_BUFFER_LEN_NB){
394 isWb_Ul= false;
395 }
396 else {
397 ASSERT_REBOOT(0);
398 isWb_Ul = false;
399 }
400
401 toPtr = SAL_Bgsnd_GetBuf_DL();
402#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
403 toPtr_Ul = SAL_Bgsnd_GetBuf_UL();
404#else
405 toPtr_Ul = toPtr;
406#endif
407
408 MD_TRC_L1SND_DSP_BUFFER_INFO(count, toPtr, dsp_buf_len);
409#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
410 MD_TRC_L1SND_DSP_BUFFER_INFO(-1, toPtr_Ul, dsp_buf_len_Ul);
411#else
412 MD_TRC_L1SND_DSP_BUFFER_INFO(count, toPtr_Ul, dsp_buf_len_Ul);
413#endif
414
415
416 if (count > DSP_BUFFER_LEN_MAX)
417 count = DSP_BUFFER_LEN_MAX;
418
419 if(count > 0) {
420
421 /* First Segemnt */
422 if(bgSnd.bufWrite < bgSnd.bufRead) {
423 segment = (bgSnd.bufSize - bgSnd.bufRead);
424 } else {
425 segment = (bgSnd.bufWrite - bgSnd.bufRead);
426 }
427
428 if(segment&1){ // keep two sample alight
429 segment =segment - 1;
430 }
431
432 /*
433 if(isNb){ // 8k
434 if (segment > (count<<1))
435 segment = (count<<1);
436
437 }else { // 16 k
438 if (segment > count)
439 segment = count;
440 }
441 */
442 if (segment > count)
443 segment = count;
444
445 if (segment > 0) {
446
447 // kal_dev_trace(TRACE_STATE, L1SND_FILLBUFFER, segment);
448 dataPtr = &(bgSnd.pBuf[bgSnd.bufRead]);
449
450 for (i=segment; i>0; (i-=2)) {
451 // first sample
452 *toPtr++ = *dataPtr;
453 *toPtr_Ul++ = *dataPtr++;
454
455 // second sample
456 if(isWb) {
457 *toPtr++ = *dataPtr;
458 }
459 if(isWb_Ul) {
460 *toPtr_Ul++ = *dataPtr;
461 }
462 dataPtr++;
463 }
464 Data_Sync_Barrier();
465
466 bgSnd.dspLastSample = *(toPtr-1);
467
468 bgSnd.bufRead += segment;
469 if (bgSnd.bufRead >= bgSnd.bufSize)
470 bgSnd.bufRead = (bgSnd.bufRead-bgSnd.bufSize);
471
472 MD_TRC_L1SND_FILLBUFFER(1, segment, bgSnd.bufRead, bgSnd.bufWrite);
473 }
474
475 /* Second Segment */
476 /*
477 if(isNb){ // 8k
478 segment = (count<<1) - segment;
479 } else {
480 segment = count - segment;
481 }
482 */
483 segment = count - segment;
484
485 if (segment > 0) {
486 // kal_dev_trace(TRACE_STATE, L1SND_FILLBUFFER, segment);
487 // dataPtr = bgSnd.pBuf;
488 dataPtr = &(bgSnd.pBuf[bgSnd.bufRead]);
489 for (i=segment; i>0; (i-=2)) {
490 // first sample
491 *toPtr++ = *dataPtr;
492 *toPtr_Ul++ = *dataPtr++;
493
494 // second sample
495 if(isWb) {
496 *toPtr++ = *dataPtr;
497 }
498 if(isWb_Ul) {
499 *toPtr_Ul++ = *dataPtr;
500 }
501 dataPtr++;
502 }
503 Data_Sync_Barrier();
504
505 bgSnd.dspLastSample = *(toPtr-1);
506 bgSnd.bufRead += segment;
507 if (bgSnd.bufRead >= bgSnd.bufSize)
508 bgSnd.bufRead = (bgSnd.bufRead-bgSnd.bufSize);
509
510 MD_TRC_L1SND_FILLBUFFER(2, segment, bgSnd.bufRead, bgSnd.bufWrite);
511 }
512
513 }
514
515
516 /* Put silence (last sample) if MCU buffer is empty */
517 if (count < DSP_BUFFER_LEN_MAX) {
518
519 kal_uint16 last_sample;
520
521 last_sample = bgSnd.dspLastSample;
522 // segment = dsp_buf_len - count;
523 segment = DSP_BUFFER_LEN_MAX - count;
524 MD_TRC_L1SND_PUT_SILENCE(segment, last_sample);
525
526 /*
527 for (i=segment; i>0; i--) {
528 *toPtr++ = last_sample;
529 }
530 */
531 for (i=segment; i>0; (i-=2)) {
532 // first sample
533 *toPtr++ = last_sample;
534 *toPtr_Ul++ = last_sample;
535
536 // second sample
537 if(isWb) {
538 *toPtr++ = last_sample;
539 }
540 if(isWb_Ul) {
541 *toPtr_Ul++ = last_sample;
542 }
543
544 }
545 Data_Sync_Barrier();
546 }
547}
548
549
550void bgsndHisr( void *pram )
551{
552
553 // gain and setting update
554 bgsndUpdateMixer();
555
556 // handle extra notify and closing state
557 if ((BGSND_STATE_RUN != bgSnd.state) && (BGSND_STATE_STOP !=bgSnd.state))
558 return;
559 // if ( ihdl->end_status != MEDIA_NONE )
560 // return;
561
562 if(!SAL_Bgsnd_IsRunning())
563 return;
564
565 bgsnd_WriteToDSP();
566
567 if( bgSnd.bgSnd_hisrHandler != NULL) {
568 bgSnd.bgSnd_hisrHandler();
569 }
570}
571
572#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
573void bgsndDlHisr( void * param)
574{
575 if(true == bgSnd.isDlHisrCome) {
576 MD_TRC_L1SND_REENTER_HISR(bgSnd.isDlHisrCome, bgSnd.isUlHisrCome);
577 } else {
578 bgSnd.isDlHisrCome = true;
579
580 if(bgSnd.isUlHisrCome == bgSnd.isDlHisrCome) {
581 bgsndHisr(param);
582 bgSnd.isUlHisrCome = false;
583 bgSnd.isDlHisrCome = false;
584 }
585 }
586}
587
588void bgsndUlHisr( void * param)
589{
590 if(true == bgSnd.isUlHisrCome) {
591 MD_TRC_L1SND_REENTER_HISR(bgSnd.isDlHisrCome, bgSnd.isUlHisrCome);
592 } else {
593 bgSnd.isUlHisrCome = true;
594
595 if(bgSnd.isUlHisrCome == bgSnd.isDlHisrCome) {
596 bgsndHisr(param);
597 bgSnd.isUlHisrCome = false;
598 bgSnd.isDlHisrCome = false;
599 }
600 }
601
602}
603
604#endif // DSP_BGS_UP_DOWN_INT_SEPERATE
605
606void bgsndOnHandler(void)
607{
608
609 AM_SND_PlaybackOn();
610 SAL_Bgsnd_SetInit();
611 //*DSP_SOUND_EFFECT_CTRL = DP_BGSND_STATE_READY;
612 {
613 uint32 I;
614 for( I = 0; ; I++ ) {
615 //if( *DSP_SOUND_EFFECT_CTRL == DP_BGSND_STATE_PLAYING)
616 if(SAL_Bgsnd_IsRunning())
617 break;
618 ASSERT_REBOOT( I < 20 );
619 kal_sleep_task( AUD_1TICK(2) );
620 }
621 }
622}
623
624void bgsndOffHandler(void)
625{
626
627 if(BGSND_STATE_STOP != bgSnd.state) {
628 return;
629 }
630
631 uint32 I;
632 if(SAL_Bgsnd_IsRunning())
633 SAL_Bgsnd_SetFinal();
634 for ( I = 0; ; I++ ) {
635 if ( SAL_Bgsnd_IsIdle()) /* DSP returns to idle state */
636 break;
637 ASSERT_REBOOT( I < 20 );
638 kal_sleep_task( AUD_1TICK(2) );
639 }
640
641
642 AM_SND_PlaybackOff( true );
643}
644
645void bgsndTimerCallback(void)
646{
647 L1Audio_SetEvent(bgSnd.aud_id, NULL);
648}
649
650/**
651 Run on AUDIO task
652*/
653void bgsndEventHandler(void)
654{
655 MD_TRC_L1SND_ENTER_EVENT_HANDLER(bgSnd.state);
656
657 switch (bgSnd.state)
658 {
659 case BGSND_STATE_STOP:
660 {
661 // int32 I = 0;
662 // Flush and Disable DSP.
663 //while( I++ >= 0 ){
664 while(bgSnd.endCount++ >=0){
665 int32 count = bgsndGetDataCount();
666
667 // if( I >=40 ){
668 if(bgSnd.endCount >=20) {
669 MD_TRC_L1SND_STOP_FLUSH_LEAVE(count);
670 break;
671 }
672
673 if( count > BGSND_BUF_PTR_DIFF ){
674 MD_TRC_L1SND_STOP_FLUSH_COUNT(count);
675 // kal_sleep_task( AUD_1TICK(1) );
676 kal_set_timer(bgSnd.timer, (kal_timer_func_ptr)(bgsndTimerCallback), NULL, AUD_1TICK(2), AUD_1TICK(0));
677 return;
678 }
679
680 }
681 //if ( *DSP_SOUND_EFFECT_CTRL == DP_BGSND_STATE_PLAYING ) {
682 // *DSP_SOUND_EFFECT_CTRL = DP_BGSND_STATE_STOP; /* give ABORT command to the DSP */
683 //}
684 kal_cancel_timer(bgSnd.timer);
685 bgsndOffHandler();
686
687 if(NULL != bgSnd.bgSnd_offHandler){
688 bgSnd.bgSnd_offHandler();
689 }
690 }
691 break;
692 default:
693 break;
694 }
695
696
697}
698/*===========================================================================*/
699
700
701/**
702 @srcBuf:
703 @bufLen: unit is byte
704*/
705void BGSND_WriteData(kal_uint8 *srcBuf, kal_int32 bufLen)
706{
707 int32 freeLen;
708 int32 srcBufLen = bufLen >> 1; // unit i s word
709 int32 currentRead = bgSnd.bufRead;
710
711 if(currentRead > bgSnd.bufWrite || currentRead < BGSND_BUF_PTR_DIFF) { // one segment
712 if(currentRead > bgSnd.bufWrite){
713 freeLen=currentRead - bgSnd.bufWrite-BGSND_BUF_PTR_DIFF;
714 }else {
715 freeLen=bgSnd.bufSize - bgSnd.bufWrite-BGSND_BUF_PTR_DIFF;
716 }
717
718 MD_TRC_L1SND_WRITE_DATA(1, srcBufLen, freeLen, bgSnd.bufRead, bgSnd.bufWrite+srcBufLen); /* using write information which is after memory copy*/
719
720 ASSERT(srcBufLen <= freeLen); // unit is 2 byte
721 memcpy(bgSnd.pBuf+bgSnd.bufWrite, srcBuf, srcBufLen*sizeof(uint16));
722
723 bgSnd.bufWrite += srcBufLen;
724
725 //kal_prompt_trace(MOD_L1SP, "[pDebug]BGSND_WriteData1, bgSnd.bufRead=%d, bgSnd.bufWrite=%d", bgSnd.bufRead, bgSnd.bufWrite);
726
727
728 } else { // two segment
729
730 int32 segment;
731 kal_uint8 *p2SrcBuf;
732
733 freeLen= currentRead + bgSnd.bufSize - bgSnd.bufWrite-BGSND_BUF_PTR_DIFF;
734
735 MD_TRC_L1SND_WRITE_DATA(2, srcBufLen, freeLen, 0, 0);
736 ASSERT(srcBufLen <= freeLen);
737
738 p2SrcBuf = srcBuf;
739 segment = bgSnd.bufSize - bgSnd.bufWrite; // bug
740 if(segment > srcBufLen){
741 segment = srcBufLen;
742 }
743
744 if(segment>0) { //first segment
745
746 // kal_prompt_trace(MOD_L1SP, "xbgs temp3: bgSnd.pBuf+bgSnd.bufWrite=%x, p2SrcBuf=%x, segment*sizeof(kal_uint16)=%x",
747 // bgSnd.pBuf+bgSnd.bufWrite, p2SrcBuf, segment*sizeof(kal_uint16));
748
749 memcpy(bgSnd.pBuf+bgSnd.bufWrite, p2SrcBuf, segment*sizeof(kal_uint16));
750
751 //update pointer
752 p2SrcBuf = srcBuf + segment*sizeof(kal_uint16);
753 bgSnd.bufWrite += segment;
754 if(bgSnd.bufWrite>=bgSnd.bufSize){
755 bgSnd.bufWrite = 0;
756 }
757
758 // kal_prompt_trace(MOD_L1SP, "[pDebug]BGSND_WriteData2-1, bgSnd.bufRead=%d, bgSnd.bufWrite=%d", bgSnd.bufRead, bgSnd.bufWrite);
759 MD_TRC_L1SND_WRITE_DATA(3, 0, 0, bgSnd.bufRead, bgSnd.bufWrite);
760
761 segment = srcBufLen - segment;
762 }
763
764 if(segment>0) { //second segement
765 // kal_prompt_trace(MOD_L1SP, "xbgs temp5: bgSnd.pBuf=%x, p2SrcBuf=%x, segment*sizeof(kal_uint16=%x)",
766 // bgSnd.pBuf, p2SrcBuf, segment*sizeof(kal_uint16));
767
768 memcpy(bgSnd.pBuf, p2SrcBuf, segment*sizeof(kal_uint16));
769 bgSnd.bufWrite = segment;
770
771 // kal_prompt_trace(MOD_L1SP, "[pDebug]BGSND_WriteData2-2, bgSnd.bufRead=%d, bgSnd.bufWrite=%d", bgSnd.bufRead, bgSnd.bufWrite);
772 MD_TRC_L1SND_WRITE_DATA(4, 0, 0, bgSnd.bufRead, bgSnd.bufWrite);
773
774 }
775 }
776
777 /*
778 freeLen=bgSnd.bufRead - bgSnd.bufWrite-1;
779 if(freeLen<0){ // two segment
780 int32 segment;
781 kal_uint8 *p2SrcBuf;
782
783 freeLen += bgSnd.bufSize;
784
785
786 p2SrcBuf = srcBuf;
787 segment = bgSnd.bufSize - bgSnd.bufWrite;
788 memcpy(bgSnd.pBuf+bgSnd.bufWrite, p2SrcBuf, segment*sizeof(kal_uint16));
789 //update pointer
790 p2SrcBuf = srcBuf + (segment<<1);
791 bgSnd.bufWrite = 0;
792
793
794 segment = srcBufLen - segment;
795 memcpy(bgSnd.pBuf+bgSnd.bufWrite, p2SrcBuf, segment*sizeof(kal_uint16));
796 bgSnd.bufWrite = segment;
797
798 } else { // one segment
799 ASSERT(bufLen <= freeLen);
800 memcpy(bgSnd.pBuf+bgSnd.bufWrite, srcBuf, bufLen);
801
802 // for debug
803 kal_prompt_trace(MOD_L1SP, "bgs temp: bgSnd.pBuf=%x, bgSnd.bufWrite=%x, bgSnd.pBuf+bgSnd.bufWrite = %x",
804 bgSnd.pBuf, bgSnd.bufWrite, bgSnd.pBuf+bgSnd.bufWrite);
805
806 bgSnd.bufWrite += (bufLen>>1);
807
808 // for debg
809 kal_prompt_trace(MOD_L1SP, "bgs temp2: new bgSnd.bufWrite = %x", bgSnd.bufWrite);
810
811 }
812 */
813
814}
815
816/**
817 @return: size is 16-bit (2byte)
818*/
819int32 BGSND_GetFreeSpace(void)
820{
821 int32 count;
822
823 count = bgSnd.bufSize + bgSnd.bufRead - bgSnd.bufWrite-BGSND_BUF_PTR_DIFF; // (int32)ihdl->mh.rbInfo.read - (int32)ihdl->mh.rbInfo.write - 1;
824 if( count > bgSnd.bufSize )
825 count = count - bgSnd.bufSize;
826 return count;
827}
828
829/**
830 The function sets the playback mode.
831
832 @bULSPHFlag: Mixer switch for uplink speech, 1 for SPH+background Sound, 0 for background sound only
833 @ULSNDGain: Sound effect gain for uplink mixer
834*/
835void BGSND_ConfigULMixer(kal_bool bULSPHFlag, kal_int8 ULSNDGain )
836{
837#if defined(__ENABLE_SPEECH_DVT__)
838 ULSNDGain = 7;
839#endif // defined(__ENABLE_SPEECH_DVT__)
840 MD_TRC_L1SND_CONFIG_ULMIXER(bULSPHFlag, ULSNDGain);
841
842 ASSERT(ULSNDGain>=0 && ULSNDGain<=7);
843 if( ULSNDGain == 0 )
844 bgSnd.ULGain = 0;
845 else {
846 bgSnd.ULGain = (kal_int16)(32767 >> (7 - ULSNDGain));
847 }
848 bgSnd.fULSPH = bULSPHFlag;
849}
850
851
852/**
853 The function sets the playback mode.
854
855 @bDLSPHFlag: Mixer switch for downlink speech, 1 for SPH+background Sound, 0 for background sound only
856 @DLSNDGain: Sound effect gain for downlink mixer
857*/
858void BGSND_ConfigDLMixer(kal_bool bDLSPHFlag, kal_int8 DLSNDGain )
859{
860#if defined(__ENABLE_SPEECH_DVT__)
861 DLSNDGain = 7;
862#endif // defined(__ENABLE_SPEECH_DVT__)
863 MD_TRC_L1SND_CONFIG_DLMIXER(bDLSPHFlag, DLSNDGain);
864
865 ASSERT(DLSNDGain>=0 && DLSNDGain<=7);
866 if( DLSNDGain == 0)
867 bgSnd.DLGain = 0;
868 else {
869 bgSnd.DLGain = (kal_int16)(32767 >> (7 - DLSNDGain));
870 }
871 bgSnd.fDLSPH = bDLSPHFlag;
872}
873
874/**
875
876 The function starts the background sound playback of the media handle.
877
878 @bgSnd_hdlr: handler
879 @ULGainLevel: uplink gain level, from 0~7
880 @DLGainLevel: downlink gain level, from 0~7
881
882*/
883void BGSND_Start(void (*bgSnd_hisrHandler)(void), void (*bgSnd_offHandler)(void),
884 kal_uint8 ULGainLevel , kal_uint8 DLGainLevel)
885{
886 MD_TRC_L1SND_ENTER_BGSND_START();
887
888 // clean up
889 bgSnd.dspLastSample = 0;
890 bgSnd.endCount = 0;
891
892 // buffer reset
893 memset(bgSndBuf, 0, sizeof(kal_uint16)*BGSND_BUF_SIZE);
894 bgSnd.pBuf = bgSndBuf;
895 bgSnd.bufSize = BGSND_BUF_SIZE;
896 bgSnd.bufRead = 0;
897 bgSnd.bufWrite = BGSND_BUF_PTR_DIFF;
898
899 // clear hisr flag
900 bgSnd.isDlHisrCome = false;
901 bgSnd.isUlHisrCome = false;
902
903 // lock DSP for sherif writing.
904 L1Audio_SetFlag( bgSnd.aud_id ); // REIMIND: Before Locking SleepMode, to access DSP sherrif tasks much time. So access DSP must be after SetFlag1
905
906 // L1Audio_SetEventHandler(bgSnd.aud_id, BGSND_eventHandler );
907 bgSnd.bgSnd_hisrHandler = bgSnd_hisrHandler;
908#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
909 L1Audio_HookHisrHandler(D2C_SOUND_EFFECT_INT_ID_DL, bgsndDlHisr, 0);
910 L1Audio_HookHisrHandler(D2C_SOUND_EFFECT_INT_ID_UL, bgsndUlHisr, 0);
911#else
912 L1Audio_HookHisrHandler(D2C_SOUND_EFFECT_INT_ID_DL, bgsndHisr, 0);
913#endif
914
915 bgSnd.bgSnd_offHandler = bgSnd_offHandler;
916
917 // gain setting and update
918 if(AM_IsSpeechOn()){
919 BGSND_ConfigULMixer(KAL_TRUE, ULGainLevel);
920 BGSND_ConfigDLMixer(KAL_TRUE, DLGainLevel);
921 } else {
922 BGSND_ConfigULMixer(KAL_FALSE, ULGainLevel);
923 BGSND_ConfigDLMixer(KAL_FALSE, DLGainLevel);
924 }
925 bgsndUpdateMixer();
926
927
928 // Before dynamic download, all application should be off.
929 // But background sound do not need to dynamic download, so the following is unnecessary.
930 // KT_StopAndWait();
931
932 // turn on.
933 bgsndOnHandler();
934
935 // L1SP_Register_BgsService(bgsndOnHandler, bgsndOffHandler);
936 bgSnd.state = BGSND_STATE_RUN;
937}
938
939/*
940 * Description
941 * ---------
942 * The function stops the background sound playback of the media handle.
943 *
944 * Syntax
945 * ---------
946 * void BGSND_Stop();
947 *
948 * where
949 * hdl The media handle
950 *
951 * Return Value
952 * ---------
953 * None
954 */
955void BGSND_Stop(void)
956{
957
958
959
960 MD_TRC_L1SND_ENTER_BGSND_STOP();
961
962 /*
963 if ( !L1Audio_CheckFlag( bgSnd.aud_id ) )
964 return;
965 */
966
967 // unregister service
968 // L1SP_UnRegister_BgsService();
969
970 bgSnd.state = BGSND_STATE_STOP;
971
972 // set event to trigger close process
973 L1Audio_SetEvent(bgSnd.aud_id, NULL);
974}
975
976void BGSND_Close(void)
977{
978
979 L1Audio_ClearFlag( bgSnd.aud_id );
980
981#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
982 L1Audio_UnhookHisrHandler(D2C_SOUND_EFFECT_INT_ID_DL);
983 L1Audio_UnhookHisrHandler(D2C_SOUND_EFFECT_INT_ID_UL);
984#else
985 L1Audio_UnhookHisrHandler(D2C_SOUND_EFFECT_INT_ID_DL);
986#endif
987
988 // reset the pointer
989 bgSnd.pBuf = NULL;
990 bgSnd.bufSize = 0;
991 bgSnd.bgSnd_hisrHandler = NULL;
992
993
994 bgSnd.state = BGSND_STATE_IDLE;
995}
996
997
998/*
999 * Description
1000 * ---------
1001 * The function sets the output device.
1002 *
1003 * Syntax
1004 * ---------
1005 * void BGSND_SetOutputDevice( kal_uint8 device );
1006 *
1007 * where
1008 * device The output device (L1SP_SPEAKER1, L1SP_SPEAKER2, L1SP_LOUD_SPEAKER)
1009 *
1010 * Return Value
1011 * ---------
1012 * None
1013
1014void BGSND_SetOutputDevice( kal_uint8 device )
1015{
1016 //if( !AM_IsSpeechOn() )
1017#ifdef ANALOG_AFE_PATH_EXIST
1018 AFE_SetOutputDevice( L1SP_SND_EFFECT, device );
1019#endif
1020}
1021*/
1022
1023
1024void BGSND_INIT()
1025{
1026 memset(&bgSnd, 0, sizeof(BGSND_T));
1027
1028 // get audio ID
1029 bgSnd.aud_id = L1Audio_GetAudioID();
1030 L1Audio_SetEventHandler( bgSnd.aud_id, (L1Audio_EventHandler)bgsndEventHandler );
1031 bgSnd.timer = kal_create_timer("bgSnd");
1032}
1033