请问API函数waveOutOpen如何使用回调函数?(300分)

  • 主题发起人 主题发起人 ow
  • 开始时间 开始时间
O

ow

Unregistered / Unconfirmed
GUEST, unregistred user!
我希望在使用waveOutOpen时用一个回调函数,即CALLBACK_FUNCTION.
请问应该如何定义和使用这个回调函数?
 
抄人家的

回调函数必须位于动态连接库中且被限定在回调函数中产生的系统调用。

uses Mmsystem;
procedure TForm1.Button1Click(Sender: TObject);
var
; i: Integer;
; hwo: HWAVEOUT;
; wfx: TWAVEFORMATEX;
; woh: TWAVEHDR;
; WaveBuffer: Array[0..2047] of Byte;
begin
; for i := 0 to 1203 do
; ; WaveBuffer := Round(128+32*Sin(i));
; wfx.nChannels := 1;
; wfx.wBitsPerSample := 8;
; wfx.nSamplesPerSec := 11025;
; wfx.wFormatTag := WAVE_FORMAT_PCM;
; waveOutOpen(@hwo,0,@wfx,Handle,0,CALLBACK_WINDOW);
; with woh do
; ; begin
; ; lpData := @WaveBuffer[0];
; ; dwBufferLength := 1024;
; ; dwBytesRecorded := 0;
; ; dwUser := 0;
; ; dwFlags := 0;
; ; dwLoops := 0;
; ; lpNext := nil;
; ; reserved := 0;
; ; end;
; waveOutPrepareHeader(hwo,@woh,SizeOf(TWAVEHDR));
; waveOutWrite(hwo, @woh, sizeof(TWAVEHDR));
; waveOutUnprepareHeader(hwo,@woh,sizeof(TWAVEHDR));
; waveOutClose(hwo);
end;
 
其实我的目的就是在后台循环播放wav文件,希望在回调函数中
调用
; waveOutUnprepareHeader(FWaveOut, W, sizeof(TWAVEHDR));
; FreeMem(W, FBufferSize + sizeof(TWAVEHDR));
; Replay;
进行重放,因为我设计的类得不到窗口句柄,所以绝对不能用窗口的
方式回调,其它的方式,事件或者回调函数的方式,只要能实现重放
功能,都可以得分。
 
The waveOutProc function is the callback function used with
the waveform-audio output device. The waveOutProc function is
a placeholder for the application-defined function name. The
address of this function can be specified in the callback-address
parameter of the waveOutOpen function.

//回调函数格式如下,你会调用成功的(^_^)
void CALLBACK waveOutProc(

; ; HWAVEOUT hwo,
; ; UINT uMsg,
; ; DWORD dwInstance,
; ; DWORD dwParam1,
; ; DWORD dwParam2
; ;);

Parameters

hwo
Handle of the waveform-audio device associated with the callback.

uMsg
Waveform-audio output message. It can be one of the following values:

WOM_CLOSE
Sent when the device is closed using the waveOutClose function.

WOM_DONE
Sent when the device driver is finished with a data block sent using the waveOutWrite function.

WOM_OPEN
Sent when the device is opened using the waveOutOpen function.

dwInstance
User-instance data specified with waveOutOpen.

dwParam1
Message parameters.

dwParam2
Message parameters.

Return Values
This function does not return a value.
 
to 刘李子:
; ;不好意思,没说清楚,我要的是Delphi形式的回调函数写法。
 
或者有没有什么方法能向非窗口类发消息?
 
还是来个VC的例子吧。//shy

Audio Streaming Sample Code
The following code sample demonstrates how to stream audio data using the IAudioMediaStream, IAudioStreamSample, IMemoryData, and IAudioData interfaces.

#include <windows.h>
#include <mmsystem.h>
#include <amstream.h>

/********************************************************************

; ;Trivial wave player stuff

;********************************************************************/

class CWaveBuffer;

class CWaveBuffer {
; ; public:
; ; ; ; CWaveBuffer();
; ; ; ; ~CWaveBuffer();
; ; ; ; BOOL Init(HWAVEOUT hWave, int Size);
; ; ; ; void Done();
; ; ; ; BOOL Write(PBYTE pData, int nBytes, int& BytesWritten);
; ; ; ; void Flush();

; ; private:
; ; ; ; WAVEHDR ; ; ;m_Hdr;
; ; ; ; HWAVEOUT ; ; m_hWave;
; ; ; ; int ; ; ; ; ;m_nBytes;
};

class CWaveOut {
; ; public:
; ; ; ; CWaveOut(LPCWAVEFORMATEX Format, int nBuffers, int BufferSize);
; ; ; ; ~CWaveOut();
; ; ; ; void Write(PBYTE Data, int nBytes);
; ; ; ; void Flush();
; ; ; ; void Wait();
; ; ; ; void Reset();
; ; private:
; ; ; ; const HANDLE ; m_hSem;
; ; ; ; const int ; ; ;m_nBuffers;
; ; ; ; int ; ; ; ; ; ;m_CurrentBuffer;
; ; ; ; BOOL ; ; ; ; ; m_NoBuffer;
; ; ; ; CWaveBuffer ; *m_Hdrs;
; ; ; ; HWAVEOUT ; ; ; m_hWave;
};

/*
; ; CWaveBuffer
*/

CWaveBuffer::CWaveBuffer()
{
}

BOOL CWaveBuffer::Init(HWAVEOUT hWave, int Size)
{
; ; m_hWave ;= hWave;
; ; m_nBytes = 0;

; ; /* ;Allocate a buffer and initialize the header. */
; ; m_Hdr.lpData = (LPSTR)LocalAlloc(LMEM_FIXED, Size);
; ; if (m_Hdr.lpData == NULL) {
; ; ; ; return FALSE;
; ; }
; ; m_Hdr.dwBufferLength ;= Size;
; ; m_Hdr.dwBytesRecorded = 0;
; ; m_Hdr.dwUser = 0;
; ; m_Hdr.dwFlags = 0;
; ; m_Hdr.dwLoops = 0;
; ; m_Hdr.lpNext = 0;
; ; m_Hdr.reserved = 0;

; ; /* ;Prepare it. */
; ; waveOutPrepareHeader(hWave, &m_Hdr, sizeof(WAVEHDR));

; ; return TRUE;
}

CWaveBuffer::~CWaveBuffer() {
; ; if (m_Hdr.lpData) {
; ; ; ; waveOutUnprepareHeader(m_hWave, &m_Hdr, sizeof(WAVEHDR));
; ; ; ; LocalFree(m_Hdr.lpData);
; ; }
}

void CWaveBuffer::Flush()
{
; ; // ASSERT(m_nBytes != 0);
; ; m_nBytes = 0;
; ; waveOutWrite(m_hWave, &m_Hdr, sizeof(WAVEHDR));
}

BOOL CWaveBuffer::Write(PBYTE pData, int nBytes, int& BytesWritten)
{
; ; // ASSERT((DWORD)m_nBytes != m_Hdr.dwBufferLength);
; ; BytesWritten = min((int)m_Hdr.dwBufferLength - m_nBytes, nBytes);
; ; CopyMemory((PVOID)(m_Hdr.lpData + m_nBytes), (PVOID)pData, BytesWritten);
; ; m_nBytes += BytesWritten;
; ; if (m_nBytes == (int)m_Hdr.dwBufferLength) {
; ; ; ; /* ;Write it! */
; ; ; ; m_nBytes = 0;
; ; ; ; waveOutWrite(m_hWave, &m_Hdr, sizeof(WAVEHDR));
; ; ; ; return TRUE;
; ; }
; ; return FALSE;
}

void CALLBACK WaveCallback(HWAVEOUT hWave, UINT uMsg, DWORD dwUser,
; ; ; ; ; ; ; ; ; ; ; ; ; ;DWORD dw1, DWORD dw2)
{
; ; if (uMsg == WOM_DONE) {
; ; ; ; ReleaseSemaphore((HANDLE)dwUser, 1, NULL);
; ; }
}

/*
; ; CWaveOut
*/

CWaveOut::CWaveOut(LPCWAVEFORMATEX Format, int nBuffers, int BufferSize) :
; ; m_nBuffers(nBuffers),
; ; m_CurrentBuffer(0),
; ; m_NoBuffer(TRUE),
; ; m_hSem(CreateSemaphore(NULL, nBuffers, nBuffers, NULL)),
; ; m_Hdrs(new CWaveBuffer[nBuffers]),
; ; m_hWave(NULL)
{
; ; /* ;Create wave device. */
; ; waveOutOpen(&m_hWave,
; ; ; ; ; ; ; ; WAVE_MAPPER,
; ; ; ; ; ; ; ; Format,
; ; ; ; ; ; ; ; (DWORD)WaveCallback,
; ; ; ; ; ; ; ; (DWORD)m_hSem,
; ; ; ; ; ; ; ; CALLBACK_FUNCTION);

; ; /* ;Initialize the wave buffers. */
; ; for (int i = 0; i < nBuffers; i++) {
; ; ; ; m_Hdrs.Init(m_hWave, BufferSize);
; ; }
}

CWaveOut::~CWaveOut()
{
; ; /* ;First, get the buffers back. */
; ; waveOutReset(m_hWave);

; ; /* ;Free the buffers. */
; ; delete [] m_Hdrs;

; ; /* ;Close the wave device. */
; ; waveOutClose(m_hWave);

; ; /* ;Free the semaphore. */
; ; CloseHandle(m_hSem);
}

void CWaveOut::Flush()
{
; ; if (!m_NoBuffer) {
; ; ; ; m_Hdrs[m_CurrentBuffer].Flush();
; ; ; ; m_NoBuffer = TRUE;
; ; ; ; m_CurrentBuffer = (m_CurrentBuffer + 1) % m_nBuffers;
; ; }
}

void CWaveOut::Reset()
{
; ; waveOutReset(m_hWave);
}


void CWaveOut::Write(PBYTE pData, int nBytes)
{
; ; while (nBytes != 0) {
; ; ; ; /* ;Get a buffer if necessary. */
; ; ; ; if (m_NoBuffer) {
; ; ; ; ; ; WaitForSingleObject(m_hSem, INFINITE);
; ; ; ; ; ; m_NoBuffer = FALSE;
; ; ; ; }

; ; ; ; /* ;Write into a buffer. */
; ; ; ; int nWritten;
; ; ; ; if (m_Hdrs[m_CurrentBuffer].Write(pData, nBytes, nWritten)) {
; ; ; ; ; ; m_NoBuffer = TRUE;
; ; ; ; ; ; m_CurrentBuffer = (m_CurrentBuffer + 1) % m_nBuffers;
; ; ; ; ; ; nBytes -= nWritten;
; ; ; ; ; ; pData += nWritten;
; ; ; ; } else {
; ; ; ; ; ; // ASSERT(nWritten == nBytes);
; ; ; ; ; ; break;
; ; ; ; }
; ; }
}

void CWaveOut::Wait()
{
; ; /* ;Send any remaining buffers. */
; ; Flush();

; ; /* ;Wait for the buffers back. */
; ; for (int i = 0; i < m_nBuffers; i++) {
; ; ; ; WaitForSingleObject(m_hSem, INFINITE);
; ; }
; ; LONG lPrevCount;
; ; ReleaseSemaphore(m_hSem, m_nBuffers, &lPrevCount);
}

/************************************************************

; End of wave player stuff

;************************************************************/


