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

📄 wavepdd.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (C) NEC Electronics Inc. 1997-1999.
 *
 * File:    Wavepdd.c
 *
 * VRC4173 WaveDev PDD
 */
#include <windows.h>
#include <types.h>
#include <memory.h>
#include <excpt.h>
#include <wavepdd.h>
#include <waveddsi.h>
//#include <nkintr.h>
//#include <oalintr.h>
#include <wavedbg.h>
#include <drvlib.h>
#include <vrc4173.h>
//#include "eagle.h"

static int  SampleRate[2];
static void (*GetBuf)(PWAVEHDR pwh, ULONG page, ULONG nSamples);
static void (*FillBuf)(PWAVEHDR pwh, ULONG page, ULONG nSamples);

static ULONG    physDMAbase[2];
static PBYTE    dma_page[2][2];

static BOOL AIUactive[2];

static ULONG    v_nVolume;  // used for GETVOLUME and SETVOLUME
static LONG Volume;     // real volume

static BOOL v_fMoreData[2];
static ULONG    v_nNextPage[2];

static BOOL InPowerHandler = FALSE;
static BOOL initialized = FALSE;

#define SAMPLERATE_MAXDIFF  1000    // Maximum allow sampling rate difference for output

#define AUDIO_SILENCE_REC   0x0800
#define AUDIO_SILENCE_PLAY  0x0200
#define AUDIO_DMA_PAGE_SIZE 1024

//
// function prototypes
static void AIU_ClockEnable(WAPI_INOUT apidir);
static void AIU_ClockDisable(WAPI_INOUT apidir);
static MMRESULT Aud_GetDevCaps(WAPI_INOUT apidir, PWAVEOUTCAPS pCaps, UINT wSize);
static MMRESULT Aud_Open(WAPI_INOUT apidir, LPWAVEFORMATEX lpFormat, BOOL fQueryFormatOnly);
static MMRESULT Aud_Close(WAPI_INOUT apidir);
static void AudIn_GetBufferM8(PWAVEHDR pwh, ULONG page, ULONG nSamples);
static void AudIn_GetBufferS8(PWAVEHDR pwh, ULONG page, ULONG nSamples);
static void AudIn_GetBufferM16(PWAVEHDR pwh, ULONG page, ULONG nSamples);
static void AudIn_GetBufferS16(PWAVEHDR pwh, ULONG page, ULONG nSamples);
static void AudIn_Start(PWAVEHDR pwh);
static void AudIn_Continue(PWAVEHDR pwh);
static void AudIn_Stop(PWAVEHDR pwh);
static void AudIn_Standby(void);
static void AudOut_FillBufferM8(PWAVEHDR pwh, ULONG page, ULONG nSamples);
static void AudOut_FillBufferS8(PWAVEHDR pwh, ULONG page, ULONG nSamples);
static void AudOut_FillBufferM16(PWAVEHDR pwh, ULONG page, ULONG nSamples);
static void AudOut_FillBufferS16(PWAVEHDR pwh, ULONG page, ULONG nSamples);
static void AudOut_Start(PWAVEHDR pwh);
static void AudOut_Continue(PWAVEHDR pwh);
static void AudOut_EndOfData(void);
static void AudOut_Stop(void);
static void AudOut_Standby(void);
AUDIO_STATE PDD_AudioGetInterruptType(VOID);
DWORD       PDD_AudioMessage(UINT uMsg, DWORD dwParam1, DWORD dwParam2);
BOOL        PDD_AudioInitialize(DWORD dwIndex);
VOID        PDD_AudioDeinitialize(VOID);
VOID        PDD_AudioPowerHandler(BOOL power_down);
MMRESULT    PDD_WaveProc(WAPI_INOUT apidir, DWORD dwCode, DWORD dwParam1, DWORD dwParam2);

extern DWORD gIntrAudio; //= SYSINTR_AUDIO;

//
// AIU common routines

