📄 win_snd.c
字号:
if (nosound)
return;
dsbuffer = StackSounds[handle].lpSndBuf;
#ifdef SURROUND
if (dsbuffer == NULL)
return;
dssurround = StackSounds[handle].lpSurround;
if (dssurround)
{
dssurround->lpVtbl->GetStatus(dssurround, &dwStatus);
surround_inuse = (dwStatus & (DSBSTATUS_PLAYING | DSBSTATUS_LOOPING));
}
// If pan changed to stereo...
if (sep != -128)
{
if (surround_inuse)
{
dssurround->lpVtbl->Stop(dssurround);
surround_inuse = FALSE;
}
}
else
// Just update volumes and start the surround if need
if (!surround_inuse)
{
I_UpdateSoundVolume(dssurround, vol);
I_UpdateSoundPanning(dsbuffer, 0);
dsbuffer->lpVtbl->GetCurrentPosition(dsbuffer, &pos, NULL);
dssurround->lpVtbl->SetCurrentPosition(dssurround, pos);
dssurround->lpVtbl->Play(dssurround, 0, 0, 0);
surround_inuse = TRUE;
}
else
I_UpdateSoundVolume(dssurround, vol);
I_UpdateSoundVolume(dsbuffer, vol);
if (!surround_inuse)
I_UpdateSoundPanning(dsbuffer, sep);
#else
if (dsbuffer) {
I_UpdateSoundVolume (dsbuffer, vol);
I_UpdateSoundPanning (dsbuffer, sep);
}
#endif
}
//
// Shutdown DirectSound
//
void I_ShutdownSound(void)
{
int i;
CONS_Printf("I_ShutdownSound()\n");
#ifdef HW3SOUND
if (hws_mode != HWS_DEFAULT_MODE)
{
HW3S_Shutdown();
Shutdown3DSDriver();
return;
}
#endif
// release any temporary 'duplicated' secondary buffers
for (i=0; i<MAXSTACKSOUNDS; i++)
if (StackSounds[i].lpSndBuf)
// stops the sound and release it if it is a duplicate
I_StopSound (i);
if (DSnd)
{
IDirectSound_Release(DSnd);
DSnd = NULL;
}
}
// ==========================================================================
// Startup DirectSound
// ==========================================================================
void I_StartupSound()
{
HRESULT hr;
LPDIRECTSOUNDBUFFER lpDsb;
DSBUFFERDESC dsbdesc;
WAVEFORMATEX wfm;
int cooplevel;
int frequency;
int p;
#ifdef HW3SOUND
char *sdrv_name;
snddev_t snddev;
#endif
sound_started = false;
if (nosound)
return;
// Secure and configure sound device first.
CONS_Printf("I_StartupSound: ");
// frequency of primary buffer may be set at cmd-line
p = M_CheckParm ("-freq");
if (p && p < myargc-1) {
frequency = atoi(myargv[p+1]);
CONS_Printf (" requested frequency of %d hz\n", frequency);
}
else
frequency = 22050;
// Set cooperative level
// Cooperative sound with other applications can be requested at cmd-line
if (M_CheckParm("-coopsound"))
cooplevel = DSSCL_PRIORITY;
else
cooplevel = DSSCL_EXCLUSIVE;
#ifdef HW3SOUND
if (M_CheckParm("-ds3d"))
{
hws_mode = HWS_DS3D;
sdrv_name = "s_ds3d.dll";
};
// There must be further sound drivers (such as A3D and EAX)!!!
if (hws_mode != HWS_DEFAULT_MODE)
{
if (Init3DSDriver(sdrv_name))
{
//nosound = true;
I_AddExitFunc(I_ShutdownSound);
snddev.cooplevel = cooplevel;
snddev.bps = 16;
snddev.hWnd = hWndMain;
snddev.sample_rate = frequency;
if (HW3S_Init(I_Error, &snddev))
{
CONS_Printf("HW 3D sound started\n");
return;
}
// Falls back to default sound system
HW3S_Shutdown();
Shutdown3DSDriver();
}
hws_mode = HWS_DEFAULT_MODE;
}
#endif
// Create DirectSound, use the default sound device
hr = DirectSoundCreate( NULL, &DSnd, NULL);
if ( FAILED( hr ) ) {
CONS_Printf (" DirectSoundCreate FAILED\n"
" there is no sound device or the sound device is under\n"
" the control of another application\n" );
nosound = true;
return;
}
// register exit code, now that we have at least DirectSound to close
I_AddExitFunc (I_ShutdownSound);
hr = DSnd->lpVtbl->SetCooperativeLevel (DSnd, hWndMain, cooplevel);
if ( FAILED( hr ) ) {
CONS_Printf (" SetCooperativeLevel FAILED\n");
nosound = true;
return;
}
// Set up DSBUFFERDESC structure.
ZeroMemory (&dsbdesc, sizeof(DSBUFFERDESC) );
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER |
DSBCAPS_CTRLVOLUME;
dsbdesc.dwBufferBytes = 0; // Must be 0 for primary buffer
dsbdesc.lpwfxFormat = NULL; // Must be NULL for primary buffer
// Set up structure for the desired format
ZeroMemory (&wfm, sizeof(WAVEFORMATEX));
wfm.wFormatTag = WAVE_FORMAT_PCM;
wfm.nChannels = 2; //STEREO SOUND!
wfm.nSamplesPerSec = frequency;
wfm.wBitsPerSample = 16;
wfm.nBlockAlign = wfm.wBitsPerSample / 8 * wfm.nChannels;
wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign;
// Gain access to the primary buffer
hr = DSnd->lpVtbl->CreateSoundBuffer (DSnd, &dsbdesc, &lpDsb, NULL);
if ( FAILED( hr ) ) {
CONS_Printf ("CreateSoundBuffer FAILED: %s (ErrNo %d)\n", DXErrorToString(hr), hr);
nosound = true;
return;
}
// Set the primary buffer to the desired format,
// but only if we are allowed to do it
if (cooplevel >= DSSCL_PRIORITY)
{
if (SUCCEEDED ( hr ))
{
// Set primary buffer to the desired format. If this fails,
// we'll just ignore and go with the default.
hr = lpDsb->lpVtbl->SetFormat (lpDsb, &wfm);
if (FAILED(hr))
CONS_Printf ("I_StartupSound : couldn't set primary buffer format.\n");
}
// move any on-board sound memory into a contiguous block
// to make the largest portion of free memory available.
CONS_Printf (" Compacting onboard sound-memory...");
hr = DSnd->lpVtbl->Compact (DSnd);
CONS_Printf (" %s\n", SUCCEEDED(hr) ? "done" : "FAILED");
}
// set the primary buffer to play continuously, for performance
// "... this method will ensure that the primary buffer is playing even when no secondary
// buffers are playing; in that case, silence will be played. This can reduce processing
// overhead when sounds are started and stopped in sequence, because the primary buffer
// will be playing continuously rather than stopping and starting between secondary buffers."
hr = lpDsb->lpVtbl->Play (lpDsb, 0, 0, DSBPLAY_LOOPING);
if ( FAILED ( hr ) )
CONS_Printf (" Primary buffer continuous play FAILED\n");
#ifdef DEBUGSOUND
{
DSCAPS DSCaps;
DSCaps.dwSize = sizeof(DSCAPS);
hr = DSnd->lpVtbl->GetCaps (DSnd, &DSCaps);
if (SUCCEEDED (hr))
{
if (DSCaps.dwFlags & DSCAPS_CERTIFIED)
CONS_Printf ("This driver has been certified by Microsoft\n");
if (DSCaps.dwFlags & DSCAPS_EMULDRIVER)
CONS_Printf ("No driver with DirectSound support installed (no hardware mixing)\n");
if (DSCaps.dwFlags & DSCAPS_PRIMARY16BIT)
CONS_Printf ("Supports 16-bit primary buffer\n");
if (DSCaps.dwFlags & DSCAPS_PRIMARY8BIT)
CONS_Printf ("Supports 8-bit primary buffer\n");
if (DSCaps.dwFlags & DSCAPS_SECONDARY16BIT)
CONS_Printf ("Supports 16-bit, hardware-mixed secondary buffers\n");
if (DSCaps.dwFlags & DSCAPS_SECONDARY8BIT)
CONS_Printf ("Supports 8-bit, hardware-mixed secondary buffers\n");
CONS_Printf ("Maximum number of hardware buffers: %d\n", DSCaps.dwMaxHwMixingStaticBuffers);
CONS_Printf ("Size of total hardware memory: %d\n", DSCaps.dwTotalHwMemBytes);
CONS_Printf ("Size of free hardware memory= %d\n", DSCaps.dwFreeHwMemBytes);
CONS_Printf ("Play Cpu Overhead (%% cpu cycles): %d\n", DSCaps.dwPlayCpuOverheadSwBuffers);
}
else
CONS_Printf (" couldn't get sound device caps.\n");
}
#endif
// save pointer to the primary DirectSound buffer for volume changes
DSndPrimary = lpDsb;
ZeroMemory (StackSounds, sizeof(StackSounds));
CONS_Printf("sound initialised.\n");
sound_started = true;
}
// ==========================================================================
//
// MUSIC API using MidiStream
//
// ==========================================================================
#define MIDBUFFERSIZE 128*1024L // buffer size for Mus2Midi conversion (ugly code)
#define SPECIAL_HANDLE_CLEANMIDI -1999 // tell I_StopSong() to do a full (slow) midiOutReset() on exit
static BOOL bMusicStarted;
static char* pMus2MidData; // buffer allocated at program start for Mus2Mid conversion
static UINT uMIDIDeviceID, uCallbackStatus;
static HMIDISTRM hStream;
static HANDLE hBufferReturnEvent; // for synch between the callback thread and main program thread
// (we need to synch when we decide to stop/free stream buffers)
static int nCurrentBuffer = 0, nEmptyBuffers;
static BOOL bBuffersPrepared = FALSE;
static DWORD dwVolCache[MAX_MIDI_IN_TRACKS];
DWORD dwVolumePercent; // accessed by win_main.c
// this is accessed by mid2strm.c conversion code
BOOL bMidiLooped = FALSE, bMidiPlaying = FALSE, bMidiPaused = FALSE;
CONVERTINFO ciStreamBuffers[NUM_STREAM_BUFFERS];
#define STATUS_KILLCALLBACK 100 // Signals that the callback should die
#define STATUS_CALLBACKDEAD 200 // Signals callback is done processing
#define STATUS_WAITINGFOREND 300 // Callback's waiting for buffers to play
#define DEBUG_CALLBACK_TIMEOUT 2000 // Wait 2 seconds for callback
// faB: don't freeze the main code if we debug..
#define VOL_CACHE_INIT 127 // for dwVolCache[]
static BOOL bMidiCanSetVolume; // midi caps
static void Mid2StreamFreeBuffers( void );
static void CALLBACK MidiStreamCallback (HMIDIIN hMidi, UINT uMsg, DWORD dwInstance,
DWORD dwParam1, DWORD dwParam2 );
static BOOL StreamBufferSetup( unsigned char* pMidiData, int iMidiSize );
// -------------------
// MidiErrorMessageBox
// Calls the midiOutGetErrorText() function and displays the text which
// corresponds to a midi subsystem error code.
// -------------------
static void MidiErrorMessageBox(MMRESULT mmr)
{
char szTemp[256];
/*szTemp[0] = '\2'; //white text to stand out*/
midiOutGetErrorText (mmr, szTemp/*+1*/, sizeof(szTemp));
CONS_Printf (szTemp);
/*MessageBox (GetActiveWindow(), szTemp+1, "LEGACY",
MB_OK | MB_ICONSTOP );*/
//wsprintf( szDebug, "Midi subsystem error: %s", szTemp );
}
// ----------------
// I_InitAudioMixer
// ----------------
#ifdef TESTCODE
void I_InitAudioMixer (void)
{
UINT cMixerDevs;
cMixerDevs = mixerGetNumDevs();
CONS_Printf ("%d mixer devices available\n", cMixerDevs);
}
#endif
// -----------
// I_InitMusic
// Startup Midi device for streaming output
// -----------
void I_InitMusic(void)
{
DWORD idx;
MMRESULT mmrRetVal;
UINT cMidiDevs;
MIDIOUTCAPS MidiOutCaps;
char* szTechnology;
bMusicStarted = false;
CONS_Printf("I_InitMusic()\n");
if (nomusic)
return;
// check out number of MIDI devices available
//
cMidiDevs = midiOutGetNumDevs();
if (!cMidiDevs) {
CONS_Printf ("No MIDI devices available, music is disabled\n");
nomusic = true;
return;
}
#ifdef DEBUGMIDISTREAM
else {
CONS_Printf ("%d MIDI devices available\n", cMidiDevs);
}
#endif
if( M_CheckParm("-winmidi") )
uMIDIDeviceID = atoi(M_GetNextParm());
else
uMIDIDeviceID = MIDI_MAPPER;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -