1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092 |
- /*
- * Seven Kingdoms: Ancient Adversaries
- *
- * Copyright 1997,1998 Enlight Software Ltd.
- *
- * 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 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 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/>.
- *
- */
- //Filename : OAUDIO.CPP
- //Description : Object Midi Audio and Digitized Sound
- //Ownership : Gilbert
- #include <windows.h>
- #include <windowsx.h>
- #include <commdlg.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <direct.h>
- #include <mmsystem.h>
- #include <string.h>
- #include <limits.h>
- #include <OSYS.h>
- #include <OBOX.h>
- #include <OAUDIO.h>
- #include <OVGALOCK.h>
- //---------------- Define constant ------------------//
- //
- // DirectSoundBuffer size = LWAV_STREAM_BUFSIZ * LWAV_BANKS
- // if it is going to play a high transfer rate wave
- // (e.g. 16-bit 44.1kHz Stereo), increase LWAV_STREAM_BUFSIZ
- //
- //---------------------------------------------------//
- #define LWAV_STREAM_BUFSIZ 0x1000
- #define LWAV_BANKS 4
- #define LOOPWAV_STREAM_BUFSIZ 0x1000
- #define LOOPWAV_BANKS 4
- #ifndef DSBCAPS_CTRLDEFAULT
- #define DSBCAPS_CTRLDEFAULT (DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLPAN|DSBCAPS_CTRLVOLUME)
- #endif
- //---------- Define static variables ---------//
- static MCI_PLAY_PARMS mci_play;
- static MCI_OPEN_PARMS mci_open;
- static MCI_SET_PARMS mci_set;
- //--------- Begin of function wavefile_offset -------//
- //
- // find the "data" tag in a wave file
- //
- static char * wavefile_data(char *wavfile_buf)
- {
- //----- position at WAVEfmt tag size ------//
- char *p = wavfile_buf+0x10;
- DWORD tagSize=*(DWORD *)p;
- //-------- go to next tag field -----------//
- for( p += sizeof(DWORD)+tagSize; strncmp(p, "data", 4) != 0;
- p += sizeof(DWORD)+tagSize)
- {
- p += 4; // pointing at size of tag field
- tagSize = *(DWORD *)p; // get the size of this tage field
- if(p - wavfile_buf > 128)
- return NULL;
- }
- //----- p pointing at the start of "data" tag ------//
- return p;
- }
- //--------- End of function wavefile_offset------------//
- //--------- Begin of function Audio::Audio ----------//
- Audio::Audio()
- {
- init_flag = 0;
- }
- //--------- Begin of function Audio::Audio ----------//
- //--------- Begin of function Audio::~Audio ----------//
- Audio::~Audio()
- {
- deinit();
- }
- //--------- Begin of function Audio::~Audio ----------//
- //--------- Begin of function Audio::init ----------//
- //
- // Initialize the mid driver
- //
- // return : <int> 1 - initialized successfully
- // 0 - init fail
- //
- int Audio::init()
- {
- //-------- init vars -----------//
- run_yield = 0;
- mid_init_flag = 0; // the init flag is on when the driver is initialized successfully
- wav_init_flag = 0;
- cd_init_flag = 0;
- mid_flag = 1;
- wav_flag = 1;
- cd_flag = 1;
- mid_buf = NULL;
- wav_buf = NULL;
- mid_buf_size = 0;
- wav_buf_size = 0;
- int i;
- for(i = 0; i < MAX_WAV_CHANNEL; ++i)
- {
- lp_wav_ch_dsb[i] = NULL;
- wav_serial_no[i] = 0;
- }
- max_lwav_serial_no = 0;
- for(i=0; i < MAX_LONG_WAV_CH; ++i)
- {
- lp_lwav_ch_dsb[i] = NULL;
- lwav_serial_no[i] = 0;
- lwav_fileptr[i] = NULL;
- }
- max_lwav_serial_no = 0;
- for(i=0; i < MAX_LOOP_WAV_CH; ++i)
- {
- lp_loop_ch_dsb[i] = NULL;
- loopwav_fileptr[i] = NULL;
- }
- // wav_volume = 0;
- wav_volume = 100; // 0(slient) - 100(loudest)
- //--------- init devices ----------//
- if( init_wav() )
- {
- wav_res.init( DIR_RES"A_WAVE2.RES", 0, 0 ); // 2nd 0-don't read all, 3rd 0-don't use vga buffer
- wav_buf = mem_add(DEFAULT_WAV_BUF_SIZE);
- wav_buf_size = DEFAULT_WAV_BUF_SIZE;
- }
- /*
- if( init_mid() )
- {
- mid_res.init( DIR_RES"A_MIDI.RES", 0, 0 ); // 2nd 0-don't read all, 3rd 0-don't use vga buffer
- mid_buf = mem_add(DEFAULT_MID_BUF_SIZE);
- mid_buf_size = DEFAULT_MID_BUF_SIZE;
- }
- */
- init_cd();
- //----------------------------------//
- init_flag = wav_init_flag || cd_init_flag;
- return 1;
- }
- //--------- End of function Audio::init ----------//
- //--------- Begin of function Audio::deinit ----------//
- void Audio::deinit()
- {
- if( init_flag )
- {
- //------- deinit vars --------//
- run_yield = 0;
- init_flag = 0;
- //------- deinit devices -------//
- deinit_wav();
- deinit_mid();
- deinit_cd();
- }
- }
- //--------- End of function Audio::deinit ----------//
- //--------- Begin of function Audio::init_wav ----------//
- //
- // Initialize digitized wav driver
- //
- // return : <int> 1 - initialized successfully
- // 0 - init fail
- //
- int Audio::init_wav()
- {
- if( wav_init_flag )
- return 1;
- //-------- create DirectSound object -------//
- HRESULT rc=DirectSoundCreate(NULL, &lp_direct_sound, NULL);
- //------------------------------------------//
- if( rc==DS_OK ) // Create succeeded
- {
- lp_direct_sound->SetCooperativeLevel(sys.main_hwnd, DSSCL_NORMAL);
- wav_init_flag=1;
- }
- return wav_init_flag;
- }
- //--------- End of function Audio::init_wav ----------//
- //--------- Begin of function Audio::init_mid ----------//
- //
- // Initialize MIDI mid driver
- //
- // return : <int> 1 - initialized successfully
- // 0 - init fail
- //
- int Audio::init_mid()
- {
- if( mid_init_flag )
- return 1;
- //.. insert code here ...//
- mid_init_flag=1;
- return 1;
- }
- //--------- End of function Audio::init_mid ----------//
- //--------- Begin of function Audio::init_cd ----------//
- //
- // Initialize the audio CD player
- //
- // return : <int> 1 - initialized successfully
- // 0 - init fail
- //
- int Audio::init_cd()
- {
- mci_open.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO;
- if( mciSendCommand( NULL, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID,
- (DWORD) (LPVOID) &mci_open) == 0 ||
- mciSendCommand( NULL, MCI_OPEN, MCI_OPEN_TYPE |
- MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
- (DWORD) (LPVOID) &mci_open)== 0 )
- {
- mci_set.dwTimeFormat = MCI_FORMAT_TMSF;
- mciSendCommand( mci_open.wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT,
- (DWORD) (LPVOID) &mci_set);
- cd_init_flag = 1;
- return 1;
- }
- cd_init_flag = 0;
- return 0;
- }
- //--------- End of function Audio::init_cd ----------//
- //--------- Begin of function Audio::deinit_cd ----------//
- void Audio::deinit_cd()
- {
- if( cd_init_flag )
- {
- stop_cd();
- mciSendString ("close cdaudio", NULL, 0, NULL);
- cd_init_flag = 0;
- }
- }
- //--------- End of function Audio::deinit_cd ----------//
- //--------- Begin of function Audio::deinit_wav ----------//
- void Audio::deinit_wav()
- {
- stop_wav();
- if( wav_buf )
- {
- mem_del(wav_buf);
- wav_buf = NULL;
- }
- if(wav_init_flag)
- {
- lp_direct_sound->Release();
- wav_init_flag = 0;
- }
- }
- //--------- End of function Audio::deinit_wav ----------//
- //--------- Begin of function Audio::deinit_mid ----------//
- void Audio::deinit_mid()
- {
- if( !mid_init_flag )
- return;
- stop_mid();
- //.. insert code here ...//
- mem_del(mid_buf);
- mid_buf = NULL;
- mid_init_flag = 0;
- }
- //--------- End of function Audio::deinit_mid ----------//
- //------- Begin of function Audio::play_mid -------//
- //
- // Play a midi mid from the mid resource file
- //
- // <char*> midName = name of the mid in the resource file
- //
- // return : <int> 1 - mid loaded and is playing
- // 0 - mid not played
- //
- int Audio::play_mid(char* midName)
- {
- if( !mid_init_flag || !mid_flag ) // a initialized and workable midi device can be disabled by user setting
- return 0;
- stop_mid(); // stop currently playing mid if any
- //------ Load mid file -------//
- int dataSize;
- File* filePtr = mid_res.get_file(midName, dataSize);
- if( !filePtr )
- return 0;
- if( dataSize > mid_buf_size )
- {
- mid_buf_size = dataSize;
- mid_buf = mem_resize( mid_buf, mid_buf_size );
- }
- if( !filePtr->file_read( mid_buf, dataSize ) )
- return 0;
- //-------- Play mid file --------//
- //.. insert code here ...//
- return 1;
- }
- //------- End of function Audio::play_mid -------//
- //------- Begin of function Audio::stop_mid -------//
- //
- void Audio::stop_mid()
- {
- if( !mid_init_flag || !mid_flag )
- return;
- //.. insert code here ...//
- mciSendCommand(mci_open.wDeviceID, MCI_STOP, NULL, NULL);
- }
- //------- End of function Audio::stop_mid -------//
- //------- Begin of function Audio::play_wav -------//
- //
- // Play digitized wav from the wav resource file
- //
- // <char*> wavName = name of the wav in the resource file
- // long vol = volume (0 to 100)
- // long pan = pan (-10000 to 10000)
- //
- // return : <int> non-zero - wav loaded and is playing, return a serial no. to be referred in stop_wav and is_wav_playing
- // 0 - wav not played
- //
- int Audio::play_wav(char* wavName, DsVolume dsVolume)
- {
- /*
- //---- redirect to play_long_wav -------//
- String str;
- str = DIR_SOUND;
- str += wavName;
- str += ".WAV";
- if( m.is_file_exist(str) )
- return play_long_wav(str);
- else
- return 0;
- //------------------------------------//
- */
- if( !wav_init_flag || !wav_flag ) // a initialized and workable midi device can be disabled by user setting
- return 0;
- //-------- Load wav file header-------//
- int dataSize;
- DWORD wavDataOffset, wavDataLength;
- File* filePtr = wav_res.get_file(wavName, dataSize);
- if( !filePtr )
- return 0;
- // load small part of the wave file (first 128 bytes) enough to hold
- // the hold header
- //#define LOAD_FULL_WAVE
- #ifdef LOAD_FULL_WAVE
- if( dataSize > wav_buf_size )
- {
- wav_buf_size = dataSize;
- wav_buf = mem_resize( wav_buf, wav_buf_size );
- }
- if( !filePtr->file_read( wav_buf, dataSize))
- #else
- if( !filePtr->file_read( wav_buf, 128 ) )
- #endif
- return 0;
- // short-cut to test play_resided_wave()
- #ifdef LOAD_FULL_WAVE
- return play_resided_wav(wav_buf);
- #endif
- // determine the wave data offset and length
- char * dataTag = wavefile_data(wav_buf);
- if (!dataTag)
- {
- err_now("Invalid wave file format");
- return 0; // invalid RIFF WAVE format
- }
- wavDataOffset = (dataTag - wav_buf) + 4 + sizeof(DWORD);
- wavDataLength = *(DWORD *)(dataTag+4);
- #ifndef LOAD_FULL_WAVE
- // seek to the start of wave data
- filePtr->file_seek(wavDataOffset-128,FILE_CURRENT);
- #endif
- //------- Create DirectSoundBuffer to store a wave ------//
- LPDIRECTSOUNDBUFFER lpDsb;
- DSBUFFERDESC dsbDesc;
- HRESULT hr;
- DWORD dsbStatus;
- // set up DSBUFFERDESC structure
- memset(&dsbDesc, 0, sizeof(DSBUFFERDESC)); // zero it out
- dsbDesc.dwSize = sizeof(DSBUFFERDESC);
- dsbDesc.dwFlags = DSBCAPS_CTRLDEFAULT; // Need defaul controls (pan, volume, frequency)
- dsbDesc.dwBufferBytes = wavDataLength;
- dsbDesc.lpwfxFormat = (LPWAVEFORMATEX) (wav_buf+0x14);
- // ------- assign buffer to a channel number ----------//
- lpDsb = NULL;
- int chanNum;
- for( chanNum = 0; chanNum < MAX_WAV_CHANNEL; ++chanNum)
- if(lp_wav_ch_dsb[chanNum] == NULL || (lp_wav_ch_dsb[chanNum]->GetStatus(&dsbStatus),
- !(dsbStatus & DSBSTATUS_PLAYING)))
- {
- if(lp_wav_ch_dsb[chanNum])
- {
- lp_wav_ch_dsb[chanNum]->Release();
- lp_wav_ch_dsb[chanNum] = NULL;
- }
- // found an idle channel, create DirectSoundBuffer
- hr = lp_direct_sound->CreateSoundBuffer(&dsbDesc, &lpDsb, NULL);
- if (DS_OK != hr)
- {
- // failed!
- err_now("Cannot create DirectSoundBuffer");
- return 0;
- }
- lp_wav_ch_dsb[chanNum] = lpDsb;
- break;
- }
- if( chanNum >= MAX_WAV_CHANNEL)
- {
- return 0;
- }
- // Note : if not found, just play the sound, don't play the sound
- // increase MAX_WAV_CHANNEL
- //------- copy sound data to DirectSoundBuffer--------//
- // unlock vga_front
- VgaFrontLock vgaLock;
- // lock the buffer first
- LPVOID lpvPtr1;
- DWORD dwBytes1;
- LPVOID lpvPtr2;
- DWORD dwBytes2;
- hr = lpDsb->Lock(0, wavDataLength, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
- if(DS_OK != hr)
- {
- // fail to lock
- err_now("Cannot lock DirectSoundBuffer");
- return 0;
- }
- // write to pointers
- #ifdef LOAD_FULL_WAVE
- memcpy(lpvPtr1, wav_buf+wavDataOffset, dwBytes1);
- #else
- filePtr->file_read(lpvPtr1, dwBytes1);
- #endif
- if(lpvPtr2)
- {
- #ifdef LOAD_FULL_WAVE
- memcpy(lpvPtr2, wav_buf+wavDataOffset+dwBytes1, dwBytes2);
- #else
- filePtr->file_read(lpvPtr2, dwBytes2);
- #endif
- }
- // unlock data back
- hr = lpDsb->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
- if(DS_OK != hr)
- {
- // fail to unlock
- err_now("Cannot unlock DirectSoundBuffer");
- return 0;
- }
- //------- Set volume and pan -----------//
- lpDsb->SetVolume(dsVolume.ds_vol);
- lpDsb->SetPan(dsVolume.ds_pan);
- //------- Play wav file --------//
- if(lpDsb->Play(0, 0, 0) != DS_OK)
- {
- // fail to play
- err_now("Cannot play DirectSoundBuffer");
- return 0;
- }
- return wav_serial_no[chanNum] = assign_serial(max_wav_serial_no);
- }
- //------- End of function Audio::play_wav -------//
- //------- Begin of function Audio::play_wav -------//
- //
- // Play digitized wav from the wav resource file
- //
- // short resIdx = index of wave file in A_WAVE2.RES
- // long vol = volume (0 to 100)
- // long pan = pan (-10000 to 10000)
- //
- // return : <int> 1 - wav loaded and is playing
- // 0 - wav not played
- //
- int Audio::play_wav(short resIdx, DsVolume dsVolume)
- {
- if( !wav_init_flag || !wav_flag ) // a initialized and workable midi device can be disabled by user setting
- return 0;
- //-------- Load wav file header-------//
- int dataSize;
- DWORD wavDataOffset, wavDataLength;
- File* filePtr = wav_res.get_file(resIdx, dataSize);
- if( !filePtr )
- return 0;
- // load small part of the wave file (first 128 bytes) enough to hold
- // the hold header
- #ifdef LOAD_FULL_WAVE
- if( dataSize > wav_buf_size )
- {
- wav_buf_size = dataSize;
- wav_buf = mem_resize( wav_buf, wav_buf_size );
- }
- if( !filePtr->file_read( wav_buf, dataSize))
- #else
- if( !filePtr->file_read( wav_buf, 128 ) )
- #endif
- return 0;
- // short-cut to test play_resided_wave()
- #ifdef LOAD_FULL_WAVE
- return play_resided_wav(wav_buf);
- #endif
- // determine the wave data offset and length
- char * dataTag = wavefile_data(wav_buf);
- if (!dataTag)
- {
- err_now("Invalid wave file format");
- return 0; // invalid RIFF WAVE format
- }
- wavDataOffset = (dataTag - wav_buf) + 4 + sizeof(DWORD);
- wavDataLength = *(DWORD *)(dataTag+4);
- #ifndef LOAD_FULL_WAVE
- // seek to the start of wave data
- filePtr->file_seek(wavDataOffset-128,FILE_CURRENT);
- #endif
- //------- Create DirectSoundBuffer to store a wave ------//
- LPDIRECTSOUNDBUFFER lpDsb;
- DSBUFFERDESC dsbDesc;
- HRESULT hr;
- DWORD dsbStatus;
- // set up DSBUFFERDESC structure
- memset(&dsbDesc, 0, sizeof(DSBUFFERDESC)); // zero it out
- dsbDesc.dwSize = sizeof(DSBUFFERDESC);
- dsbDesc.dwFlags = DSBCAPS_CTRLDEFAULT; // Need defaul controls (pan, volume, frequency)
- dsbDesc.dwBufferBytes = wavDataLength;
- dsbDesc.lpwfxFormat = (LPWAVEFORMATEX) (wav_buf+0x14);
- // ------- assign buffer to a channel number ----------//
- lpDsb = NULL;
- int chanNum;
- for( chanNum = 0; chanNum < MAX_WAV_CHANNEL; ++chanNum)
- if(lp_wav_ch_dsb[chanNum] == NULL || (lp_wav_ch_dsb[chanNum]->GetStatus(&dsbStatus),
- !(dsbStatus & DSBSTATUS_PLAYING)))
- {
- if(lp_wav_ch_dsb[chanNum])
- {
- lp_wav_ch_dsb[chanNum]->Release();
- lp_wav_ch_dsb[chanNum] = NULL;
- }
- // found an idle channel, create DirectSoundBuffer
- hr = lp_direct_sound->CreateSoundBuffer(&dsbDesc, &lpDsb, NULL);
- if (DS_OK != hr)
- {
- // failed!
- err_now("Cannot create DirectSoundBuffer");
- return 0;
- }
- lp_wav_ch_dsb[chanNum] = lpDsb;
- break;
- }
- if( chanNum >= MAX_WAV_CHANNEL)
- {
- return 0;
- }
- // Note : if not found, just play the sound, don't play the sound
- // increase MAX_WAV_CHANNEL
-
- //------- copy sound data to DirectSoundBuffer--------//
- // unlock vga_front
- VgaFrontLock vgaLock;
- // lock the buffer first
- LPVOID lpvPtr1;
- DWORD dwBytes1;
- LPVOID lpvPtr2;
- DWORD dwBytes2;
- hr = lpDsb->Lock(0, wavDataLength, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
- if(DS_OK != hr)
- {
- // fail to lock
- err_now("Cannot lock DirectSoundBuffer");
- return 0;
- }
- // write to pointers
- #ifdef LOAD_FULL_WAVE
- memcpy(lpvPtr1, wav_buf+wavDataOffset, dwBytes1);
- #else
- filePtr->file_read(lpvPtr1, dwBytes1);
- #endif
- if(lpvPtr2)
- {
- #ifdef LOAD_FULL_WAVE
- memcpy(lpvPtr2, wav_buf+wavDataOffset+dwBytes1, dwBytes2);
- #else
- filePtr->file_read(lpvPtr2, dwBytes2);
- #endif
- }
- // unlock data back
- hr = lpDsb->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
- if(DS_OK != hr)
- {
- // fail to unlock
- err_now("Cannot unlock DirectSoundBuffer");
- return 0;
- }
- //------- Set volume and pan -----------//
- lpDsb->SetVolume(dsVolume.ds_vol);
- lpDsb->SetPan(dsVolume.ds_pan);
- //------- Play wav file --------//
- if(lpDsb->Play(0, 0, 0) != DS_OK)
- {
- // fail to play
- err_now("Cannot play DirectSoundBuffer");
- return 0;
- }
- return wav_serial_no[chanNum] = assign_serial(max_wav_serial_no);
- }
- //------- End of function Audio::play_wav -------//
- //------- Begin of function Audio::play_resided_wav -------//
- //
- // Play digitized wav from the wav file in memory
- //
- // <char*> wavBuf = point to the wav in memory
- // long vol = volume (0 to 100)
- // long pan = pan (-10000 to 10000)
- //
- // return : <int> 1 - wav loaded and is playing
- // 0 - wav not played
- //
- int Audio::play_resided_wav(char* wavBuf, DsVolume dsVolume)
- {
- if( !wav_init_flag || !wav_flag ) // a initialized and workable midi device can be disabled by user setting
- return 0;
- //-------- Load wav file header-------//
- DWORD wavDataOffset, wavDataLength;
- // determine the wave data offset and length
- char * dataTag = wavefile_data(wavBuf);
- if (!dataTag)
- {
- err_now("Invalid wave file format");
- return 0; // invalid RIFF WAVE format
- }
- wavDataOffset = (dataTag - wavBuf) + 4 + sizeof(DWORD);
- wavDataLength = *(DWORD *)(dataTag+4);
- //------- Create DirectSoundBuffer to store a wave ------//
- LPDIRECTSOUNDBUFFER lpDsb;
- DSBUFFERDESC dsbDesc;
- HRESULT hr;
- DWORD dsbStatus;
- // set up DSBUFFERDESC structure
- memset(&dsbDesc, 0, sizeof(DSBUFFERDESC)); // zero it out
- dsbDesc.dwSize = sizeof(DSBUFFERDESC);
- dsbDesc.dwFlags = DSBCAPS_CTRLDEFAULT; // Need defaul controls (pan, volume, frequency)
- dsbDesc.dwBufferBytes = wavDataLength;
- dsbDesc.lpwfxFormat = (LPWAVEFORMATEX) (wavBuf+0x14);
- // ------- assign buffer to a channel number ----------//
- lpDsb = NULL;
- int chanNum;
- for( chanNum = 0; chanNum < MAX_WAV_CHANNEL; ++chanNum)
- if(lp_wav_ch_dsb[chanNum] == NULL || (lp_wav_ch_dsb[chanNum]->GetStatus(&dsbStatus),
- !(dsbStatus & DSBSTATUS_PLAYING)))
- {
- if(lp_wav_ch_dsb[chanNum])
- {
- lp_wav_ch_dsb[chanNum]->Release();
- lp_wav_ch_dsb[chanNum] = NULL;
- }
- // found an idle channel, create DirectSoundBuffer
- hr = lp_direct_sound->CreateSoundBuffer(&dsbDesc, &lpDsb, NULL);
- if (DS_OK != hr)
- {
- // failed!
- err_now("Cannot create DirectSoundBuffer");
- return 0;
- }
- lp_wav_ch_dsb[chanNum] = lpDsb;
- break;
- }
- if( chanNum >= MAX_WAV_CHANNEL)
- {
- return 0;
- }
- // Note : if not found, just play the sound, don't play the sound
- // increase MAX_WAV_CHANNEL
-
- //------- copy sound data to DirectSoundBuffer--------//
- // unlock vga_front
- VgaFrontLock vgaLock;
- // lock the buffer first
- LPVOID lpvPtr1;
- DWORD dwBytes1;
- LPVOID lpvPtr2;
- DWORD dwBytes2;
- hr = lpDsb->Lock(0, wavDataLength, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
- if(DS_OK != hr)
- {
- // fail to lock
- err_now("Cannot lock DirectSoundBuffer");
- return 0;
- }
- // write to pointers
- memcpy(lpvPtr1, wavBuf+wavDataOffset, dwBytes1);
- if(lpvPtr2)
- {
- memcpy(lpvPtr2, wavBuf+wavDataOffset+dwBytes1, dwBytes2);
- }
- // unlock data back
- hr = lpDsb->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
- if(DS_OK != hr)
- {
- // fail to unlock
- err_now("Cannot unlock DirectSoundBuffer");
- return 0;
- }
- //------- Set volume -----------//
- lpDsb->SetVolume(dsVolume.ds_vol);
- lpDsb->SetPan(dsVolume.ds_pan);
- //------- Play wav file --------//
- if(lpDsb->Play(0, 0, 0) != DS_OK)
- {
- // fail to play
- err_now("Cannot play DirectSoundBuffer");
- return 0;
- }
- return wav_serial_no[chanNum] = assign_serial(max_wav_serial_no);
- }
- //------- End of function Audio::play_resided_wav -------//
- // ###### begin Gilbert 6/12 ########//
- //------- Begin of function Audio::get_free_wav_ch --------//
- int Audio::get_free_wav_ch()
- {
- int count = 0;
- DWORD dsbStatus;
- for( int chanNum = 0; chanNum < MAX_WAV_CHANNEL; ++chanNum)
- {
- if( lp_wav_ch_dsb[chanNum] != NULL && (lp_wav_ch_dsb[chanNum]->GetStatus(&dsbStatus),
- !(dsbStatus & DSBSTATUS_PLAYING)) )
- {
- lp_wav_ch_dsb[chanNum]->Release();
- lp_wav_ch_dsb[chanNum] = NULL;
- }
- if( !lp_wav_ch_dsb[chanNum] )
- count++;
- }
-
- return count;
- }
- //------- End of function Audio::get_free_wav_ch --------//
- // ###### end Gilbert 6/12 ########//
- //------- Begin of function Audio::stop_wav ------------//
- //
- // stop a short sound effect started by play_wav or play_resided_wav
- //
- // <int> the serial no returned by play_wav or play_resided_wav
- //
- // return 1 - channel is found and stopped / channel not found
- // return 0 - cannot stop the channel
- //
- int Audio::stop_wav(int serial)
- {
- for( int chanNum = 0; chanNum < MAX_WAV_CHANNEL; ++chanNum)
- {
- if(lp_wav_ch_dsb[chanNum] != NULL && wav_serial_no[chanNum] == serial)
- {
- lp_wav_ch_dsb[chanNum]->Stop();
- lp_wav_ch_dsb[chanNum]->Release();
- lp_wav_ch_dsb[chanNum] = NULL;
- wav_serial_no[chanNum] = 0;
- return 1;
- }
- }
- return 0;
- }
- //------- End of function Audio::stop_wav ------------//
- //------- Begin of function Audio::is_wav_playing ------------//
- //
- // return wheather a short sound effect is stopped
- //
- // <int> the serial no returned by play_wav or play_resided_wav
- //
- int Audio::is_wav_playing(int serial)
- {
- DWORD dsbStatus;
- for( int chanNum = 0; chanNum < MAX_WAV_CHANNEL; ++chanNum)
- {
- if(lp_wav_ch_dsb[chanNum] != NULL && wav_serial_no[chanNum] == serial
- && lp_wav_ch_dsb[chanNum]->GetStatus(&dsbStatus) )
- {
- return dsbStatus & DSBSTATUS_PLAYING;
- }
- }
- return 0;
- }
- //------- End of function Audio::is_wav_playing ------------//
- //------- Begin of function Audio::play_long_wav --------//
- //
- // Play digitized wav from the wav file
- // suitable for very large wave file
- //
- // <char*> wavName = name of the wave file
- //
- // return : <int> 1 - wav loaded and is playing
- // 0 - wav not played
- // note : it uses streaming DirectSoundBuffer
- // Audio::yield() keeps on feeding data to it
- // Create a DirectSoundBuffer of size lwav_buf_size[c]*LWAV_BANKS
- // divide into LWAV_BANKS parts. Each time Audio::yield() is called,
- // load wave file into one part. lwav_bank[c] record which part to be
- // filled next for channel c.
- int Audio::play_long_wav(char *wavName, DsVolume dsVolume)
- {
- if( !wav_init_flag || !wav_flag ) // a initialized and workable midi device can be disabled by user setting
- return 0;
- //-------- Load wav file header-------//
- DWORD wavDataOffset,wavDataLength;
- if( LWAV_STREAM_BUFSIZ*LWAV_BANKS > wav_buf_size )
- {
- wav_buf_size = LWAV_STREAM_BUFSIZ*LWAV_BANKS;
- wav_buf = mem_resize( wav_buf, wav_buf_size );
- }
- // File* filePtr = (File *)mem_add(sizeof(File)); // new File;
- File* filePtr = new File; // new File;
- if(!filePtr->file_open(wavName,0,0))
- {
- char errmsg[60];
- sprintf(errmsg, "Cannot open %s", wavName);
- box.msg(errmsg);
- delete filePtr;
- return 0;
- }
- if( !filePtr )
- {
- delete filePtr;
- return 0;
- }
- // load small part of the wave file (first 128 bytes) enough to hold
- // the hold header
- if( !filePtr->file_read( wav_buf, 128 ) )
- {
- delete filePtr;
- return 0;
- }
- // determine the wave data offset
- char * dataTag = wavefile_data(wav_buf);
- if (!dataTag)
- {
- err_now("Invalid wave file format");
- delete filePtr;
- return 0; // invalid RIFF WAVE format
- }
- wavDataOffset = (dataTag - wav_buf) + 4 + sizeof(DWORD);
- wavDataLength = *(DWORD *)(dataTag+4);
- // seek to the start of wave data
- long temp1 = filePtr->file_seek(wavDataOffset,FILE_BEGIN);
- WORD OptBufferSize=LWAV_STREAM_BUFSIZ,
- MinRemainder =(WORD)(wavDataLength % (OptBufferSize * LWAV_BANKS));
- //------- find out the best buffer size -------//
- // store it in OptBufferSize
- // criteria : below or equal to LWAV_STREAM_BUFSIZ and
- // minimize wavDataLength % (OptBufferSize * LWAV_BANKS)
- // i.e. minimize the truncation to the wave file
- for(WORD TryBufSiz=LWAV_STREAM_BUFSIZ-0x200; TryBufSiz <= LWAV_STREAM_BUFSIZ;
- TryBufSiz+=0x20)
- {
- WORD TryRemainder = (WORD)(wavDataLength % (TryBufSiz * LWAV_BANKS));
- if(TryRemainder < MinRemainder)
- {
- MinRemainder = TryRemainder;
- OptBufferSize = TryBufSiz;
- }
- }
- //------- Create DirectSoundBuffer to store a wave ------//
- LPDIRECTSOUNDBUFFER lpDsb;
- DSBUFFERDESC dsbDesc;
- HRESULT hr;
- DWORD dsbStatus;
- // set up DSBUFFERDESC structure
- memset(&dsbDesc, 0, sizeof(DSBUFFERDESC)); // zero it out
- dsbDesc.dwSize = sizeof(DSBUFFERDESC);
- dsbDesc.dwFlags = DSBCAPS_CTRLDEFAULT; // Need defaul controls (pan, volume, frequency)
- dsbDesc.dwBufferBytes = OptBufferSize * LWAV_BANKS;
- dsbDesc.lpwfxFormat = (LPWAVEFORMATEX) (wav_buf+0x14);
- // ------- assign buffer to a channel number ----------//
- lpDsb = NULL;
- int chanNum;
- for( chanNum = 0; chanNum < MAX_LONG_WAV_CH; ++chanNum)
- if(lp_lwav_ch_dsb[chanNum] == NULL || (lp_lwav_ch_dsb[chanNum]->GetStatus(&dsbStatus),
- !(dsbStatus & DSBSTATUS_PLAYING)))
- {
- if(lp_lwav_ch_dsb[chanNum])
- {
- lp_lwav_ch_dsb[chanNum]->Release();
- lp_lwav_ch_dsb[chanNum] = NULL;
- // mem_del(lwav_fileptr[chanNum]); // delete lwav_fileptr[chanNum];
- delete lwav_fileptr[chanNum];
- lwav_fileptr[chanNum] = NULL;
- }
- // found an idle channel, create DirectSoundBuffer
- hr = lp_direct_sound->CreateSoundBuffer(&dsbDesc, &lpDsb, NULL);
- if (DS_OK != hr)
- {
- // failed!
- err_now("Cannot create Stream DirectSoundBuffer");
- delete filePtr;
- return 0;
- }
- lp_lwav_ch_dsb[chanNum] = lpDsb;
- lwav_fileptr[chanNum] = filePtr; // no need to delete filePtr any more
- lwav_bank[chanNum] = 0;
- lwav_bufsiz[chanNum] = OptBufferSize;
- break;
- }
- if( chanNum >= MAX_LONG_WAV_CH)
- {
- delete filePtr;
- return 0;
- }
- // Note : if not found, just play the sound, don't play the sound
- // increase MAX_LONG_WAV_CH
-
- //------- copy sound data to DirectSoundBuffer--------//
- // unlock vga_front
- VgaFrontLock vgaLock;
- // lock the buffer first
- LPVOID lpvPtr1;
- DWORD dwBytes1;
- LPVOID lpvPtr2;
- DWORD dwBytes2;
- // load wave data into buffer
- // load data before lock DirectSoundBuffer in case the wave file
- // is very short
- DWORD startPos = filePtr->file_pos();
- if( !filePtr->file_read(wav_buf, OptBufferSize*LWAV_BANKS))
- {
- // file error
- err_now("Missing wave file");
- return 0;
- }
- DWORD readStreamSize = filePtr->file_pos() - startPos;
- DWORD playFlag = DSBPLAY_LOOPING;
- hr = lpDsb->Lock(0, OptBufferSize*LWAV_BANKS, &lpvPtr1, &dwBytes1,
- &lpvPtr2, &dwBytes2, 0);
- if(DS_OK != hr)
- {
- // fail to lock
- err_now("Cannot lock DirectSoundBuffer");
- return 0;
- }
- // write to pointers
- memcpy(lpvPtr1, wav_buf, min(dwBytes1, readStreamSize));
- if( dwBytes1 > readStreamSize )
- { // end of file, fill the remaining with zero
- memset((char *)lpvPtr1+readStreamSize, 0, dwBytes1 - readStreamSize);
- playFlag &= ~DSBPLAY_LOOPING;
- }
- else
- {
- readStreamSize -= dwBytes1;
- if(lpvPtr2 && dwBytes2 > 0)
- {
- memcpy(lpvPtr2, wav_buf+dwBytes1, min(dwBytes2, readStreamSize));
- if( dwBytes2 > readStreamSize )
- { // end of file, fill the remaining with zero
- memset((char *)lpvPtr2+readStreamSize, 0 , dwBytes2 - readStreamSize);
- playFlag &= ~DSBPLAY_LOOPING;
- }
- }
- }
- // unlock data back
- hr = lpDsb->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
- if(DS_OK != hr)
- {
- // fail to unlock
- err_now("Cannot unlock DirectSoundBuffer");
- return 0;
- }
- //------- Set volume -----------//
- lpDsb->SetVolume(dsVolume.ds_vol);
- lpDsb->SetPan(dsVolume.ds_pan);
- //------- Play wav file --------//
- if(lpDsb->Play(0, 0, playFlag) != DS_OK)
- {
- // fail to play
- err_now("Cannot play DirectSoundBuffer");
- return 0;
- }
- run_yield = 1;
- return lwav_serial_no[chanNum] = assign_serial(max_lwav_serial_no);
- }
- //------- End of function Audio::play_long_wav ----------//
- //------- Begin of function Audio::stop_long_wav ------------//
- //
- // stop a short sound effect started by play_long_wav
- //
- // <int> the serial no returned by play_long_wav
- //
- // return 1 - channel is found and stopped / channel not found
- // return 0 - cannot stop the channel
- //
- int Audio::stop_long_wav(int serial)
- {
- for( int chanNum = 0; chanNum < MAX_LONG_WAV_CH; ++chanNum)
- {
- if(lp_lwav_ch_dsb[chanNum] != NULL && lwav_serial_no[chanNum] == serial)
- {
- lp_lwav_ch_dsb[chanNum]->Stop();
- lp_lwav_ch_dsb[chanNum]->Release();
- lp_lwav_ch_dsb[chanNum] = NULL;
- delete lwav_fileptr[chanNum];
- lwav_fileptr[chanNum] = NULL;
- lwav_serial_no[chanNum] = 0;
- return 1;
- }
- }
- return 0;
- }
- //------- End of function Audio::stop_long_wav ------------//
- //------- Begin of function Audio::is_long_wav_playing ------------//
- //
- // return wheather a short sound effect is stopped
- //
- // <int> the serial no returned by play_wav or play_resided_wav
- //
- int Audio::is_long_wav_playing(int serial)
- {
- DWORD dsbStatus;
- for( int chanNum = 0; chanNum < MAX_LONG_WAV_CH; ++chanNum)
- {
- if(lp_lwav_ch_dsb[chanNum] != NULL && lwav_serial_no[chanNum] == serial
- && lp_lwav_ch_dsb[chanNum]->GetStatus(&dsbStatus) == DS_OK )
- {
- return dsbStatus & DSBSTATUS_PLAYING;
- }
- }
- return 0;
- }
- //------- End of function Audio::is_long_wav_playing ------------//
- //--------------- Begin of Audio::vol_multiply --------------//
- long Audio::vol_multiply(int relVolume)
- {
- long dsVolume = (wav_volume * relVolume) - 10000;
- if( dsVolume > 0 )
- dsVolume = 0;
- else if( dsVolume < -10000 )
- dsVolume = -10000;
- return dsVolume;
- }
- //--------------- End of Audio::vol_multiply --------------//
- //--------------- Begin of Audio::vol_divide --------------//
- int Audio::vol_divide(long dsVolume)
- {
- if( wav_volume == 0)
- return 0;
- int relVolume = (dsVolume + 10000) / wav_volume;
- if( relVolume < 0)
- relVolume = 0;
- else if( relVolume > 100 )
- relVolume = 100;
- return relVolume;
- }
- //--------------- End of Audio::vol_divide --------------//
- //------- Begin of function Audio::play_loop_wav -------//
- //
- // Play digitized wav from the wav resource file
- //
- // <char*> wavName = name of the wav in the resource file
- // int repeatOffset = offset of wave data to play on repeat
- // i.e. 0 to start of wave data
- //
- // return : <int> channel number (1 - MAX_LOOP_WAV_CH)
- // 0 not played
- //
- int Audio::play_loop_wav(char *wavName, int repeatOffset, DsVolume dsVolume)
- {
- if( !wav_init_flag || !wav_flag ) // a initialized and workable midi device can be disabled by user setting
- return 0;
- //-------- Load wav file header-------//
- DWORD wavDataOffset,wavDataLength;
- // File* filePtr = (File *)mem_add(sizeof(File)); // new File;
- File* filePtr = new File;
- if(!filePtr->file_open(wavName,0,0))
- {
- char errmsg[60];
- sprintf(errmsg, "Cannot open %s", wavName);
- box.msg(errmsg);
- delete filePtr;
- return 0;
- }
- if( !filePtr )
- return 0;
- // load small part of the wave file (first 128 bytes) enough to hold
- // the hold header
- if( !filePtr->file_read( wav_buf, 128 ) )
- {
- delete filePtr;
- return 0;
- }
- // determine the wave data offset
- char * dataTag = wavefile_data(wav_buf);
- if (!dataTag)
- {
- err_now("Invalid wave file format");
- delete filePtr;
- return 0; // invalid RIFF WAVE format
- }
- wavDataOffset = (dataTag - wav_buf) + 4 + sizeof(DWORD);
- wavDataLength = *(DWORD *)(dataTag+4);
- // seek to the start of wave data
- long temp1 = filePtr->file_seek(wavDataOffset,FILE_BEGIN);
- WORD OptBufferSize=LOOPWAV_STREAM_BUFSIZ;
- //------- Create DirectSoundBuffer to store a wave ------//
- LPDIRECTSOUNDBUFFER lpDsb;
- DSBUFFERDESC dsbDesc;
- HRESULT hr;
- DWORD dsbStatus;
- // set up DSBUFFERDESC structure
- memset(&dsbDesc, 0, sizeof(DSBUFFERDESC)); // zero it out
- dsbDesc.dwSize = sizeof(DSBUFFERDESC);
- dsbDesc.dwFlags = DSBCAPS_CTRLDEFAULT; // Need defaul controls (pan, volume, frequency)
- dsbDesc.dwBufferBytes = OptBufferSize * LWAV_BANKS;
- dsbDesc.lpwfxFormat = (LPWAVEFORMATEX) (wav_buf+0x14);
- // ------- assign buffer to a channel number ----------//
- lpDsb = NULL;
- int chanNum;
- for( chanNum = 0; chanNum < MAX_LOOP_WAV_CH; ++chanNum)
- if(lp_loop_ch_dsb[chanNum] == NULL || (lp_loop_ch_dsb[chanNum]->GetStatus(&dsbStatus),
- !(dsbStatus & DSBSTATUS_PLAYING)))
- {
- if(lp_loop_ch_dsb[chanNum])
- {
- lp_loop_ch_dsb[chanNum]->Release();
- lp_loop_ch_dsb[chanNum] = NULL;
- // mem_del(loopwav_fileptr[chanNum]); // delete lwav_fileptr[chanNum];
- delete loopwav_fileptr[chanNum];
- loopwav_fileptr[chanNum] = NULL;
- }
- // found an idle channel, create DirectSoundBuffer
- hr = lp_direct_sound->CreateSoundBuffer(&dsbDesc, &lpDsb, NULL);
- if (DS_OK != hr)
- {
- // failed!
- err_now("Cannot create Stream DirectSoundBuffer");
- return 0;
- }
- lp_loop_ch_dsb[chanNum] = lpDsb;
- loopwav_fileptr[chanNum] = filePtr; // no need to delete filePtr any more
- loopwav_bank[chanNum] = 0;
- repeat_offset[chanNum] = wavDataOffset + repeatOffset;
- loopwav_fade_rate[chanNum] = 0;
- break;
- }
- if( chanNum >= MAX_LOOP_WAV_CH)
- {
- delete filePtr;
- return 0;
- }
- // Note : if not found, just play the sound, don't play the sound
-
- //------- copy sound data to DirectSoundBuffer--------//
- // unlock vga_front
- VgaFrontLock vgaLock;
- // lock the buffer first
- LPVOID lpvPtr1;
- DWORD dwBytes1;
- LPVOID lpvPtr2;
- DWORD dwBytes2;
- // load wave data into buffer
- // load data before lock DirectSoundBuffer in case the wave file
- // is very short
- DWORD startPos = filePtr->file_pos();
- if( !filePtr->file_read(wav_buf, OptBufferSize*LOOPWAV_BANKS))
- {
- // file error
- err_now("Missing wave file");
- return 0;
- }
- DWORD readStreamSize = filePtr->file_pos() - startPos;
- DWORD playFlag = DSBPLAY_LOOPING;
- hr = lpDsb->Lock(0, OptBufferSize*LOOPWAV_BANKS, &lpvPtr1, &dwBytes1,
- &lpvPtr2, &dwBytes2, 0);
- if(DS_OK != hr)
- {
- // fail to lock
- err_now("Cannot lock DirectSoundBuffer");
- return 0;
- }
- // write to pointers, assume wave file repeating size is
- // larger than OptBufferSize * LOOPWAV_BANKS
- memcpy(lpvPtr1, wav_buf, min(dwBytes1, readStreamSize));
- if( dwBytes1 < readStreamSize )
- {
- readStreamSize -= dwBytes1;
- if(lpvPtr2 && dwBytes2 > 0)
- {
- memcpy(lpvPtr2, wav_buf+dwBytes1, min(dwBytes2, readStreamSize));
- }
- }
- // unlock data back
- hr = lpDsb->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
- if(DS_OK != hr)
- {
- // fail to unlock
- err_now("Cannot unlock DirectSoundBuffer");
- return 0;
- }
- //------- Set volume -----------//
- lpDsb->SetVolume(dsVolume.ds_vol);
- lpDsb->SetPan(dsVolume.ds_pan);
- //------- Play wav file --------//
- if(lpDsb->Play(0, 0, playFlag) != DS_OK)
- {
- // fail to play
- err_now("Cannot play DirectSoundBuffer");
- return 0;
- }
- run_yield = 1;
- return chanNum+1;
- }
- //------- End of function Audio::play_loop_wav ---------//
- //------- Begin of function Audio::volume_loop_wav -------//
- void Audio::volume_loop_wav(int ch, DsVolume dsVolume)
- {
- int chanNum = ch-1;
- if( chanNum < 0 || chanNum >= MAX_LOOP_WAV_CH)
- return;
- if(lp_loop_ch_dsb[chanNum])
- {
- lp_loop_ch_dsb[chanNum]->SetVolume(dsVolume.ds_vol);
- lp_loop_ch_dsb[chanNum]->SetPan(dsVolume.ds_pan);
-
- // stop fading
- loopwav_fade_rate[chanNum] = 0;
- }
- }
- //------- End of function Audio::volume_loop_wav -------//
- //------- Begin of function Audio::fade_out_loop_wav -------//
- //
- // <int> fadeRate, time for volume 100 wave drop to slience
- //
- void Audio::fade_out_loop_wav(int ch, int fadeRate)
- {
- int chanNum = ch-1;
- if( chanNum < 0 || chanNum >= MAX_LOOP_WAV_CH)
- return;
- if(lp_loop_ch_dsb[chanNum])
- {
- loopwav_fade_rate[chanNum] = fadeRate;
- loopwav_fade_time[chanNum] = m.get_time();
- }
- }
- //------- End of function Audio::fade_out_loop_wav -------//
- //------- Begin of function Audio::get_loop_wav_volume -------//
- DsVolume Audio::get_loop_wav_volume(int ch)
- {
- int chanNum = ch-1;
- if( chanNum < 0 || chanNum >= MAX_LOOP_WAV_CH)
- {
- RelVolume rel = RelVolume(0,0);
- return DsVolume(rel);
- }
- LONG volume;
- LONG pan;
- LPDIRECTSOUNDBUFFER lpDsb= lp_loop_ch_dsb[chanNum];
- if( lpDsb && lpDsb->GetVolume(&volume) == DS_OK &&
- lpDsb->GetPan(&pan) == DS_OK )
- {
- return DsVolume(volume, pan);
- }
- RelVolume rel = RelVolume(0,0);
- return DsVolume(rel);
- }
- //------- End of function Audio::get_loop_wav_volume -------//
- //------- Begin of function Audio::is_loop_wav_fading -------//
- int Audio::is_loop_wav_fading(int ch)
- {
- int chanNum = ch-1;
- if( chanNum < 0 || chanNum >= MAX_LOOP_WAV_CH)
- return 0;
- return lp_loop_ch_dsb[chanNum] && loopwav_fade_rate[chanNum];
- }
- //------- End of function Audio::is_loop_wav_fading -------//
- //------- Begin of function Audio::yield ---------------//
- void Audio::yield()
- {
- #ifndef WIN32
- // unlock vga_front
- VgaFrontLock vgaLock;
- #endif
- if( !run_yield)
- return;
- run_yield = 0; // suspend recursive Audio::yield();
- #ifdef WIN32
- // unlock vga_front
- VgaFrontLock vgaLock;
- #endif
- // set break point beyond this point
- int i;
- for(i = 0; i < MAX_LONG_WAV_CH; ++i)
- {
- if( !lp_lwav_ch_dsb[i] )
- continue;
- // if a wav is not play, or buffer lost, stop it
- LPDIRECTSOUNDBUFFER& lpDsb = lp_lwav_ch_dsb[i];
- DWORD dsbStatus;
- if( lpDsb->GetStatus(&dsbStatus) != DS_OK)
- err_here();
- if( !(dsbStatus & DSBSTATUS_PLAYING) ||
- (dsbStatus & DSBSTATUS_BUFFERLOST) && lpDsb->Restore() != DS_OK )
- {
- lpDsb->Stop();
- lpDsb->Release();
- lpDsb = NULL;
- // mem_del(lwav_fileptr[i]);
- delete lwav_fileptr[i];
- lwav_fileptr[i] = NULL;
- continue;
- }
- char writeTooFast = 1;
- // buffer lost, succeeded in restoring
- if( dsbStatus & DSBSTATUS_BUFFERLOST )
- {
- writeTooFast = 0;
- }
- else
- {
- // perform flow control
- DWORD tmpPlayCursor, tmpWriteCursor;
- if( lpDsb->GetCurrentPosition(&tmpPlayCursor, &tmpWriteCursor) == DS_OK)
- {
- writeTooFast = ((short)(tmpPlayCursor / lwav_bufsiz[i]) == lwav_bank[i]);
- }
- }
-
- if(!writeTooFast)
- {
- // lock a channel for lwav_bufsiz[i]
- LPVOID lpvPtr1;
- DWORD dwBytes1;
- LPVOID lpvPtr2;
- DWORD dwBytes2;
- File *filePtr = lwav_fileptr[i];
- HRESULT hr = lpDsb->Lock(lwav_bank[i]*lwav_bufsiz[i], lwav_bufsiz[i],
- &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
- lwav_bank[i] = (lwav_bank[i] + 1) % LWAV_BANKS; // next bank to fill
- if(DS_OK != hr)
- {
- // fail to lock
- err_now("Cannot lock DirectSoundBuffer");
- run_yield = 1;
- return;
- }
- long startPos;
- long readStreamSize;
- DWORD playFlag = DSBPLAY_LOOPING;
- // write to pointers
- startPos = filePtr->file_pos();
- // filePtr->file_read(wav_buf, dwBytes1);
- // readStreamSize = filePtr->file_pos() - startPos; // bytes read in
- // memcpy(lpvPtr1, wav_buf, readStreamSize);
- filePtr->file_read(lpvPtr1, dwBytes1);
- readStreamSize = filePtr->file_pos() - startPos; // bytes read in
- if((long)dwBytes1 > readStreamSize)
- { // end of file, fill the remaining with zero
- // memset((char *)lpvPtr1+readStreamSize, 0, dwBytes1 - readStreamSize);
- playFlag &= ~DSBPLAY_LOOPING; // clear DSBPLAY_LOOPING
- }
- else
- {
- if( lpvPtr2 && dwBytes2 > 0)
- {
- startPos = filePtr->file_pos();
- filePtr->file_read(lpvPtr2, dwBytes2);
- readStreamSize = filePtr->file_pos() - startPos; // bytes read in
- if((long)dwBytes2 > readStreamSize)
- { // end of file
- // memset((char *)lpvPtr2+readStreamSize, 0, dwBytes2 - readStreamSize);
- playFlag &= ~DSBPLAY_LOOPING; // clear DSBPLAY_LOOPING
- }
- }
- }
- // unlock data back
- hr = lpDsb->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
- if(DS_OK != hr)
- {
- // fail to unlock
- err_now("Cannot unlock DirectSoundBuffer");
- run_yield = 1;
- return;
- }
- // load file into a channel, on last stream, don't loop back
- //------- Play wav file --------//
- if(lpDsb->Play(0, 0, playFlag) != DS_OK)
- {
- // fail to play
- err_now("Cannot play DirectSoundBuffer");
- run_yield = 1;
- return;
- }
- }
- }
- for(i = 0; i < MAX_LOOP_WAV_CH; ++i)
- {
- if( !lp_loop_ch_dsb[i] )
- continue;
- // if a channel is not playing, or can't restore release it
- LPDIRECTSOUNDBUFFER& lpDsb = lp_loop_ch_dsb[i];
- DWORD dsbStatus;
- if( lpDsb->GetStatus(&dsbStatus) != DS_OK )
- err_here();
- if( !(dsbStatus & DSBSTATUS_PLAYING) ||
- (dsbStatus & DSBSTATUS_BUFFERLOST) && lpDsb->Restore() != DS_OK )
- {
- lpDsb->Stop();
- lpDsb->Release();
- lpDsb = NULL;
- // mem_del(loopwav_fileptr[i]);
- delete loopwav_fileptr[i];
- loopwav_fileptr[i] = NULL;
- continue;
- }
- char writeTooFast = 1;
- // buffer lost, succeeded in restoring
- if( dsbStatus & DSBSTATUS_BUFFERLOST )
- {
- writeTooFast = 0;
- }
- else
- {
- // perform flow control
- DWORD tmpPlayCursor, tmpWriteCursor;
- if( lpDsb->GetCurrentPosition(&tmpPlayCursor, &tmpWriteCursor) == DS_OK)
- {
- writeTooFast = ((short)(tmpPlayCursor / LOOPWAV_STREAM_BUFSIZ) == loopwav_bank[i]);
- }
- }
-
- if(!writeTooFast)
- {
- // lock a channel for loopwav_bufsiz[i]
- LPVOID lpvPtr1;
- DWORD dwBytes1;
- LPVOID lpvPtr2;
- DWORD dwBytes2;
- File *filePtr = loopwav_fileptr[i];
- HRESULT hr = lpDsb->Lock(loopwav_bank[i]*LOOPWAV_STREAM_BUFSIZ, LOOPWAV_STREAM_BUFSIZ,
- &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
- loopwav_bank[i] = (loopwav_bank[i] + 1) % LOOPWAV_BANKS; // next bank to fill
- if(DS_OK != hr)
- {
- // fail to lock
- err_now("Cannot lock DirectSoundBuffer");
- run_yield = 1;
- return;
- }
- long startPos;
- long readStreamSize;
- DWORD playFlag = DSBPLAY_LOOPING;
- // write to pointers
- startPos = filePtr->file_pos();
- filePtr->file_read(lpvPtr1, dwBytes1);
- readStreamSize = filePtr->file_pos() - startPos; // bytes read in
- if((long)dwBytes1 > readStreamSize)
- { // end of file, seek to beginning and read again
- filePtr->file_seek(repeat_offset[i]);
- filePtr->file_read((char *)lpvPtr1+readStreamSize, dwBytes1-readStreamSize);
- }
- // unlock data back
- hr = lpDsb->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
- if(DS_OK != hr)
- {
- // fail to unlock
- err_now("Cannot unlock DirectSoundBuffer");
- run_yield = 1;
- return;
- }
- // set volume if fading
- if( loopwav_fade_rate[i] )
- {
- DWORD nextFadeTime = m.get_time();
- LONG volume;
- if( DS_OK == (hr = lpDsb->GetVolume(&volume)) )
- {
- // calculate new volume
- volume -= (nextFadeTime - loopwav_fade_time[i]) * loopwav_fade_rate[i];
- if( volume < DSBVOLUME_MIN )
- volume = DSBVOLUME_MIN;
- else if( volume > DSBVOLUME_MAX )
- volume = DSBVOLUME_MAX;
- if( DS_OK == (hr = lpDsb->SetVolume(volume)) )
- {
- loopwav_fade_time[i] = nextFadeTime;
- }
- }
- }
- // load file into a channel, on last stream, don't loop back
- //------- Play wav file --------//
- if(lpDsb->Play(0, 0, playFlag) != DS_OK)
- {
- // fail to play
- err_now("Cannot play DirectSoundBuffer");
- run_yield = 1;
- return;
- }
- }
- }
- run_yield = 1; // resume Audio::yield();
- }
- //------- End of function Audio::yield ---------------//
- //------- Begin of function Audio::stop_wav -------//
- //
- void Audio::stop_wav()
- {
- if( !wav_init_flag || !wav_flag )
- return;
- // ---------- stop all short wave ------------- //
- int i;
- for(i = 0; i < MAX_WAV_CHANNEL; ++i)
- if(lp_wav_ch_dsb[i])
- {
- lp_wav_ch_dsb[i]->Stop();
- lp_wav_ch_dsb[i]->Release();
- lp_wav_ch_dsb[i] = NULL;
- }
- // ----------- stop all long wave ------------- //
- stop_long_wav();
- // ------------ stop all loop wave ------------//
- for(i = 1; i <= MAX_LOOP_WAV_CH; ++i)
- {
- stop_loop_wav(i);
- }
- }
- //------- End of function Audio::stop_wav -------//
- //------- Begin of function Audio::stop_long_wav -------//
- //
- void Audio::stop_long_wav()
- {
- if( !wav_init_flag || !wav_flag )
- return;
- for(int i = 0; i < MAX_LONG_WAV_CH; ++i)
- if(lp_lwav_ch_dsb[i])
- {
- lp_lwav_ch_dsb[i]->Stop();
- lp_lwav_ch_dsb[i]->Release();
- lp_lwav_ch_dsb[i] = NULL;
- // mem_del(lwav_fileptr[i]);
- delete lwav_fileptr[i];
- lwav_fileptr[i] = NULL;
- }
- }
- //------- End of function Audio::stop_long_wav -------//
- //------- Begin of function Audio::stop_loop_wav -------//
- void Audio::stop_loop_wav(int ch)
- {
- int chanNum = ch-1;
- if( chanNum < 0 || chanNum >= MAX_LOOP_WAV_CH)
- return;
- if(lp_loop_ch_dsb[chanNum])
- {
- lp_loop_ch_dsb[chanNum]->Stop();
- lp_loop_ch_dsb[chanNum]->Release();
- lp_loop_ch_dsb[chanNum] = NULL;
- // mem_del(loopwav_fileptr[chanNum]); // delete lwav_fileptr[chanNum];
- delete loopwav_fileptr[chanNum];
- loopwav_fileptr[chanNum] = NULL;
- }
- }
- //------- End of function Audio::stop_loop_wav ---------//
- //------- Begin of function Audio::play_cd -------//
- //
- // <int> trackId - the id. of the CD track to play.
- //
- int Audio::play_cd(int trackId, int volume)
- {
- if( !cd_init_flag || !cd_flag )
- return 0;
- // ###### begin Gilbert 3/10 ########//
- MCIERROR mciError;
- DWORD maxTrack = 99;
- // Get the number of tracks;
- // limit to number that can be displayed (20).
- MCI_STATUS_PARMS mciStatusParms;
- mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
- mciError = mciSendCommand(mci_open.wDeviceID, MCI_STATUS,
- MCI_STATUS_ITEM, (DWORD)(LPVOID) &mciStatusParms);
- if( !mciError )
- maxTrack = mciStatusParms.dwReturn;
- //--- Send an MCI_PLAY command to the CD Audio driver ---//
- mci_open.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO;
- mci_play.dwFrom = MCI_MAKE_TMSF(trackId , 0, 0, 0);
- mci_play.dwTo = MCI_MAKE_TMSF(trackId+1, 0, 0, 0);
- DWORD cmdFlag = MCI_FROM;
- if( (DWORD) trackId < maxTrack )
- cmdFlag |= MCI_TO; // if MCI_TO is missing, play until the end
- mciError = mciSendCommand( mci_open.wDeviceID, MCI_PLAY, cmdFlag,
- (DWORD) (LPVOID) &mci_play);
- if( mciError )
- return 0;
- return 1;
- // ###### end Gilbert 3/10 ########//
- }
- //------- End of function Audio::play_cd -------//
- //------- Begin of function Audio::stop_cd -------//
- //
- void Audio::stop_cd()
- {
- if( !cd_init_flag || !cd_flag )
- return;
- DWORD dwResult;
- dwResult = mciSendCommand(mci_open.wDeviceID, MCI_STOP,
- MCI_WAIT, (DWORD)(LPVOID)NULL);
- }
- //------- End of function Audio::stop_cd -------//
- //------- Begin of function Audio::is_mid_playing -------//
- //
- int Audio::is_mid_playing()
- {
- if( !mid_init_flag || !mid_flag ) // a initialized and workable midi device can be disabled by user setting
- return 0;
- //... insert code here ...//
- return 0;
- }
- //------- End of function Audio::is_mid_playing -------//
- //------- Begin of function Audio::is_wav_playing -------//
- //
- int Audio::is_wav_playing()
- {
- int playingChannelCount = 0;
- DWORD dwStatus;
- if( !wav_init_flag || !wav_flag ) // a initialized and workable midi device can be disabled by user setting
- return 0;
- //------ find any wav channel is playing -----//
- // update lp_wav_ch_dsb[x] if necessary
- for(int ch=0; ch < MAX_WAV_CHANNEL; ++ch)
- if( lp_wav_ch_dsb[ch])
- if( lp_wav_ch_dsb[ch]->GetStatus(&dwStatus) == DS_OK)
- if (dwStatus & DSBSTATUS_PLAYING )
- // a channel is playing
- playingChannelCount++;
- else
- // is not playing, clear it
- lp_wav_ch_dsb[ch] = NULL;
- else
- // GetStatus not ok, clear it
- lp_wav_ch_dsb[ch] = NULL;
- else
- {
- // nothing
- }
- return (playingChannelCount > 0);
- }
- //------- End of function Audio::is_wav_playing -------//
- //------- Begin of function Audio::is_cd_playing -------//
- //
- int Audio::is_cd_playing()
- {
- if( !cd_init_flag || !cd_flag ) // a initialized and workable midi device can be disabled by user setting
- return 0;
- MCI_STATUS_PARMS status;
- DWORD dwResult;
- //
- // get the current status
- //
- status.dwItem = MCI_STATUS_MODE;
- dwResult = mciSendCommand(mci_open.wDeviceID, MCI_STATUS,
- MCI_WAIT | MCI_STATUS_ITEM, (DWORD)(LPVOID)&status);
- if (dwResult == 0)
- return status.dwReturn == MCI_MODE_PLAY;
- return 0;
- }
- //------- End of function Audio::is_cd_playing -------//
- //----------------- Begin of Audio::toggle_mid -----------------//
- //
- void Audio::toggle_mid(int midFlag)
- {
- if( !midFlag )
- stop_mid();
- mid_flag = midFlag;
- }
- //------------------- End of Audio::toggle_mid ------------------//
- //----------------- Begin of Audio::toggle_wav -----------------//
- //
- void Audio::toggle_wav(int wavFlag)
- {
- if( !wavFlag )
- stop_wav();
- wav_flag = wavFlag;
- }
- //------------------- End of Audio::toggle_wav ------------------//
- //----------------- Begin of Audio::toggle_cd -----------------//
- //
- void Audio::toggle_cd(int cdFlag)
- {
- if( !cdFlag )
- stop_cd();
- cd_flag = cdFlag;
- }
- //------------------- End of Audio::toggle_cd ------------------//
- //-------------- Begin of Audio::set_mid_volume -------------//
- //
- // Set mid volume
- //
- // <int> midVolume = mid volume, 0-100
- //
- void Audio::set_mid_volume(int midVolume)
- {
- if( !mid_init_flag )
- return;
- //.. insert code here ...//
- }
- //--------------- End of Audio::set_mid_volume --------------//
- //-------------- Begin of Audio::set_wav_volume -------------//
- //
- // Set wav volume
- //
- // <int> wavVolume = wav volume, 0-100
- //
- void Audio::set_wav_volume(int wavVolume)
- {
- if( !wav_init_flag )
- return;
- LONG dsVolume;
- long dsVolDiff = (wavVolume - wav_volume) * 100;
- // change volume for all channels
- int i;
- for( i = 0; i < MAX_WAV_CHANNEL; ++i)
- {
- if( lp_wav_ch_dsb[i] &&
- lp_wav_ch_dsb[i]->GetVolume(&dsVolume) == DS_OK)
- {
- dsVolume += dsVolDiff;
- if( dsVolume > DSBVOLUME_MAX )
- dsVolume = DSBVOLUME_MAX;
- if( dsVolume < DSBVOLUME_MIN )
- dsVolume = DSBVOLUME_MIN;
- lp_wav_ch_dsb[i]->SetVolume(dsVolume);
- }
- }
- for( i = 0; i < MAX_LONG_WAV_CH; ++i)
- {
- if( lp_lwav_ch_dsb[i] &&
- lp_lwav_ch_dsb[i]->GetVolume(&dsVolume) == DS_OK)
- {
- dsVolume += dsVolDiff;
- if( dsVolume > DSBVOLUME_MAX )
- dsVolume = DSBVOLUME_MAX;
- if( dsVolume < DSBVOLUME_MIN )
- dsVolume = DSBVOLUME_MIN;
- lp_lwav_ch_dsb[i]->SetVolume(dsVolume);
- }
- }
- for( i = 0; i < MAX_LOOP_WAV_CH; ++i)
- {
- if( lp_loop_ch_dsb[i] &&
- lp_loop_ch_dsb[i]->GetVolume(&dsVolume) == DS_OK)
- {
- dsVolume += dsVolDiff;
- if( dsVolume > DSBVOLUME_MAX )
- dsVolume = DSBVOLUME_MAX;
- if( dsVolume < DSBVOLUME_MIN )
- dsVolume = DSBVOLUME_MIN;
- lp_loop_ch_dsb[i]->SetVolume(dsVolume);
- }
- }
- wav_volume = wavVolume;
- }
- //--------------- End of Audio::set_wav_volume --------------//
- //-------------- Begin of Audio::set_cd_volume -------------//
- //
- // Set cd volume
- //
- // <int> cdVolume = cd volume, 0-100
- //
- void Audio::set_cd_volume(int cdVolume)
- {
- if( !cd_init_flag )
- return;
- //.. insert code here ...//
- }
- //--------------- End of Audio::set_cd_volume --------------//
- //-------------- Begin of function Audio::assign_serial ----------//
- int Audio::assign_serial(int &s)
- {
- if( s == INT_MAX)
- return s = 1;
- return ++s;
- }
- //-------------- End of function Audio::assign_serial ----------//
- // ------------ Begin of function Audio::volume_long_wav -------//
- void Audio::volume_long_wav(int serial, DsVolume dsVolume)
- {
- if( is_long_wav_playing(serial) )
- {
- for( int chanNum = 0; chanNum < MAX_LONG_WAV_CH; ++chanNum)
- {
- if(lp_lwav_ch_dsb[chanNum] != NULL && lwav_serial_no[chanNum] == serial )
- {
- lp_lwav_ch_dsb[chanNum]->SetVolume(dsVolume.ds_vol);
- // lp_lwav_ch_dsb[chanNum]->SetPan(dsVolume.ds_pan);
- break;
- }
- }
- }
- }
- // ------------ End of function Audio::volume_long_wav -------//
|