static void
AIU_ClockEnable(WAPI_INOUT apidir)
{
    AIUactive[apidir] = TRUE;
    InterlockedAndOr16((volatile UINT16 *)(pVRC4173+CMU73CLKMSK), 0xFFFF, MSKAIU);
}

static void
AIU_ClockDisable(WAPI_INOUT apidir)
{
    AIUactive[apidir] = FALSE;
    if (!(AIUactive[WAPI_IN] || AIUactive[WAPI_OUT])) {
        InterlockedAndOr16((volatile UINT16 *)(pVRC4173+CMU73CLKMSK), ~MSKAIU, 0);
    }
}

//
// DDSI in/out common subroutines

static MMRESULT
Aud_GetDevCaps(WAPI_INOUT apidir, PWAVEOUTCAPS pCaps, UINT wSize)
{
    if (pCaps) {
        //
        // Fill in the DevCaps here.
        //    
        pCaps->wMid = MM_MICROSOFT;
        if (apidir == WAPI_IN) {
            pCaps->wPid = 23;   // MM_MSFT_GENERIC_WAVEIN
        } else {
            pCaps->wPid = 24;   // MM_MSFT_GENERIC_WAVEOUT
            pCaps->dwSupport = WAVECAPS_VOLUME;
        }
        pCaps->vDriverVersion = 0x0001;
        wsprintf (pCaps->szPname, TEXT("VRC4173 Audio (%hs)"), __DATE__);
        pCaps->dwFormats =  WAVE_FORMAT_1M08 | WAVE_FORMAT_1M16 |
                    WAVE_FORMAT_1S08 | WAVE_FORMAT_1S16 |
                    WAVE_FORMAT_2M08 | WAVE_FORMAT_2M16 |
                    WAVE_FORMAT_2S08 | WAVE_FORMAT_2S16 |
                    WAVE_FORMAT_4M08 | WAVE_FORMAT_4M16 |
                    WAVE_FORMAT_4S08 | WAVE_FORMAT_4S16;
        pCaps->wChannels = 2;
    }

    return MMSYSERR_NOERROR;
}

static MMRESULT
Aud_Open(WAPI_INOUT apidir, LPWAVEFORMATEX lpFormat, BOOL fQueryFormatOnly)
{
    int s, maxdiff;

    //
    // Allow PCM, mono or stereo, 8 or 16 bit at 11k, 22k or 44kHz
    //
    if ((lpFormat->wFormatTag     != WAVE_FORMAT_PCM) ||
        (lpFormat->nChannels      != 1 &&
         lpFormat->nChannels      != 2) ||
        (lpFormat->wBitsPerSample != 8 &&
         lpFormat->wBitsPerSample != 16)) {
        return WAVERR_BADFORMAT;
    }

    s = lpFormat->nSamplesPerSec;

    // allow inaccure sampling rate on wave output
    maxdiff = (apidir == WAPI_OUT) ? SAMPLERATE_MAXDIFF : 0;

    if (s>=(8000-maxdiff) && s<=(8000+maxdiff)) {
        s = 8000;
    } else if (s>=(11025-maxdiff) && s<=(11025+maxdiff)) {
        s = 11025;
    } else if (s>=(22050-maxdiff) && s<=(22050+maxdiff)) {
        s = 22050;
    } else if (s>=(44100-maxdiff) && s<=(44100+maxdiff)) {
        s = 44100;
    } else {
        return WAVERR_BADFORMAT;
    }

    if (fQueryFormatOnly) {
        return MMSYSERR_NOERROR;
    }

    // real open request

    // BUGBUG: block open only on recording. not block on playing.
    if (apidir == WAPI_IN && AIUactive[apidir]) {
        return MMSYSERR_ALLOCATED;
    }

    SampleRate[apidir] = s;

    if (apidir == WAPI_IN) {
        if (lpFormat->wBitsPerSample == 8) {
            if (lpFormat->nChannels == 1) {
                GetBuf = AudIn_GetBufferM8;
            } else {
                GetBuf = AudIn_GetBufferS8;
            }
        } else {
            if (lpFormat->nChannels == 1) {
                GetBuf = AudIn_GetBufferM16;
            } else {
                GetBuf = AudIn_GetBufferS16;
            }
        }
    } else {
        if (lpFormat->wBitsPerSample == 8) {
            if (lpFormat->nChannels == 1) {
                FillBuf = AudOut_FillBufferM8;
            } else {
                FillBuf = AudOut_FillBufferS8;
            }
        } else {
            if (lpFormat->nChannels == 1) {
                FillBuf = AudOut_FillBufferM16;
            } else {
                FillBuf = AudOut_FillBufferS16;
            }
        }
    }

    return MMSYSERR_NOERROR;
}    

static MMRESULT
Aud_Close(WAPI_INOUT apidir)
{
    // do nothing...
    return MMSYSERR_NOERROR;
}

//
// Wave input private routines

static void
AudIn_GetBufferM8(PWAVEHDR pwh, ULONG page, ULONG nSamples)
{
    ULONG           a;
    SAMPLE_8_MONO       *pm8;
    volatile UINT16     *pbuf;

    if (pwh == NULL) {
        return;
    }

    pbuf = (volatile UINT16 *)dma_page[WAPI_IN][page];
    pm8 = (SAMPLE_8_MONO *)(pwh->lpData + pwh->dwBytesRecorded);

    for (a=0; a<nSamples; a++) {
        if (pwh->dwBytesRecorded >= pwh->dwBufferLength) {
            pwh = pwh->lpNext;
            if (pwh == NULL)
                break;
            pm8 = (SAMPLE_8_MONO *)(pwh->lpData + pwh->dwBytesRecorded);
        }

        pm8->sample = (BYTE)(pbuf[a] >> 4);
        pm8++;
        pwh->dwBytesRecorded++;
    }
}

static void
AudIn_GetBufferS8(PWAVEHDR pwh, ULONG page, ULONG nSamples)
{
    ULONG           a;
    LONG            sample;
    SAMPLE_8_STEREO     *ps8;
    volatile UINT16     *pbuf;

    if (pwh == NULL) {
        return;
    }

    pbuf = (volatile UINT16 *)dma_page[WAPI_IN][page];
    ps8 = (SAMPLE_8_STEREO *)(pwh->lpData + pwh->dwBytesRecorded);

    for (a=0; a<nSamples; a++) {
        if (pwh->dwBytesRecorded >= pwh->dwBufferLength) {
            pwh = pwh->lpNext;
            if (pwh == NULL)
                break;
            ps8 = (SAMPLE_8_STEREO *)(pwh->lpData + pwh->dwBytesRecorded);
        }

        sample = pbuf[a] >> 4;
        ps8->sample_left = (BYTE)sample;
        ps8->sample_right = (BYTE)sample;
        ps8++;
        pwh->dwBytesRecorded += 2;
    }
}

static void
AudIn_GetBufferM16(PWAVEHDR pwh, ULONG page, ULONG nSamples)
{
    ULONG           a;
    SAMPLE_16_MONO      *pm16;
    volatile UINT16     *pbuf;

    if (pwh == NULL) {
        return;
    }

    pbuf = (volatile UINT16 *)dma_page[WAPI_IN][page];
    pm16 = (SAMPLE_16_MONO *)(pwh->lpData + pwh->dwBytesRecorded);

    for (a=0; a<nSamples; a++) {
        if (pwh->dwBytesRecorded >= pwh->dwBufferLength) {
            pwh = pwh->lpNext;
            if (pwh == NULL)
                break;
            pm16 = (SAMPLE_16_MONO *)(pwh->lpData + pwh->dwBytesRecorded);
        }

        pm16->sample = (INT16)((pbuf[a] << 4) - 32768);
        pm16++;
        pwh->dwBytesRecorded += 2;
    }
}

static void
AudIn_GetBufferS16(PWAVEHDR pwh, ULONG page, ULONG nSamples)
{
    ULONG           a;
    LONG            sample;
    SAMPLE_16_STEREO    *ps16;
    volatile UINT16     *pbuf;

    if (pwh == NULL) {
        return;
    }

    pbuf = (volatile UINT16 *)dma_page[WAPI_IN][page];
    ps16 = (SAMPLE_16_STEREO *)(pwh->lpData + pwh->dwBytesRecorded);

    for (a=0; a<nSamples; a++) {
        if (pwh->dwBytesRecorded >= pwh->dwBufferLength) {
            pwh = pwh->lpNext;
            if (pwh == NULL)
                break;
            ps16 = (SAMPLE_16_STEREO *)(pwh->lpData + pwh->dwBytesRecorded);
        }

        sample = (pbuf[a] << 4) - 32768;
        ps16->sample_left = (INT16)sample;
        ps16->sample_right = (INT16)sample;
        ps16++;
        pwh->dwBytesRecorded += 4;
    }
}

static void
AudIn_Start(PWAVEHDR pwh)
{
    v_fMoreData[WAPI_IN] = TRUE;        // we expect to have more data coming...
    v_nNextPage[WAPI_IN] = 0;

    // setup input DMA address
    REG32(pVRC4173+AIUIBALREG) = physDMAbase[WAPI_IN];
    REG32(pVRC4173+AIUIALREG) = physDMAbase[WAPI_IN];
    // enable input DMA
    InterlockedAndOr16((volatile UINT16 *)(pVRC4173+DMA73MSKREG), 0xFFFF, DMAMSKAIN);

    // enable AIU Tclock
    AIU_ClockEnable(WAPI_IN);

    // set input sampling rate
    switch (SampleRate[WAPI_IN]) {
    case 8000:
        REG16(pVRC4173+AIUMCNVRREG) = CNVR_8K;
        break;
    case 11025:
        REG16(pVRC4173+AIUMCNVRREG) = CNVR_11K;
        break;
    case 22050:
        REG16(pVRC4173+AIUMCNVRREG) = CNVR_22K;
        break;
    case 44100:
        REG16(pVRC4173+AIUMCNVRREG) = CNVR_44K;
        break;
    default:
        RETAILMSG(1, (TEXT("AudIn_Start: bad sampling rate\r\n")));
    }

    // A/D Vref power on
    REG16(pVRC4173+AIUMCNTREG) = ADENAIU;   // MSTOPEN=0, ADENAIU=1
    RtcWait(1);             // wait for Vref stable

    // clear input interrupts
    REG16(pVRC4173+AIUINTREG) = AIUINTMIDLE | AIUINTM | AIUINTMEND;

    // activate AIU input
    InterlockedAndOr16((volatile UINT16 *)(pVRC4173+AIUSEQREG), 0xFFFF, AIUMEN);
}

// prepare next input DMA buffer
static void
AudIn_Continue(PWAVEHDR pwh)
{
    // get data from DMA buffer
    (*GetBuf)(pwh, v_nNextPage[WAPI_IN], AUDIO_DMA_PAGE_SIZE/2);

    // flip page
    v_nNextPage[WAPI_IN] ^= 1;
}

// stop input immediately
static void
AudIn_Stop(PWAVEHDR pwh)
{
    ULONG nSamples;

    // Stop recording
    v_fMoreData[WAPI_IN] = FALSE;
    AudIn_Standby();

    // Get partial samples in DMA buffer
    nSamples = (REG32(pVRC4173+AIUIALREG) & (AUDIO_DMA_PAGE_SIZE-1)) / 2;
    (*GetBuf)(pwh, v_nNextPage[WAPI_IN], nSamples);
}

