📄 aaci_dma.c_zq
字号:
#include <windows.h>
#include <pkfuncs.h>
#include <ceddk.h>
#include <oalfuncs.h>
#include <dma.h>
#include "oalintr.h"
#include "wavemdd.h"
#include "pdd_audio.h"
#define DebugMsg_Normal 0x00
#define DebugMsg_Important 0x02
#define DebugMsg_Trace 0x04
#define DebugMsgMask (DebugMsg_Important|DebugMsg_Normal)
int ReleasePlayDMA(void);
int InitPlayDMA();
int AllocPlayDMA(void);
void GetPlayBuffer( unsigned int *buf );
int InitAll();
int StartPlayDMA( unsigned int bufphy, int size , int* actualbuffered );
int ReleaseAll();
int AllocRecordDMA(void);
int InitRecordDMA(void);
int StartRecordDMA( LPSTR buffer , DWORD size , int* actualbuffered);
DWORD AudioDMAThread(LPVOID p);
static HANDLE DmaPlayEvent = 0;
static HANDLE PlayCmdEvent = 0;
static volatile int WaitPlayBuffer = 0;
static HANDLE DmaRecordEvent = 0;
static HANDLE RecordCmdEvent = 0;
static volatile int WaitRecordBuffer = 0;
static volatile int DMAPlayCmd;
static volatile int DMARecordCmd;
static int TotalPlayBufferCnt = 0;
static volatile int PlayBufferPlayIndex = 0;
static volatile int PlayBufferStoreIndex = 0;
static int PlayDMAChannelNumber = -1;
static int PlayDmaIntID = 0;
static int RecordDMAChannelNumber = -1;
static int RecordDmaIntID = 0;
static HANDLE DmaThread = 0;
static HANDLE DmaRecordThread = 0;
#define RecordTempCnt 4
#define RecordTempSize 0x1000
#define MinRecordSize 160
static char RecordTemp[RecordTempCnt][RecordTempSize];
static int RecordSize[RecordTempCnt];
static int RecordIndex = 0;
static int RecordUsedIndex = 0;
WAVEFORMATEX RecordFormat;
static int playcount = 0;
static int playedcount = 0;
int InRemove = 0;
static int recordcount = 0;
static int recordedcount = 0;
#define DMA_PLAY_STOP 0
#define DMA_PLAY_START 1
#define DMA_PLAY_EXIT 2
#define DMA_RECORD_STOP 0
#define DMA_RECORD_START 1
#define DMA_RECORD_EXIT 2
static int RecordOver = 0;
static char DebugMsg[1024*512];
static int MsgLength = 0;
CRITICAL_SECTION Critical;
static void StartDebugMsg()
{
MsgLength = 0;
memset( DebugMsg , 0 , sizeof(DebugMsg) );
}
static void EndDebugMsg()
{
return;
EnterCriticalSection( &Critical );
if( MsgLength )
{
char temp[256];
FILE* fp;
sprintf( temp , "save %d" , MsgLength );
fp = fopen( temp , "wb" );
if( fp )
{
fwrite( DebugMsg + MsgLength , 1 , sizeof(DebugMsg)-MsgLength , fp );
fwrite( DebugMsg , 1 , MsgLength , fp );
fclose( fp );
}
MsgLength = 0;
}
LeaveCriticalSection( &Critical );
}
static void AddDebugMsg( char* fmt, ... )
{
char temp[256];
int length;
va_list args;
return;
EnterCriticalSection( &Critical );
va_start(args, fmt);
vsprintf( temp , fmt , args);
length = strlen( temp );
if( MsgLength + length >= sizeof(DebugMsg) )
MsgLength = 0;
{
memcpy( DebugMsg+MsgLength , temp , length );
MsgLength += length;
DebugMsg[MsgLength++] = '\0';
}
LeaveCriticalSection( &Critical );
}
int OnInit()
{
int error = 0;
if( InitAll() != 0 )
error = 1;
if( error )
{
DMAPlayCmd = DMA_PLAY_EXIT;
DMARecordCmd = DMA_RECORD_EXIT;
}
else
{
DMAPlayCmd = DMA_PLAY_STOP;
DMARecordCmd = DMA_RECORD_STOP;
}
InitializeCriticalSection( &Critical );
return error;
}
int OnDeinit()
{
int error = 0;
ReleaseAll();
return error;
}
int OnRecordOpen()
{
int error = 0;
DMARecordCmd = DMA_RECORD_STOP;
recordcount = recordedcount = 0;
RecordIndex = RecordOver = 0;
StartDebugMsg();
//RETAILMSG( (DebugMsgMask&DebugMsg_Normal) , (TEXT( "OnRecordOpen\r\n" ) ));
return error;
}
int OnRecordStart()
{
int error = 0;
DMARecordCmd = DMA_RECORD_START;
RETAILMSG( (DebugMsgMask&DebugMsg_Normal), (TEXT( "OnRecordStart\r\n" ) ));
RecordIndex = RecordUsedIndex = 0;
SetEvent( RecordCmdEvent );
return error;
}
int OnRecordStop()
{
int error = 0;
DMARecordCmd = DMA_RECORD_STOP;
return error;
}
int OnRecordClose()
{
int error = 0;
EndDebugMsg();
DMARecordCmd = DMA_RECORD_STOP;
SetEvent( RecordCmdEvent );
//RETAILMSG( (DebugMsgMask&DebugMsg_Normal), (TEXT( "OnRecordClose\r\n" ) ));
return error;
}
int OnPlayOpen()
{
int error = 0;
PlayBufferPlayIndex = PlayBufferStoreIndex = 0;
DMAPlayCmd = DMA_PLAY_START;
playcount = playedcount = 0;
StartDebugMsg();
//RETAILMSG( (DebugMsgMask&DebugMsg_Normal), (TEXT( "OnPlayOpen\r\n" ) ));
return error;
}
int OnPlayStart()
{
int error = 0;
DMAPlayCmd = DMA_PLAY_START;
RETAILMSG( (DebugMsgMask&DebugMsg_Normal), (TEXT( "OnPlayStart\r\n" ) ));
return error;
}
int OnPlayStop()
{
int error = 0;
DMAPlayCmd = DMA_PLAY_STOP;
MsgLength = 0;
SetEvent( PlayCmdEvent );
return error;
}
int OnPlayClose()
{
int error = 0;
DMAPlayCmd = DMA_PLAY_STOP;
//RETAILMSG( (DebugMsgMask&DebugMsg_Normal), (TEXT( "OnPlayClose\r\n" ) ));
return error;
}
int RemoveRecordBuffer( int toremove )
{
PWAVEHDR g_pwh;
int error = 0;
LOCK_GSI(WAPI_IN);
if( gsi[WAPI_IN].bStarted == TRUE )
{
g_pwh = gsi[WAPI_IN].pwh;
while( g_pwh && g_pwh->dwBytesRecorded == g_pwh->dwBufferLength )
g_pwh = g_pwh->lpNext;
while( toremove-- && g_pwh )
{
memcpy( g_pwh->lpData + g_pwh->dwBytesRecorded ,
RecordTemp[ RecordUsedIndex ] ,
RecordSize[ RecordUsedIndex ] );
g_pwh->dwBytesRecorded += RecordSize[ RecordUsedIndex ];
RecordUsedIndex = (RecordUsedIndex+1)%RecordTempCnt;
if( g_pwh->dwBytesRecorded == g_pwh->dwBufferLength )
{
MARK_BUFFER_DONE(g_pwh);
g_pwh->reserved = 0;
g_pwh = g_pwh->lpNext;
recordedcount ++;
if( recordcount == recordedcount )
RETAILMSG( 1 , (TEXT("record buffer over")));
}
}
RemoveCompleteBlocks(WAPI_IN);
}
else
{
error = 1;
}
UNLOCK_GSI(WAPI_IN);
return error;
}
int RemovePlayBuffer( int toremove )
{
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 == g_pwh->dwBufferLength)
g_pwh = g_pwh->lpNext;
while( toremove-- && g_pwh )
{
g_pwh->dwBytesRecorded = g_pwh->dwBufferLength;
g_pwh = g_pwh->lpNext;
playedcount ++;
}
MarkFullAsDone(WAPI_OUT);
InRemove = 1;
RemoveCompleteBlocks(WAPI_OUT);
InRemove = 0;
}
else
{
AddDebugMsg( "play not started\n" );
error = 1;
}
UNLOCK_GSI(WAPI_OUT);
return error;
}
/*
typedef struct tWAVEFORMATEX
{
WORD wFormatTag; format type/
WORD nChannels; number of channels (i.e. mono, stereo...)
DWORD nSamplesPerSec; sample rate
DWORD nAvgBytesPerSec; /* for buffer estimation
WORD nBlockAlign; /* block size of data
WORD wBitsPerSample; /* number of bits per sample of mono data
WORD cbSize; /* the count in bytes of the size of
/* extra information (after cbSize)
} WAVEFORMATEX, *PWAVEFORMATEX, NEAR *NPWAVEFORMATEX, FAR *LPWAVEFORMATEX;
*/
int AddRecordBuffer( int* left , int* morebuffer)
{
PWAVEHDR g_pwh;
int error = 0;
LOCK_GSI(WAPI_IN);
if( gsi[WAPI_IN].bStarted == TRUE )
{
g_pwh = gsi[WAPI_IN].pwh;
while( g_pwh && ( g_pwh->dwBytesRecorded == g_pwh->dwBufferLength || g_pwh->reserved == g_pwh->dwBufferLength) )
g_pwh = g_pwh->lpNext;
if( g_pwh )
{
DWORD size = g_pwh->dwBufferLength - g_pwh->reserved;
DWORD torecord;
//#define RecordTempSize 0x1000
//#define MinRecordSize 160
if( size <= RecordTempSize )
torecord = size;
else if( size < RecordTempSize + MinRecordSize )
torecord = size / 2;
else
torecord = RecordTempSize;
torecord = (torecord/RecordFormat.nBlockAlign)*RecordFormat.nBlockAlign;//把数据取成BLOCK的整数倍
//StartRecordDMA( g_pwh->lpData , g_pwh->dwBufferLength , left );
StartRecordDMA( RecordTemp[RecordIndex] , torecord , left );
RecordSize[RecordIndex] = torecord;
g_pwh->reserved += torecord;
RecordIndex = (RecordIndex+1)%RecordTempCnt;
if( g_pwh->lpNext || g_pwh->reserved < g_pwh->dwBufferLength )
*morebuffer = 1;
else
*morebuffer = 0;
RETAILMSG( (DebugMsgMask&DebugMsg_Trace) , (TEXT("g_pwh->reserved ---morebuffer : %d,%d \r\n") , g_pwh->reserved,morebuffer));
RETAILMSG( (DebugMsgMask&DebugMsg_Trace) , (TEXT("aaci : addrecord : %x , %x\r\n") ,g_pwh->lpData , g_pwh->dwBufferLength));
}
else
{
error = 2;
*morebuffer = 0;
}
}
else
{
//DMARecordCmd = DMA_RECORD_STOP;
error = 1;
}
UNLOCK_GSI(WAPI_IN);
return error;
}
/*
/* wave data block header
typedef struct wavehdr_tag {
LPSTR lpData; /* pointer to locked data buffer
DWORD dwBufferLength; /* length of data buffer
DWORD dwBytesRecorded; /* used for input only
DWORD dwUser; /* for client's use
DWORD dwFlags; /* assorted flags (see defines)
DWORD dwLoops; /* loop control counter
struct wavehdr_tag FAR *lpNext; /* reserved for driver
DWORD reserved; /* reserved for driver
} WAVEHDR, *PWAVEHDR, NEAR *NPWAVEHDR, FAR *LPWAVEHDR;
*/
//DWORD size = g_pwh->dwBufferLength - g_pwh->reserved;
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;
}
int OnPlayDmaFail()
{
{
GET_ERROR_PARAMS p;
GET_ERROR_RESULT r;
KernelIoControl( IOCTL_HAL_GET_ERROR_STATUS , &p , sizeof(GET_ERROR_PARAMS) , &r , sizeof(GET_ERROR_RESULT) , 0);
RETAILMSG( 1 , (TEXT("OnPlayDmaFail %x\r\n" ) , r.ucErrorStatus ));
}
{
CLEAR_ERROR_PARAMS p;
CLEAR_ERROR_RESULT r;
KernelIoControl( IOCTL_HAL_CLEAR_ERROR_STATUS, &p , sizeof(CLEAR_ERROR_PARAMS) , &r , sizeof(CLEAR_ERROR_RESULT) , 0);
}
{
int param1 = 1 , param2 = 0;
KernelIoControl( HAL_IOCTL_AACI_CLEARSTATUS , ¶m1 , sizeof(int) , ¶m2 , sizeof(int) , 0);
}
return 0;
}
int OnRecordDmaFail()
{
{
GET_ERROR_PARAMS p;
GET_ERROR_RESULT r;
KernelIoControl( IOCTL_HAL_GET_ERROR_STATUS , &p , sizeof(GET_ERROR_PARAMS) , &r , sizeof(GET_ERROR_RESULT) , 0);
RETAILMSG( 1 , (TEXT("OnRecordDmaFail %x\r\n" ) , r.ucErrorStatus ));
}
{
CLEAR_ERROR_PARAMS p;
CLEAR_ERROR_RESULT r;
KernelIoControl( IOCTL_HAL_CLEAR_ERROR_STATUS, &p , sizeof(CLEAR_ERROR_PARAMS) , &r , sizeof(CLEAR_ERROR_RESULT) , 0);
}
{
int param1 = 0 , param2 = 1;
KernelIoControl( HAL_IOCTL_AACI_CLEARSTATUS , ¶m1 , sizeof(int) , ¶m2 , sizeof(int) , 0);
}
return 0;
}
#define RecordBufferCount 1
//#define RecordBufferCount 2
DWORD AudioRecordThread( LPVOID p )
{
int leftrecordblock = 0 , bufferedrecordblock = 0 , moreinputblock = 0 , error = 0;
int loopcount = 0 ,temp;
SetProcPermissions( 0xFFFFFFFF );
RETAILMSG( (DebugMsgMask&DebugMsg_Important ), (TEXT( "AACI : DMA : Enter record Thread\r\n" ) ));
while( !error && DMARecordCmd != DMA_RECORD_EXIT )
{
if( (loopcount++%1000) == 0 )
RETAILMSG( (DebugMsgMask&DebugMsg_Trace) , (TEXT("AudioRecordThread loop %d\r\n" ) , bufferedrecordblock ));
//如果 DMARecordCmd == DMA_RECORD_STOP则清除DMA状态
if( DMARecordCmd == DMA_RECORD_STOP )
{
int param1 = 0 , param2 = 1;
KernelIoControl( HAL_IOCTL_AACI_CLEARSTATUS , ¶m1 , sizeof(int) , ¶m2 , sizeof(int) , 0);
bufferedrecordblock = 0;
RETAILMSG( (DebugMsgMask&DebugMsg_Trace) , (TEXT( "AACI : record : stoped \r\n" ) ));
}
//如果当前为DMARecordCmd == DMA_RECORD_STOP 或则没有更多的录音需求则等待
if( DMARecordCmd == DMA_RECORD_STOP || moreinputblock == 0 )//
{
WaitRecordBuffer = 1;
WaitForSingleObject( RecordCmdEvent , INFINITE );//等待有录音需求来唤醒
WaitRecordBuffer = 0;
}
if( bufferedrecordblock && ( bufferedrecordblock == RecordBufferCount||moreinputblock==0) )
{
if( WaitForSingleObject( DmaRecordEvent , INFINITE ) == 0 )
InterruptDone( RecordDmaIntID );
AddDebugMsg( "wait record dma over\n" );
}
if( (DMARecordCmd != DMA_RECORD_START) )
continue;
RETAILMSG( (DebugMsgMask&DebugMsg_Trace) , (TEXT( "AACI : DMA : start work\r\n" ) ));
AddDebugMsg( "to get record status \n" );
//获取当前kernel中没有准备好数据的buff 数量
KernelIoControl( HAL_IOCTL_AACI_GETBUFFER , &temp , sizeof(int) , &leftrecordblock , sizeof(int) , 0);
AddDebugMsg("get record status %d %d %d\n" , leftrecordblock, bufferedrecordblock , temp);
if( DMARecordCmd == DMA_RECORD_START )
//bufferedrecordblock 当前kernel中有的buff数量
//leftrecordblock 当前kernel中没有准备好数据的buff数量
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -