From b08a63790c0fbeacb3f96a74e3eb15abe8c70dab Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Mon, 25 Jun 2012 19:59:17 +0200 Subject: SDL project - added (very basic) SDL template in CApplication and CEngine - split project into two targets: colobot_old (dependent on DirectX and WinAPI) and colobot_new (dependent on SDL and OpenGL) - moved sound.h/cpp to old/ and created new template in Snd namespace - added platform-independent dialog boxes in app/system.h/cpp --- src/sound/sound.cpp | 1659 --------------------------------------------------- 1 file changed, 1659 deletions(-) (limited to 'src/sound/sound.cpp') diff --git a/src/sound/sound.cpp b/src/sound/sound.cpp index f307838..e69de29 100644 --- a/src/sound/sound.cpp +++ b/src/sound/sound.cpp @@ -1,1659 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch -// * -// * This program is free software: you can redistribute it and/or modify -// * it under the terms of the GNU General Public License as published by -// * the Free Software Foundation, either version 3 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 General Public License for more details. -// * -// * You should have received a copy of the GNU General Public License -// * along with this program. If not, see http://www.gnu.org/licenses/. - -// sound.cpp - - -#include -#include -#include -#include -#include - -#include "common/language.h" -#include "common/struct.h" -#include "common/iman.h" -#include "math/geometry.h" -#include "math/conv.h" -#include "old/math3d.h" -#include "sound/sound.h" - - -///////////////////////////////////////////////////////////////////////////// - - -const int LXIMAGE = 640; -const int LYIMAGE = 480; - - - -// Header .WAV file. - -struct WaveHeader -{ - BYTE RIFF[4]; // "RIFF" - DWORD dwSize; // size of data to follow - BYTE WAVE[4]; // "WAVE" - BYTE fmt_[4]; // "fmt " - DWORD dw16; // 16 - WORD wOne_0; // 1 - WORD wChnls; // number of Channels - DWORD dwSRate; // sample Rate - DWORD BytesPerSec; // sample Rate - WORD wBlkAlign; // 1 - WORD BitsPerSample; // sample size - BYTE DATA[4]; // "DATA" - DWORD dwDSize; // number of Samples -}; - - - - -// Displays an error DirectSound. - -void DisplayError(char *name, Sound sound, HRESULT err) -{ - char s[100]; - unsigned int i = err; - if ( err == DS_OK ) return; - sprintf(s, "SoundError in %s, sound=%d err=%d\n", name, sound, i); - OutputDebugString(s); - - if ( err == DSERR_ALLOCATED ) OutputDebugString("DSERR_ALLOCATED\n"); - if ( err == DSERR_CONTROLUNAVAIL ) OutputDebugString("DSERR_CONTROLUNAVAIL\n"); - if ( err == DSERR_INVALIDPARAM ) OutputDebugString("DSERR_INVALIDPARAM\n"); - if ( err == DSERR_INVALIDCALL ) OutputDebugString("DSERR_INVALIDCALL\n"); - if ( err == DSERR_GENERIC ) OutputDebugString("DSERR_GENERIC\n"); - if ( err == DSERR_PRIOLEVELNEEDED ) OutputDebugString("DSERR_PRIOLEVELNEEDED\n"); - if ( err == DSERR_OUTOFMEMORY ) OutputDebugString("DSERR_OUTOFMEMORY\n"); - if ( err == DSERR_BADFORMAT ) OutputDebugString("DSERR_BADFORMAT\n"); - if ( err == DSERR_UNSUPPORTED ) OutputDebugString("DSERR_UNSUPPORTED\n"); - if ( err == DSERR_NODRIVER ) OutputDebugString("DSERR_NODRIVER\n"); - if ( err == DSERR_ALREADYINITIALIZED ) OutputDebugString("DSERR_ALREADYINITIALIZED\n"); - if ( err == DSERR_NOAGGREGATION ) OutputDebugString("DSERR_NOAGGREGATION\n"); - if ( err == DSERR_BUFFERLOST ) OutputDebugString("DSERR_BUFFERLOST\n"); - if ( err == DSERR_OTHERAPPHASPRIO ) OutputDebugString("DSERR_OTHERAPPHASPRIO\n"); - if ( err == DSERR_UNINITIALIZED ) OutputDebugString("DSERR_UNINITIALIZED\n"); - if ( err == DSERR_NOINTERFACE ) OutputDebugString("DSERR_NOINTERFACE\n"); - if ( err == DSERR_ACCESSDENIED ) OutputDebugString("DSERR_ACCESSDENIED\n"); -} - -// Returns the name of the current folder. - -void GetCurrentDir(char *pName, int lg) -{ - int i; - - strncpy(pName, _pgmptr, lg-1); - pName[lg-1] = 0; - - lg = strlen(pName); - if ( lg == 0 ) return; - - for ( i=0 ; i 0 ) - { - lg --; - if ( pName[lg] == '\\' ) - { - pName[lg+1] = 0; - break; - } - } - - if ( lg > 6 && strcmp(pName+lg-6, "\\debug\\") == 0 ) - { - pName[lg-5] = 0; // ignores the folder \debug! - } - - if ( lg > 6 && strcmp(pName+lg-6, "\\release\\") == 0 ) - { - pName[lg-7] = 0; // ignores the folder \release ! - } -} - - - - -///////////////////////////////////////////////////////////////////////////// - - -// Changes the volume of midi. -// The volume is between 0 and 20! - -void InitMidiVolume(int volume) -{ - int nb, i, n; - MMRESULT result; - HMIDIOUT hmo = 0; - - static int table[21] = - { - 0x00000000, - 0x11111111, - 0x22222222, - 0x33333333, - 0x44444444, - 0x55555555, - 0x66666666, - 0x77777777, - 0x88888888, - 0x99999999, - 0xAAAAAAAA, - 0xBBBBBBBB, - 0xCCCCCCCC, - 0xDDDDDDDD, - 0xEEEEEEEE, - 0xF222F222, - 0xF555F555, - 0xF777F777, - 0xFAAAFAAA, - 0xFDDDFDDD, - 0xFFFFFFFF, - }; - - if ( volume < 0 ) volume = 0; - if ( volume > MAXVOLUME ) volume = MAXVOLUME; - - nb = midiOutGetNumDevs(); - for ( i=0 ; i MAXVOLUME ) volume = MAXVOLUME; - - // Open the mixer. This opens the mixer with a deviceID of 0. If you - // have a single sound card/mixer, then this will open it. If you have - // multiple sound cards/mixers, the deviceIDs will be 0, 1, 2, and - // so on. - rc = mixerOpen(&hMixer, 0,0,0,0); - if ( rc != MMSYSERR_NOERROR ) - { - return false; // Couldn't open the mixer. - } - - // Initialize MIXERLINE structure. - ZeroMemory(&mxl,sizeof(mxl)); - mxl.cbStruct = sizeof(mxl); - - // Specify the line you want to get. You are getting the input line - // here. If you want to get the output line, you need to use - // MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT. - mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC; - - rc = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl, - MIXER_GETLINEINFOF_COMPONENTTYPE); - if ( rc != MMSYSERR_NOERROR ) - { - return false; // Couldn't get the mixer line. - } - - // Get the control. - ZeroMemory(&mxlc, sizeof(mxlc)); - mxlc.cbStruct = sizeof(mxlc); - mxlc.dwLineID = mxl.dwLineID; -//? mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_PEAKMETER; -//? mxlc.dwControlType = MIXERCONTROL_CONTROLF_UNIFORM; - mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; - mxlc.cControls = 1; - mxlc.cbmxctrl = sizeof(mxc); - mxlc.pamxctrl = &mxc; - ZeroMemory(&mxc, sizeof(mxc)); - mxc.cbStruct = sizeof(mxc); - rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc, - MIXER_GETLINECONTROLSF_ONEBYTYPE); -//? MIXER_GETLINECONTROLSF_ALL); - if ( rc != MMSYSERR_NOERROR ) - { - return false; // Couldn't get the control. - } - - // After successfully getting the peakmeter control, the volume range - // will be specified by mxc.Bounds.lMinimum to mxc.Bounds.lMaximum. - - MIXERCONTROLDETAILS mxcd; // Gets the control values. - MIXERCONTROLDETAILS_SIGNED volStruct; // Gets the control values. - - volStruct.lValue = volume*(mxc.Bounds.lMaximum-mxc.Bounds.lMinimum); - volStruct.lValue /= MAXVOLUME; - volStruct.lValue += mxc.Bounds.lMinimum; - - // Initialize the MIXERCONTROLDETAILS structure - ZeroMemory(&mxcd, sizeof(mxcd)); - mxcd.cbStruct = sizeof(mxcd); - mxcd.cbDetails = sizeof(volStruct); - mxcd.dwControlID = mxc.dwControlID; - mxcd.paDetails = &volStruct; - mxcd.cChannels = 1; - - // Get the current value of the peakmeter control. Typically, you - // would set a timer in your program to query the volume every 10th - // of a second or so. - rc = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd, - MIXER_SETCONTROLDETAILSF_VALUE); - if ( rc != MMSYSERR_NOERROR ) - { - return false; // Couldn't get the current volume. - } -#endif - - return true; -} - - -///////////////////////////////////////////////////////////////////////////// - - -// Constructor. - -CSound::CSound(CInstanceManager* iMan) -{ - int i; - - m_iMan = iMan; - m_iMan->AddInstance(CLASS_SOUND, this); - - m_bEnable = false; - m_bState = false; - m_bAudioTrack = true; - m_ctrl3D = true; - m_bDebugMode = false; - m_MidiDeviceID = 0; - m_MIDIMusic = 0; - m_audioVolume = 20; - m_midiVolume = 15; - m_lastMidiVolume = 0; - m_listener = 0; - m_lastTime = 0.0f; - m_playTime = 0.0f; - m_uniqueStamp = 0; - m_maxSound = MAXSOUND; - m_eye = Math::Vector(0.0f, 0.0f, 0.0f); - m_hWnd = 0; - - m_lpDS = NULL; - - ZeroMemory(m_channel, sizeof(SoundChannel)*MAXSOUND); - for ( i=0 ; iStop(); - m_channel[i].soundBuffer->Release(); - m_channel[i].soundBuffer = 0; - m_channel[i].bUsed = false; - } - } - - if ( m_listener != NULL ) - { - m_listener->Release(); - m_listener = NULL; - } - - if ( m_lpDS != NULL ) - { - m_lpDS->Release(); - m_lpDS = NULL; - } -} - - -// Specifies whether you are in debug mode. - -void CSound::SetDebugMode(bool bMode) -{ - m_bDebugMode = bMode; -} - - -// Initializes DirectSound. - -bool CSound::Create(HWND hWnd, bool b3D) -{ - LPDIRECTSOUNDBUFFER primary; - DSBUFFERDESC dsbdesc; - DSCAPS dscaps; - WAVEFORMATEX wfx; - HRESULT hr; - - if ( !DirectSoundCreate(NULL, &m_lpDS, NULL) == DS_OK ) - { - OutputDebugString("Fatal error: DirectSoundCreate\n"); - m_bEnable = false; - return false; - } - -//? m_lpDS->SetCooperativeLevel(hWnd, DSSCL_NORMAL); - m_lpDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY); - - if ( !RetSound3DCap() ) b3D = false; - - m_ctrl3D = false; - if ( b3D ) - { - // Obtain primary buffer, asking it for 3D control. - ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); - dsbdesc.dwSize = sizeof(DSBUFFERDESC); - dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D; - hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL ); - if ( hr == S_OK ) - { - m_ctrl3D = true; - } - } - - if ( !m_ctrl3D ) - { - // Obtain primary buffer, without 3D control. - ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); - dsbdesc.dwSize = sizeof(DSBUFFERDESC); - dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; - hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL ); - if ( hr != S_OK ) - { - return false; - } - m_ctrl3D = false; - } - - if ( m_ctrl3D ) - { - hr = primary->QueryInterface( IID_IDirectSound3DListener, - (VOID**)&m_listener ); - if ( hr != S_OK ) - { - primary->Release(); - return false; - } - } - - // Set primary buffer format to 44kHz and 16-bit output. - ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); - wfx.wFormatTag = WAVE_FORMAT_PCM; - wfx.nChannels = 2; - wfx.nSamplesPerSec = 22050; -//? wfx.nSamplesPerSec = 44100; - wfx.wBitsPerSample = 16; - wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; - wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; - hr = primary->SetFormat(&wfx); - if ( hr != S_OK ) - { - DisplayError("SetFormat", SOUND_CLICK, hr); - } - - // Release the primary buffer, since it is not need anymore. - primary->Release(); - - // Search the maximum possible voices. - if ( m_ctrl3D ) - { - ZeroMemory( &dscaps, sizeof(DSCAPS) ); - dscaps.dwSize = sizeof(DSCAPS); - hr = m_lpDS->GetCaps(&dscaps); - if ( hr == DS_OK ) - { - m_maxSound = dscaps.dwMaxHwMixingAllBuffers; - if ( dscaps.dwMaxHw3DAllBuffers > 0 && - m_maxSound > (int)dscaps.dwMaxHw3DAllBuffers ) - { - m_maxSound = dscaps.dwMaxHw3DAllBuffers; - } - if ( m_maxSound > MAXSOUND ) m_maxSound = MAXSOUND; - } - } - - m_bEnable = true; - m_hWnd = hWnd; - return true; -} - - -// Indicates whether to play sounds in 3D or not. - -void CSound::SetSound3D(bool bMode) -{ - StopAll(); - - if ( m_listener != NULL ) - { - m_listener->Release(); - m_listener = NULL; - } - - if ( m_lpDS != NULL ) - { - m_lpDS->Release(); - m_lpDS = NULL; - } - - Create(m_hWnd, bMode); -} - -bool CSound::RetSound3D() -{ - return m_ctrl3D; -} - -// Indicates whether it is possible to play sounds in 3D. - -bool CSound::RetSound3DCap() -{ - DSCAPS dscaps; - HRESULT hr; - - ZeroMemory( &dscaps, sizeof(DSCAPS) ); - dscaps.dwSize = sizeof(DSCAPS); - hr = m_lpDS->GetCaps(&dscaps); - if ( hr != DS_OK ) return false; - - return ( dscaps.dwMaxHw3DAllBuffers > 0 ); -} - - - -// Returns the state of DirectSound. - -bool CSound::RetEnable() -{ - return m_bEnable; -} - - -// Switches on or off the sound. - -void CSound::SetState(bool bState) -{ - m_bState = bState; -} - -// Specifies the pathname to the CD. - -void CSound::SetCDpath(char *path) -{ - strcpy(m_CDpath, path); -} - -// Switches on or off the CD-audio music. - -void CSound::SetAudioTrack(bool bAudio) -{ - m_bAudioTrack = bAudio; -} - - -// Manages volumes of audio (. Wav) and midi (. Mid). - -void CSound::SetAudioVolume(int volume) -{ - m_audioVolume = volume; -} - -int CSound::RetAudioVolume() -{ - if ( !m_bEnable ) return 0; - return m_audioVolume; -} - -void CSound::SetMidiVolume(int volume) -{ - m_midiVolume = volume; - - if ( m_bAudioTrack ) - { - InitAudioTrackVolume(m_midiVolume); - } -} - -int CSound::RetMidiVolume() -{ - if ( !m_bEnable ) return 0; - return m_midiVolume; -} - - -// Reads a file. - -bool CSound::ReadFile(Sound sound, char *metaname, char *filename) -{ - WaveHeader wavHdr; - DWORD size; - int err; - - // Open the wave file. - err = g_metafile.Open(metaname, filename); - if ( err != 0 ) return false; - - // Read in the wave header. - g_metafile.Read(&wavHdr, sizeof(wavHdr)); - - // Figure out the size of the data region. - size = wavHdr.dwDSize; - - if ( m_files[sound] != 0 ) - { - free(m_files[sound]); - } - m_files[sound] = (char*)malloc(sizeof(WaveHeader)+size); - - memcpy(m_files[sound], &wavHdr, sizeof(WaveHeader)); - g_metafile.Read(m_files[sound]+sizeof(WaveHeader), size); - - // Close out the wave file. - g_metafile.Close(); - return true; -} - -// Hides all sound files (. Wav). - -void CSound::CacheAll() -{ - int i; - char meta[50]; - char name[50]; - - if ( !m_bEnable ) return; - - if ( m_bDebugMode ) - { - strcpy(meta, ""); - } - else - { -#if _SCHOOL - strcpy(meta, "ceebot3.dat"); -#else - strcpy(meta, "colobot3.dat"); -#endif - } - - for ( i=0 ; iGetStatus(&status); - if ( (status&DSBSTATUS_PLAYING) == 0 ) - { - m_channel[i].priority = priority; - m_channel[i].uniqueStamp = m_uniqueStamp++; - channel = i; - bAlreadyLoaded = true; - return true; - } - } -#endif - - // Seeks a channel completely free. - for ( i=0 ; iGetStatus(&status); - if ( (status&DSBSTATUS_PLAYING) == 0 ) - { - m_channel[i].soundBuffer->Release(); - m_channel[i].soundBuffer = 0; - m_channel[i].priority = priority; - m_channel[i].uniqueStamp = m_uniqueStamp++; - - channel = i; - bAlreadyLoaded = false; - return true; - } - } - - // Seeks a lower priority channel used. - for ( i=0 ; i= priority ) continue; - - m_channel[i].soundBuffer->Stop(); - m_channel[i].soundBuffer->Release(); - m_channel[i].soundBuffer = 0; - m_channel[i].priority = priority; - m_channel[i].uniqueStamp = m_uniqueStamp++; - - channel = i; - bAlreadyLoaded = false; - return true; - } - - // Seeks a channel used the same or lower priority. - for ( i=0 ; i priority ) continue; - - m_channel[i].soundBuffer->Stop(); - m_channel[i].soundBuffer->Release(); - m_channel[i].soundBuffer = 0; - m_channel[i].priority = priority; - m_channel[i].uniqueStamp = m_uniqueStamp++; - - channel = i; - bAlreadyLoaded = false; - return true; - } - - char s[100]; - sprintf(s, "Sound %d forget (priority=%d)\n", sound, priority); - OutputDebugString(s); - - return false; -} - -// Reads in data from a wave file. - -bool CSound::ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size) -{ - LPVOID pData1; - DWORD dwData1Size; - LPVOID pData2; - DWORD dwData2Size; - HRESULT hr; - - // Lock data in buffer for writing. - hr = lpDSB->Lock(0, size, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR); - if ( hr != DS_OK ) - { - return false; - } - - // Read in first chunk of data. - if ( dwData1Size > 0 ) - { - memcpy(pData1, m_files[sound]+sizeof(WaveHeader), dwData1Size); - } - - // Read in second chunk if necessary. - if ( dwData2Size > 0 ) - { - memcpy(pData2, m_files[sound]+sizeof(WaveHeader)+dwData1Size, dwData2Size); - } - - // Unlock data in buffer. - hr = lpDSB->Unlock(pData1, dwData1Size, pData2, dwData2Size); - if ( hr != DS_OK ) - { - return false; - } - - return true; -} - -// Creates a DirectSound buffer. - -bool CSound::CreateSoundBuffer(int channel, DWORD size, DWORD freq, - DWORD bitsPerSample, DWORD blkAlign, - bool bStereo) -{ - PCMWAVEFORMAT pcmwf; - DSBUFFERDESC dsbdesc; - DS3DBUFFER bufferParams; // 3D buffer properties - HRESULT hr; - - // Set up wave format structure. - memset( &pcmwf, 0, sizeof(PCMWAVEFORMAT) ); - pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM; - pcmwf.wf.nChannels = bStereo ? 2 : 1; - pcmwf.wf.nSamplesPerSec = freq; - pcmwf.wf.nBlockAlign = (WORD)blkAlign; - pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign; - pcmwf.wBitsPerSample = (WORD)bitsPerSample; - - // Set up DSBUFFERDESC structure. - memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out. - dsbdesc.dwSize = sizeof(DSBUFFERDESC); - if ( m_ctrl3D ) - { - dsbdesc.dwFlags = DSBCAPS_CTRL3D|DSBCAPS_MUTE3DATMAXDISTANCE| - DSBCAPS_LOCDEFER| - DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLFREQUENCY; - } - else - { - dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN|DSBCAPS_CTRLFREQUENCY; - } - dsbdesc.dwBufferBytes = size; - dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf; - - hr = m_lpDS->CreateSoundBuffer(&dsbdesc, &m_channel[channel].soundBuffer, NULL); - if ( hr != DS_OK ) return false; - - if ( m_ctrl3D ) - { - hr = m_channel[channel].soundBuffer->QueryInterface - ( - IID_IDirectSound3DBuffer, - (VOID**)&m_channel[channel].soundBuffer3D - ); - if ( hr != DS_OK ) return false; - } - - m_channel[channel].bUsed = true; - m_channel[channel].bMute = false; - return true; -} - -// Creates a DirectSound buffer from a wave file. - -bool CSound::CreateBuffer(int channel, Sound sound) -{ - WaveHeader* wavHdr; - DWORD size; - bool bStereo; - - if ( m_files[sound] == 0 ) return false; - - wavHdr = (WaveHeader*)m_files[sound]; - size = wavHdr->dwDSize; - bStereo = wavHdr->wChnls > 1 ? true : false; - - // Create the sound buffer for the wave file. - if ( !CreateSoundBuffer(channel, size, wavHdr->dwSRate, - wavHdr->BitsPerSample, wavHdr->wBlkAlign, bStereo) ) - { - return false; - } - - // Read the data for the wave file into the sound buffer. - if ( !ReadData(m_channel[channel].soundBuffer, sound, size) ) - { - return false; - } - - m_channel[channel].type = sound; - - // Close out the wave file. - return true; -} - -// Calculates the volume and pan of a sound, non-3D mode. - -void CSound::ComputeVolumePan2D(int channel, const Math::Vector &pos) -{ - float dist, a, g; - - if ( pos.x == m_eye.x && - pos.y == m_eye.y && - pos.z == m_eye.z ) - { - m_channel[channel].volume = 1.0f; // maximum volume - m_channel[channel].pan = 0.0f; // at the center - return; - } - -#if _TEEN - dist = Math::Distance(pos, m_eye); - if ( dist >= 210.0f ) // very far? - { - m_channel[channel].volume = 0.0f; // silence - m_channel[channel].pan = 0.0f; // at the center - return; - } - if ( dist <= 10.0f ) // very close? - { - m_channel[channel].volume = 1.0f; // maximum volume - m_channel[channel].pan = 0.0f; // at the center - return; - } - m_channel[channel].volume = 1.0f-((dist-10.0f)/200.0f); -#else - dist = Math::Distance(pos, m_eye); - if ( dist >= 110.0f ) // very far? - { - m_channel[channel].volume = 0.0f; // silence - m_channel[channel].pan = 0.0f; // at the center - return; - } - if ( dist <= 10.0f ) // very close? - { - m_channel[channel].volume = 1.0f; // maximum volume - m_channel[channel].pan = 0.0f; // at the center - return; - } - m_channel[channel].volume = 1.0f-((dist-10.0f)/100.0f); -#endif - - a = Math::RotateAngle(m_lookat.x-m_eye.x, m_eye.z-m_lookat.z); - g = Math::RotateAngle(pos.x-m_eye.x, m_eye.z-pos.z); - m_channel[channel].pan = sinf(Math::Direction(a, g)); -} - -// Sounds in the middle. -// Returns the associated channel or -1. - -int CSound::Play(Sound sound, float amplitude, float frequency, bool bLoop) -{ - return Play(sound, m_lookat, amplitude, frequency, bLoop); -} - -// Sounds at a given position. -// Returns the associated channel or -1. - -int CSound::Play(Sound sound, Math::Vector pos, - float amplitude, float frequency, bool bLoop) -{ - DS3DBUFFER sb; - int channel, iVolume, iPan, iFreq, uniqueStamp; - bool bAlreadyLoaded; - DWORD flag, freq; - HRESULT err; - - if ( !m_bEnable ) return -1; - if ( !m_bState || m_audioVolume == 0 ) return -1; - -//? if ( Math::Distance(pos, m_eye) > 100.0f ) return -1; - - if ( !SearchFreeBuffer(sound, channel, bAlreadyLoaded) ) return -1; - - if ( !bAlreadyLoaded ) - { - if ( !CreateBuffer(channel, sound) ) - { - if ( m_channel[channel].bUsed && - m_channel[channel].soundBuffer != 0 ) - { - m_channel[channel].soundBuffer->Release(); - m_channel[channel].soundBuffer = 0; - } - m_channel[channel].bUsed = false; - return -1; - } - } - - m_channel[channel].pos = pos; - - if ( m_ctrl3D ) - { - m_channel[channel].volume = 1.0f; - m_channel[channel].pan = 0.0f; - } - else - { - ComputeVolumePan2D(channel, pos); - } - -#if 0 - DWORD status; - m_channel[channel].soundBuffer->GetStatus(&status); - char s[100]; - sprintf(s, "Play sound=%d status=%d channel=%d flag=%d\n", sound, status, channel, bAlreadyLoaded); - OutputDebugString(s); -#endif - - m_channel[channel].oper[0].bUsed = false; - m_channel[channel].startAmplitude = amplitude; - m_channel[channel].startFrequency = frequency; - m_channel[channel].changeFrequency = 1.0f; - - if ( m_ctrl3D ) - { - sb.dwSize = sizeof(DS3DBUFFER); - err = m_channel[channel].soundBuffer3D->GetAllParameters(&sb); - DisplayError("GetAllParameters", sound, err); - - sb.vPosition = VEC_TO_D3DVEC(pos); -//? sb.dwInsideConeAngle = 90; -//? sb.dwOutsideConeAngle = 180; -//? sb.vConeOrientation = Math::Vector(0.0f, 1.0f, 0.0f); - sb.lConeOutsideVolume = DSBVOLUME_MIN; -#if _TEEN - sb.flMinDistance = 50.0f; -#else - sb.flMinDistance = 20.0f; -#endif - sb.flMaxDistance = DS3D_DEFAULTMAXDISTANCE; - - err = m_channel[channel].soundBuffer3D->SetAllParameters(&sb, DS3D_IMMEDIATE); - DisplayError("SetAllParameters", sound, err); - } - - amplitude *= m_channel[channel].volume; - amplitude *= (float)m_audioVolume/MAXVOLUME; - iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f); - if ( iVolume > 0 ) iVolume = 0; - err = m_channel[channel].soundBuffer->SetVolume(iVolume); - DisplayError("SetVolume", sound, err); - - if ( !m_ctrl3D ) - { - iPan = (int)(m_channel[channel].pan*10000.0f); - err = m_channel[channel].soundBuffer->SetPan(iPan); - DisplayError("SetPan", sound, err); - } - - if ( !bAlreadyLoaded ) - { - err = m_channel[channel].soundBuffer->GetFrequency(&freq); - DisplayError("GetFrequency", sound, err); - m_channel[channel].initFrequency = freq; - } - iFreq = (int)(frequency*m_channel[channel].initFrequency); - err = m_channel[channel].soundBuffer->SetFrequency(iFreq); - DisplayError("SetFrequency", sound, err); - - err = m_channel[channel].soundBuffer->SetCurrentPosition(0); - DisplayError("SetCurrentPosition", sound, err); - - flag = bLoop?DSBPLAY_LOOPING:0; -//? flag |= DSBPLAY_LOCHARDWARE|DSBPLAY_TERMINATEBY_DISTANCE; -//? flag |= DSBPLAY_TERMINATEBY_DISTANCE; - err = m_channel[channel].soundBuffer->Play(0, 0, flag); - DisplayError("Play", sound, err); - if ( err == DSERR_BADFORMAT ) - { - iFreq = m_channel[channel].initFrequency; - err = m_channel[channel].soundBuffer->SetFrequency(iFreq); - DisplayError("SetFrequency (repeat)", sound, err); - - err = m_channel[channel].soundBuffer->Play(0, 0, flag); - DisplayError("Play (repeat)", sound, err); - } - - uniqueStamp = m_channel[channel].uniqueStamp; - return channel | ((uniqueStamp&0xffff)<<16); -} - -// Check a channel number. -// Adapts the channel, so it can be used as an offset in m_channel. - -bool CSound::CheckChannel(int &channel) -{ - int uniqueStamp; - - uniqueStamp = (channel>>16)&0xffff; - channel &= 0xffff; - - if ( !m_bEnable ) return false; - if ( !m_bState || m_audioVolume == 0 ) return false; - - if ( channel < 0 || channel >= m_maxSound ) return false; - if ( !m_channel[channel].bUsed ) return false; - - if ( m_channel[channel].uniqueStamp != uniqueStamp ) return false; - - return true; -} - -// Removes all envelopes. - -bool CSound::FlushEnvelope(int channel) -{ - if ( !CheckChannel(channel) ) return false; - - m_channel[channel].oper[0].bUsed = false; - return true; -} - -// Adds an operation envelope. - -bool CSound::AddEnvelope(int channel, float amplitude, float frequency, - float time, SoundNext oper) -{ - int i; - - if ( !CheckChannel(channel) ) return false; - - for ( i=0 ; iSetPosition(pos.x, pos.y, pos.z, DS3D_DEFERRED); - } - else - { - ComputeVolumePan2D(channel, pos); - - if ( !m_channel[channel].oper[0].bUsed ) - { - amplitude = m_channel[channel].startAmplitude; - amplitude *= m_channel[channel].volume; - amplitude *= (float)m_audioVolume/MAXVOLUME; - iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f); - if ( iVolume > 0 ) iVolume = 0; - err = m_channel[channel].soundBuffer->SetVolume(iVolume); - DisplayError("SetVolume", m_channel[channel].type, err); - } - - pan = m_channel[channel].pan; - iPan = (int)(pan*10000.0f); - err = m_channel[channel].soundBuffer->SetPan(iPan); - DisplayError("SetPan", m_channel[channel].type, err); - } - return true; -} - -// Changes the frequency of a sound. -// 0.5 down of an octave and 2.0 up of an octave. - -bool CSound::Frequency(int channel, float frequency) -{ - HRESULT err; - int iFreq; - - if ( !CheckChannel(channel) ) return false; - - m_channel[channel].changeFrequency = frequency; - - if ( !m_channel[channel].oper[0].bUsed ) - { - iFreq = (int)(frequency*m_channel[channel].initFrequency); - err = m_channel[channel].soundBuffer->SetFrequency(iFreq); - DisplayError("Frequency", m_channel[channel].type, err); - } - - return true; -} - -// Stops sound. - -bool CSound::Stop(int channel) -{ - if ( !CheckChannel(channel) ) return false; - - m_channel[channel].soundBuffer->Stop(); - return true; -} - -// Stops all sounds. - -bool CSound::StopAll() -{ - DWORD status; - int i; - - for ( i=0 ; iGetStatus(&status); - if ( (status&DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING ) - { - m_channel[i].soundBuffer->Stop(); - } - m_channel[i].soundBuffer->Stop(); - m_channel[i].soundBuffer->Release(); - m_channel[i].soundBuffer = 0; - - m_channel[i].bUsed = false; - } - return true; -} - -// Silent all sounds. - -bool CSound::MuteAll(bool bMute) -{ - int i; - - for ( i=0 ; iSetVolume(-10000); // silence - continue; - } - - m_channel[i].oper[0].currentTime += rTime; - - progress = m_channel[i].oper[0].currentTime / m_channel[i].oper[0].totalTime; - if ( progress > 1.0f ) progress = 1.0f; - - volume = progress; - volume *= m_channel[i].oper[0].finalAmplitude-m_channel[i].startAmplitude; - volume += m_channel[i].startAmplitude; - volume *= m_channel[i].volume; - volume *= (float)m_audioVolume/MAXVOLUME; - iVolume = (int)((powf(volume, 0.2f)-1.0f)*10000.0f); - if ( iVolume > 0 ) iVolume = 0; - m_channel[i].soundBuffer->SetVolume(iVolume); - - freq = progress; - freq *= m_channel[i].oper[0].finalFrequency-m_channel[i].startFrequency; - freq += m_channel[i].startFrequency; - freq *= m_channel[i].changeFrequency; - iFreq = (int)(freq*m_channel[i].initFrequency); - err = m_channel[i].soundBuffer->SetFrequency(iFreq); - DisplayError("FrameMove::Frequency", m_channel[i].type, err); - - if ( m_channel[i].oper[0].currentTime >= - m_channel[i].oper[0].totalTime ) - { - next = m_channel[i].oper[0].nextOper; - - if ( next == SOPER_LOOP ) - { - m_channel[i].oper[0].currentTime = 0.0f; - } - else - { - OperNext(i); - - if ( next == SOPER_STOP ) - { - m_channel[i].soundBuffer->Stop(); - } - } - } - } - - m_lastTime += rTime; - if ( m_lastTime >= 0.05f && m_listener != 0 ) - { - m_lastTime = 0.0f; - m_listener->CommitDeferredSettings(); - } -} - -// Specifies the position of the listener. -// Must be called whenever the camera moves. - -void CSound::SetListener(Math::Vector eye, Math::Vector lookat) -{ - DS3DLISTENER listenerParams; - HRESULT err; - float amplitude, pan; - int i, iVolume, iPan; - - m_eye = eye; - m_lookat = lookat; - - if ( m_listener == 0 ) - { - if ( m_ctrl3D ) return; - - for ( i=0 ; i 0 ) iVolume = 0; - err = m_channel[i].soundBuffer->SetVolume(iVolume); - DisplayError("SetVolume", m_channel[i].type, err); - } - - pan = m_channel[i].pan; - iPan = (int)(pan*10000.0f); - err = m_channel[i].soundBuffer->SetPan(iPan); - DisplayError("SetPan", m_channel[i].type, err); - } - return; - } - - // Get listener parameters. - listenerParams.dwSize = sizeof(DS3DLISTENER); - m_listener->GetAllParameters(&listenerParams); - - listenerParams.vPosition = VEC_TO_D3DVEC(eye); - listenerParams.vOrientFront = VEC_TO_D3DVEC(lookat-eye); - listenerParams.vOrientTop = D3DVECTOR(0.0f, 1.0f, 0.0f); - listenerParams.flDistanceFactor = 10.0f; - listenerParams.flRolloffFactor = 1.0f; - - m_listener->SetAllParameters(&listenerParams, DS3D_DEFERRED); -} - - - - -// Uses MCI to play a MIDI file. The window procedure -// is notified when playback is complete. - -bool CSound::PlayMusic(int rank, bool bRepeat) -{ - MCI_OPEN_PARMS mciOpenParms; - MCI_PLAY_PARMS mciPlayParms; - DWORD dwReturn; - char filename[MAX_PATH]; - - m_bRepeatMusic = bRepeat; - m_playTime = 0.0f; - - if ( m_midiVolume == 0 ) return true; - - if ( m_bAudioTrack ) - { - return PlayAudioTrack(rank); - } - - if ( !m_bEnable ) return true; - InitMidiVolume(m_midiVolume); - m_lastMidiVolume = m_midiVolume; - - GetCurrentDir(filename, MAX_PATH-30); - sprintf(filename+strlen(filename), "sound\\music%.3d.blp", rank-1); - - // Open the device by specifying the device and filename. - // MCI will attempt to choose the MIDI mapper as the output port. - mciOpenParms.lpstrDeviceType = "sequencer"; - mciOpenParms.lpstrElementName = filename; - dwReturn = mciSendCommand(NULL, - MCI_OPEN, - MCI_OPEN_TYPE|MCI_OPEN_ELEMENT, - (DWORD)(LPVOID)&mciOpenParms); - if ( dwReturn != 0 ) - { - mciGetErrorString(dwReturn, filename, 128); - // Failed to open device. Don't close it; just return error. - return false; - } - - // The device opened successfully; get the device ID. - m_MidiDeviceID = mciOpenParms.wDeviceID; - - // Begin playback. - mciPlayParms.dwCallback = (DWORD)m_hWnd; - dwReturn = mciSendCommand(m_MidiDeviceID, - MCI_PLAY, - MCI_NOTIFY, - (DWORD)(LPVOID)&mciPlayParms); - if ( dwReturn != 0 ) - { - mciGetErrorString(dwReturn, filename, 128); - StopMusic(); - return false; - } - - m_MIDIMusic = rank; - return true; -} - -// Uses MCI to play a CD-audio track. The window procedure -// is notified when playback is complete. -// The rank parameter is in space [1..n] ! -// For CD mix (data/audio), it will be [2..n] ! - -bool CSound::PlayAudioTrack(int rank) -{ -#if _SOUNDTRACKS - MCI_OPEN_PARMS mciOpenParms; - MCI_PLAY_PARMS mciPlayParms; - MCI_SET_PARMS mciSetParms; - DWORD dwReturn; - char filename[MAX_PATH]; - char device[10]; - - if ( !m_bEnable ) return true; -//? if ( m_midiVolume == 0 ) return true; - InitAudioTrackVolume(m_midiVolume); - m_lastMidiVolume = m_midiVolume; - - // Open the device by specifying the device and filename. - // MCI will attempt to choose the MIDI mapper as the output port. - memset(&mciOpenParms, 0, sizeof(MCI_OPEN_PARMS)); -//? mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO; -//? dwReturn = mciSendCommand(NULL, -//? MCI_OPEN, -//? MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID, -//? (DWORD)(LPVOID)&mciOpenParms); - mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO; - if ( m_CDpath[0] == 0 ) - { - dwReturn = mciSendCommand(NULL, - MCI_OPEN, - MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID, - (DWORD)(LPVOID)&mciOpenParms); - } - else - { - device[0] = m_CDpath[0]; - device[1] = ':'; - device[2] = 0; - mciOpenParms.lpstrElementName = device; - dwReturn = mciSendCommand(NULL, - MCI_OPEN, - MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT, - (DWORD)(LPVOID)&mciOpenParms); - } - if ( dwReturn != 0 ) - { - mciGetErrorString(dwReturn, filename, 128); - // Failed to open device. Don't close it; just return error. - return false; - } - - // The device opened successfully; get the device ID. - m_MidiDeviceID = mciOpenParms.wDeviceID; - - // Set the time format to track/minute/second/frame (TMSF). - memset(&mciSetParms, 0, sizeof(MCI_SET_PARMS)); - mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF; - dwReturn = mciSendCommand(m_MidiDeviceID, - MCI_SET, - MCI_SET_TIME_FORMAT, - (DWORD)&mciSetParms); - if ( dwReturn != 0 ) - { - mciGetErrorString(dwReturn, filename, 128); - StopMusic(); - return false; - } - - // Begin playback. - memset(&mciPlayParms, 0, sizeof(MCI_PLAY_PARMS)); - mciPlayParms.dwCallback = (DWORD)m_hWnd; - mciPlayParms.dwFrom = MCI_MAKE_TMSF(rank+0, 0, 0, 0); - mciPlayParms.dwTo = MCI_MAKE_TMSF(rank+1, 0, 0, 0); - dwReturn = mciSendCommand(m_MidiDeviceID, - MCI_PLAY, - MCI_NOTIFY|MCI_FROM|MCI_TO, - (DWORD)(LPVOID)&mciPlayParms); - if ( dwReturn != 0 ) - { - mciGetErrorString(dwReturn, filename, 128); - StopMusic(); - return false; - } - - m_MIDIMusic = rank; -#endif - return true; -} - -// Restart the MIDI player. - -bool CSound::RestartMusic() -{ - if ( !m_bRepeatMusic ) return false; - - OutputDebugString("RestartMusic\n"); - if ( !m_bEnable ) return true; -//? if ( m_midiVolume == 0 ) return true; - if ( m_MIDIMusic == 0 ) return false; - if ( m_playTime < 5.0f ) return false; - - return PlayMusic(m_MIDIMusic, true); -} - -// Shuts down the MIDI player. - -void CSound::SuspendMusic() -{ - if ( !m_bEnable ) return; - -//? if ( m_MidiDeviceID && m_midiVolume != 0 ) - if ( m_MidiDeviceID ) - { - if ( m_bAudioTrack ) mciSendCommand(m_MidiDeviceID, MCI_STOP, 0, NULL); - mciSendCommand(m_MidiDeviceID, MCI_CLOSE, 0, NULL); - } - m_MidiDeviceID = 0; -} - -// Shuts down the MIDI player. - -void CSound::StopMusic() -{ - SuspendMusic(); - m_MIDIMusic = 0; -} - -// Returns true if the music is in progress. - -bool CSound::IsPlayingMusic() -{ - return (m_MIDIMusic != 0); -} - -// Adjusts the volume of currently music, if necessary. - -void CSound::AdaptVolumeMusic() -{ - if ( m_midiVolume != m_lastMidiVolume ) - { - if ( m_bAudioTrack ) - { - InitAudioTrackVolume(m_midiVolume); - } - else - { - InitMidiVolume(m_midiVolume); - } - m_lastMidiVolume = m_midiVolume; - RestartMusic(); - } -} - -- cgit v1.2.3-1-g7c22