4952|5

854

帖子

0

TA的资源

五彩晶圆(中级)

楼主
 

wince 音频放音录音驱动学习 [复制链接]

// -----------------------------------------------------------------------------
//
//  @doc    WDEV_EXT
//
//  @func   BOOL | WAV_IOControl | Device IO control routine
//
//  @parm   DWORD | dwOpenData | Value returned from WAV_Open call
//
//  @parm   DWORD | dwCode |
//          IO control code for the function to be performed. WAV_IOControl only
//          supports one IOCTL value (IOCTL_WAV_MESSAGE)
//
//  @parm   PBYTE | pBufIn |
//          Pointer to the input parameter structure ().
//
//  @parm   DWORD | dwLenIn |
//          Size in bytes of input parameter structure (sizeof()).
//
//  @parm   PBYTE | pBufOut | Pointer to the return value (DWORD).
//
//  @parm   DWORD | dwLenOut | Size of the return value variable (sizeof(DWORD)).
//
//  @parm   PDWORD | pdwActualOut | Unused
//
//  @rdesc  Returns TRUE for success, FALSE for failure
//
//  @xref    (WIDM_XXX)
//          (WODM_XXX)
//
// -----------------------------------------------------------------------------
BOOL WAV_IOControl(DWORD  dwOpenData,
                   DWORD  dwCode,
                   PBYTE  pBufIn,
                   DWORD  dwLenIn,
                   PBYTE  pBufOut,
                   DWORD  dwLenOut,
                   PDWORD pdwActualOut)
{
    _try
    {
        switch (dwCode)
        {
        case IOCTL_MIX_MESSAGE:
            return HandleMixerMessage((PMMDRV_MESSAGE_PARAMS)pBufIn, (DWORD *)pBufOut);// 重低音,混音等控制

        case IOCTL_WAV_MESSAGE:
            return HandleWaveMessage((PMMDRV_MESSAGE_PARAMS)pBufIn, (DWORD *)pBufOut);// 放音录音控制

        default:
            return g_pHWContext->IOControl(dwOpenData, dwCode, pBufIn, dwLenIn, pBufOut, dwLenOut, pdwActualOut);
        }
    }

    _except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("EXCEPTION IN WAV_IOControl!!!!\r\n")));
        SetLastError(E_FAIL);
    }

    return FALSE;
}
先看HandleWaveMessage 这个函数 的一些控制结构
关于录音
WIDM_GETDEVCAPS
This message is used to request a waveform input driver to return the capabilities of a specified device.

WIDM_GETNUMDEVS
This message is used to request a waveform input driver to return the number of devices that it supports.

WIDM_GETPOS
This message is used to request a stream input driver to return the current input position within a waveform. The input position is relative to the first recorded sample of the waveform.

WIDM_OPEN
This message is used to request a waveform input driver to open a stream of a specified device.

WIDM_PREPARE
This message is used to request a waveform input driver to prepare a system-exclusive data buffer for input.

WIDM_RESET
This message is used to request a waveform input driver to stop recording and return all buffers in the input queue to the caller.

WIDM_START
This message is used to request a waveform input driver to begin recording.

WIDM_STOP
This message is used to request a waveform input driver to stop recording.

WIDM_UNPREPARE
This message is used to request a waveform input driver to undo the buffer preparation that was performed in response to a WIDM_PREPARE message.



下表中列出了各个输出driver消息
Programming element
Description

WODM_BREAKLOOP
This message is used to request a waveform output driver to break an output loop that was created with a WODM_WRITE message.

WODM_CLOSE
This message is used to request a waveform output driver to close a specified stream that was previously opened with a WODM_OPEN message.

WODM_GETDEVCAPS
This message is used to request a waveform output driver to return the capabilities of a specified device.

WODM_GETNUMDEVS
This message is used to request a waveform output driver to return the number of device instances that it supports.

WODM_GETPITCH
This message is used to request a waveform output driver to return the specified device's current pitch multiplier value.

WODM_GETPLAYBACKRATE
This message is to request a waveform output driver to return the current playback rate multiplier value for the specified device.

WODM_GETPOS
This message is used to return the current position within a stream. The position is relative to the beginning of the waveform.

WODM_GETVOLUME
This message is used to request a waveform output driver to return the current volume level setting for the specified device or stream.

WODM_OPEN
This message is used to request a waveform output driver to open a stream on the specified device.

WODM_PAUSE
This message is used to request a waveform output driver to pause playback of a waveform.

WODM_PREPARE
This message is used to request a waveform output driver to prepare a system-exclusive data buffer for output.

WODM_RESET
This message is used to request a waveform output driver to stop sending output data and return all output buffers to the list.

WODM_RESTART

This message is used to request a waveform output driver to continue playback of a waveform after playback has been paused with WODM_PAUSE.

WODM_SETPITCH
This message is used to request a waveform output driver to set the specified device's pitch multiplier value.

WODM_SETPLAYBACKRATE
This message is used to request a waveform output driver to set the playback rate multiplier value for the specified device.

WODM_SETVOLUME
This message is used to request a waveform output driver to set the playback rate multiplier value for the specified device.

WODM_UNPREPARE
This message is used to request a waveform output driver to remove the buffer preparation performed in response to WODM_PREPARE.

WODM_WRITE
This message is used to request a waveform output driver to write a waveform data block to the specified device.
点赞 关注
个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460

回复
举报

854

帖子

0

TA的资源

五彩晶圆(中级)

沙发
 
[WAV] WDM_GETPOS
[WAV] WODM_WRITE
[WAV] WDM_GETPOS
[WAV] WDM_GETPOS
[WAV] WODM_WRITE
[WAV] WDM_GETPOS
[WAV] WODM_WRITE
[WAV] WDM_GETPOS
[WAV] WODM_WRITE
[WAV] WDM_GETPOS
[WAV] WDM_GETPOS
[WAV] WODM_WRITE
[WAV] WDM_GETPOS
[WAV] WODM_WRITE
[WAV] WDM_GETPOS
[WAV] WODM_WRITE
[WAV] WDM_GETPOS
[WAV] WODM_WRITE
[WAV] WDM_GETPOS
[WAV] WDM_GETPOS
[WAV] WODM_WRITE——看来这个就是写数据给音频芯片的,看打印信息
 
个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
 

回复

854

帖子

0

TA的资源

五彩晶圆(中级)

板凳
 

音频驱动分析:

1、这里主要介绍一下流式音频驱动,在应用程序进行音频操作之前,首先向内核产生一个调用,内核将这个调用传给驱动程序的WAV_IOCcontrol进行处理,内核传递这个调用的模块被称为Wave_API管理器,然后驱动程序对硬件进行操作,和普通的流接口驱动程一样,音频驱动也使用注册表来存储信息并且向系统注册自身,在Platform.reg中添加如下键:HKEY_LOCAL_MACHINE/Drivers/Builtin/Audio用于存储信息。在系统启动时,设备管理器将加载音频驱动,并且创建HKEY_LOCAL_MACHINE/Drivers/Active键。

流接口驱动程序接口如下,在wavedev.def中导出。

LIBRARY         WAVEDEV

EXPORTS

    WAV_Init

    WAV_Deinit

    WAV_Open

    WAV_Close

    WAV_PowerUp

    WAV_PowerDown

WAV_IOControl

(二)驱动中主要用的类:

1.  Devctxt.h中定义DviceContext类;分成两个子类InputDeviceContext,OutputDeviceContext。主要实现了对音设备的性能参数设定与返回,以及对音频流操作方法,(对音频数据流的操作最终调用的是StreamContext类里面的方法)。

2.  Strmctxt.h中定义StreamContext类,在该类中主要实现了对音频流文件进行操作的方法。(最终是通过系统的回调函数实现的)

3.  Hwctxt.h 中定义HardwareContext类,在该类中主要包含了一些对硬进行操作的代码,IIS、DMA、AUDIO芯片操作。

(三)主要数据结构:

1.typedef struct {

    UINT uDeviceId;

    UINT uMsg;

    DWORD dwUser;

    DWORD dwParam1;

    DWORD dwParam2;

} MMDRV_MESSAGE_PARAMS, *PMMDRV_MESSAGE_PARAMS;

(在../public/common/sdk/inc/wavedev.h定义)

这个是传输给WAV_IOControlr的数据结构。

(1)其中dwUser 参数在使用时为被强制转换成StreamContext,

例如:StreamContext *pStreamContext = (StreamContext *)dwUser;

(2)uMsg参数表示驱动要执行什么样的操作。具体对应如下:

// messages sent to wodMessage() entry-point function

#define WODM_GETNUMDEVS       3   //请求WAVEFORM输出驱动返回其支持的设备实例数量。

