⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cvc_headset.c

📁 bluelab 3.52 里面的立体声程序源代码
💻 C
字号:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2004-2006
Part of BlueLab 3.5.2-release

FILE NAME
	cvc_headset.c        

DESCRIPTION
    Support for CVC in av_headset_hfp
	
	Only active if INCLUDE_CVC is defined in the project properties.
	
NOTES
	The supporting DSP code is supplied as a preassembled .kap file and is
	time limited until licenced.
*/

#ifdef INCLUDE_CVC

/****************************************************************************
	Header files
*/

#include "headset_codec.h"
#include "headset_private.h"
#include "headset_tones.h"
#include "headset_volume.h"
#include "cvc_headset.h"
#include "cvcdsp.h"


#include <codec.h>
#include <file.h>
#include <kalimba.h>
#include <kalimba_standard_messages.h>
#include <pcm.h>
#include <stdlib.h>
#include <string.h>
#include <transform.h>
#include <panic.h>
#include <ps.h>
#include <pio.h>
#include <message.h>
#include <stream.h>


#ifdef DEBUG_CVC
#define CVC_DEBUG(x) DEBUG(x)
#else
#define CVC_DEBUG(x) 
#endif

/* 5 Minute Demonstration Mode */
/* If ENABLE_DEMO_MODE is defined the audio will mute in 5 minutes */
/* if the CVC security signature is invalid.					   */
/* If ENABLE_DEMO_MODE is not defined the audio will mute 		   */
/* immediately if the CVC security signature is invalid.  This	   */
/* can be used for immediate notification of an invalid security   */
/* signature during production testing.							   */

#define ENABLE_DEMO_MODE	 

/* CVC Message IDs From Kalimba */
#define CVC_READY				0x1000
#define CVC_SETMODE				0x1001
#define CVC_VOLUME				0x1002

#define CVC_CODEC				0x1006
#define CVC_STATUS		        0x1007
#define CVC_SECPASSED			0x100c

/* CVC Message IDs Not From Kalimba */
/* Security Failure Message ID */
#define	CVC_SECFAILED			0x1000

/* System Modes */
#define SYSMODE_HFK			1
#define SYSMODE_ASR			2
#define SYSMODE_PSTHRGH		3
#define SYSMODE_STANDBY	    6

/* Call State */
#define CALLST_CONNECTED	1
#define CALLST_MUTE         3


/* Filename containing the CHF DSP code.	*/
static const char enc_codec[] = "cvc/cvc.kap";

static bool cvc_init(headsetTaskData* app);
static void start_kalimba(headsetTaskData* app);
static void connect_streams(headsetTaskData *app);
static void dsp_handler(Task, MessageId, Message);

/* This is the table of codec gain values used with CVC */
/* Table entries are configurable, but the maximum value cannot exceed 15 */
static const uint8 vgsToCodecGainCvc[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};

/* The Sidetone level can be controlled 3 different ways:                                 */
/* 1) The VM application can send the level as a parameter to the CVC_VOLUME message.     */
/* 2) The level can be specified in the cvc "parameters.psr" file.                        */
/* 3) The value specified in the cvc "parameter.psr" file can be auto leveled by the      */
/*    dsp such that the level is always constant or it can be made to change with volume. */
/*                                                                                        */
/* The cvc ParamMgr.exe is used to write a psr file that specifies which method is being  */
/* used.  Regardless of the method, the maximum level that the sidetone gain can be is    */
/* -11 dBFS.                                                                              */

/* If the sidetone level is being controlled by the VM application the following table    */
/* will be used.  Otherwise, the values sent from this table will be ignored by the dsp.  */
/* Note if a value larger than 0x23D7 is used, it will be limited to 0x23D7 by the dsp.   */
/* This corresponds to a limit -11 dBFS.                                                  */

static const uint8 SideToneGain[16] = {0x23D7, 0x23D7, 0x23D7, 0x23D7, 0x23D7, 0x23D7, 0x23D7, 0x23D7,  	
									   0x23D7, 0x23D7, 0x23D7, 0x1CA7, 0x1449, 0x0E5C, 0x0A2A, 0x0732};



static bool cvc_init(headsetTaskData* app)
{
    bool ret = FALSE;

    if (!app->cvc.hfkdspready)
    {
        start_kalimba(app);
        codec_configure_mono_8000(app);
        ret = TRUE;        
    }
   
    return ret;
}

/* The following function is used to start the DSP code.  The code    */
/* for the DSP resides in the constant data area as a file in a file  */
/* system.  Once the file is located, the file is loaded into the DSP */
/* and started.                                                       */

static void start_kalimba(headsetTaskData* app)
{
    /* Find the codec file in the file system */
    FILE_INDEX index = FileFind(FILE_ROOT,enc_codec,sizeof(enc_codec)-1/*don't pass terminator*/);

    if(index == FILE_NONE)
    {
        /* Error - can't find file        */
        CVC_DEBUG(("CVC: CHF file index = %x \n",index));
	   Panic();
    }
    
    (void) MessageCancelAll(&app->cvc.task, MESSAGE_FROM_KALIMBA);
    MessageKalimbaTask(&app->cvc.task);
   
    /* Load the cvc algorithm into Kalimba */
    if(!KalimbaLoad(index))
    {
        CVC_DEBUG(("CVC: Kalimba load fail\n"));
        Panic();
    }
   
    /* Now the kap file has been loaded, wait for the CVC_READY message from the */
    /* dsp to be sent to the dsp_handler function.                               */  
}

static void connect_streams(headsetTaskData *app)
{
    bool r1, r2, r3, r4;

    /* Mute audio before connecting the stream */
	
	 CodecSetOutputGainNow(app->codec_task, 0, left_and_right_ch); 
	/* Connect the stream from the Mic to the DSP and the stream  */
    /* from the DSP to the Speaker.                               */
    r1 = StreamConnect(StreamPcmSource(0),StreamKalimbaSink(0));
    r2 = StreamConnect(StreamKalimbaSource(0),StreamPcmSink(0));
    
	/* Plug Incoming SCO link into DSP Channel 1 Input. */
	r3 = StreamConnect(StreamSourceFromSink(app->sco_sink),StreamKalimbaSink(1));
	/* Plug DSP Channel 1 Output into Outoing SCO Link. */
	r4 = StreamConnect(StreamKalimbaSource(1),app->sco_sink);
    
    CVC_DEBUG(("CVC: connect_streams %d %d %d %d\n",r1,r2,r3,r4));
    
	/* Tell cvc to set the DAC gain */
    CvcHeadsetVolume(app);
    
    /* Set the Dsp mode */
    CvcSetMode(app); 
}

/* The following function is used to handle messages that are        */
/* dispatched from the DSP.                                          */

typedef struct
{
    uint16 id;
    uint16 a;
    uint16 b;
    uint16 c;
    uint16 d;
} DSP_REGISTER_T;


static void dsp_handler(Task task, MessageId id, Message message) 
{
	
	headsetTaskData *app = getApp();
	switch(id)
	{
	case MESSAGE_FROM_KALIMBA:
		{
			const DSP_REGISTER_T *m = (const DSP_REGISTER_T *) message;
			uint16 a      = m->a;
			uint16 b      = m->b;
	        
	        CVC_DEBUG(("CVC: dsp_handler dsp_id = %x a= %x b= %x c= %x d= %x\n" ,m->id,a,b,m->c,m->d));
		
			switch (m->id) 
			 {
	         case CVC_READY:
	            /* This command is sent to us to indicate that the DSP is      */
	            /* initialized and ready.  At this point we need to send the   */
	            /* configuration parameters to the DSP and allocate memory to  */
	            /* hold a configuration record.  This is done within the       */
				/* CvcConfigureDsp() function which is defined in the          */ 
                /* libcvcdsp.a file.                                           */
                /*                                                             */
                /* If multiple sets of parameters are required,  Persistent    */
				/* Store Keys can be defined for each and CvcConfigureDsp can  */
                /* be called to load the various parameter sets.  Note that    */
			    /* the first call to CvcConfigureDsp must be done here as a    */
				/* response to the CVC_READY message, but that successive      */
				/* calls do not need to be here.                               */
					
				a = CvcConfigureDsp(PS_PARAM_BASE,NULL,0,PS_PARAM_BASE2,NULL,0);

	            CVC_DEBUG(("CVC: CVC_READY: DSP is initialized and ready (%x)\n",a));
	            
	            /* DSP is up and running */
	   			app->cvc.hfkdspready = 1;

	            if (app->sco_sink && (app->pcm_audio_state == pcm_sco))
	            {
	                CVC_DEBUG(("CVC: Ok to connect streams\n"));
	    			connect_streams(app);
	            }
				
				
				/* Set timer for security fail condition					*/
				/* If the security check on the kalimba passes this mesage  */
				/* will be cancelled - see CVC_SECPASSED below.				*/
				app->cvc.sec_mute = 0;			
				MessageSendLater(task, CVC_SECFAILED, 0, 500);
			    break;
				
			case CVC_CODEC:
	            /* We have received a message that defines the values that  */
	            /* are to be loaded for gain levels.  Parameter 1 (a)       */
	            /* defines the DAC (speaker) gain.  Parameter 2 (b) defines */
	            /* the ADC (microphone gain).  The mic level is meant to be */
	            /* fixed throughout CVC operation.  The DAC level changes   */
	            /* in correspondace with volume changes.  When using the    */
	            /* CVC algorithm, the DAC gain should always be set using   */
				/* the CvcHeadsetVolume message so that CVC is aware of the */
				/* DAC gain.												*/
	 			
				app->cvc.cvc_output_codec_gain = a;
	            app->cvc.cvc_input_codec_gain = b;
	   			CodecSetOutputGainNow(app->codec_task, a, left_and_right_ch);
	            CVC_DEBUG(("CVC: CVC_CODEC: Input gain = 0x%x  Output gain = 0x%x\n",b,a));
	            if((b & 0x8000)  == 0x8000)
				{
					CodecEnableMicInputGainA(1);
					CodecEnableMicInputGainB(1);
				}
				else
				{
					CodecEnableMicInputGainA(0);
					CodecEnableMicInputGainB(0);
				}
				
				/* Clear the upper bytes of the input gain argument */
				b &= 0xff;			
	            CodecSetInputGainNow(app->codec_task, b, left_and_right_ch);
	            break;
				
			case CVC_SECPASSED:
				CVC_DEBUG(("CVC:  Security passed.\n"));
				MessageCancelAll(task, CVC_SECFAILED);
				break;
	      }
		}
		break;
	
	case	CVC_SECFAILED:	/* message not from kalimba */
		
#ifdef	ENABLE_DEMO_MODE
		CVC_DEBUG(("CVC:  Running in Demo Mode.\n"));

#else
		CVC_DEBUG(("CVC:  Security failed.\n"));		
		app->cvc.sec_mute = 1;
		CvcSetMode(app);
#endif
		break;
		
	}
		
}

	
	
void CvcInitialise(headsetTaskData *app)
{
    app->cvc.task.handler = dsp_handler;    
    app->cvc.cvc_output_codec_gain = 0;
    app->cvc.cvc_input_codec_gain = 0;
}

void CvcHeadsetConnect(headsetTaskData *app)
{
	CVC_DEBUG(("CVC: hfkdspready = %x\n",app->cvc.hfkdspready));
	CVC_DEBUG(("CVC: hfp_state = %x\n",app->hfp_state));
	if (!cvc_init(app))
    {
        /* Disconnect anything already connected to PCM slots 0 and 1 */
        StreamDisconnect(StreamPcmSource(0), StreamPcmSink(0));
        /* Now connect up the new streams */
    	connect_streams(app);
        CVC_DEBUG(("CVC: Cvc sco connected\n"));
    }
}

void CvcHeadsetUnloaded(headsetTaskData *app)
{
    /* The DSP has been reloaded by some other part of the application */
    app->cvc.hfkdspready = 0;	
    CVC_DEBUG(("CVC: Cvc unloaded\n"));
}

void CvcHeadsetVolume(headsetTaskData *app)
{
    uint16 volume_index = app->speaker_volume.hfp_volume;
	if(app->cvc.hfkdspready)
    {
       CVC_DEBUG(("CVC: Cvc volume = %x\n",volume_index));
	   CVC_DEBUG(("CVC: Cvc DAC gain = %x\n",app->cvc.cvc_output_codec_gain)); 
	   if(!KalimbaSendMessage(CVC_VOLUME, volume_index, 0, vgsToCodecGainCvc[volume_index], SideToneGain[volume_index]))
	   {
		  CVC_DEBUG(("CVC: SetVolume FAILURE\n"));
	   }
   }
}

void CvcSetMode(headsetTaskData *app)
{
    if (!app->cvc.hfkdspready)
        return;
    
	if(app->cvc.sec_mute)
	{
		if(!KalimbaSendMessage(CVC_SETMODE, SYSMODE_STANDBY, 0, 0, 0))
        {
		    CVC_DEBUG(("CVC: SetMode SYSMODE_STANDBY\n"));
        }
	}
    else if (app->voice.voice_recognition_enabled)
    {
        CVC_DEBUG(("CVC: SetMode SYSMODE_ASR\n"));
        /* Set the DSP mode to apply noise reduction only. */
        if(!KalimbaSendMessage(CVC_SETMODE, SYSMODE_ASR, 0, 0, 0))
        {
		    CVC_DEBUG(("CVC: SetMode SYSMODE_ASR FAILURE\n"));
        }
    }
    else
    { 
        CVC_DEBUG(("CVC: Set mode SYSMODE_HFK "));
        if (app->mic_mute_on)
        {
            CVC_DEBUG(("(CALLST_MUTE)\n"));
            if (!KalimbaSendMessage(CVC_SETMODE, SYSMODE_HFK, 0, CALLST_MUTE, 0))
            {
                CVC_DEBUG(("CVC: Set Mode SYSMODE_HFK (CALLST_MUTE) FAILURE\n"));
            }
        }
        else
        {   
            CVC_DEBUG(("(CALLST_CONNECTED)\n"));
            /* Set the DSP mode to apply echo cancellation and noise reduction. */
            if(!KalimbaSendMessage(CVC_SETMODE, SYSMODE_HFK, 0, CALLST_CONNECTED, 0))
            {
		        CVC_DEBUG(("CVC: SetMode SYSMODE_HFK (CALLST_CONNECTED) FAILURE\n"));
            }
        }
    }
}

#else /* ifndef INCLUDE_CVC */

extern int cvc_headset_dummy_int; /* Suppress empty-file error */

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -