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

📄 wavein.cpp

📁 CIRRUS 93XX系列windows mobile 6.0 BSP
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//**********************************************************************
//                                                                      
// Filename: wavein.cpp
//                                                                      
// Description:  Implements the WIDM_XXX messages that are passed to the
//               wave audio driver via the <f WAV_IOControl> function. 
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Use of this source code is subject to the terms of the Cirrus end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to 
// use this source code. For a copy of the EULA, please see the 
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2005, All Rights Reserved                       
//                                                                      
//**********************************************************************
#include "wavecommon.h"


//
// Sample conversion functions.
//

void ConvertWordsToBytes
(
    PVOID   pUnused,
    PULONG  pulSrc, 
    PUCHAR  pucDst, 
    PULONG  pulSrcSamples,
    PULONG  pulDstSamples
);
void ConvertWordsToShorts
(
    PVOID       pUnused,
    PULONG      pulSrc, 
    PUSHORT     pusDst, 
    PULONG      pulSrcSamples,
    PULONG      pulDstSamples
);
void ConvertWordsToBytesStereoToMono
(
    PVOID       pUnused,
    PULONG      pulSrc, 
    PUCHAR      pucDst, 
    PULONG      pulSrcSamples,
    PULONG      pulDstSamples
);
void ConvertWordsToShortsStereoToMono
(
    PVOID       pUnused,
    PULONG      pulSrc, 
    PUSHORT     pusDst, 
    PULONG      pulSrcSamples,
    PULONG      pulDstSamples
);
void ConvertShortsToShorts
(
    PVOID   pUnused,
    PUSHORT pusSrc, 
    PUCHAR  pucDst, 
    PULONG  pulSrcSamples,
    PULONG  pulDstSamples
);
void ConvertShortsToBytesStereoToMono
(
    PVOID       pUnused,
    PUSHORT     pusSrc, 
    PUCHAR      pucDst, 
    PULONG      pulSrcSamples,
    PULONG      pulDstSamples
);
void ConvertShortsStereoToMono
(
    PVOID       pUnused,
    PUSHORT     pusSrc, 
    PUSHORT     pusDst, 
    PULONG      pulSrcSamples,
    PULONG      pulDstSamples
);
void ConvertShortsToBytes
(
    PVOID       pUnused,
    PUSHORT     pusSrc, 
    PUCHAR      pucDst, 
    PULONG      pulSrcSamples,
    PULONG      pulDstSamples
);

#define MAX_RATE_CONVERTER_TAPS     13
#define MAX_POLY_PHASES             23
#define MAX_FILTER_SIZE (MAX_RATE_CONVERTER_TAPS * MAX_POLY_PHASES)

//****************************************************************************
// WaveIn::WaveIn
//****************************************************************************
// 
// 
//
WaveIn::WaveIn(): m_pCodec(0),
                  m_pWaveHead(0),
                  m_pWaveNext(0),
                  m_pfnCallback(0),
                  m_hCallback(0),
                  m_dwInstance(0),
                  m_dwRecordedBytes(0),
                  m_bIsRecording(FALSE),
                  m_dwSourceFactor(0),
                  m_dwDestFactor(0),
                  m_pfnWaveCopyFunc(0),
                  m_bUseSrc(FALSE),
                  m_pRateConverterBuffer(0),
                  m_pBuffer(0),
                  m_pDmaBuffer(0),
                  m_ulDmaBufferSize(0)


{
    FUNC_WAVEIN((L"+WaveIn::WaveIn"));

    memset(&m_WaveFormat,sizeof(WAVEFORMATEX), 0);
    memset(&m_Src, sizeof(tSRC),0);

    //
    // Initialize the Critical Section.
    //
    InitializeCriticalSection(&m_CriticalSection);

    FUNC_WAVEIN((L"-WaveIn::WaveIn"));
}

//****************************************************************************
// WaveIn::~WaveIn
//****************************************************************************
// 
// 
//
WaveIn::~WaveIn()
{
    FUNC_WAVEIN((L"+WaveIn::~WaveIn"));

    //
    // Delete the Critical Section.
    //
    DeleteCriticalSection(&m_CriticalSection);

    if(m_pRateConverterBuffer)
    {
        delete m_pRateConverterBuffer;
        m_pRateConverterBuffer = 0;
    }

    FUNC_WAVEIN((L"-WaveIn::~WaveIn"));
}

//****************************************************************************
// WaveIn::Initialize
//****************************************************************************
// 
// 
//
MMRESULT WaveIn::Initialize(CodecInterface * ci, BOOL bPIO)
{
    FUNC_WAVEIN((L"+WaveIn::~Initialize"));
    BOOL            bAC97;
    MMRESULT        mmRet = MMSYSERR_NOERROR;
    

    //
    // Get the information to the codec.
    //
    m_pCodec = ci;

    m_ulDmaBufferSize = DMA_BUFFER_SIZE * (m_pCodec->DmaSampleSize() / 8);
    m_bPIO  = bPIO;


    //
    // Initialize the DMA class
    //
    if(bPIO)
    {
        //
        // For now assume that if it has an SRC then it is an AC97 codec.
        //
        bAC97 = m_pCodec->HasSRC();

        mmRet = m_SwDma.Initialize
        (
			NULL,
            m_ulDmaBufferSize,
            bAC97,
            FALSE
        );

        m_pDma = &m_SwDma;
    }
    else
    {
        mmRet = m_HwDma.Initialize
        (
			NULL,
            DMA_M2P1_RX_BASE,
            m_pCodec->GetDmaPort(), 
            m_ulDmaBufferSize,
			FALSE
        );

        m_pDma = &m_HwDma;
    }

    if(mmRet == MMSYSERR_NOERROR)
    {
        m_pDmaBuffer = m_pDma->GetVirtBuffAddress();
        mmRet =m_pDmaBuffer?MMSYSERR_NOERROR: MMSYSERR_NOMEM;
    }

    //
    // If the codec has a sample rate converter there is no need to copy
    // extra bytes.
    //
    if(!m_pCodec->HasSRC())
    {
        //
        // Allocate a buffer that is cached for fast Sample rate conversion.
        //
        m_pRateConverterBuffer = 
                 new UCHAR[m_ulDmaBufferSize + ((MAX_FILTER_SIZE) * sizeof(ULONG) * 2)];
        if(!m_pRateConverterBuffer)
        {
            mmRet = m_pRateConverterBuffer ? MMSYSERR_NOERROR : MMSYSERR_NOMEM;
        }
    }
    else
    {
        m_pBuffer = m_pDmaBuffer;
    }


    //
    // Set the callback function to the interrupt handler.
    //
    m_pDma->SetCallBack(WaveIn::InterruptHandler, (HANDLE )this);


    FUNC_WAVEIN((L"-WaveIn::~Initialize"));
    return(mmRet);
}

//****************************************************************************
// WaveIn::AddBuffer
//****************************************************************************
// 
// 
//
MMRESULT WaveIn::AddBuffer    
(
    PWAVEHDR    pWaveHdr,
    DWORD       dwSize
)
{
    FUNC_WAVEIN((L"+WaveIn::AddBuffer"));
    PWAVEHDR        pTempHdr;

    EnterCriticalSection( &m_CriticalSection);

    //
    // Mark the Wave header nas not done and as in the queue.
    //
    pWaveHdr->dwFlags &= ~WHDR_DONE;
    pWaveHdr->dwFlags |= WHDR_INQUEUE;
    pWaveHdr->lpNext = (LPWAVEHDR)NULL;
    pWaveHdr->dwBytesRecorded = 0;

    //
    // If there are currently no wave headers on the list, then start the list
    // with this wave header.
    //
    if(!m_pWaveHead)
    {
        ASSERT(!m_pWaveNext);
        //
        // Place the wave header at the start of the list (and therefore also
        // at the end)
        //
        m_pWaveHead = pWaveHdr;
    }
    else
    {
        //
        // Find the end of the list.
        //
        for(pTempHdr = m_pWaveHead; pTempHdr->lpNext;
            pTempHdr = pTempHdr->lpNext)
        {
        }

        //
        // Add this wave header to the end of the list
        //
        pTempHdr->lpNext = pWaveHdr;
    }

    //
    // If the next list is empty then put the next item on the list in the buffer.
    //
    if(!m_pWaveNext)
    {
        m_pWaveNext = pWaveHdr;
    }

    LeaveCriticalSection( &m_CriticalSection);

    FUNC_WAVEIN((L"-WaveIn::AddBuffer"));
    return(MMSYSERR_NOERROR);
}

//****************************************************************************
// WaveIn::Close
//****************************************************************************
// 
// 
//
MMRESULT WaveIn::Close()
{
    FUNC_WAVEIN((L"+WaveIn::Close"));


    //
    // If there are unfilled wave headers then the wave device can not be
    // closed.
    //
    if(m_pWaveHead)
    {
        return(WAVERR_STILLPLAYING);
    }

    m_pCodec->m_bRecordOpened= FALSE;

    Reset();

    //
    // Make the callback function call to the Wave API Manager
    //
    WIDM_MSG((L"WaveIn: WIM_OPEN\r\n"));
    m_pfnCallback(m_hCallback, MM_WIM_CLOSE, m_dwInstance, 0, 0);

    FUNC_WAVEIN((L"-WaveIn::Close"));
    return(MMSYSERR_NOERROR);
}

//****************************************************************************
// WaveIn::GetDevCaps
//****************************************************************************
// 
// 
//
MMRESULT WaveIn::GetDevCaps
(
    PWAVEINCAPS pCaps,
    DWORD       dwSize
)
{
    FUNC_WAVEIN((L"+WaveIn::GetDevCaps"));
    MMRESULT        mmRet = MMSYSERR_NOERROR;

    if (pCaps == NULL  || dwSize < sizeof(WAVEINCAPS))
    {
       //
       // If pCaps == NULL, we are requesting if the driver PDD
       // is capable of this mode at all.  In other words, if
       // APIDIR == WAPI_IN, we return no error if input is
       // supported, and MMSYSERR_NOTSUPPORTED otherwise.  Since
       // Odo has both, we return MMSYSERR_NOERROR regardless.
       //
        mmRet = MMSYSERR_NOTSUPPORTED;
    }
    
    if(MMSUCCESS(mmRet))
    {
    
        //
        // Fill in the DevCaps here.
        //
        pCaps->wMid = MM_CRYSTAL;               // (MMREG.H)  Replace MM_MICROSOFT.
        pCaps->wPid = MM_CRYSTAL_EP9312_WAVEIN;
        pCaps->vDriverVersion = 0x0001;
        wsprintf (pCaps->szPname, TEXT("EP9312 Audio (%hs)"), __DATE__);
        pCaps->dwFormats =   WAVE_FORMAT_1M08 | WAVE_FORMAT_1M16 |   // 11km8/16
                             WAVE_FORMAT_1S08 | WAVE_FORMAT_1S16 |   // 11ks8/16
                             WAVE_FORMAT_2M08 | WAVE_FORMAT_2M16 |   // 22km8/16
                             WAVE_FORMAT_2S08 | WAVE_FORMAT_2S16 |   // 22ks8/16
                             WAVE_FORMAT_4M08 | WAVE_FORMAT_4M16 |   // 44km8/16
                             WAVE_FORMAT_4S08 | WAVE_FORMAT_4S16;    // 44ks8/16

        pCaps->wChannels = 2;
    }                           

    FUNC_WAVEIN((L"-WaveIn::GetDevCaps"));
    return(mmRet);
}

//****************************************************************************
// WaveIn::GetPosition
//****************************************************************************
// 
// 
//
MMRESULT WaveIn::GetPosition
(
    MMTIME  *pTime,
    DWORD   dwSize
)
{
    FUNC_WAVEIN((L"+WaveIn::GetPosition"));
    MMRESULT        mmRet;
    DWORD           dwBytePosition;

    if (IsBadWritePtr((PVOID)pTime, sizeof(MMTIME))) 
    {
        PRINTMSG
        (
            ZONE_WARN, 
            (
                TEXT("WARNING : WaveOut::GetPosition was passed a bad pointer (0x%X)\r\n"),
                pTime
            )
        );
        mmRet = MMSYSERR_INVALPARAM;
    } 
    else 
    {        
        //
        // This is not sample accurate but I don't think windows CE cares.
        //
        //dwBytePosition  = m_dwBytePosition;
        dwBytePosition  = m_dwRecordedBytes;

        switch (pTime->wType) 
        {
            case TIME_BYTES:
                pTime->u.cb = dwBytePosition;
                break;

            case TIME_SAMPLES:
                pTime->u.sample = (dwBytePosition * 8) / 
                    (m_WaveFormat.nChannels * m_WaveFormat.wBitsPerSample);
                break;

            case TIME_MS:
                if (m_WaveFormat.nAvgBytesPerSec != 0)
                    pTime->u.ms = (dwBytePosition * 1000) / m_WaveFormat.nAvgBytesPerSec;
                else  
                {
                    pTime->wType = TIME_BYTES;
                    pTime->u.cb = dwBytePosition;
                }
                break;

            case TIME_MIDI:
            case TIME_TICKS:
            case TIME_SMPTE:
                //
                // We don't support these, so return TIME_BYTES instead.
                //
                pTime->wType = TIME_BYTES;
                pTime->u.cb = dwBytePosition;
                break;
        }
        mmRet = MMSYSERR_NOERROR;
    }

    FUNC_WAVEIN((L"-WaveIn::GetPosition"));
    return(MMSYSERR_NOERROR);
}

//****************************************************************************
// WaveIn::Open

⌨️ 快捷键说明

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