#define WODM_GETDEVCAPS       4 //请求WAVEFORM输出驱动返回特定设备的功能。

#define WODM_OPEN             5 //请求WAVEFORM输出驱动打开一个设备对应的流接口。

#define WODM_CLOSE            6 //请求WAVEFORM输出驱动关闭由WODM_OPEN建立的流接口。

#define WODM_PREPARE          7 // 请求WAVEFORM输出驱动为输出准备一个系统中唯一的数据缓冲。

#define WODM_UNPREPARE        8 // WODM_PREPARE的逆操作。

#define WODM_WRITE            9 //

#define WODM_PAUSE            10    //请求WAVEFORM输出驱动暂停WAVEFORM的播放。

#define WODM_RESTART          11    //请求WAVEFORM输出驱动继续播放被暂停的WAVEFORM。

#define WODM_RESET            12    //请求WAVEFORM输出驱动停止发送输出数据并且返回所有的输出缓冲到列表。

#define WODM_GETPOS           13    //请求返回当前数据流中相对于WAVEFORM起始的相对位置。

#define WODM_GETPITCH         14    //

#define WODM_SETPITCH         15

#define WODM_GETVOLUME        16    //请求WAVEFORM输出驱动返回指定设备的音量水平。

#define WODM_SETVOLUME        17    //请求WAVEFORM输出驱动设置指定设备的音量水平。

#define WODM_GETPLAYBACKRATE  18//请求WAVEFORM输出驱动返回特定设备当前的播放率放大值。

#define WODM_SETPLAYBACKRATE  19//请求WAVEFORM输出驱动设置特定设备当前的播放率放大值。

#define WODM_BREAKLOOP        20//请求WAVEFORM输出驱动停止由WODM_WRIT建立的输出循环。

#define WODM_BUSY             21

#define WODM_GETEXTDEVCAPS    22    // new in Windows CE 4.0

#define WODM_GETPROP          23    // new in Windows CE 5.0

#define WODM_SETPROP          24    // new in Windows CE 5.0

#define WODM_MAPPER_STATUS              (DRVM_MAPPER_STATUS + 0)

#define WAVEOUT_MAPPER_STATUS_DEVICE    0

#define WAVEOUT_MAPPER_STATUS_MAPPED    1

#define WAVEOUT_MAPPER_STATUS_FORMAT    2

// messages sent to widMessage() entry-point function

#define WIDM_GETNUMDEVS  50

#define WIDM_GETDEVCAPS  51

#define WIDM_OPEN        52

#define WIDM_CLOSE       53//请求WAVEFORM输入驱动关闭一个指定的设备实例,这个设备实例由先前的WIDM_OPEN创建并且打开。

#define WIDM_PREPARE     54

#define WIDM_UNPREPARE   55

#define WIDM_ADDBUFFER   56//请求WAVEFORM输入驱动在输入队列中添加一个BUFFER。

#define WIDM_START       57//请求WAVEFORM输入驱动开始录音

#define WIDM_STOP        58//请求WAVEFORM输入驱动停止录音

#define WIDM_RESET       59//请求WAVEFORM输入驱动停止录音并且将所有的缓冲数据返回给调用者。

#define WIDM_GETPOS      60//请求输入流接口输入,驱动返回当前输入位置,位置是相对于第一个采样的WAVEFORM样本。

#define WIDM_GETPROP     61         // new in Windows CE 5.0

#define WIDM_SETPROP     62         // new in Windows CE 5.0

#define WIDM_MAPPER_STATUS              (DRVM_MAPPER_STATUS + 0)

#define WAVEIN_MAPPER_STATUS_DEVICE     0

#define WAVEIN_MAPPER_STATUS_MAPPED     1

#define WAVEIN_MAPPER_STATUS_FORMAT     2

(3)dwParam1参数在执行具体功能是需要强制转换成不同的结构体。

例如:  在 WODM_OPEN:

            dwRet = pDeviceContext->OpenStream((LPWAVEOPENDESC)dwParam1, dwParam2, (StreamContext **)dwUser);

(4)dwParam1参数主要作为一些标志位。

../public/common/sdk/inc/mmsystem.h

/* flags for dwFlags parameter in waveOutOpen() and waveInOpen() */

#define  WAVE_FORMAT_QUERY     0x00000001

#define  WAVE_ALLOWSYNC        0x00000002

#define  WAVE_MAPPED           0x00000004

#define  WAVE_FORMAT_DIRECT    0x00000008

#define  WAVE_FORMAT_DIRECT_QUERY  (WAVE_FORMAT_QUERY | WAVE_FORMAT_DIRECT)

#define  WAVE_NOMIXER          0x00000080           /* Windows CE only - bypass software mixer */

2.typedef struct waveopendesc_tag {

    HWAVE          hWave;             // handle驱动句柄,WAVEAPI.DLL 分派。

    LPWAVEFORMATEX lpFormat;          // format of wave data见3

    DWORD          dwCallback;        // callback

    DWORD          dwInstance;        // app's private instance information

    UINT           uMappedDeviceID;   // device to map to if WAVE_MAPPED set

} WAVEOPENDESC;

typedef WAVEOPENDESC FAR *LPWAVEOPENDESC;

在../public/common/oak/inc/mmddk.h中定义。

3.音频格式结构WAVEFORMATEX,作为打开操作的参数要事先准备好

../public/common/sdk/inc/mmsystem.h

*  extended waveform format structure used for all non-PCM formats. this

*  structure is common to all non-PCM formats.

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 */每个样本的bit数

    WORD        cbSize;             /* the count in bytes of the size of */

                    /* extra information (after cbSize) */

} WAVEFORMATEX, *PWAVEFORMATEX, NEAR *NPWAVEFORMATEX, FAR *LPWAVEFORMATEX;

typedef const WAVEFORMATEX FAR *LPCWAVEFORMATEX;

 
个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
 
 

回复

854

帖子

0

TA的资源

五彩晶圆(中级)

4
 
  1. void OutputDeviceContext::StreamReadyToRender(StreamContext *pStreamContext)
  2. {
  3.     g_pHWContext->StartOutputDMA();
  4.     return;
  5. }

  6. void InputDeviceContext::StreamReadyToRender(StreamContext *pStreamContext)
  7. {
  8.     g_pHWContext->StartInputDMA();
  9.     return;
  10. }
复制代码
DWORD StreamContext::Run()
{
    m_bRunning=TRUE;
    if (m_lpCurrData)
    {
        m_pDeviceContext->StreamReadyToRender(this);
    }

    return MMSYSERR_NOERROR;
}

case WODM_RESTART:
    case WIDM_START:
        {
            RETAILMSG(1, (L"[WAV] WDM_START\r\n"));
            dwRet = pStreamContext->Run();
            break;
        }


这个C++ 的应用还是搞的很不错的。
 
个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
 
 

回复

854

帖子

0

TA的资源

五彩晶圆(中级)

5
 

  1. /*----------------------------------------------------------------------------
  2. *Function: StartInputDMA

  3. *Parameters: None

  4. *Return Value: None

  5. *Implementation Notes:
  6. -----------------------------------------------------------------------------*/
  7. VOID
  8. HardwareContext::StartInputDMA(VOID)
  9. {
  10.     Lock();
  11.    
  12.     if(!m_pCurrentInMode->GetRunningStatus() && (GetPowerState() != D4))
  13.     {
  14.         DBGMSG(0,(L"[WAV] +++HW_InStart\r\n"));

  15.         //FORCE PWR NOTIFY
  16.         //It's good in case following
  17.         //ULP : DON'T CARE
  18.         //OUT : DON'T CARE
  19.         //IN  : STOP
  20.         DevicePowerNotify(WAVE_POWER_NAME, D0, POWER_NAME);
  21.         
  22.         m_pCurrentInMode->StartTransfer();
  23.         CodecPowerControl(m_pCurrentOutMode->GetRunningStatus(), TRUE);
  24.         CodecMuteControl(DMA_CH_IN, FALSE);    // Unmute Input Channel        
  25.         
  26.         DBGMSG(0,(L"[WAV] ---HW_InStart\r\n"));
  27.     }

  28.     Unlock();
  29. }