// power down AIU input
static void
AudIn_Standby(void)
{
    // disable AIU input
    InterlockedAndOr16((volatile UINT16 *)(pVRC4173+AIUSEQREG), ~AIUMEN, 0);

    // clear input interrupts
    REG16(pVRC4173+AIUINTREG) = AIUINTMIDLE | AIUINTM | AIUINTMEND;

    // A/D Vref power off
    REG16(pVRC4173+AIUMCNTREG) = 0; // MSTOPEN=0, ADENAIU=0

    // disable input DMA
    InterlockedAndOr16((volatile UINT16 *)(pVRC4173+DMA73MSKREG), ~DMAMSKAIN, 0);

    AIU_ClockDisable(WAPI_IN);
}


//
// Wave output private routines

static void
AudOut_FillBufferM8(PWAVEHDR pwh, ULONG page, ULONG nSamples)
{
    ULONG           a;
    LONG            sample;
    SAMPLE_8_MONO       *pm8;
    volatile UINT16     *pbuf;

    if (pwh == NULL) {
        return;
    }

    pbuf = (volatile UINT16 *)dma_page[WAPI_OUT][page];
    pm8 = (SAMPLE_8_MONO *)(pwh->lpData + pwh->dwBytesRecorded);

    for (a=0; a<nSamples; a++) {
        if (pwh->dwBytesRecorded >= pwh->dwBufferLength) {
            pwh = pwh->lpNext;
            if (pwh == NULL)
                break;
            pm8 = (SAMPLE_8_MONO *)(pwh->lpData + pwh->dwBytesRecorded);
        }

        sample = ((((LONG)pm8->sample) - 128) * Volume) >> 14;
        pbuf[a] = (UINT16)(sample + AUDIO_SILENCE_PLAY);
        pm8++;
        pwh->dwBytesRecorded++;
    }

    // fill rest space
    while (a < nSamples) {
        pbuf[a++] = AUDIO_SILENCE_PLAY;
    }
}

static void
AudOut_FillBufferS8(PWAVEHDR pwh, ULONG page, ULONG nSamples)
{
    ULONG           a;
    LONG            sample;
    SAMPLE_8_STEREO     *ps8;
    volatile UINT16     *pbuf;

    if (pwh == NULL) {
        return;
    }

    pbuf = (volatile UINT16 *)dma_page[WAPI_OUT][page];
    ps8 = (SAMPLE_8_STEREO *)(pwh->lpData + pwh->dwBytesRecorded);

    for (a=0; a<nSamples; a++) {
        if (pwh->dwBytesRecorded >= pwh->dwBufferLength) {
            pwh = pwh->lpNext;
            if (pwh == NULL)
                break;
            ps8 = (SAMPLE_8_STEREO *)(pwh->lpData + pwh->dwBytesRecorded);
        }

        sample = ((LONG)ps8->sample_left) + ((LONG)ps8->sample_right) - 256;
        sample = (sample*Volume) >> 15;
        pbuf[a] = (UINT16)(sample + AUDIO_SILENCE_PLAY);
        ps8++;
        pwh->dwBytesRecorded += 2;
    }

    // fill rest space
    while (a < nSamples) {
        pbuf[a++] = AUDIO_SILENCE_PLAY;
    }
}

static void
AudOut_FillBufferM16(PWAVEHDR pwh, ULONG page, ULONG nSamples)
{
    ULONG           a;
    LONG            sample;
    SAMPLE_16_MONO      *pm16;
    volatile UINT16     *pbuf;

    if (pwh == NULL) {
        return;
    }

    pbuf = (volatile UINT16 *)dma_page[WAPI_OUT][page];
    pm16 = (SAMPLE_16_MONO *)(pwh->lpData + pwh->dwBytesRecorded);

    for (a=0; a<nSamples; a++) {
        if (pwh->dwBytesRecorded >= pwh->dwBufferLength) {

⌨️ 快捷键说明

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