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

📄 waveout.c

📁 基于wince 操作系统的开发的i2s驱动程序
💻 C
字号:
/*++
Copyright (c) 1999-2004  BSQUARE Corporation.  All rights reserved.

Module Name:

    waveout.c

Module Description:

    This module contains the implementation of the audio output driver.

Author:

Revision History:

--*/

#include <windows.h>
#include <bceddk.h>
#include "psc_i2s.h"

#include <wavedbg.h>

extern PWAVE_DEVICE_INSTANCE WaveDevice;
extern PWAVE_RESOURCE WaveOutResource;

//
// Private Routines.
//

static int
FillOutputBuffer (
	IN OUT PWAVE_RESOURCE WaveResource
	)
{
    PWAVEHDR Header = WaveResource->WaveHeader;
	PUCHAR pDMABuffer;
	ULONG bytesCopied;

	// Check Wave header is valid
	if ((Header==NULL) || (Header->dwBufferLength==0)) {
		return 0;
	}

	pDMABuffer = HalGetNextDMABuffer(WaveDevice->DMAChannelOutput);

	// copy as much data as possible
	bytesCopied = min(WaveResource->DmaBufferSize, (Header->dwBufferLength-Header->dwBytesRecorded));

	// copy the data
	memcpy(pDMABuffer, Header->lpData+Header->dwBytesRecorded, bytesCopied);
	
	// Update bytes recorded 
	Header->dwBytesRecorded += bytesCopied;

	// Send DMA buffer
	HalActivateDMABuffer(WaveDevice->DMAChannelOutput, pDMABuffer, bytesCopied);

    return bytesCopied;
}

static int
FillTwoOutputBuffers (
	IN OUT PWAVE_RESOURCE WaveResource
	)
{
    PWAVEHDR Header = WaveResource->WaveHeader;
	PUCHAR pDMABuffer;
	ULONG bytesCopied;

	// Check Wave header is valid
    if ((Header == NULL) || (Header->dwBufferLength==0)) {
		return 0;
	}

	// work out how much data we can copy
	bytesCopied = min(WaveResource->DmaBufferSize,
	                  (Header->dwBufferLength-Header->dwBytesRecorded)/2);

	// Do the first buffer
	pDMABuffer = HalGetNextDMABuffer(WaveDevice->DMAChannelOutput);
	memcpy(pDMABuffer, Header->lpData+Header->dwBytesRecorded, bytesCopied);
	Header->dwBytesRecorded += bytesCopied;
	// Send DMA buffer
	HalActivateDMABuffer(WaveDevice->DMAChannelOutput, pDMABuffer, bytesCopied);

	// Now do the second buffer
	pDMABuffer = HalGetNextDMABuffer(WaveDevice->DMAChannelOutput);
	memcpy(pDMABuffer, Header->lpData+Header->dwBytesRecorded, bytesCopied);
	Header->dwBytesRecorded += bytesCopied;
	// Send DMA buffer
	HalActivateDMABuffer(WaveDevice->DMAChannelOutput, pDMABuffer, bytesCopied);

    return bytesCopied*2;
}


//
// Exported Routines.
//

MMRESULT
GetOutputVolume(
    IN PWAVE_DEVICE_INSTANCE WaveInstance,
    OUT PULONG VolumeSetting
    )

/*++

Routine Description:

    

Arguments:

    VolumeSetting - Pointer to the volume variable.

Return Value:

    Returns MMSYSERR_NOERROR if successful, MMSYSERR_NOMEM if
    unsuccessful.  Note that this is probably not a good error
    code to return, but it's the best of the bunch to choose from.

--*/

{
   ULONG Volume = 0;

   Volume = CodecGetVolume(WaveInstance->hSMBus);
   *VolumeSetting = Volume;

   return MMSYSERR_NOERROR;
}


MMRESULT
SetOutputVolume(
    IN PWAVE_DEVICE_INSTANCE WaveInstance,
    IN ULONG VolumeSetting
    )

/*++

Routine Description:

    Takes the input volume setting and sets the attenuation
    accordingly.  The input volume has a scale from 0 to 0xFFFF,
    where 0 is for silence and 0xFFFF for the highest volume
    setting.  Note that the high order 16-bits are masked
    because for stereo sound, it is the right channel volume.

Arguments:

    VolumeSetting - Requested volume variable.

Return Value:

    Returns MMSYSERR_NOERROR if successful, MMSYSERR_NOMEM if
    unsuccessful.  Note that this is probably not a good error
    code to return, but it's the best of the bunch to choose from.

--*/

{
    MMRESULT ReturnValue;
    BOOLEAN Success;
    DEBUGMSG(1|ZONE_WODM, (TEXT("+SetOutputVolume(%x)\r\n"),VolumeSetting));

    ReturnValue = MMSYSERR_ERROR;

    Success = CodecSetVolume(WaveInstance->hSMBus,
                             VolumeSetting);

    if (Success == FALSE) {

        DEBUGMSG(ZONE_WODM, (
                 TEXT("SetOutputVolume: Failed codec write.\r\n")));

        goto ErrorReturn;
    }

    ReturnValue = MMSYSERR_NOERROR;

ErrorReturn:
    DEBUGMSG(ZONE_WODM, (TEXT("-SetOutputVolume\r\n")));

    return ReturnValue;
}

VOID
WaveOutStart(
    IN OUT PWAVE_RESOURCE WaveResource,
    IN OUT PWAVEHDR WaveHeader
    )

/*++

Routine Description:

    This routine handles set up of a new wave output stream.

Arguments:

    WaveResource - Pointer to the wave resource structure corresponding to the
        stream to be started.

    WaveHeader - Pointer to the wave header information.

Return Value:

    None.

--*/

{
    WaveResource->MoreData = TRUE;
	WaveResource->WaveHeader = WaveHeader;
	FillTwoOutputBuffers(WaveResource);
	StartDma(WaveResource);
}



VOID
WaveOutContinue (
    IN OUT PWAVE_RESOURCE WaveResource,
    IN OUT PWAVEHDR WaveHeader
    )

/*++

Routine Description:

    This routine handles continuation of a playing audio output stream.
    The operations are similar to starting wave output.

Arguments:

    WaveHeader - Pointer to the wave header information.

Return Value:

    None.

--*/

{
	WaveResource->WaveHeader = WaveHeader;
	
	if (HalDMAIsUnderflowed(WaveResource->DMAChannel)) {
		FillTwoOutputBuffers(WaveResource);
	} else {
		FillOutputBuffer(WaveResource);
	}
}



VOID
WaveOutEndOfData(
    IN OUT PWAVE_RESOURCE WaveResource
    )

/*++

Routine Description:

    This routine handles clean up of audio output when the wave
    output stream has ended.  It stops any output DMA transfer
    in progress and mutes audio output on the codec.

Arguments:



Return Value:

    None.

--*/

{
    DEBUGMSG(ZONE_WODM, (TEXT("+WaveOutEndOfData\r\n")));
	HalWaitForDMA(WaveResource->DMAChannel);
    WaveResource->MoreData = FALSE;
	ShutdownDma(WaveResource);
    DEBUGMSG(ZONE_WODM, (TEXT("-WaveOutEndOfData\r\n")));
}

⌨️ 快捷键说明

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