HRESULT RenderStreamToDevice(IMultiMediaStream *pMMStream)
{
; ; WAVEFORMATEX wfx;
; ; #define DATA_SIZE 5000
; ; PBYTE pBuffer = (PBYTE)LocalAlloc(LMEM_FIXED, DATA_SIZE);

; ; IMediaStream *pStream;
; ; IAudioStreamSample *pSample;
; ; IAudioMediaStream *pAudioStream;
; ; IAudioData *pAudioData;

; ; pMMStream->GetMediaStream(MSPID_PrimaryAudio, &pStream);
; ; pStream->QueryInterface(IID_IAudioMediaStream, (void **)&pAudioStream);
; ; pAudioStream->GetFormat(&wfx);
; ; CoCreateInstance(CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER,
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; IID_IAudioData, (void **)&pAudioData);
; ; pAudioData->SetBuffer(DATA_SIZE, pBuffer, 0);
; ; pAudioData->SetFormat(&wfx);
; ; pAudioStream->CreateSample(pAudioData, 0, &pSample);
; ; HANDLE hEvent = CreateEvent(FALSE, NULL, NULL, FALSE);
; ; CWaveOut WaveOut(&wfx, 4, 2048);
; ; int iTimes;
; ; for (iTimes = 0; iTimes < 3; iTimes++) {
; ; ; ; DWORD dwStart = timeGetTime();
; ; ; ; for (; ; ) {
; ; ; ; ; ; HRESULT hr = pSample->Update(0, hEvent, NULL, 0);
; ; ; ; ; ; if (FAILED(hr) || MS_S_ENDOFSTREAM == hr) {
; ; ; ; ; ; ; ; break;
; ; ; ; ; ; }
; ; ; ; ; ; WaitForSingleObject(hEvent, INFINITE);
; ; ; ; ; ; DWORD dwTimeDiff = timeGetTime() - dwStart;
; ; ; ; ; ; // Limit to 10 seconds
; ; ; ; ; ; if (dwTimeDiff > 10000) {
; ; ; ; ; ; ; ; break;
; ; ; ; ; ; }
; ; ; ; ; ; DWORD dwLength;
; ; ; ; ; ; pAudioData->GetInfo(NULL, NULL, &dwLength);
; ; ; ; ; ; WaveOut.Write(pBuffer, dwLength);
; ; ; ; }
; ; ; ; pMMStream->Seek(0);
; ; }

; ; pAudioData->Release();
; ; pSample->Release();
; ; pStream->Release();
; ; pAudioStream->Release();
; ; LocalFree((HLOCAL)pBuffer);

; ; return S_OK;
}

HRESULT RenderFileToMMStream(
; ; WCHAR * pszFileName, IMultiMediaStream **ppMMStream)
{
; ; IAMMultiMediaStream *pAMStream;
; ; CoCreateInstance(CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER,
; ; ; ; ; ; ; IID_IAMMultiMediaStream, (void **)&pAMStream);
; ; pAMStream->Initialize(STREAMTYPE_READ, AMMSF_NOGRAPHTHREAD, NULL);
; ; pAMStream->AddMediaStream(NULL, &MSPID_PrimaryAudio, 0, NULL);
; ; pAMStream->OpenFile(pszFileName, AMMSF_RUN);
; ; *ppMMStream = pAMStream;
; ; return S_OK;
}

int _CRTAPI1 main(int argc, char *argv[])
{
; ; IMultiMediaStream *pMMStream;
; ; CoInitialize(NULL);
; ; WCHAR wszName[1000];
; ; MultiByteToWideChar(CP_ACP, 0, argv[1], -1, wszName,
; ; ; ; sizeof(wszName) / sizeof(wszName[0]));
; ; RenderFileToMMStream(wszName, &pMMStream);
; ; RenderStreamToDevice(pMMStream);
; ; pMMStream->Release();
; ; CoUninitialize();
; ; return 0;
}
 
to lww:
; 在回调里面执行ReleaseSemaphore是不是会有问题,MSDN里面好像说不行?
 
多人接受答案了。
 
后退
顶部