?? dsdrv2.c
字號:
/* * $Id: dsdrv2.c 0.4 1998/12/26 chasan Exp $ * * DirectSound accelerated audio driver (Experimental) * * Copyright (C) 1998-1999 Carlos Hasan * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */#include <windows.h>#include <objbase.h>#include <dsound.h>#include <math.h>#include "audio.h"#include "drivers.h"#if 0#define MSGBOX(text) MessageBox(NULL, text, "DirectSound", MB_OK)#else#define MSGBOX(text)#endifstatic struct { LPDIRECTSOUND lpDirectSound; LPDIRECTSOUNDBUFFER lpPrimaryBuffer; LPDIRECTSOUNDBUFFER aSoundBuffer[AUDIO_MAX_VOICES]; LPFNAUDIOTIMER lpfnTimerHandler; LONG aLogVolumeTable[AUDIO_MAX_VOLUME+1]; LONG aLogPanningTable[AUDIO_MAX_PANNING+1]; DWORD aFormatTable[AUDIO_MAX_VOICES]; LONG aFrequencyTable[AUDIO_MAX_VOICES]; UINT aVolumeTable[AUDIO_MAX_VOICES]; UINT aPanningTable[AUDIO_MAX_VOICES]; LONG dwTimer; LONG dwTimerAccum; LONG dwTimerRate;} DS;static HRESULT _DirectSoundCreate(GUID FAR *lpGuid, LPDIRECTSOUND *lplpDirectSound, IUnknown FAR *lpUnkOuter){ HRESULT hresult; CoInitialize(NULL); hresult = CoCreateInstance(&CLSID_DirectSound, lpUnkOuter, CLSCTX_ALL, &IID_IDirectSound, lplpDirectSound); if (!FAILED(hresult)) hresult = IDirectSound_Initialize(*lplpDirectSound, NULL); return hresult;}static HRESULT _DirectSoundDestroy(LPDIRECTSOUND lpDirectSound){ HRESULT hresult; hresult = IDirectSound_Release(lpDirectSound); CoUninitialize(); return hresult;}static UINT AIAPI SetAudioMixerValue(UINT, UINT);/* * DirectSound audio driver API interface */static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps){ static AUDIOCAPS Caps = { AUDIO_PRODUCT_NONE, "DirectSound (experimental)", AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 | AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 | AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 | AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 | AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 | AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16 }; memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS)); return AUDIO_ERROR_NONE;}static UINT AIAPI PingAudio(VOID){ LPDIRECTSOUND lpDirectSound; if (_DirectSoundCreate(NULL, &lpDirectSound, NULL) != DS_OK) return AUDIO_ERROR_NODEVICE; _DirectSoundDestroy(lpDirectSound); return AUDIO_ERROR_NONE;}static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo){ LPDIRECTSOUNDBUFFER lpPrimaryBuffer; DSBUFFERDESC dsbd; WAVEFORMATEX wfx; DSCAPS dsc; LONG nPanning; memset(&DS, 0, sizeof(DS)); if (lpInfo == NULL) return AUDIO_ERROR_INVALPARAM; /* create direct sound object */ if (_DirectSoundCreate(NULL, &DS.lpDirectSound, NULL) != DS_OK) return AUDIO_ERROR_NODEVICE; /* set direct sound cooperative level */ if (DS.lpDirectSound->lpVtbl->SetCooperativeLevel(DS.lpDirectSound, GetForegroundWindow(), DSSCL_PRIORITY) != DS_OK) { _DirectSoundDestroy(DS.lpDirectSound); return AUDIO_ERROR_NODEVICE; } /* get direct sound capabilities */ dsc.dwSize = sizeof(dsc); if (DS.lpDirectSound->lpVtbl->GetCaps(DS.lpDirectSound, &dsc) != DS_OK) { _DirectSoundDestroy(DS.lpDirectSound); return AUDIO_ERROR_NODEVICE; } /* adjust the format settings */ lpInfo->nSampleRate = 44100; if (!(dsc.dwFlags & DSCAPS_PRIMARYSTEREO)) lpInfo->wFormat &= ~AUDIO_FORMAT_STEREO; if (!(dsc.dwFlags & DSCAPS_PRIMARY16BIT)) lpInfo->wFormat &= ~AUDIO_FORMAT_16BITS; /* setup wave format structure */ wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = lpInfo->wFormat & AUDIO_FORMAT_STEREO ? 2 : 1; wfx.wBitsPerSample = lpInfo->wFormat & AUDIO_FORMAT_16BITS ? 16 : 8; wfx.nSamplesPerSec = lpInfo->nSampleRate; wfx.nAvgBytesPerSec = lpInfo->nSampleRate; wfx.nBlockAlign = 1; wfx.cbSize = 0; if (lpInfo->wFormat & AUDIO_FORMAT_STEREO) { wfx.nAvgBytesPerSec <<= 1; wfx.nBlockAlign <<= 1; } if (lpInfo->wFormat & AUDIO_FORMAT_16BITS) { wfx.nAvgBytesPerSec <<= 1; wfx.nBlockAlign <<= 1; } /* create primary sound buffer */ memset(&dsbd, 0, sizeof(dsbd)); dsbd.dwSize = sizeof(dsbd); dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; dsbd.dwBufferBytes = 0; dsbd.lpwfxFormat = NULL; if (DS.lpDirectSound->lpVtbl->CreateSoundBuffer(DS.lpDirectSound, &dsbd, &DS.lpPrimaryBuffer, NULL) != DS_OK) { MSGBOX("Can't create primary buffer"); _DirectSoundDestroy(DS.lpDirectSound); return AUDIO_ERROR_NODEVICE; } /* setup primary buffer format */ while (DS.lpPrimaryBuffer->lpVtbl->SetFormat(DS.lpPrimaryBuffer, &wfx) != DS_OK) { if (lpInfo->nSampleRate <= 11025) { MSGBOX("Can't change primary buffer format"); _DirectSoundDestroy(DS.lpDirectSound); return AUDIO_ERROR_NODEVICE; } wfx.nSamplesPerSec >>= 1; wfx.nAvgBytesPerSec >>= 1; wfx.nBlockAlign >>= 1; lpInfo->nSampleRate >>= 1; } /* start playing primary buffer */ DS.lpPrimaryBuffer->lpVtbl->Play(DS.lpPrimaryBuffer, 0, 0, DSBPLAY_LOOPING); /* set the timer settings */ DS.dwTimer = GetTickCount(); DS.dwTimerAccum = 0; /* set default master volume */ SetAudioMixerValue(AUDIO_MIXER_MASTER_VOLUME, 96); /* create log panning table */ for (nPanning = 0; nPanning <= AUDIO_MAX_PANNING; nPanning++) { DS.aLogPanningTable[nPanning] = (2000 * (nPanning - 128)) >> 7; } return AUDIO_ERROR_NONE;}static UINT AIAPI CloseAudio(VOID){ UINT i; if (DS.lpDirectSound != NULL) { /* stop and release primary buffer */ if (DS.lpPrimaryBuffer != NULL) { DS.lpPrimaryBuffer->lpVtbl->Stop(DS.lpPrimaryBuffer); DS.lpPrimaryBuffer->lpVtbl->Release(DS.lpPrimaryBuffer); } /* release duplicated sound buffers */ for (i = 0; i < AUDIO_MAX_VOICES; i++) { if (DS.aSoundBuffer[i] != NULL) { DS.aSoundBuffer[i]->lpVtbl->Stop(DS.aSoundBuffer[i]); DS.aSoundBuffer[i]->lpVtbl->Release(DS.aSoundBuffer[i]); } } /* release direct sound buffer */ _DirectSoundDestroy(DS.lpDirectSound); } /* clean up DirectSound driver variables */ memset(&DS, 0, sizeof(DS)); return AUDIO_ERROR_NONE;}static UINT AIAPI UpdateAudio(UINT nFrames){ LONG dwTimer = GetTickCount(); /* call the virtual audio timer callback */ if ((DS.dwTimerAccum += dwTimer - DS.dwTimer) >= DS.dwTimerRate) { DS.dwTimerAccum -= DS.dwTimerRate; if (DS.lpfnTimerHandler != NULL) DS.lpfnTimerHandler(); } DS.dwTimer = dwTimer; return AUDIO_ERROR_NONE;}static UINT AIAPI UpdateAudioSynth(VOID){ return AUDIO_ERROR_NONE;}static UINT AIAPI SetAudioMixerValue(UINT nChannel, UINT nValue){ LONG nVolume; if (nChannel != AUDIO_MIXER_MASTER_VOLUME && nChannel != AUDIO_MIXER_TREBLE && nChannel != AUDIO_MIXER_BASS && nChannel != AUDIO_MIXER_CHORUS && nChannel != AUDIO_MIXER_REVERB) return AUDIO_ERROR_INVALPARAM; if (nChannel == AUDIO_MIXER_MASTER_VOLUME && nValue <= 256) { DS.aLogVolumeTable[0] = -10000; for (nVolume = 1; nVolume <= AUDIO_MAX_VOLUME; nVolume++) { LONG value = (nValue * nVolume) >> 6; DS.aLogVolumeTable[nVolume] = (LONG) (value == 0 ? -10000.0 : -2000.0 * log(value / 256.0) / log(1.0/256.0)); } } return AUDIO_ERROR_NONE;}static UINT AIAPI OpenVoices(UINT nVoices){ if (nVoices <= AUDIO_MAX_VOICES) { return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM;}static UINT AIAPI CloseVoices(VOID){ UINT i; for (i = 0; i < AUDIO_MAX_VOICES; i++) { /* stop and release duplicated sound buffers */ if (DS.aSoundBuffer[i] != NULL) { DS.aSoundBuffer[i]->lpVtbl->Stop(DS.aSoundBuffer[i]); DS.aSoundBuffer[i]->lpVtbl->Release(DS.aSoundBuffer[i]); } } /* clean up duplicated sound buffer array */ memset(DS.aSoundBuffer, 0, sizeof(DS.aSoundBuffer)); return AUDIO_ERROR_NONE;}static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave){ if (lpfnAudioWave != NULL) { } return AUDIO_ERROR_NONE;}static UINT AIAPI SetAudioTimerProc(LPFNAUDIOTIMER lpfnAudioTimer){ if (lpfnAudioTimer != NULL) { /* start up the timer settings */ if (DS.lpfnTimerHandler == NULL) { DS.dwTimer = GetTickCount(); DS.dwTimerAccum = 0; } DS.lpfnTimerHandler = lpfnAudioTimer; } return AUDIO_ERROR_NONE;}static UINT AIAPI SetAudioTimerRate(UINT nBPM){ if (nBPM >= 0x20 && nBPM <= 0xFF) { /* set timer rate in milliseconds */ DS.dwTimerRate = (5 * 1000L) / (2 * nBPM); return AUDIO_ERROR_NONE; } return AUDIO_ERROR_INVALPARAM;}static LONG AIAPI GetAudioDataAvail(VOID){ return 0L;}static UINT AIAPI CreateAudioData(LPAUDIOWAVE lpWave){
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -