虽然做驱动这么久了,但对于AC967的驱动认识还是一知半解,主要是我们所选择的CPU方案一般都有配备相应的AC97驱动程序,一般来说都没有什么太大问题,偶尔会有一些小BUG须要小的改动,但这一般都没有什么难度。所以没有认真的去研究这个AC97驱动倒底是什么样的一个原理。不过昨天有客户发现我们做的一个CPU方案的耳机左右声道是反向的(当然这不是我的案子),部门负责人让我看一下能不能在WINCE自带的Media player上来改变声音的左右声道,即把左声道的声音让他从右声道输出来,刚开始我以为是我自己听说了,可能他是要我做一个左右声道切换的吧,后来仔细询问了一下才确认是要将左右声道交换,这样一来就把我急坏了,原因如下。
1:WInce自带的Media Player没有左右声道识别和切换功能,须要自己加上去。
2:只有左声道的音源我们却非要让他重右声道输出我们应该如何做(改驱动完全可以实现,等会我们现讲驱动如改)。
3:不能改驱动,因为我没有那一个CPU方案的BSP等资料。
不知道是谁说TCPMP就可以实现这个功能,但我没有完全搞懂TCPMP怎么实现的这个功能,按照正常的情况来说我个人认为要实现声道转换须要以下几个流程。
1:如果要将只有左声道音源让他从右声道输出须要将文件先分解并转换为左右双声道的音源,并记录原来的音源是那个通道的。
2:如果原音源是左声道,我们在程序中就将其处理,让右声道输出,反之一样
3:如查原来的是双声道。那只须要将他们交换一下就OK了,这个问题不大
这样一来工程量还是蛮大的,所以我觉得还是修改AC97驱动要好,但本部门的负责人说驱动改不了(我没有那个方案的AC97驱动,无只有他们才有,不知道为何改不了),静下一想其实原理是一样的应该可以实殃,现在就结合我做的这一个方案来讲一下怎么修改AC97的驱动实现声道的交换。
由于音频设置使用的数据量大所以我们用的是通过DMA数据通迅以减少CPU的负载。我现在使用的处理器的DMA控制器有16个DMA通道。可以响应内部或外部设备的请求,完成数据从主存储器(内存)的读出和写人。
既然有左右声道就会有两个通道的问题,本驱动中AACI_WaveOpen ()时就可以判定是否支持双通道。这时候你还可以设置AC97的通道(具体怎么设置要看DataSheet).
int AddPlayBuffer( int* left )
{
PWAVEHDR g_pwh;
int error = 0;
LOCK_GSI(WAPI_OUT);
if( gsi[WAPI_OUT].bStarted == TRUE )
{
g_pwh = gsi[WAPI_OUT].pwh;
while( g_pwh && g_pwh->dwBytesRecorded != 0)
g_pwh = g_pwh->lpNext;
if( g_pwh )
{
DWORD bufphy;
int size = g_pwh->dwBufferLength;
g_pwh->dwBytesRecorded = size/2;
GetPlayBuffer( &bufphy );
StartPlayDMA( bufphy , size , left );
}
else
error = 2;
}
else
{
// DMAPlayCmd = DMA_PLAY_STOP;
error = 1;
}
UNLOCK_GSI(WAPI_OUT);
return error;
}
AACI_WaveOpen (WAPI_INOUT apidir,
LPWAVEFORMATEX lpFormat,
BOOL fQueryFormatOnly)
{
MMRESULT mmRet = MMSYSERR_NOERROR;
RETAILMSG(0,(TEXT("/r/n<<<<<<<+AACI_WaveOpen v1.25>>>>>>>>/r/n")));
//如果你给出的格式不是下面的格式则直接退出
if ((lpFormat->wFormatTag != WAVE_FORMAT_PCM) ||
(lpFormat->nChannels !=1 && lpFormat->nChannels != 2) ||//通道为1/2
{
goto EXIT;
}
判断格式就是准备数据的过程,然后就是:传送DMA了
int StartPlayDMA( unsigned int bufphy, int size , int* actualbuffered )
{
int error = 0;
DWORD FIFOAddr = 0x20037090 , dwRet;
START_DMA_PARAMS StartDMAParams;
StartDMAParams.ucChannelNumber = (unsigned char)PlayDMAChannelNumber;
........
return error;
}
AC97会根据你对AC97 芯片的设置将数据送往不同的声道DAC 然后到不同的channel .
因此这时候你只须要将原来设置的通道改调换一下就OK了,比如我的是这样
if(lpFormat->nChannels == 1)
{
AACI_RegWrite32( AACIReg_Channel1RxControl,
AACI_RegRead32(AACIReg_Channel1RxControl)& (~0x08) );
}
else
{
AACI_RegWrite32( AACIReg_Channel1RxControl,
AACI_RegRead32(AACIReg_Channel1RxControl) |
AACIBit_EnableFIFO|0x08 );
}
这辈子没法做太多事情,所以每一件都要做到精彩绝伦