This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/snd_dx/s_stream.c

245 lines
5.4 KiB
C

//=======================================================================
// Copyright XashXT Group 2009 ©
// s_stream.c - sound streaming
//=======================================================================
#include "sound.h"
#include "byteorder.h"
portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
int s_rawend;
static bg_track_t s_bgTrack;
/*
=================
S_StartBackgroundTrack
=================
*/
void S_StartBackgroundTrack( const char *introTrack, const char *mainTrack )
{
S_StopBackgroundTrack();
if(( !introTrack || !*introTrack ) && ( !mainTrack || !*mainTrack ))
return;
if( !introTrack )
{
introTrack = "";
}
if( !mainTrack || !*mainTrack )
{
mainTrack = introTrack;
}
if( !*introTrack ) return;
if( mainTrack )
{
com.strncpy( s_bgTrack.loopName, mainTrack, sizeof( s_bgTrack.loopName ));
}
else s_bgTrack.loopName[0] = 0;
S_StartStreaming();
// close the background track, but DON'T reset s_rawend
// if restarting the same back ground track
if( s_bgTrack.stream )
{
FS_CloseStream( s_bgTrack.stream );
s_bgTrack.stream = NULL;
}
// open stream
s_bgTrack.stream = FS_OpenStream( va( "media/%s", introTrack ));
}
void S_StopBackgroundTrack( void )
{
S_StopStreaming();
if( !s_bgTrack.stream ) return;
FS_CloseStream( s_bgTrack.stream );
Mem_Set( &s_bgTrack, 0, sizeof( bg_track_t ));
s_rawend = 0;
}
/*
=================
S_StreamBackgroundTrack
=================
*/
void S_StreamBackgroundTrack( void )
{
int bufferSamples;
int fileSamples;
byte raw[MAX_RAW_SAMPLES];
int r, fileBytes;
float musicVolume = 0.5f;
if( !s_bgTrack.stream ) return;
// graeme see if this is OK
musicVolume = ( musicVolume + ( s_musicvolume->value * 2 )) / 4.0f;
// don't bother playing anything if musicvolume is 0
if( musicVolume <= 0 ) return;
// see how many samples should be copied into the raw buffer
if( s_rawend < soundtime )
s_rawend = soundtime;
while( s_rawend < soundtime + MAX_RAW_SAMPLES )
{
wavdata_t *info = FS_StreamInfo( s_bgTrack.stream );
bufferSamples = MAX_RAW_SAMPLES - (s_rawend - soundtime);
// decide how much data needs to be read from the file
fileSamples = bufferSamples * info->rate / dma.speed;
// our max buffer size
fileBytes = fileSamples * ( info->width * info->channels );
if( fileBytes > sizeof( raw ))
{
fileBytes = sizeof( raw );
fileSamples = fileBytes / ( info->width * info->channels );
}
// read
r = FS_ReadStream( s_bgTrack.stream, fileBytes, raw );
if( r < fileBytes )
{
fileBytes = r;
fileSamples = r / ( info->width * info->channels );
}
if( r > 0 )
{
// add to raw buffer
// FIXME: apply musicVolume
S_StreamRawSamples( fileSamples, info->rate, info->width, info->channels, raw );
}
else
{
// loop
if( s_bgTrack.loopName[0] )
{
FS_CloseStream( s_bgTrack.stream );
s_bgTrack.stream = NULL;
S_StartBackgroundTrack( s_bgTrack.loopName, NULL );
if( !s_bgTrack.stream ) return;
}
else
{
S_StopBackgroundTrack();
return;
}
}
}
}
/*
=================
S_StartStreaming
=================
*/
void S_StartStreaming( void )
{
}
/*
=================
S_StopStreaming
=================
*/
void S_StopStreaming( void )
{
// clear s_rawend here ?
}
/*
============
S_StreamRawSamples
Cinematic streaming and voice over network
============
*/
void S_StreamRawSamples( int samples, int rate, int width, int channels, const byte *data )
{
int i, src, dst;
float scale;
if( s_rawend < paintedtime )
s_rawend = paintedtime;
scale = (float)rate / dma.speed;
if( channels == 2 && width == 2 )
{
if( scale == 1.0f )
{
// optimized case
for( i = 0; i < samples; i++ )
{
dst = s_rawend & (MAX_RAW_SAMPLES - 1);
s_rawend++;
s_rawsamples[dst].left = LittleShort(((short *)data)[i*2]) << 8;
s_rawsamples[dst].right = LittleShort(((short *)data)[i*2+1]) << 8;
}
}
else
{
for( i = src = 0; src < samples; i++ )
{
src = i * scale;
if( src >= samples ) break;
dst = s_rawend & (MAX_RAW_SAMPLES - 1);
s_rawend++;
s_rawsamples[dst].left = LittleShort(((short *)data)[src*2]) << 8;
s_rawsamples[dst].right = LittleShort(((short *)data)[src*2+1]) << 8;
}
}
}
else if( channels == 1 && width == 2 )
{
for( i = src = 0; src < samples; i++ )
{
src = i * scale;
if( src >= samples ) break;
dst = s_rawend & (MAX_RAW_SAMPLES - 1);
s_rawend++;
s_rawsamples[dst].left = LittleShort(((short *)data)[src]) << 8;
s_rawsamples[dst].right = LittleShort(((short *)data)[src]) << 8;
}
}
else if( channels == 2 && width == 1 )
{
for( i = src = 0; src < samples; i++ )
{
src = i * scale;
if( src >= samples ) break;
dst = s_rawend & (MAX_RAW_SAMPLES - 1);
s_rawend++;
s_rawsamples[dst].left = ((char *)data)[src*2] << 16;
s_rawsamples[dst].right = ((char *)data)[src*2+1] << 16;
}
}
else if( channels == 1 && width == 1 )
{
for( i = src = 0; src < samples; i++ )
{
src = i * scale;
if( src >= samples ) break;
dst = s_rawend & (MAX_RAW_SAMPLES - 1);
s_rawend++;
s_rawsamples[dst].left = (((byte *)data)[src]-128) << 16;
s_rawsamples[dst].right = (((byte *)data)[src]-128) << 16;
}
}
}