12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385 |
- /*=============================================================================
- Name : sstream.c
- Purpose : Low level audio streamer routines
- Created 01/10/1998 by salfreds
- Copyright Relic Entertainment, Inc. All rights reserved.
- =============================================================================*/
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #include <string.h>
- #include <mmsystem.h>
- #include <dsound.h>
- #include <process.h>
- #include "types.h"
- #include "switches.h"
- #include "debug.h"
- #include "soundlow.h"
- #include "soundcmn.h"
- #include "file.h"
- #include "fqeffect.h"
- #include "soundstructs.h"
- #include "speechevent.h"
- #include "subtitle.h"
- /* functions */
- sdword isoundstreamreadheader(STREAM *pstream);
- /* variables */
- streamprintfunction debugfunction = NULL;
- char debugtext[256];
- //filehandle streamfile;
- CHANNEL speechchannels[SOUND_MAX_STREAM_BUFFERS];
- STREAM streams[SOUND_MAX_STREAM_BUFFERS];
- sdword numstreams;
- #if VCE_BACKWARDS_COMPATIBLE
- bool ssOldFormatVCE = FALSE;
- #endif
- extern LPDIRECTSOUND lpDirectSound;
- extern CHANNEL channels[];
- extern SENTENCELUT *SentenceLUT;
- extern bool soundinited;
- extern SOUNDCOMPONENT streamer;
- extern udword mixerticks;
- extern bool bSoundPaused;
- extern bool bSoundDeactivated;
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- void soundstreamquery(sdword maxstreams, sdword *pbuffersize, sdword *pstreamersize)
- {
- if (maxstreams > SOUND_MAX_STREAM_BUFFERS)
- {
- *pstreamersize = 0;
- *pbuffersize = 0;
- return;
- }
- numstreams = maxstreams;
- /* figure out how much memory we need for the array of stream structures */
- *pstreamersize = (sdword)(maxstreams * sizeof(STREAM));
- /* figure out how big each stream buffer needs to be */
- *pbuffersize = SOUND_STREAM_BUFFER_SIZE + 4; // needs 4 extra bytes for dequantizing.
- }
- sdword streamStartThread(void)
- {
- _beginthread(isoundstreamupdate, 0, NULL);
-
- streamer.status = SOUND_PLAYING;
- return (SOUND_OK);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword soundstreaminit(void *pstreamer, sdword size, sdword nostreams, streamprintfunction printfunction)
- {
- sdword i, j;
- STREAM *pstream;
- memset(pstreamer, 0, size);
- dbgAssert(streamer.status == SOUND_FREE);
- /* go through stream structures and init */
- for (i = 0; i < numstreams; i++)
- {
- pstream = &streams[i];
- pstream->buffer = NULL;
- for (j = 0; j < SOUND_MAX_STREAM_QUEUE; j++)
- {
- pstream->queue[j].fhandle = SOUND_ERR;
- pstream->queue[j].offset = SOUND_ERR;
- }
- pstream->numqueued = 0;
- pstream->numtoplay = 0;
- if (i < SentenceLUT->numactors)
- {
- pstream->dataPeriod = SND_BLOCK_TIME / (SentenceLUT->compbitrate[i] / 8);
- }
- else
- {
- pstream->dataPeriod = SND_BLOCK_TIME / (SentenceLUT->compbitrate[0] / 8);
- }
-
- speechchannels[i].status = SOUND_FREE;
- }
- if (printfunction != NULL)
- {
- debugfunction = printfunction;
- }
-
- streamStartThread();
- return (SOUND_OK);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- udword soundstreamopenfile(char *pszStreamFile, sdword *handle)
- {
- filehandle streamfile;
- udword identifier;
- udword checksum;
- udword flags;
- /* Check Data dir on HD... */
- flags = 0;
- if (!fileExists(pszStreamFile, flags))
- {
- /* Check first CDROM drive... */
- flags = FF_CDROM;
- if (!fileExists(pszStreamFile, flags))
- {
- /* Death, destruction and general chaos! Should never happen (taken care of in utyGameSystemsInit()...*/
- dbgFatalf(DBG_Loc, "Homeworld CD not detected.");
- }
- }
- streamfile = fileOpen(pszStreamFile, flags);
- *handle = streamfile;
- #if VCE_BACKWARDS_COMPATIBLE
- fileBlockRead(streamfile, &identifier, sizeof(identifier));//read in an identifier
- if (identifier == ID_STREAM_DATA)
- { //if it's 'DATA'
- ssOldFormatVCE = TRUE;
- }
- #else
- fileSeek(streamfile, 4, FS_Start);
- #endif
- fileBlockRead(streamfile, &checksum, sizeof(checksum));
- fileSeek(streamfile, 0, FS_Start);
- return (checksum);
- }
- /*-----------------------------------------------------------------------------
- Name : soundstreamcreatebuffer
- Description :
- Inputs : pstreambuffer: pointer to a buffer allocated by the game
- size: the size of streambuffer
- Outputs :
- Return : the handle to the stream
- ----------------------------------------------------------------------------*/
- sdword soundstreamcreatebuffer(void *pstreambuffer, sdword size, uword bitrate)
- {
- sdword channel = 0;
- CHANNEL *pchan;
- STREAM *pstream;
- sdword i;
- for (i = 0; i < numstreams; i++)
- {
- if (streams[i].status == SOUND_STREAM_FREE)
- {
- pchan = &speechchannels[i];
- pstream = &streams[i];
- channel = i;
- pstream->status = SOUND_STREAM_INUSE;
- pstream->buffersize = SOUND_STREAM_BUFFER_SIZE;
- pstream->buffer = pstreambuffer;
- pstream->playing = FALSE;
- memset(pstream->buffer, 0, pstream->buffersize);
-
- fqAcModel(NULL, NULL, 0, pstream->delaybuffer1, DELAY_BUF_SIZE, &(pstream->delaypos1));
- fqAcModel(NULL, NULL, 0, pstream->delaybuffer2, DELAY_BUF_SIZE, &(pstream->delaypos2));
- break;
- }
- }
- if (pstream == NULL)
- {
- SNDreleasebuffer(pchan);
- }
- if (pstream->buffersize % ((bitrate >> 3) * 4))
- {
- pstream->buffersize /= ((bitrate >> 3) * 4);
- pstream->buffersize *= ((bitrate >> 3) * 4);
- }
- pchan->currentpos = pchan->freqdata = (sbyte *)pstream->buffer;
- pchan->endpos = (sbyte *)(pstream->buffer + pstream->buffersize);
- pchan->fqsize = FQ_HSIZE;
- pstream->writepos = pstream->buffer;
- pstream->readblock = 0;
- pstream->writeblock = 0;
- pstream->blocksize = pstream->buffersize / 2;
- pchan->handle = SNDcreatehandle(channel);
- pstream->handle = pchan->handle;
- return (pchan->handle);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword soundstreamnumqueued(sdword streamhandle)
- {
- #if 1
- if (speechchannels[SNDchannel(streamhandle)].status <= SOUND_INUSE)
- {
- return (0);
- }
- else
- {
- return (1);
- }
- #endif
- return (streams[SNDchannel(streamhandle)].numqueued);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- void soundstreamstopall(real32 fadetime)
- {
- sdword i;
- for (i = 0; i < numstreams; i++)
- {
- soundstreamvolume(speechchannels[i].handle, SOUND_VOL_AUTOSTOP, fadetime);
- // streams[i].status = SOUND_STREAM_INUSE;
- // streams[i].queueindex = 0;
- // streams[i].writeindex = 0;
- // streams[i].playindex = 0;
- // speechchannels[i].status = SOUND_FREE;
- }
- }
- sdword soundstreamover(sdword streamhandle)
- {
- sdword channel;
- if (!soundinited)
- {
- return (TRUE);
- }
-
- if (streamer.status != SOUND_PLAYING)
- {
- return (TRUE);
- }
-
- channel = SNDchannel(streamhandle);
- if (channel >= SOUND_OK)
- {
- if (speechchannels[SNDchannel(streamhandle)].status <= SOUND_STOPPED)
- {
- return (TRUE);
- }
- }
- return (FALSE);
- }
- sdword soundstreamfading(sdword streamhandle)
- {
- sdword channel;
- if (!soundinited)
- {
- return (FALSE);
- }
-
- if (streamer.status != SOUND_PLAYING)
- {
- return (FALSE);
- }
-
- channel = SNDchannel(streamhandle);
- if (channel >= SOUND_OK)
- {
- if (speechchannels[channel].volfade != 0.0f)
- {
- return (TRUE);
- }
- }
- return (FALSE);
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs : actornum - actor index of event we're queueing up
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- sdword soundstreamqueuePatch(sdword streamhandle, sdword filehandle, sdword offset, udword flags, sword vol, sword pan, sword numchannels, sword bitrate, EFFECT *peffect, STREAMEQ *pEQ, STREAMDELAY *pdelay, void *pmixpatch, sdword level, real32 silence, real32 fadetime, sdword actornum, sdword speechEvent, bool bWait)
- {
- sdword chan;
- STREAM *pstream;
- PATCH *ppatch;
- STREAMQUEUE *pqueue;
- // make sure the damn offset is valid.
- #ifdef salfreds
- if (!(flags & SOUND_FLAGS_QUEUESILENCE))
- {
- dbgAssert(offset >= 0);
- }
- #endif
- if (streamer.status == SOUND_STOPPING)
- {
- return (SOUND_ERR);
- }
- chan = SNDchannel(streamhandle);
- dbgAssert(chan >= 0);
- pstream = &streams[chan];
- if (pstream->handle != streamhandle)
- {
- /* hmmm, bad. do something */
- return (SOUND_ERR);
- }
- if ((pstream->queueindex == pstream->playindex) && (pstream->status > SOUND_STREAM_INUSE))
- {
- return (SOUND_ERR);
- }
- if ((flags & SOUND_FLAGS_QUEUESTREAM) || (flags & SOUND_FLAGS_QUEUESILENCE))
- {
- if (pstream->numqueued < (SOUND_MAX_STREAM_QUEUE - 1))
- {
- pqueue = &pstream->queue[pstream->queueindex];
- pqueue->offset = offset;
- pqueue->flags = flags;
- pqueue->vol = vol;
- pqueue->pan = pan;
- pqueue->numchannels = numchannels;
- pqueue->bitrate = bitrate;
- pqueue->fadetime = fadetime;
- pqueue->volfactorL = (real32)vol / SOUND_VOL_MAX;
- pqueue->volfactorR = (real32)vol / SOUND_VOL_MAX;
- pqueue->silencetime = silence;
- pqueue->actornum = actornum;
- pqueue->speechEvent = speechEvent;
- if (pmixpatch != NULL)
- {
- pqueue->pmixPatch = (PATCH *)pmixpatch;
- pqueue->mixLevel = level;
- }
- else
- {
- pqueue->pmixPatch = NULL;
- pqueue->mixLevel = SOUND_VOL_MIN;
- }
- pqueue->mixHandle = SOUND_DEFAULT;
- if (pan < SOUND_PAN_CENTER)
- {
- /* panned left so attenuate right */
- pqueue->volfactorR *= (real32)(SOUND_PAN_RIGHT + pan) / SOUND_PAN_RIGHT;
- }
- else if (pan > SOUND_PAN_CENTER)
- {
- /* panned right so attenuate left */
- pqueue->volfactorL *= (real32)(SOUND_PAN_RIGHT - pan) / SOUND_PAN_RIGHT;
- }
-
- if (pEQ != NULL)
- {
- pqueue->eq = pEQ;
- }
- else
- {
- pqueue->eq = NULL;
- }
-
- if (pdelay != NULL)
- {
- pqueue->delay = pdelay;
- }
- else
- {
- pqueue->delay = NULL;
- }
-
- if (peffect != NULL)
- {
- pqueue->effect = peffect;
- }
- else
- {
- pqueue->effect = NULL;
- }
- pstream->numqueued++;
- pstream->numtoplay++;
- pstream->queueindex++;
- if (pstream->queueindex >= SOUND_MAX_STREAM_QUEUE)
- {
- pstream->queueindex = 0;
- }
- pqueue->fhandle = filehandle;
- if ((pstream->status == SOUND_STREAM_INUSE) && !bWait)
- {
- pstream->blockstatus[0] = 0;
- pstream->blockstatus[1] = 0;
- pstream->readblock = 0;
- pstream->writeblock = 0;
- pstream->writepos = 0;
- pstream->status = SOUND_STREAM_STARTING;
- }
- }
- }
- else if (flags & SOUND_FLAGS_QUEUEPATCH)
- {
- if (pstream->numqueued < (SOUND_MAX_STREAM_QUEUE - 1))
- {
- ppatch = SNDgetpatch((void *)filehandle, offset);
- if (ppatch != NULL)
- {
- pqueue = &pstream->queue[pstream->queueindex];
- pqueue->offset = (sdword)ppatch;
- pqueue->flags = flags;
- pqueue->vol = vol;
- pqueue->pan = pan;
- pqueue->numchannels = numchannels;
- pqueue->bitrate = ppatch->bitrate;
- pqueue->fadetime = 0.0f;
- pqueue->volfactorL = (real32)vol / SOUND_VOL_MAX;
- pqueue->volfactorR = (real32)vol / SOUND_VOL_MAX;
- pqueue->pmixPatch = NULL;
- pqueue->mixLevel = SOUND_VOL_MIN;
- pqueue->mixHandle = SOUND_DEFAULT;
- pqueue->actornum = actornum;
-
- if (pan < SOUND_PAN_CENTER)
- {
- /* panned left so attenuate right */
- pqueue->volfactorR *= (real32)(SOUND_PAN_RIGHT + pan) / SOUND_PAN_RIGHT;
- }
- else if (pan > SOUND_PAN_CENTER)
- {
- /* panned right so attenuate left */
- pqueue->volfactorL *= (real32)(SOUND_PAN_RIGHT - pan) / SOUND_PAN_RIGHT;
- }
-
- if (pEQ != NULL)
- {
- pqueue->eq = pEQ;
- }
- else
- {
- pqueue->eq = NULL;
- }
-
- if (pdelay != NULL)
- {
- pqueue->delay = pdelay;
- }
- else
- {
- pqueue->delay = NULL;
- }
-
- if (peffect != NULL)
- {
- pqueue->effect = peffect;
- }
- else
- {
- pqueue->effect = NULL;
- }
- pstream->numqueued++;
- pstream->numtoplay++;
- pstream->queueindex++;
- if (pstream->queueindex >= SOUND_MAX_STREAM_QUEUE)
- {
- pstream->queueindex = 0;
- }
- pqueue->fhandle = filehandle;
-
- if ((pstream->status == SOUND_STREAM_INUSE) && !bWait)
- {
- pstream->blockstatus[0] = 0;
- pstream->blockstatus[1] = 0;
- pstream->readblock = 0;
- pstream->writeblock = 0;
- pstream->writepos = 0;
- pstream->status = SOUND_STREAM_STARTING;
- }
- }
- }
- }
- return (SOUND_OK);
- }
- /*-----------------------------------------------------------------------------
- Name : soundstreamvolume
- Description :
- Inputs : handle - the handle to a sound returned by soundplay
- vol - the volume to set this sound to (range of SOUND_MIN_VOL - SOUND_MAX_VOL)
- Outputs :
- Return : SOUND_OK if successful, SOUND_ERR on error
- ----------------------------------------------------------------------------*/
- sdword soundstreamvolume(sdword handle, sword vol, real32 fadetime)
- {
- HRESULT hr = SOUND_ERR;
- CHANNEL *pchan;
- sdword channel;
- bool stop = FALSE;
- sdword fadeblocks = -1;
- STREAM *pstream;
- sdword i;
- if (!soundinited)
- {
- return (SOUND_ERR);
- }
-
- if (streamer.status != SOUND_PLAYING)
- {
- return (SOUND_ERR);
- }
- if (vol > SOUND_VOL_MAX)
- {
- vol = SOUND_VOL_MAX;
- }
- else if (vol == -1)
- {
- vol = SOUND_VOL_MIN;
- stop = TRUE;
- }
- else if (vol <= SOUND_VOL_MIN)
- {
- vol = SOUND_VOL_MIN;
- }
- channel = SNDchannel(handle);
- if (channel < 0)
- {
- return (SOUND_ERR);
- }
- pchan = &speechchannels[channel];
- if (pchan != NULL)
- {
- fadeblocks = (sdword)(fadetime * SOUND_FADE_TIMETOBLOCKS);
- if (fadeblocks < NUM_FADE_BLOCKS)
- {
- fadeblocks = NUM_FADE_BLOCKS;
- }
- if ((vol != pchan->voltarget) || stop)
- {
- if (vol == (sword)pchan->volume)
- {
- pchan->voltarget = vol;
- pchan->volticksleft = 1;
- pchan->volfade = 0.0f;
- }
- else if (fadeblocks > 0)
- {
- pchan->voltarget = vol;
- pchan->volticksleft = fadeblocks;
- pchan->volfade = (real32)(pchan->voltarget - pchan->volume) / (real32)pchan->volticksleft;
- if (pchan->volfade == 0.0f)
- {
- pchan->volfade = 0.01f;
- if (pchan->voltarget < pchan->volume)
- {
- pchan->volfade = -0.01f;
- }
- }
- }
- else if (fadeblocks == -1)
- {
- pchan->voltarget = vol;
- pchan->volfade = 0.01f;
- pchan->volticksleft = ((sword)pchan->volume - vol) * 100;
- if (pchan->volticksleft < 0)
- {
- pchan->volticksleft *= -1;
- }
- }
- else
- {
- pchan->volume = vol;
- pchan->voltarget = vol;
- pchan->volticksleft = 1;
- pchan->volfade = 0.0f;
- }
-
- if (stop)
- {
- pchan->status = SOUND_STOPPING;
- /* need to clean up the queue */
- pstream = &streams[channel];
- pstream->writeindex = pstream->playindex;
- if (pstream->status == SOUND_STREAM_INUSE)
- {
- pstream->queueindex = pstream->writeindex;
- }
- else
- {
- pstream->queueindex = pstream->writeindex + 1;
- if (pstream->queueindex >= SOUND_MAX_STREAM_QUEUE)
- {
- pstream->queueindex = 0;
- }
- }
- // pstream->queue[pstream->writeindex].fhandle = SOUND_ERR;
- pstream->numqueued = 0;
- for (i = 0; i < SOUND_MAX_STREAM_QUEUE; i++)
- {
- if (i != pstream->playindex)
- {
- pstream->queue[i].fhandle = SOUND_ERR;
- }
- }
- }
- }
- }
- return (SOUND_OK);
- }
- /*-----------------------------------------------------------------------------
- Name : ssSubtitleRead
- Description : Read in a subtitle and pass it on to the subtitle code.
- Inputs : handle - handle of the file to read from, queued up to the
- start of the subtitle
- actornum - index of actor or -1 if there is no actor
- speechEvent - what speechEvent this was
- dataPeriod - inverse of data rate, in seconds/byte
- Outputs : header - header for the data of the speech phrase. We need
- to read this here to determine the length of the phrase.
- Return : length of subtitle info read or -1 if there is no subtitle
- ----------------------------------------------------------------------------*/
- sdword ssSubtitleRead(STREAMHEADER *header, filehandle handle, sdword actornum, sdword speechEvent, real32 dataPeriod)
- {
- sdword length, length2;
- char subTitle[SUB_SubtitleLength];
- real32 time;
- #if VCE_BACKWARDS_COMPATIBLE
- STREAMHEADER header2, headerTemp;
- udword currentOffset;
- #endif //VCE_BACKWARDS_COMPATIBLE
- length = fileBlockRead(handle, header, sizeof(STREAMHEADER));//read in the "INFO" and length
- dbgAssert(length == sizeof(STREAMHEADER));
- if (header->ID != ID_STREAM_INFO)
- { //if we didn't read "INFO"
- //!!!dbgAssert(header->ID == ID_STREAM_DATA); //it must have been "DATA"
- if (header->ID != ID_STREAM_DATA)
- {
- return(sizeof(STREAMHEADER)); //skip the subtitle
- }
- #if VCE_BACKWARDS_COMPATIBLE
- if (ssOldFormatVCE)
- { //if it's an old-format file
- currentOffset = fileSeek(handle, 0, FS_Current);//get current location in file
- fileSeek(handle, header->size, FS_Current); //seek to end of data to read in the info
- length2 = fileBlockRead(handle, &header2, sizeof(STREAMHEADER));//read in the "INFO" and length
- if (header2.ID != ID_STREAM_INFO)
- { //if didn't find data
- fileSeek(handle, currentOffset, FS_Start); //seek back to start of data
- }
- else
- { //it did find the info
- headerTemp = *header;
- *header = header2;
- goto foundInfo;
- }
- }
- #endif //VCE_BACKWARDS_COMPATIBLE
- return(sizeof(STREAMHEADER)); //skip the subtitle
- }
- #if VCE_BACKWARDS_COMPATIBLE
- foundInfo:;
- #endif
- dbgAssert(header->size >= 0);
- dbgAssert(header->size < SUB_SubtitleLength);
- length = fileBlockRead(handle, subTitle, header->size); //read in the actual subtitle
- dbgAssert(length == header->size);
- subTitle[header->size] = 0; //NULL-terminate the string (it's not terminated in the file)
- //now read in the "DATA" header
- #if VCE_BACKWARDS_COMPATIBLE
- if (ssOldFormatVCE)
- { //if it's old format
- fileSeek(handle, currentOffset, FS_Start); //seek back to start of data
- *header = headerTemp; //restore the header
- length = -length2; //so neither of these will be reported in the return length
- }
- else
- {
- length2 = fileBlockRead(handle, header, sizeof(STREAMHEADER));
- }
- #endif
- dbgAssert(length2 == sizeof(STREAMHEADER));
- //!!!dbgAssert(header->ID == ID_STREAM_DATA);
- time = (real32)header->size * dataPeriod;
- if (actornum >= 0 && length > 0)
- {
- if (actornum == 0)
- { //all single-player voices are on the same channel
- if (bitTest(speechEvent, ACTOR_FLEETCOMMAND_FLAG))
- {
- actornum = STA_FleetCommand;
- }
- else if (bitTest(speechEvent, ACTOR_FLEETINTEL_FLAG))
- {
- actornum = STA_FleetIntel;
- }
- else if (bitTest(speechEvent, ACTOR_TRADERS_FLAG))
- {
- actornum = STA_Traders;
- }
- else if (bitTest(speechEvent, ACTOR_PIRATES2_FLAG))
- {
- actornum = STA_Pirates2;
- }
- else if (bitTest(speechEvent, ACTOR_ALLSHIPSENEMY_FLAG))
- {
- actornum = STA_AllEnemyShips;
- }
- else if (bitTest(speechEvent, ACTOR_AMBASSADOR_FLAG))
- {
- actornum = STA_Ambassador;
- }
- else if (bitTest(speechEvent, ACTOR_NARRATOR_FLAG))
- {
- actornum = STA_Narrator;
- }
- else if (bitTest(speechEvent, ACTOR_DEFECTOR_FLAG))
- {
- actornum = STA_Defector;
- }
- else if (bitTest(speechEvent, ACTOR_EMPEROR_FLAG))
- {
- actornum = STA_Emperor;
- }
- else if (bitTest(speechEvent, ACTOR_KHARSELIM_FLAG))
- {
- actornum = STA_KharSelim;
- }
- else
- {
- //dbgFatalf(DBG_Loc, "Invalid actor 0x%x with speech event 0x%x", actornum, speechEvent);
- ;//just assume fleet command!!!is this valid?
- }
- }
- subTitleAdd(actornum, speechEvent, subTitle, length, time);
- }
- return(length + length2 + sizeof(STREAMHEADER));
- }
- sword soundstreamgetvol(sdword handle)
- {
- sdword channel;
-
- if (!soundinited)
- {
- return (SOUND_ERR);
- }
-
- if (streamer.status != SOUND_PLAYING)
- {
- return (SOUND_ERR);
- }
- channel = SNDchannel(handle);
- if (channel >= SOUND_OK)
- {
- return ((sword)speechchannels[channel].volume);
- }
- return (SOUND_ERR);
- }
- sdword isoundstreamreadheader(STREAM *pstream)
- {
- sdword ret, length, i;
- STREAMQUEUE *pqueue;
- PATCH *ppatch;
- pqueue = &pstream->queue[pstream->writeindex];
- if (pqueue->fhandle == SOUND_ERR)
- {
- if (pstream->numqueued == 1)
- {
- for (i = 0; i < SOUND_MAX_STREAM_QUEUE; i++)
- {
- if (pstream->queue[i].fhandle > 0)
- {
- pstream->writeindex = i;
- pstream->playindex = i;
- pstream->queueindex = i + 1;
- if (pstream->queueindex >= SOUND_MAX_STREAM_QUEUE)
- {
- pstream->queueindex = 0;
- }
- pqueue = &pstream->queue[pstream->writeindex];
- break;
- }
- }
- if (i == SOUND_MAX_STREAM_QUEUE)
- {
- pstream->dataleft = 0;
- pstream->numqueued = 0;
- return (-4); //(SOUND_ERR);
- }
- }
- else
- {
- pstream->dataleft = 0;
- pstream->numqueued--;
- if (pstream->numqueued < 0)
- {
- pstream->numqueued = 0;
- }
- return (-1); //(SOUND_ERR);
- }
- }
- if (pqueue->flags & SOUND_FLAGS_QUEUESTREAM)
- {
- ret = fileSeek(pqueue->fhandle, pqueue->offset, FS_Start); //pstream->lastpos);
- if (ret != pqueue->offset)
- {
- /* yuck, bad */
- return (-2); //(SOUND_ERR);
- }
- //read in the subTitle, if there is any
- length = ssSubtitleRead(&pstream->header, pqueue->fhandle, pqueue->actornum, pqueue->speechEvent, pstream->dataPeriod); //read the subtitle
- pstream->lastpos = ret + length;
-
- if (pstream->header.ID != ID_STREAM_DATA)
- {
- /* this is not stream data */
- dbgMessage("\nsoundstreamreadheader: bad ID");
- return (-3); //(SOUND_ERR);
- }
- // need to assign a size to this item
- pqueue->size = pstream->header.size;
- if (pqueue->pmixPatch != NULL)
- {
- pqueue->mixHandle = splayMUTE((void *)pqueue->pmixPatch, SOUND_FLAGS_PATCHPOINTER, pqueue->pan, SOUND_PRIORITY_STREAM, pqueue->mixLevel);
- }
- }
- else if (pqueue->flags & SOUND_FLAGS_QUEUEPATCH)
- {
- ppatch = (PATCH *)pqueue->offset;
- pstream->header.ID = ppatch->id;
- pstream->header.size = ppatch->datasize - ppatch->dataoffset;
- pstream->lastpos = ppatch->dataoffset;
-
- // need to assign a size to this item
- pqueue->size = pstream->header.size;
- }
- else if (pqueue->flags & SOUND_FLAGS_QUEUESILENCE)
- {
- pstream->header.ID = 0;
- pstream->header.size = (sdword)(pqueue->silencetime * SOUND_FADE_TIMETOBLOCKS * (pqueue->bitrate >> 3)); // * bitrate?
- pstream->lastpos = 0;
-
- if (pqueue->pmixPatch != NULL)
- {
- pqueue->mixHandle = splayMUTE((void *)pqueue->pmixPatch, SOUND_FLAGS_PATCHPOINTER, pqueue->pan, SOUND_PRIORITY_STREAM, pqueue->mixLevel);
- }
- }
-
- pstream->dataleft = pstream->header.size;
- pstream->numqueued--;
-
- return (SOUND_OK);
- }
- sdword isoundstreamreadblock(STREAMQUEUE *pqueue, void *buffer, sdword position, sdword size)
- {
- sdword ret = SOUND_ERR;
- if (pqueue->fhandle == -1)
- {
- return (-1);
- }
- if (pqueue->flags & SOUND_FLAGS_QUEUESTREAM)
- {
- /* read a block of data */
- ret = fileSeek(pqueue->fhandle, position, FS_Start);
- if (ret != position)
- {
- /* yuck, bad */
- return (-2);
- }
-
- ret = fileBlockRead(pqueue->fhandle, buffer, size);
- if (ret != size)
- {
- /* yuck, bad */
- dbgMessagef("\nsoundstreamupdate95: couldn't read file block.");
- return (-3);
- }
- }
- else if (pqueue->flags & SOUND_FLAGS_QUEUEPATCH)
- {
- memcpy((sbyte *)buffer, (sbyte *)position, size);
- ret = size;
- }
- else if (pqueue->flags & SOUND_FLAGS_QUEUESILENCE)
- {
- // memset((sbyte *)buffer, 0, size);
- ret = size;
- }
- return (ret);
- }
- void isoundstreamcleanup(void)
- {
- sdword i;
- /* clean up all the streams */
- for (i = 0; i < numstreams; i++)
- {
- streams[i].status = SOUND_STREAM_INUSE;
- streams[i].buffersize = SOUND_STREAM_BUFFER_SIZE;
- memset(streams[i].buffer, 0, SOUND_STREAM_BUFFER_SIZE);
- speechchannels[i].currentpos = speechchannels[i].freqdata = (sbyte *)streams[i].buffer;
- streams[i].writepos = streams[i].buffer;
- streams[i].readblock = 0;
- streams[i].writeblock = 0;
- }
- }
- /*-----------------------------------------------------------------------------
- Name :
- Description :
- Inputs :
- Outputs :
- Return :
- ----------------------------------------------------------------------------*/
- void isoundstreamupdate(void *dummy)
- {
- sdword i;
- STREAM *pstream;
- CHANNEL *pchan;
- sdword ret;
- sdword readsize;
- BYTE *bufferpos;
- sdword bufsize;
- STREAMQUEUE *pqueue;
-
- if (streams == NULL)
- {
- /* not inited yet */
- return;
- }
- while (soundinited && (streamer.status >= SOUND_STOPPED))
- {
- if (streamer.status == SOUND_STOPPING)
- {
- /* check and see if its done yet */
- if (streamer.timeout <= mixerticks)
- {
- isoundstreamcleanup();
- streamer.timeout = 0;
- streamer.status = SOUND_STOPPED;
- }
- }
-
- if (bSoundDeactivated && (streamer.status == SOUND_PLAYING) && !bSoundPaused)
- {
- // isoundstreamcleanup();
- // streamer.status = SOUND_STOPPED;
- streamer.status = SOUND_PAUSED;
- }
-
- if ((streamer.status >= SOUND_PLAYING) && (streamer.status < SOUND_PAUSED))
- {
- if (bSoundPaused && (streamer.status == SOUND_PLAYING))
- {
- streamer.status = SOUND_STOPPING;
- }
-
- for (i = 0; i < numstreams; i++)
- {
- pstream = &streams[i];
- pchan = &speechchannels[i];
- pqueue = &pstream->queue[pstream->writeindex];
-
- if (pstream->status == SOUND_STREAM_STARTING)
- {
- pstream->playindex = pstream->writeindex;
- ret = isoundstreamreadheader(pstream);
- if (ret != SOUND_OK)
- {
- // bad
- /* dbgMessagef("\nsoundstreamupdate95: couldn't read stream header.");
- pqueue->fhandle = SOUND_ERR;
- dbgMessagef("\nisoundstreamreadheader returned %d\n", ret);
- dbgAssert(FALSE); */
- goto Recover;
- }
- else
- {
- if ((pstream->readblock != pstream->writeblock) && (pstream->blockstatus[pstream->readblock] == 0))
- {
- pstream->writeblock = pstream->readblock;
- }
- pstream->status = SOUND_STREAM_WRITING;
- pchan->volfactorL = pqueue->volfactorL;
- pchan->volfactorR = pqueue->volfactorR;
-
- pchan->voltarget = pqueue->vol;
- if (pqueue->fadetime != 0.0f)
- {
- pchan->volume = 0.0f;
- pchan->volticksleft = (sdword)(pqueue->fadetime * SOUND_FADE_TIMETOBLOCKS);
- pchan->volfade = (real32)(pchan->voltarget - pchan->volume) / (real32)pchan->volticksleft;
-
- if (pchan->volfade == 0.0f)
- {
- pchan->volfade = 0.01f;
- if (pchan->voltarget < pchan->volume)
- {
- pchan->volfade = -0.01f;
- }
- }
- }
- else
- {
- pchan->volume = (real32)pqueue->vol;
- pchan->volticksleft = 0;
- pchan->volfade = 0.0f;
- }
-
- pchan->pan = pqueue->pan;
- pchan->numchannels = pqueue->numchannels;
- pchan->bitrate = pqueue->bitrate;
- pchan->amountread = 0;
-
- bufsize = SOUND_STREAM_BUFFER_SIZE;
-
- if (bufsize % ((pchan->bitrate >> 3) * 8))
- {
- bufsize /= ((pchan->bitrate >> 3) * 8);
- bufsize *= ((pchan->bitrate >> 3) * 8);
- }
- pstream->buffersize = bufsize;
- pstream->blocksize = pstream->buffersize / 2;
- pchan->endpos = (sbyte *)(pstream->buffer + pstream->buffersize);
- pchan->currentpos = (sbyte *)pstream->buffer;
-
- pstream->numtoplay--;
- pchan->status = SOUND_PLAYING;
- }
- }
-
- if (pstream->status == SOUND_STREAM_WRITING)
- {
- if (pstream->blockstatus[pstream->writeblock] == 0)
- {
- if (pstream->dataleft == 0)
- { /* HMMM, WE'RE OUT OF DATA HERE */
- if (pqueue->flags & SOUND_FLAGS_LOOPING)
- {
- /* LOOKS LIKE A LOOPER, BACK TO THE START YOU GO */
- isoundstreamreadheader(pstream);
- }
- else
- {
- /* IS THERE ANOTHER STREAM IN THE HOUSE? */
- pqueue->fhandle = SOUND_ERR;
-
- pqueue->nextplay = pstream->buffer + (pstream->blocksize * pstream->writeblock);
-
- pstream->writeindex++;
-
- if (pstream->writeindex >= SOUND_MAX_STREAM_QUEUE)
- {
- pstream->writeindex = 0;
- }
-
- pqueue = &pstream->queue[pstream->writeindex];
-
- if (pqueue->fhandle != SOUND_ERR)
- {
- isoundstreamreadheader(pstream);
- }
- else
- {
- pstream->status = SOUND_STREAM_INUSE;
- pstream->queueindex = 0;
- pstream->writeindex = 0;
- pstream->numqueued = 0;
- pchan->status = SOUND_STOPPING;
- continue;
- }
- }
- }
-
- if (pstream->dataleft >= pstream->blocksize)
- {
- /* WE HAVE LOTS OF DATA HERE */
- ret = isoundstreamreadblock(pqueue, (void *)(pstream->buffer + (pstream->blocksize * pstream->writeblock)), pstream->lastpos, pstream->blocksize);
-
- if (ret != pstream->blocksize)
- {
- /* yuck, bad */
- /* dbgMessagef("\nsoundstreamupdate95: couldn't read file block.");*/
- goto Recover;
- }
-
- pstream->lastpos += ret;
- pstream->dataleft -= pstream->blocksize;
- }
- else
- {
- /* HMMM, GETTING KINDA LOW, NEED A TOP UP */
- ret = isoundstreamreadblock(pqueue, (void *)(pstream->buffer + (pstream->blocksize * pstream->writeblock)), pstream->lastpos, pstream->dataleft);
-
- if (ret != pstream->dataleft)
- {
- /* yuck, bad */
- /* dbgMessagef("\nsoundstreamupdate95: couldn't read file block."); */
- goto Recover;
- }
- pstream->lastpos += ret;
-
- if (!(pqueue->flags & SOUND_FLAGS_LOOPING))
- {
- /* IS THERE ANOTHER STREAM IN THE HOUSE? */
- pqueue->fhandle = SOUND_ERR;
-
- pqueue->nextplay = pstream->buffer + (pstream->blocksize * pstream->writeblock) + pstream->dataleft;
-
- pstream->writeindex++;
-
- if (pstream->writeindex >= SOUND_MAX_STREAM_QUEUE)
- {
- pstream->writeindex = 0;
- }
-
- pqueue = &pstream->queue[pstream->writeindex];
- }
-
- readsize = pstream->blocksize - pstream->dataleft;
- bufferpos = pstream->buffer + (pstream->blocksize * pstream->writeblock) + pstream->dataleft;
- pstream->dataleft = 0;
-
- if (pqueue->fhandle != SOUND_ERR)
- {
- /* LOOKS LIKE WE HAVE ANOTHER STREAM HERE */
- isoundstreamreadheader(pstream);
-
- if (pstream->dataleft >= readsize)
- {
- /* read a block of data */
- ret = isoundstreamreadblock(pqueue, (void *)(bufferpos), pstream->lastpos, readsize);
-
- if (ret != readsize)
- {
- /* yuck, bad */
- }
- pstream->lastpos += ret;
- pstream->dataleft -= readsize;
- }
- else
- {
- ret = isoundstreamreadblock(pqueue, (void *)(bufferpos), pstream->lastpos, pstream->dataleft);
-
- if (ret != pstream->dataleft)
- {
- /*bad*/
- /* dbgAssert(FALSE); */
- goto Recover;
- }
-
- if (pstream->writeindex + 1 >= SOUND_MAX_STREAM_QUEUE)
- {
- if (pstream->queue[0].fhandle != SOUND_ERR)
- {
- memset(bufferpos + pstream->dataleft, 0, readsize - pstream->dataleft);
- }
- else
- {
- pstream->writepos = bufferpos + pstream->dataleft;
- }
- }
- else
- {
- if (pstream->queue[pstream->writeindex+1].fhandle != SOUND_ERR)
- {
- memset(bufferpos + pstream->dataleft, 0, readsize - pstream->dataleft);
- }
- else
- {
- pstream->writepos = bufferpos + pstream->dataleft;
- }
- }
- pstream->lastpos += ret;
- pstream->dataleft = 0;
- }
- }
- else
- {
- /* NO MORE STREAMS FOR NOW, BYE, BYE */
- pstream->writepos = bufferpos;
- pstream->status = SOUND_STREAM_INUSE;
- pstream->queueindex = 0;
- pstream->writeindex = 0;
- pstream->numqueued = 0;
- pchan->status = SOUND_STOPPING;
- }
- }
- pstream->blockstatus[pstream->writeblock++] = 1;
- if (pstream->writeblock >= 2)
- {
- pstream->writeblock = 0;
- }
- }
- }
- continue;
- Recover:
- {
- /* IS THERE ANOTHER STREAM IN THE HOUSE? */
- pqueue->fhandle = SOUND_ERR;
-
- pqueue->nextplay = pstream->buffer + (pstream->blocksize * pstream->writeblock);
-
- pstream->writeindex++;
-
- if (pstream->writeindex >= SOUND_MAX_STREAM_QUEUE)
- {
- pstream->writeindex = 0;
- }
-
- pqueue = &pstream->queue[pstream->writeindex];
- if (pqueue->fhandle != SOUND_ERR)
- {
- isoundstreamreadheader(pstream);
- }
- else
- {
- pstream->status = SOUND_STREAM_INUSE;
- pstream->queueindex = 0;
- pstream->writeindex = 0;
- pstream->numqueued = 0;
- pchan->status = SOUND_STOPPING;
- continue;
- }
- }
- }
- }
- else if (streamer.status == SOUND_STOPPED)
- {
- /* mixer is paused so don't do nothing */
- if (!bSoundPaused) // && (!bSoundDeactivated))
- {
- streamer.status = SOUND_PLAYING;
- }
- }
- else if (streamer.status == SOUND_PAUSED)
- {
- if (!bSoundDeactivated)
- {
- streamer.status = SOUND_PLAYING;
- }
- }
-
- Sleep(SOUND_STREAM_SLEEP);
- }
-
- /* clean up all the streams */
- for (i = 0; i < numstreams; i++)
- {
- streams[i].status = SOUND_STREAM_INUSE;
- streams[i].buffersize = SOUND_STREAM_BUFFER_SIZE;
- memset(streams[i].buffer, 0, SOUND_STREAM_BUFFER_SIZE);
- speechchannels[i].currentpos = speechchannels[i].freqdata = (sbyte *)streams[i].buffer;
- streams[i].writepos = streams[i].buffer;
- streams[i].readblock = 0;
- streams[i].writeblock = 0;
- }
- streamer.status = SOUND_FREE;
- _endthread();
- }
|