复制代码

  1. /*----------------------------------------------------------------------------
  2. *Function: StartOutputDMA

  3. *Parameters: None

  4. *Return Value: None

  5. *Implementation Notes:
  6. -----------------------------------------------------------------------------*/
  7. VOID
  8. HardwareContext::StartOutputDMA(VOID)
  9. {   
  10.     Lock();
  11.    
  12.     if(!m_pCurrentOutMode->GetRunningStatus() && (GetPowerState() != D4))
  13.     {
  14.         DBGMSG(0,(L"[WAV] +++HW_OutStart\r\n"));

  15.         //DBGMSG(TRUE, (L"[WAV] EPLL_CLK : %d\r\n", GET_EPLLCLK(m_pSysConReg->PLL_CON.EPLL_CON0)));
  16.         //DBGMSG(TRUE, (L"[WAV] ASS_CLK_SRC : 0x%X\r\n", m_pASSClkReg->ASS_CLK_SRC));
  17.         //DBGMSG(TRUE, (L"[WAV] ASS_CLK_DIV : 0x%X\r\n", m_pASSClkReg->ASS_CLK_DIV));
  18.         //FORCE PWR NOTIFY
  19.         //It's good in case following
  20.         //ULP : DON'T CARE
  21.         //OUT : STOP
  22.         //IN  : DON'T CARE
  23.         DevicePowerNotify(WAVE_POWER_NAME, D0, POWER_NAME);
  24.         
  25.         m_pCurrentOutMode->StartTransfer();
  26.         CodecPowerControl(TRUE, m_pCurrentInMode->GetRunningStatus());  
  27.         CodecMuteControl(DMA_CH_OUT, FALSE);
  28.         
  29.         DBGMSG(0,(L"[WAV] ---HW_OutStart\r\n"));
  30.     }

  31.     Unlock();
  32. }
复制代码
 
个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
 
 

回复

854

帖子

0

TA的资源

五彩晶圆(中级)

6
 
  1. BOOL
  2. InNormalMode::StartTransfer()
  3. {
  4.     DBGMSG(WAVE_NMMODE, (L"[WAV] +++NIM_StartTransfer()\r\n"));

  5.     m_bDMARunning = TRUE;
  6.    
  7.     m_dwTransfered[DMA_BUFFER0] = 0;
  8.     m_dwTransfered[DMA_BUFFER1] = 0;
  9.     m_dwDMAStatus = DMA_CLEAR;

  10.     IIS_set_rx_mode_control(IIS_TRANSFER_NOPAUSE);
  11.     DMA_channel_start(&m_DMACtxt);
  12.     IIS_set_active_on();

  13.     DBGMSG(WAVE_NMMODE, (L"[WAV] ---NIM_StartTransfer()\r\n"));

  14.     return TRUE;
  15. }
复制代码

  1. BOOL
  2. OutNormalMode::StartTransfer()
  3. {
  4.     ULONG dwXferedCnt;

  5.     Lock();
  6. //    DBGMSG(1, (L"[WAV] +++NOM_StartTransfer(FIRST)\r\n"));

  7.     //2 1. Member variable initialization
  8.     m_bDMARunning = TRUE;
  9.     m_dwElapsedTime = 0;
  10.    
  11.     m_dwTransfered[DMA_BUFFER0] = 0;
  12.     m_dwTransfered[DMA_BUFFER1] = 0;
  13.     m_dwDMAStatus = (DMA_DONE0 | DMA_DONE1) & ~DMA_BIU;
  14.     dwXferedCnt = TransferBuffer();

  15.     if(dwXferedCnt)
  16.     {
  17.         //2 2. I2S Setting
  18.         //PRIMARY FIFO

  19.         //OP_MUX_SEL
  20.         
  21.         IIS_set_tx_mode_control(IIS_TRANSFER_NOPAUSE);
  22.         DMA_channel_start(&m_DMACtxt);
  23.     DBGMSG(1, (L"[WAV] I2S Setting..................\r\n"));
  24.         //DBGMSG(WAVE_NMMODE,(L"[WAV] IB%d\r\n", ((g_pIISReg->IISFIC>>8)&0x3F)));
  25.         IIS_set_active_on();
  26.     }
  27.     else
  28.     {
  29.         ERRMSG((L"WAV:ERR] NOM_StartTransfer() : There is no data to transfer\r\n"));
  30.                     DBGMSG(1, (L"WAV:ERR] NOM_StartTransfer() : There is no data to transfer\r\n"));
  31.         m_bDMARunning = FALSE;
  32.     }

  33. #ifdef DEBUG_MODE
  34.     gdwISTPeriodTick = GetTickCount();
  35. #endif

  36.     DBGMSG(1, (L"[WAV] ---NOM_StartTransfer()\r\n"));
  37.     Unlock();

  38.     return m_bDMARunning;
  39. }
复制代码
 
个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表