📄 waveout.cpp
字号:
//**********************************************************************
//
// Filename: waveout.cpp
//
// Description: File handles all of the WODM messages.
//
// 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
// LICENSE.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2002, All Rights Reserved
//
//**********************************************************************
#include "wavecommon.h"
//#include <mmreg.h>
//#include <ceddk.h>
//
// I2C format conversion functions.
//
void ConvertShortsToWords
(
PULONG pulDst,
PUSHORT pusSrc,
ULONG ulNumberOfBytes
);
void ConvertBytesToWordsMonoToStereo
(
PULONG pulDst,
PUCHAR pucSrc,
ULONG ulNumberOfBytes
);
void ConvertShortsToWordsMonoToStereo
(
PULONG pulDst,
PUSHORT pusSrc,
ULONG ulNumberOfBytes
);
void ConvertBytesToWords
(
PULONG pulDst,
PUCHAR pucSrc,
ULONG ulNumberOfBytes
);
//
// AC97 format conversion functions.
//
void ConvertShortsMonoToStereo
(
PULONG pulDst,
PUSHORT pusSrc,
ULONG ulNumberOfBytes
);
void ConvertBytesToShortsMonoToStereo
(
PULONG pulDst,
PUCHAR pucSrc,
ULONG ulNumberOfBytes
);
void ConvertBytesToShorts
(
PUSHORT pusDst,
PUCHAR pucSrc,
ULONG ulNumberOfBytes
);
//****************************************************************************
// WaveOut::WaveOut
//****************************************************************************
// Constructor Initializes the variables.
//
WaveOut::WaveOut()
{
FUNC_WAVEOUT((L"+WaveOut::WaveOut\n"));
m_bLock = FALSE;
m_bIsPlaying = FALSE;
m_bIsPaused = FALSE;
m_bStopAtNextInterrupt = FALSE;
m_dwLoopCount = 0;
m_dwBytePosition = 0;
m_dwPreviousStart = 0;
m_dwPreviousEnd = 0;
m_pWaveHead = 0;
m_pWaveNext = 0;
m_pBuffer = 0;
m_pfnCallback = 0;
m_hCallback = 0;
m_dwInstance = 0;
m_usRightVolume = 0xFFFF;
m_usLeftVolume = 0xFFFF;
m_usMasterRightVolume = 0xFFFF;
m_usMasterLeftVolume = 0xFFFF;
m_ulDmaBufferSize = 0;
//
// These values are initialized on wave open.
//
m_ulDMASampleSize = 0;
m_pfnConversion = 0;
m_ulBufferShift = -1;
memset( &m_CriticalSection, 0,sizeof(CRITICAL_SECTION));
memset( &m_WaveFormat, 0,sizeof(WAVEFORMATEX));
FUNC_WAVEOUT((L"-WaveOut::WaveOut\n"));
}
//****************************************************************************
// WaveOut::~WaveOut
//****************************************************************************
// Destructor
//
WaveOut::~WaveOut()
{
FUNC_WAVEOUT((L"+WaveOut::~WaveOut\n"));
//BOOL bRet;
//
// Delete the critical section.
//
DeleteCriticalSection( &m_CriticalSection);
FUNC_WAVEOUT((L"-WaveOut::~WaveOut\n"));
}
//****************************************************************************
// WaveOut::Initialize
//****************************************************************************
// Allocates memory and initializes the Wave Out interface.
//
//
MMRESULT WaveOut::Initialize(CodecInterface *ci)
{
FUNC_WAVEOUT((L"+WaveOut::Initialize\n"));
MMRESULT mmRet = MMSYSERR_NOERROR;
//
// Save off a pointer to the codec interface.
//
m_pCodec = ci;
//
// Initialize the Critical Section.
//
InitializeCriticalSection(&m_CriticalSection);
m_ulDmaBufferSize = DMA_BUFFER_SIZE * (m_pCodec->DmaSampleSize() / 8);
//
// Initialize the buffer.
//
mmRet = m_Dma.Initialize
(
DMA_M2P0_TX_BASE,
m_pCodec->GetDmaPort(),
m_ulDmaBufferSize
);
if(mmRet == MMSYSERR_NOERROR)
{
m_pBuffer = m_Dma.GetVirtBuffAddress();
mmRet =m_pBuffer?MMSYSERR_NOERROR: MMSYSERR_NOMEM;
}
//
// Set the callback function to the interrupt handler.
//
m_Dma.SetCallBack(WaveOut::InterruptHandler, (HANDLE )this);
//mmRet = m_pCodec->SetSampleRate(44100, 0);
//ASSERT(MMSUCCESS(mmRet));
//mmRet = m_pCodec->StartPlayback(0);
//ASSERT(MMSUCCESS(mmRet));
//for(ulCount = 0 ;ulCount< BUFFER_SIZE/sizeof(ULONG); ulCount++)
//{
// ((volatile ULONG *)m_pBuffer)[ulCount] = (ulCount & 0x40)? 0x7fffff:0x800000;
//}
//m_Dma.Start();
//while(1);
FUNC_WAVEOUT((L"-WaveOut::Initialize\n"));
return(mmRet);
}
//****************************************************************************
// WaveOut::Open
//****************************************************************************
// Called on WODM_OPEN.
//
//
MMRESULT WaveOut::Open
(
DWORD * pdwUser,
WAVEOPENDESC * pOpenDesc,
DWORD dwFlags
)
{
FUNC_WAVEOUT((L"+WaveOut::Open\n"));
WAVEFORMATEX * pFormat = pOpenDesc->lpFormat;
MMRESULT mmRet = MMSYSERR_NOERROR;
ASSERT(pFormat);
if(dwFlags & WAVE_FORMAT_QUERY)
{
WODM_MSG((L"Wave Format Query: \n"));
}
else
{
WODM_MSG((L"Wave Format Open: \n"));
}
WODM_MSG((L" nSamplesPerSec = %d\n",pFormat->nSamplesPerSec));
WODM_MSG((L" nChannels = %d\n",pFormat->nChannels));
WODM_MSG((L" wBitsPerSample = %d\n",pFormat->wBitsPerSample));
//
// Allow PCM, mono or stereo, 8 or 16 bit at any frequency supported
// by the AC97 Codec.
//
if( (pFormat->wFormatTag != WAVE_FORMAT_PCM) ||
(pFormat->nChannels != 1 && pFormat->nChannels != 2) ||
(pFormat->wBitsPerSample != 8 && pFormat->wBitsPerSample != 16))
{
mmRet = WAVERR_BADFORMAT;
}
//
// Check to see if the sample rate is correct.
//
if(MMSUCCESS(mmRet))
{
switch( pFormat->nSamplesPerSec)
{
case 48000:
case 44100:
case 32000:
case 22050:
case 16000:
case 11025:
case 8000:
break;
default:
mmRet = WAVERR_BADFORMAT;
break;
}
}
//
// If the Application is querying if we can play a certain format,
// then just return.
//
if(dwFlags & WAVE_FORMAT_QUERY)
{
FUNC_WAVEOUT((L"-WaveOut::Open\n"));
return mmRet;
}
//
// Only one playback stream is allowed.
//
if(m_pCodec->m_bPlaybackOpened)
{
return(MMSYSERR_ALLOCATED);
}
if (MMSUCCESS(mmRet))
{
m_WaveFormat = *pFormat;
m_bIsPlaying = FALSE;
m_bIsPaused = FALSE;
m_bStopAtNextInterrupt = FALSE;
m_dwLoopCount = 0;
m_dwBytePosition = 0;
m_dwPreviousStart = 0;
m_dwPreviousEnd = 0;
m_pfnCallback = (DRVCALLBACK *) pOpenDesc->dwCallback;
m_hCallback = pOpenDesc->hWave;
m_dwInstance = pOpenDesc->dwInstance;
m_pWaveHead = 0;
m_pWaveNext = 0;
m_ulDMASampleSize = m_pCodec->DmaSampleSize();
if(m_ulDMASampleSize == 32 )
{
if(pFormat->nChannels == 1 && pFormat->wBitsPerSample == 8)
{
m_pfnConversion = (WaveOutConversionFunc *)&ConvertBytesToWordsMonoToStereo;
m_ulBufferShift = 3;
}
else if(pFormat->nChannels == 1 && pFormat->wBitsPerSample == 16)
{
m_pfnConversion = (WaveOutConversionFunc *)&ConvertShortsToWordsMonoToStereo;
m_ulBufferShift = 2;
}
else if(pFormat->nChannels == 2 && pFormat->wBitsPerSample == 8)
{
m_pfnConversion = (WaveOutConversionFunc *)&ConvertBytesToWords;
m_ulBufferShift = 2;
}
else if(pFormat->nChannels == 2 && pFormat->wBitsPerSample == 16)
{
m_pfnConversion = (WaveOutConversionFunc *)&ConvertShortsToWords;
m_ulBufferShift = 1;
}
}
else // DmaSample size is 16
{
if(pFormat->nChannels == 1 && pFormat->wBitsPerSample == 8)
{
m_pfnConversion = (WaveOutConversionFunc *)&ConvertBytesToShortsMonoToStereo;
m_ulBufferShift = 2;
}
else if(pFormat->nChannels == 1 && pFormat->wBitsPerSample == 16)
{
m_pfnConversion = (WaveOutConversionFunc *)&ConvertShortsMonoToStereo;
m_ulBufferShift = 1;
}
else if(pFormat->nChannels == 2 && pFormat->wBitsPerSample == 8)
{
m_pfnConversion = (WaveOutConversionFunc *)&ConvertBytesToShorts;
m_ulBufferShift = 1;
}
else if(pFormat->nChannels == 2 && pFormat->wBitsPerSample == 16)
{
m_pfnConversion = (WaveOutConversionFunc *)&memcpy;
m_ulBufferShift = 0;
}
}
}
//
// Initialize the codec.
//
if(MMSUCCESS(mmRet))
{
mmRet = m_pCodec->SetPlaybackSampleRate(pFormat->nSamplesPerSec, 0);
ASSERT(MMSUCCESS(mmRet));
}
//
// Start up the codec playback
//
if(MMSUCCESS(mmRet))
{
//m_pCodec->StartPlayback(0);
ASSERT(MMSUCCESS(mmRet));
}
//
// If there was no failures then the stream was allocated correctly.
//
if(MMSUCCESS(mmRet))
{
m_pCodec->m_bPlaybackOpened = TRUE;
*pdwUser = 1;
}
FUNC_WAVEOUT((L"-WaveOut::Open\n"));
return( mmRet);
}
//****************************************************************************
// WaveOut::Close
//****************************************************************************
// Called on WODM_CLOSE.
//
//
MMRESULT WaveOut::Close()
{
FUNC_WAVEOUT((L"+WaveOut::Close\n"));
MMRESULT mmRet = MMSYSERR_NOERROR;
EnterCriticalSection( &m_CriticalSection);
if(m_bIsPlaying && m_bIsPaused)
{
m_Dma.Stop();
Sleep(1);
m_pCodec->StopPlayback(0);
}
m_pCodec->m_bPlaybackOpened = FALSE;
m_bIsPlaying = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -