📄 drv_dart.c
字号:
/* MikMod sound library (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//*============================================================================== $Id: drv_dart.c,v 1.2 2004/01/31 22:39:40 raph Exp $ Driver for output on OS/2 MMPM/2 using direct audio (DART)==============================================================================*//* Written by Miodrag Vallat <miod@mikmod.org> Lots of improvements (basically made usable...) by Andrew Zabolotny <bit@eltech.ru>*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "mikmod_internals.h"#ifdef DRV_DART#define INCL_DOS#define INCL_OS2MM#include <os2.h>/* Prevent a warning: PPFN redefined */#define PPFN _PPFN#include <os2me.h>#undef PPFN#include <stdlib.h>#include <string.h>#define MAX_BUFFERCOUNT 8static MCI_MIX_BUFFER MixBuffers[MAX_BUFFERCOUNT];static MCI_MIXSETUP_PARMS MixSetupParms;static MCI_BUFFER_PARMS BufferParms;static ULONG DeviceIndex = 0; /* use default waveaudio device */static ULONG BufferSize = (ULONG)-1; /* autodetect buffer size */static ULONG BufferCount = 2; /* use two buffers */static ULONG DeviceID = 0;static void Dart_CommandLine(CHAR *cmdline){ char *ptr; int buf; if ((ptr = MD_GetAtom("buffer", cmdline, 0))) { buf = atoi(ptr); if (buf >= 12 && buf <= 16) BufferSize = 1 << buf; free(ptr); } if ((ptr = MD_GetAtom("count", cmdline, 0))) { buf = atoi(ptr); if (buf >= 2 && buf <= MAX_BUFFERCOUNT) BufferCount = buf; free(ptr); } if ((ptr = MD_GetAtom("device", cmdline, 0))) { buf = atoi(ptr); if (buf >= 0 && buf <= 8) DeviceIndex = buf; free(ptr); }}/* Buffer update thread (created and called by DART) This is a high-priority thread used to compute and update the audio stream, automatically created by the DART subsystem. We compute the next audio buffer and feed it to the waveaudio device. */static LONG APIENTRY Dart_UpdateBuffers(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags){ /* sanity check */ if (!pBuffer) return TRUE; /* if we have finished a buffer, we're ready to play a new one */ if ((ulFlags == MIX_WRITE_COMPLETE) || ((ulFlags == (MIX_WRITE_COMPLETE | MIX_STREAM_ERROR)) && (ulStatus == ERROR_DEVICE_UNDERRUN))) { /* refill this audio buffer and feed it again */ MUTEX_LOCK(vars); if (Player_Paused_internal()) pBuffer->ulBufferLength = VC_SilenceBytes(pBuffer->pBuffer, BufferSize); else pBuffer->ulBufferLength = VC_WriteBytes(pBuffer->pBuffer, BufferSize); MUTEX_UNLOCK(vars); MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle, pBuffer, 1); } return TRUE;}static BOOL Dart_IsPresent(void){ MCI_AMP_OPEN_PARMS AmpOpenParms; MCI_GENERIC_PARMS GenericParms; memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS)); AmpOpenParms.pszDeviceType = (PSZ) MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, (USHORT) DeviceIndex); if (mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_SHAREABLE | MCI_OPEN_TYPE_ID, (PVOID) &AmpOpenParms, 0) != MCIERR_SUCCESS) return 0; mciSendCommand(AmpOpenParms.usDeviceID, MCI_CLOSE, MCI_WAIT, (PVOID) &GenericParms, 0); return 1;}static BOOL Dart_Init(void){ MCI_AMP_OPEN_PARMS AmpOpenParms; MCI_GENERIC_PARMS GenericParms; MixBuffers[0].pBuffer = NULL; /* marker */ DeviceID = 0; memset(&GenericParms, 0, sizeof(MCI_GENERIC_PARMS)); /* open AMP device */ memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS)); AmpOpenParms.usDeviceID = 0; AmpOpenParms.pszDeviceType = (PSZ) MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, (USHORT) DeviceIndex); if (mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_SHAREABLE | MCI_OPEN_TYPE_ID, (PVOID) & AmpOpenParms, 0) != MCIERR_SUCCESS) { _mm_errno = MMERR_OPENING_AUDIO; return 1; } DeviceID = AmpOpenParms.usDeviceID; /* setup playback parameters */ memset(&MixSetupParms, 0, sizeof(MCI_MIXSETUP_PARMS)); MixSetupParms.ulBitsPerSample = (md_mode & DMODE_16BITS) ? 16 : 8; MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM; MixSetupParms.ulSamplesPerSec = md_mixfreq; MixSetupParms.ulChannels = (md_mode & DMODE_STEREO) ? 2 : 1; MixSetupParms.ulFormatMode = MCI_PLAY; MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO; MixSetupParms.pmixEvent = Dart_UpdateBuffers; if (mciSendCommand(DeviceID, MCI_MIXSETUP, MCI_WAIT | MCI_MIXSETUP_INIT, (PVOID) & MixSetupParms, 0) != MCIERR_SUCCESS) { _mm_errno = MMERR_OS2_MIXSETUP; return 1; } /* Compute audio buffer size now if necessary */ if (BufferSize == (ULONG)-1) { /* DART suggested buffer size is somewhat too big. We compute a size for circa 1/4" of playback. */ int bit; BufferSize = md_mixfreq >> 2; if (md_mode & DMODE_STEREO) BufferSize <<= 1; if (md_mode & DMODE_16BITS) BufferSize <<= 1; for (bit = 15; bit >= 12; bit--) if (BufferSize & (1 << bit)) break; BufferSize = (1 << bit); } /* make sure buffer is not greater than 64 Kb, as DART can't handle this situation. */ if (BufferSize > 65536) BufferSize = 65536; BufferParms.ulStructLength = sizeof(BufferParms); BufferParms.ulNumBuffers = BufferCount; BufferParms.ulBufferSize = BufferSize; BufferParms.pBufList = MixBuffers; if (mciSendCommand(DeviceID, MCI_BUFFER, MCI_WAIT | MCI_ALLOCATE_MEMORY, (PVOID) &BufferParms, 0) != MCIERR_SUCCESS) { _mm_errno = MMERR_OUT_OF_MEMORY; return 1; } return VC_Init();}static void Dart_Exit(void){ MCI_GENERIC_PARMS GenericParms; VC_Exit(); if (MixBuffers[0].pBuffer) { mciSendCommand(DeviceID, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &BufferParms, 0); MixBuffers[0].pBuffer = NULL; } if (DeviceID) { mciSendCommand(DeviceID, MCI_CLOSE, MCI_WAIT, (PVOID) &GenericParms, 0); DeviceID = 0; }}static BOOL Dart_PlayStart(void){ MCI_GENERIC_PARMS GenericParms; int i; if (VC_PlayStart()) return 1; /* silence buffers */ for (i = 0; i < BufferCount; i++) { VC_SilenceBytes(MixBuffers[i].pBuffer, BufferSize); MixBuffers[i].ulBufferLength = BufferSize; } /* grab exclusive rights to device instance (not entire device) */ GenericParms.hwndCallback = 0; /* Not needed, so set to 0 */ if (mciSendCommand(DeviceID, MCI_ACQUIREDEVICE, MCI_EXCLUSIVE_INSTANCE, (PVOID) &GenericParms, 0) != MCIERR_SUCCESS) { mciSendCommand(DeviceID, MCI_CLOSE, MCI_WAIT, (PVOID) &GenericParms, 0); _mm_errno = MMERR_OPENING_AUDIO; return 1; } /* wake DART up */ MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle, MixBuffers, BufferCount); return 0;}static void Dart_Update(void){ /* Nothing to do: everything is done in DART_UpdateBuffers() */}static void Dart_PlayStop(void){ MCI_GENERIC_PARMS GenericParms; GenericParms.hwndCallback = 0; mciSendCommand(DeviceID, MCI_STOP, MCI_WAIT, (PVOID) &GenericParms, 0); VC_PlayStop();}MIKMODAPI MDRIVER drv_dart = { NULL, "Direct audio (DART)", "OS/2 DART driver v1.2", 0, 255, "dart", "device:r:0,8,0:Waveaudio device index to use (0 - default)\n" "buffer:r:12,16:Audio buffer log2 size\n" "count:r:2,8,2:Number of audio buffers\n", Dart_CommandLine, Dart_IsPresent, VC_SampleLoad, VC_SampleUnload, VC_SampleSpace, VC_SampleLength, Dart_Init, Dart_Exit, NULL, VC_SetNumVoices, Dart_PlayStart, Dart_PlayStop, Dart_Update, NULL, VC_VoiceSetVolume, VC_VoiceGetVolume, VC_VoiceSetFrequency, VC_VoiceGetFrequency, VC_VoiceSetPanning, VC_VoiceGetPanning, VC_VoicePlay, VC_VoiceStop, VC_VoiceStopped, VC_VoiceGetPosition, VC_VoiceRealVolume};#elseMISSING(drv_dart);#endif/* ex:set ts=4: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -