smooth scrolling during comm (ff/frev) option --scroll=3do to enable
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@591 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
Changes towards version 0.2:
|
Changes towards version 0.2:
|
||||||
|
- Added 'smooth' scolling for ff, frev (similar to the 3DO) - PhracturedBlue
|
||||||
- New streaming code for openal/mixsdl. supports ff/frev in subtitles -PBlue
|
- New streaming code for openal/mixsdl. supports ff/frev in subtitles -PBlue
|
||||||
- New sound module "mixsdl" (experimental) -fOSSiL
|
- New sound module "mixsdl" (experimental) -fOSSiL
|
||||||
- Fixed overlapping subtitle text while switch tracks -PhracturedBlue
|
- Fixed overlapping subtitle text while switch tracks -PhracturedBlue
|
||||||
|
|||||||
@@ -101,8 +101,6 @@ Implementation bugs (low priority):
|
|||||||
vux001.ogg utwig072.ogg umgah027.ogg talkp068.ogg spaho007.ogg
|
vux001.ogg utwig072.ogg umgah027.ogg talkp068.ogg spaho007.ogg
|
||||||
syree012.ogg syree021.ogg syree028.ogg syree069.ogg orz000.ogg
|
syree012.ogg syree021.ogg syree028.ogg syree069.ogg orz000.ogg
|
||||||
- Using arrow keys with SDL_mixer will not work.
|
- Using arrow keys with SDL_mixer will not work.
|
||||||
- Arrow keys for mixsdl/openAL skip forward/back one page. We should also
|
|
||||||
have a 'smooth' scrolling mechanism like the 3do
|
|
||||||
- More work should be done to better sync the text we have.
|
- More work should be done to better sync the text we have.
|
||||||
- Slider doesn't track the audio very well
|
- Slider doesn't track the audio very well
|
||||||
Stuff still to do (large):
|
Stuff still to do (large):
|
||||||
|
|||||||
@@ -116,7 +116,14 @@ Use PC style fonts and colors.
|
|||||||
--font 3do
|
--font 3do
|
||||||
|
|
||||||
Use 3DO style fonts and colors.
|
Use 3DO style fonts and colors.
|
||||||
Default.
|
Default
|
||||||
|
|
||||||
|
--scroll pc
|
||||||
|
Scroll voice-over/subtitles 1 page at a time when using left/right arrow keys
|
||||||
|
Default
|
||||||
|
|
||||||
|
--scroll 3do
|
||||||
|
Scroll voice-over/subtitles smoothly while holding down left/right arrow keys
|
||||||
|
|
||||||
BUG REPORTS
|
BUG REPORTS
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ int optWhichMusic = OPT_3DO;
|
|||||||
int optWhichCoarseScan = OPT_3DO;
|
int optWhichCoarseScan = OPT_3DO;
|
||||||
int optWhichMenu = OPT_3DO;
|
int optWhichMenu = OPT_3DO;
|
||||||
int optWhichFonts = OPT_3DO;
|
int optWhichFonts = OPT_3DO;
|
||||||
|
int optSmoothScroll = OPT_PC;
|
||||||
|
|
||||||
char *configDir, *saveDir, *meleeDir;
|
char *configDir, *saveDir, *meleeDir;
|
||||||
BOOLEAN optSubtitles = TRUE;
|
BOOLEAN optSubtitles = TRUE;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ extern int optWhichMusic;
|
|||||||
extern int optWhichCoarseScan;
|
extern int optWhichCoarseScan;
|
||||||
extern int optWhichMenu;
|
extern int optWhichMenu;
|
||||||
extern int optWhichFonts;
|
extern int optWhichFonts;
|
||||||
|
extern int optSmoothScroll;
|
||||||
|
|
||||||
extern BOOLEAN optSubtitles;
|
extern BOOLEAN optSubtitles;
|
||||||
|
|
||||||
|
|||||||
+22
-8
@@ -1220,27 +1220,41 @@ SpewPhrases (COUNT wait_track)
|
|||||||
|
|
||||||
if (which_track)
|
if (which_track)
|
||||||
{
|
{
|
||||||
if (InputState != LastInputState && GetInputXComponent (InputState) > 0)
|
if (GetInputXComponent (InputState) > 0)
|
||||||
{
|
{
|
||||||
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 3));
|
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 3));
|
||||||
FastForward ();
|
if (optSmoothScroll == OPT_PC && InputState != LastInputState)
|
||||||
|
FastForward_Page ();
|
||||||
|
else if (optSmoothScroll == OPT_3DO)
|
||||||
|
FastForward_Smooth ();
|
||||||
ContinuityBreak = TRUE;
|
ContinuityBreak = TRUE;
|
||||||
CommData.AlienFrame = 0;
|
CommData.AlienFrame = 0;
|
||||||
}
|
}
|
||||||
else if (InputState != LastInputState && GetInputXComponent (InputState) < 0)
|
else if (GetInputXComponent (InputState) < 0)
|
||||||
{
|
{
|
||||||
Rewind:
|
Rewind:
|
||||||
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 4));
|
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 4));
|
||||||
FastReverse ();
|
if (optSmoothScroll == OPT_PC && InputState != LastInputState)
|
||||||
|
FastReverse_Page ();
|
||||||
|
else if (optSmoothScroll == OPT_3DO)
|
||||||
|
FastReverse_Smooth ();
|
||||||
ContinuityBreak = TRUE;
|
ContinuityBreak = TRUE;
|
||||||
CommData.AlienFrame = 0;
|
CommData.AlienFrame = 0;
|
||||||
}
|
}
|
||||||
else if (InputState != LastInputState && ContinuityBreak)
|
else if (ContinuityBreak)
|
||||||
{
|
{
|
||||||
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2));
|
SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2));
|
||||||
if ((which_track = PlayingTrack ())
|
if ((which_track = PlayingTrack ())
|
||||||
&& which_track <= wait_track) ;
|
&& which_track <= wait_track)
|
||||||
// ResumeTrack ();
|
{
|
||||||
|
if (optSmoothScroll == OPT_3DO)
|
||||||
|
ResumeTrack ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CommData.AlienFrame = F;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
ContinuityBreak = FALSE;
|
ContinuityBreak = FALSE;
|
||||||
}
|
}
|
||||||
else if (which_track == wait_track
|
else if (which_track == wait_track
|
||||||
@@ -2103,7 +2117,7 @@ do_subtitles (UNICODE *pStr, UNICODE *pTimeStamp, int method)
|
|||||||
talk_length = *cur_sub_ts++ * ONE_SECOND /1000;
|
talk_length = *cur_sub_ts++ * ONE_SECOND /1000;
|
||||||
silence_length = 0;
|
silence_length = 0;
|
||||||
TimeOut += talk_length;
|
TimeOut += talk_length;
|
||||||
fprintf (stderr, "Sound length is %d\n", talk_length);
|
//fprintf (stderr, "Sound length is %d\n", talk_length);
|
||||||
}
|
}
|
||||||
else if (! disable_timer)
|
else if (! disable_timer)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -441,8 +441,9 @@ uint32 SoundDecoder_Decode (TFB_SoundDecoder *decoder)
|
|||||||
return decoded_bytes;
|
return decoded_bytes;
|
||||||
}
|
}
|
||||||
case SOUNDDECODER_BUF:
|
case SOUNDDECODER_BUF:
|
||||||
|
decoder->buffer = (char *)decoder->data + decoder->pos;
|
||||||
decoder->error = SOUNDDECODER_EOF;
|
decoder->error = SOUNDDECODER_EOF;
|
||||||
return (decoder->buffer_size);
|
return (decoder->buffer_size - decoder->pos);
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
fprintf (stderr, "SoundDecoder_Decode(): unknown type %d\n", decoder->type);
|
fprintf (stderr, "SoundDecoder_Decode(): unknown type %d\n", decoder->type);
|
||||||
@@ -467,8 +468,6 @@ uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder)
|
|||||||
|
|
||||||
if (decoder->buffer_size != 0)
|
if (decoder->buffer_size != 0)
|
||||||
{
|
{
|
||||||
decoder->type = SOUNDDECODER_BUF;
|
|
||||||
decoder->error = SOUNDDECODER_OK;
|
|
||||||
|
|
||||||
/* WAVs are loaded in little-endian order
|
/* WAVs are loaded in little-endian order
|
||||||
* may need to do a word-swap
|
* may need to do a word-swap
|
||||||
@@ -480,6 +479,10 @@ uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder)
|
|||||||
SoundDecoder_SwapWords (
|
SoundDecoder_SwapWords (
|
||||||
decoder->buffer, decoder->buffer_size);
|
decoder->buffer, decoder->buffer_size);
|
||||||
}
|
}
|
||||||
|
decoder->type = SOUNDDECODER_BUF;
|
||||||
|
decoder->data = decoder->buffer;
|
||||||
|
decoder->pos = 0;
|
||||||
|
decoder->error = SOUNDDECODER_OK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -545,6 +548,8 @@ uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder)
|
|||||||
ov_clear (vf);
|
ov_clear (vf);
|
||||||
HFree (vf);
|
HFree (vf);
|
||||||
decoder->type = SOUNDDECODER_BUF;
|
decoder->type = SOUNDDECODER_BUF;
|
||||||
|
decoder->data = decoder->buffer;
|
||||||
|
decoder->pos = 0;
|
||||||
|
|
||||||
decoder->error = SOUNDDECODER_OK;
|
decoder->error = SOUNDDECODER_OK;
|
||||||
return decoded_bytes;
|
return decoded_bytes;
|
||||||
@@ -562,18 +567,26 @@ uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SoundDecoder_Rewind (TFB_SoundDecoder *decoder)
|
void SoundDecoder_Rewind (TFB_SoundDecoder *decoder)
|
||||||
|
{
|
||||||
|
SoundDecoder_Seek (decoder, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// seekTime is specified in mili-seconds
|
||||||
|
void SoundDecoder_Seek (TFB_SoundDecoder *decoder, uint32 seekTime)
|
||||||
{
|
{
|
||||||
switch (decoder->type)
|
switch (decoder->type)
|
||||||
{
|
{
|
||||||
case SOUNDDECODER_WAV:
|
case SOUNDDECODER_WAV:
|
||||||
{
|
{
|
||||||
fprintf (stderr, "SoundDecoder_Rewind(): unimplemented for wav\n");
|
fprintf (stderr, "SoundDecoder_Seek(): unimplemented for wav\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SOUNDDECODER_MOD:
|
case SOUNDDECODER_MOD:
|
||||||
{
|
{
|
||||||
MODULE *mod = (MODULE *)decoder->data;
|
MODULE *mod = (MODULE *)decoder->data;
|
||||||
Player_Start (mod);
|
Player_Start (mod);
|
||||||
|
if (seekTime)
|
||||||
|
fprintf (stderr, "SoundDecoder_Seek(): non-zero seek positions not supported for mod\n");
|
||||||
Player_SetPosition (0);
|
Player_SetPosition (0);
|
||||||
//fprintf (stderr, "SoundDecoder_Rewind(): rewound %s\n", decoder->filename);
|
//fprintf (stderr, "SoundDecoder_Rewind(): rewound %s\n", decoder->filename);
|
||||||
decoder->error = SOUNDDECODER_OK;
|
decoder->error = SOUNDDECODER_OK;
|
||||||
@@ -582,29 +595,34 @@ void SoundDecoder_Rewind (TFB_SoundDecoder *decoder)
|
|||||||
case SOUNDDECODER_OGG:
|
case SOUNDDECODER_OGG:
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
uint32 pcm_pos = 0;
|
||||||
OggVorbis_File *vf = (OggVorbis_File *) decoder->data;
|
OggVorbis_File *vf = (OggVorbis_File *) decoder->data;
|
||||||
if ((err = ov_pcm_seek (vf, decoder->start_sample)) != 0)
|
if (seekTime)
|
||||||
|
pcm_pos = seekTime * decoder->frequency / 1000;
|
||||||
|
if ((err = ov_pcm_seek (vf, decoder->start_sample + pcm_pos)) != 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "SoundDecoder_Rewind(): couldn't rewind %s, error code %d\n", decoder->filename, err);
|
fprintf (stderr, "SoundDecoder_Seek(): couldn't seek %s, error code %d\n", decoder->filename, err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (decoder->format == decoder_formats.mono16)
|
if (decoder->format == decoder_formats.mono16)
|
||||||
decoder->pos = decoder->start_sample * 2;
|
decoder->pos = (pcm_pos + decoder->start_sample) * 2;
|
||||||
else
|
else
|
||||||
decoder->pos = decoder->start_sample * 4;
|
decoder->pos = (pcm_pos + decoder->start_sample) * 4;
|
||||||
|
|
||||||
//fprintf (stderr, "SoundDecoder_Rewind(): rewound %s\n", decoder->filename);
|
//fprintf (stderr, "SoundDecoder_Seek(): seek %s\n", decoder->filename);
|
||||||
decoder->error = SOUNDDECODER_OK;
|
decoder->error = SOUNDDECODER_OK;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case SOUNDDECODER_BUF:
|
case SOUNDDECODER_BUF:
|
||||||
{
|
{
|
||||||
|
decoder->pos = seekTime * decoder->frequency *
|
||||||
|
(decoder->format == decoder_formats.mono16 ? 2 : 4) / 1000;
|
||||||
decoder->error = SOUNDDECODER_OK;
|
decoder->error = SOUNDDECODER_OK;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
fprintf (stderr, "SoundDecoder_Rewind(): unknown type %d\n", decoder->type);
|
fprintf (stderr, "SoundDecoder_Seek(): unknown type %d\n", decoder->type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -655,4 +673,41 @@ void SoundDecoder_Free (TFB_SoundDecoder *decoder)
|
|||||||
HFree (decoder);
|
HFree (decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float SoundDecoder_GetTime (TFB_SoundDecoder *decoder)
|
||||||
|
{
|
||||||
|
if (!decoder)
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (decoder->type)
|
||||||
|
{
|
||||||
|
case SOUNDDECODER_WAV:
|
||||||
|
{
|
||||||
|
//fprintf (stderr, "SoundDecoder_GetTime not supported for wav\n");
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
case SOUNDDECODER_MOD:
|
||||||
|
{
|
||||||
|
//fprintf (stderr, "SoundDecoder_GetTime not supported for mod\n");
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
case SOUNDDECODER_OGG:
|
||||||
|
case SOUNDDECODER_BUF:
|
||||||
|
{
|
||||||
|
//fprintf (stderr, "SoundDecoder_GetTime not supported for mod\n");
|
||||||
|
return (
|
||||||
|
(float)(
|
||||||
|
(decoder->pos >> (decoder->format == decoder_formats.mono16 ? 1 : 2))
|
||||||
|
- decoder->start_sample
|
||||||
|
) / decoder->frequency);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
fprintf (stderr, "SoundDecoder_GetTime(): unknown type %d\n", decoder->type);
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ TFB_SoundDecoder* SoundDecoder_Load (char *filename, uint32 buffer_size,
|
|||||||
uint32 startTime, uint32 runTime);
|
uint32 startTime, uint32 runTime);
|
||||||
uint32 SoundDecoder_Decode (TFB_SoundDecoder *decoder);
|
uint32 SoundDecoder_Decode (TFB_SoundDecoder *decoder);
|
||||||
uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder);
|
uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder);
|
||||||
|
float SoundDecoder_GetTime (TFB_SoundDecoder *decoder);
|
||||||
|
void SoundDecoder_Seek (TFB_SoundDecoder *decoder, uint32 pcm_pos);
|
||||||
void SoundDecoder_Rewind (TFB_SoundDecoder *decoder);
|
void SoundDecoder_Rewind (TFB_SoundDecoder *decoder);
|
||||||
void SoundDecoder_Free (TFB_SoundDecoder *decoder);
|
void SoundDecoder_Free (TFB_SoundDecoder *decoder);
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ PLRPlaySong (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE Priority)
|
|||||||
{
|
{
|
||||||
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
||||||
PlayStream ((*pmus), MUSIC_SOURCE, Continuous,
|
PlayStream ((*pmus), MUSIC_SOURCE, Continuous,
|
||||||
speechVolumeScale == 0.0f);
|
speechVolumeScale == 0.0f, true);
|
||||||
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
||||||
|
|
||||||
curMusicRef = MusicRef;
|
curMusicRef = MusicRef;
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ typedef struct tfb_soundsource
|
|||||||
mixSDL_Object handle;
|
mixSDL_Object handle;
|
||||||
bool stream_should_be_playing;
|
bool stream_should_be_playing;
|
||||||
Mutex stream_mutex;
|
Mutex stream_mutex;
|
||||||
uint32 start_time;
|
sint32 start_time;
|
||||||
|
|
||||||
// for oscilloscope
|
// for oscilloscope
|
||||||
void *sbuffer;
|
void *sbuffer;
|
||||||
|
|||||||
@@ -26,9 +26,10 @@
|
|||||||
bool speech_advancetrack = FALSE;
|
bool speech_advancetrack = FALSE;
|
||||||
|
|
||||||
void
|
void
|
||||||
PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope)
|
PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope, bool rewind)
|
||||||
{
|
{
|
||||||
uint32 i, pos = 0, offset = 0;
|
uint32 i, pos = 0;
|
||||||
|
sint32 offset = 0;
|
||||||
|
|
||||||
if (!sample || (!sample->read_chain_ptr && !sample->decoder))
|
if (!sample || (!sample->read_chain_ptr && !sample->decoder))
|
||||||
return;
|
return;
|
||||||
@@ -37,11 +38,14 @@ PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope)
|
|||||||
if (sample->read_chain_ptr)
|
if (sample->read_chain_ptr)
|
||||||
{
|
{
|
||||||
sample->decoder = sample->read_chain_ptr->decoder;
|
sample->decoder = sample->read_chain_ptr->decoder;
|
||||||
offset = (int) (sample->read_chain_ptr->start_time * (float)ONE_SECOND);
|
offset = (sint32) (sample->read_chain_ptr->start_time * (float)ONE_SECOND);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
offset= 0;
|
offset= 0;
|
||||||
SoundDecoder_Rewind (sample->decoder);
|
if (rewind)
|
||||||
|
SoundDecoder_Rewind (sample->decoder);
|
||||||
|
else
|
||||||
|
offset += (sint32)(SoundDecoder_GetTime (sample->decoder) * (float)ONE_SECOND);
|
||||||
soundSource[source].sample = sample;
|
soundSource[source].sample = sample;
|
||||||
soundSource[source].sample->play_chain_ptr = sample->read_chain_ptr;
|
soundSource[source].sample->play_chain_ptr = sample->read_chain_ptr;
|
||||||
soundSource[source].sample->decoder->looping = looping;
|
soundSource[source].sample->decoder->looping = looping;
|
||||||
@@ -108,7 +112,7 @@ PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope)
|
|||||||
for ( ; i <sample->num_buffers; ++i)
|
for ( ; i <sample->num_buffers; ++i)
|
||||||
sample->buffer_tag[i] = 0;
|
sample->buffer_tag[i] = 0;
|
||||||
soundSource[source].sbuf_size = pos;
|
soundSource[source].sbuf_size = pos;
|
||||||
soundSource[source].start_time = GetTimeCounter () - offset;
|
soundSource[source].start_time = (sint32)GetTimeCounter () - offset;
|
||||||
soundSource[source].stream_should_be_playing = TRUE;
|
soundSource[source].stream_should_be_playing = TRUE;
|
||||||
mixSDL_SourcePlay (soundSource[source].handle);
|
mixSDL_SourcePlay (soundSource[source].handle);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
#ifndef STREAM_H
|
#ifndef STREAM_H
|
||||||
#define STREAM_H
|
#define STREAM_H
|
||||||
|
|
||||||
void PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope);
|
void PlayStream (TFB_SoundSample *sample, uint32 source, bool looping,
|
||||||
|
bool scope, bool rewind);
|
||||||
void StopStream (uint32 source);
|
void StopStream (uint32 source);
|
||||||
void PauseStream (uint32 source);
|
void PauseStream (uint32 source);
|
||||||
void ResumeStream (uint32 source);
|
void ResumeStream (uint32 source);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ static int tcur; //currently playing subtitle track
|
|||||||
static int cur_page = 0; //current page of subtitle track
|
static int cur_page = 0; //current page of subtitle track
|
||||||
static int no_page_break = 0;
|
static int no_page_break = 0;
|
||||||
static int no_voice;
|
static int no_voice;
|
||||||
|
static int track_pos_changed = 0; // set whenever ff, frev is enabled
|
||||||
|
|
||||||
|
|
||||||
#define MAX_CLIPS 50
|
#define MAX_CLIPS 50
|
||||||
@@ -72,12 +73,13 @@ advance_track (int channel_finished)
|
|||||||
{
|
{
|
||||||
if (channel_finished <= 0)
|
if (channel_finished <= 0)
|
||||||
{
|
{
|
||||||
if (sound_sample->decoder)
|
if (sound_sample->read_chain_ptr || sound_sample->decoder)
|
||||||
{
|
{
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
PlayStream (sound_sample,
|
PlayStream (sound_sample,
|
||||||
SPEECH_SOURCE, false,
|
SPEECH_SOURCE, false,
|
||||||
speechVolumeScale != 0.0f);
|
speechVolumeScale != 0.0f, !track_pos_changed);
|
||||||
|
track_pos_changed = 0;
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
}
|
}
|
||||||
else if (channel_finished == 0)
|
else if (channel_finished == 0)
|
||||||
@@ -90,14 +92,14 @@ advance_track (int channel_finished)
|
|||||||
void
|
void
|
||||||
ResumeTrack ()
|
ResumeTrack ()
|
||||||
{
|
{
|
||||||
if (sound_sample && sound_sample->decoder)
|
if (sound_sample && sound_sample->read_chain_ptr)
|
||||||
{
|
{
|
||||||
uint32 state;
|
uint32 state;
|
||||||
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
mixSDL_GetSourcei (soundSource[SPEECH_SOURCE].handle, MIX_SOURCE_STATE, &state);
|
mixSDL_GetSourcei (soundSource[SPEECH_SOURCE].handle, MIX_SOURCE_STATE, &state);
|
||||||
|
|
||||||
if (!soundSource[SPEECH_SOURCE].stream_should_be_playing &&
|
if (!track_pos_changed && !soundSource[SPEECH_SOURCE].stream_should_be_playing &&
|
||||||
state == MIX_PAUSED)
|
state == MIX_PAUSED)
|
||||||
{
|
{
|
||||||
ResumeStream (SPEECH_SOURCE);
|
ResumeStream (SPEECH_SOURCE);
|
||||||
@@ -426,31 +428,90 @@ PauseTrack ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FastReverse ()
|
recompute_track_pos (TFB_SoundSample *sample, TFB_SoundChain *first_chain, sint32 offset)
|
||||||
|
{
|
||||||
|
TFB_SoundChain *cur_chain = first_chain;
|
||||||
|
while (cur_chain->next &&
|
||||||
|
(sint32)(cur_chain->next->start_time * (float)ONE_SECOND) < offset)
|
||||||
|
cur_chain = cur_chain->next;
|
||||||
|
if (cur_chain->tag.type)
|
||||||
|
DoTrackTag (&cur_chain->tag);
|
||||||
|
if ((sint32)((cur_chain->start_time + cur_chain->decoder->length) * (float)ONE_SECOND) < offset)
|
||||||
|
{
|
||||||
|
sample->read_chain_ptr = NULL;
|
||||||
|
sample->decoder = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sample->read_chain_ptr = cur_chain;
|
||||||
|
SoundDecoder_Seek(sample->read_chain_ptr->decoder,
|
||||||
|
(uint32)(1000 * (offset / (float)ONE_SECOND - cur_chain->start_time)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FastReverse_Smooth ()
|
||||||
|
{
|
||||||
|
if (sound_sample)
|
||||||
|
{
|
||||||
|
sint32 offset;
|
||||||
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
|
PauseStream (SPEECH_SOURCE);
|
||||||
|
track_pos_changed = 1;
|
||||||
|
soundSource[SPEECH_SOURCE].start_time += ACCEL_SCROLL_SPEED;
|
||||||
|
if (soundSource[SPEECH_SOURCE].start_time > (sint32)GetTimeCounter())
|
||||||
|
{
|
||||||
|
soundSource[SPEECH_SOURCE].start_time = GetTimeCounter();
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
offset = GetTimeCounter() - soundSource[SPEECH_SOURCE].start_time;
|
||||||
|
recompute_track_pos(soundSource[SPEECH_SOURCE].sample, first_chain, offset);
|
||||||
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
|
PlayingTrack();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FastReverse_Page ()
|
||||||
{
|
{
|
||||||
if (sound_sample)
|
if (sound_sample)
|
||||||
{
|
{
|
||||||
TFB_SoundChain *prev_chain;
|
TFB_SoundChain *prev_chain;
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
// fprintf(stderr, "playing %s at %d\n",
|
|
||||||
// sound_sample->play_chain_ptr->decoder->filename,
|
|
||||||
// sound_sample->play_chain_ptr->decoder->start_sample);
|
|
||||||
prev_chain = get_previous_chain(first_chain, sound_sample->play_chain_ptr);
|
prev_chain = get_previous_chain(first_chain, sound_sample->play_chain_ptr);
|
||||||
// fprintf(stderr, "now playing %s at %d\n",
|
|
||||||
// prev_chain->decoder->filename, prev_chain->decoder->start_sample);
|
|
||||||
if (prev_chain)
|
if (prev_chain)
|
||||||
{
|
{
|
||||||
sound_sample->read_chain_ptr = prev_chain;
|
sound_sample->read_chain_ptr = prev_chain;
|
||||||
PlayStream (sound_sample,
|
PlayStream (sound_sample,
|
||||||
SPEECH_SOURCE, false,
|
SPEECH_SOURCE, false,
|
||||||
speechVolumeScale != 0.0f);
|
speechVolumeScale != 0.0f, true);
|
||||||
}
|
}
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FastForward ()
|
FastForward_Smooth ()
|
||||||
|
{
|
||||||
|
if (sound_sample)
|
||||||
|
{
|
||||||
|
sint32 offset;
|
||||||
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
|
PauseStream (SPEECH_SOURCE);
|
||||||
|
soundSource[SPEECH_SOURCE].start_time -= ACCEL_SCROLL_SPEED;
|
||||||
|
offset = GetTimeCounter() - soundSource[SPEECH_SOURCE].start_time;
|
||||||
|
track_pos_changed = 1;
|
||||||
|
recompute_track_pos(sound_sample, first_chain, offset);
|
||||||
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
|
PlayingTrack();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FastForward_Page ()
|
||||||
{
|
{
|
||||||
if (sound_sample)
|
if (sound_sample)
|
||||||
{
|
{
|
||||||
@@ -463,7 +524,7 @@ FastForward ()
|
|||||||
sound_sample->read_chain_ptr = cur_ptr->next;
|
sound_sample->read_chain_ptr = cur_ptr->next;
|
||||||
PlayStream (sound_sample,
|
PlayStream (sound_sample,
|
||||||
SPEECH_SOURCE, false,
|
SPEECH_SOURCE, false,
|
||||||
speechVolumeScale != 0.0f);
|
speechVolumeScale != 0.0f, true);
|
||||||
}
|
}
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
}
|
}
|
||||||
@@ -621,22 +682,24 @@ GetSoundData (void *data)
|
|||||||
|
|
||||||
// tells current position of streaming speech
|
// tells current position of streaming speech
|
||||||
int
|
int
|
||||||
GetSoundInfo (int *length, int *offset)
|
GetSoundInfo (int max_len)
|
||||||
{
|
{
|
||||||
|
uint32 length, offset;
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
if (soundSource[SPEECH_SOURCE].sample)
|
if (soundSource[SPEECH_SOURCE].sample)
|
||||||
{
|
{
|
||||||
*length = (int) (soundSource[SPEECH_SOURCE].sample->length * (float)ONE_SECOND);
|
length = (uint32) (soundSource[SPEECH_SOURCE].sample->length * (float)ONE_SECOND);
|
||||||
*offset = (int) (GetTimeCounter () - soundSource[SPEECH_SOURCE].start_time);
|
offset = (uint32) (GetTimeCounter () - soundSource[SPEECH_SOURCE].start_time);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*length = 1;
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
*offset = 0;
|
return (0);
|
||||||
}
|
}
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
|
if (offset > length)
|
||||||
return 1;
|
return max_len;
|
||||||
|
return (int)(max_len * offset / length);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -392,8 +392,9 @@ ALuint SoundDecoder_Decode (TFB_SoundDecoder *decoder)
|
|||||||
return decoded_bytes;
|
return decoded_bytes;
|
||||||
}
|
}
|
||||||
case SOUNDDECODER_BUF:
|
case SOUNDDECODER_BUF:
|
||||||
|
decoder->buffer = (char *)decoder->data + decoder->pos;
|
||||||
decoder->error = SOUNDDECODER_EOF;
|
decoder->error = SOUNDDECODER_EOF;
|
||||||
return (decoder->buffer_size);
|
return (decoder->buffer_size - decoder->pos);
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
fprintf (stderr, "SoundDecoder_Decode(): unknown type %d\n", decoder->type);
|
fprintf (stderr, "SoundDecoder_Decode(): unknown type %d\n", decoder->type);
|
||||||
@@ -419,6 +420,8 @@ ALuint SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder)
|
|||||||
if (decoder->buffer_size != 0)
|
if (decoder->buffer_size != 0)
|
||||||
{
|
{
|
||||||
decoder->type = SOUNDDECODER_BUF;
|
decoder->type = SOUNDDECODER_BUF;
|
||||||
|
decoder->data = decoder->buffer;
|
||||||
|
decoder->pos = 0;
|
||||||
decoder->error = SOUNDDECODER_OK;
|
decoder->error = SOUNDDECODER_OK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -483,6 +486,8 @@ ALuint SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder)
|
|||||||
ov_clear (vf);
|
ov_clear (vf);
|
||||||
HFree (vf);
|
HFree (vf);
|
||||||
decoder->type = SOUNDDECODER_BUF;
|
decoder->type = SOUNDDECODER_BUF;
|
||||||
|
decoder->data = decoder->buffer;
|
||||||
|
decoder->pos = 0;
|
||||||
|
|
||||||
decoder->error = SOUNDDECODER_OK;
|
decoder->error = SOUNDDECODER_OK;
|
||||||
return decoded_bytes;
|
return decoded_bytes;
|
||||||
@@ -500,18 +505,26 @@ ALuint SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SoundDecoder_Rewind (TFB_SoundDecoder *decoder)
|
void SoundDecoder_Rewind (TFB_SoundDecoder *decoder)
|
||||||
|
{
|
||||||
|
SoundDecoder_Seek (decoder, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// seekTime is specified in mili-seconds
|
||||||
|
void SoundDecoder_Seek (TFB_SoundDecoder *decoder, ALuint seekTime)
|
||||||
{
|
{
|
||||||
switch (decoder->type)
|
switch (decoder->type)
|
||||||
{
|
{
|
||||||
case SOUNDDECODER_WAV:
|
case SOUNDDECODER_WAV:
|
||||||
{
|
{
|
||||||
fprintf (stderr, "SoundDecoder_Rewind(): unimplemented for wav\n");
|
fprintf (stderr, "SoundDecoder_Seek(): unimplemented for wav\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SOUNDDECODER_MOD:
|
case SOUNDDECODER_MOD:
|
||||||
{
|
{
|
||||||
MODULE *mod = (MODULE *)decoder->data;
|
MODULE *mod = (MODULE *)decoder->data;
|
||||||
Player_Start (mod);
|
Player_Start (mod);
|
||||||
|
if (seekTime)
|
||||||
|
fprintf (stderr, "SoundDecoder_Seek(): non-zero seek positions not supported for mod\n");
|
||||||
Player_SetPosition (0);
|
Player_SetPosition (0);
|
||||||
//fprintf (stderr, "SoundDecoder_Rewind(): rewound %s\n", decoder->filename);
|
//fprintf (stderr, "SoundDecoder_Rewind(): rewound %s\n", decoder->filename);
|
||||||
decoder->error = SOUNDDECODER_OK;
|
decoder->error = SOUNDDECODER_OK;
|
||||||
@@ -520,18 +533,22 @@ void SoundDecoder_Rewind (TFB_SoundDecoder *decoder)
|
|||||||
case SOUNDDECODER_OGG:
|
case SOUNDDECODER_OGG:
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
unsigned long pcm_pos = 0;
|
||||||
OggVorbis_File *vf = (OggVorbis_File *) decoder->data;
|
OggVorbis_File *vf = (OggVorbis_File *) decoder->data;
|
||||||
if ((err = ov_pcm_seek (vf, decoder->start_sample)) != 0)
|
if (seekTime)
|
||||||
|
pcm_pos = seekTime * decoder->frequency / 1000;
|
||||||
|
if ((err = ov_pcm_seek (vf, decoder->start_sample + pcm_pos)) != 0)
|
||||||
{
|
{
|
||||||
|
fprintf (stderr, "SoundDecoder_Seek(): couldn't seek %s, error code %d\n", decoder->filename, err);
|
||||||
fprintf (stderr, "SoundDecoder_Rewind(): couldn't rewind %s, error code %d\n", decoder->filename, err);
|
fprintf (stderr, "SoundDecoder_Rewind(): couldn't rewind %s, error code %d\n", decoder->filename, err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (decoder->format == AL_FORMAT_MONO16)
|
if (decoder->format == AL_FORMAT_MONO16)
|
||||||
decoder->pos = decoder->start_sample * 2;
|
decoder->pos = (pcm_pos + decoder->start_sample) * 2;
|
||||||
else
|
else
|
||||||
decoder->pos = decoder->start_sample * 4;
|
decoder->pos = (pcm_pos + decoder->start_sample) * 4;
|
||||||
|
|
||||||
//fprintf (stderr, "SoundDecoder_Rewind(): rewound %s\n", decoder->filename);
|
//fprintf (stderr, "SoundDecoder_Seek(): seek %s\n", decoder->filename);
|
||||||
decoder->error = SOUNDDECODER_OK;
|
decoder->error = SOUNDDECODER_OK;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -542,7 +559,7 @@ void SoundDecoder_Rewind (TFB_SoundDecoder *decoder)
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
fprintf (stderr, "SoundDecoder_Rewind(): unknown type %d\n", decoder->type);
|
fprintf (stderr, "SoundDecoder_Seek(): unknown type %d\n", decoder->type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -593,4 +610,41 @@ void SoundDecoder_Free (TFB_SoundDecoder *decoder)
|
|||||||
HFree (decoder);
|
HFree (decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float SoundDecoder_GetTime (TFB_SoundDecoder *decoder)
|
||||||
|
{
|
||||||
|
if (!decoder)
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (decoder->type)
|
||||||
|
{
|
||||||
|
case SOUNDDECODER_WAV:
|
||||||
|
{
|
||||||
|
//fprintf (stderr, "SoundDecoder_GetTime not supported for wav\n");
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
case SOUNDDECODER_MOD:
|
||||||
|
{
|
||||||
|
//fprintf (stderr, "SoundDecoder_GetTime not supported for mod\n");
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
case SOUNDDECODER_OGG:
|
||||||
|
case SOUNDDECODER_BUF:
|
||||||
|
{
|
||||||
|
//fprintf (stderr, "SoundDecoder_GetTime not supported for mod\n");
|
||||||
|
return (
|
||||||
|
(float)(
|
||||||
|
(decoder->pos >> (decoder->format == AL_FORMAT_MONO16 ? 1 : 2))
|
||||||
|
- decoder->start_sample
|
||||||
|
) / decoder->frequency);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
fprintf (stderr, "SoundDecoder_GetTime(): unknown type %d\n", decoder->type);
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ void SoundDecoder_Uninit (void);
|
|||||||
TFB_SoundDecoder* SoundDecoder_Load (char *filename, ALuint buffer_size, unsigned long startTime, unsigned long runTime);
|
TFB_SoundDecoder* SoundDecoder_Load (char *filename, ALuint buffer_size, unsigned long startTime, unsigned long runTime);
|
||||||
ALuint SoundDecoder_Decode (TFB_SoundDecoder *decoder);
|
ALuint SoundDecoder_Decode (TFB_SoundDecoder *decoder);
|
||||||
ALuint SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder);
|
ALuint SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder);
|
||||||
|
float SoundDecoder_GetTime (TFB_SoundDecoder *decoder);
|
||||||
|
void SoundDecoder_Seek (TFB_SoundDecoder *decoder, ALuint pcm_pos);
|
||||||
void SoundDecoder_Rewind (TFB_SoundDecoder *decoder);
|
void SoundDecoder_Rewind (TFB_SoundDecoder *decoder);
|
||||||
void SoundDecoder_Free (TFB_SoundDecoder *decoder);
|
void SoundDecoder_Free (TFB_SoundDecoder *decoder);
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ PLRPlaySong (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE Priority)
|
|||||||
{
|
{
|
||||||
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
||||||
PlayStream ((*pmus), MUSIC_SOURCE, Continuous,
|
PlayStream ((*pmus), MUSIC_SOURCE, Continuous,
|
||||||
speechVolumeScale == 0.0f ? AL_TRUE : AL_FALSE);
|
speechVolumeScale == 0.0f ? AL_TRUE : AL_FALSE,
|
||||||
|
AL_TRUE);
|
||||||
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
||||||
|
|
||||||
curMusicRef = MusicRef;
|
curMusicRef = MusicRef;
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ typedef struct tfb_soundsource
|
|||||||
ALuint handle;
|
ALuint handle;
|
||||||
BOOLEAN stream_should_be_playing;
|
BOOLEAN stream_should_be_playing;
|
||||||
Mutex stream_mutex;
|
Mutex stream_mutex;
|
||||||
ALuint start_time;
|
ALint start_time;
|
||||||
|
|
||||||
// for oscilloscope
|
// for oscilloscope
|
||||||
void *sbuffer;
|
void *sbuffer;
|
||||||
|
|||||||
@@ -29,10 +29,11 @@
|
|||||||
BOOLEAN speech_advancetrack = FALSE;
|
BOOLEAN speech_advancetrack = FALSE;
|
||||||
|
|
||||||
void
|
void
|
||||||
PlayStream (TFB_SoundSample *sample, ALuint source, ALboolean looping, ALboolean scope)
|
PlayStream (TFB_SoundSample *sample, ALuint source, ALboolean looping,
|
||||||
|
ALboolean scope, ALboolean rewind)
|
||||||
{
|
{
|
||||||
ALuint i, pos = 0;
|
ALuint i, pos = 0;
|
||||||
ALuint offset = 0;
|
ALint offset = 0;
|
||||||
if (!sample || (!sample->read_chain_ptr && !sample->decoder))
|
if (!sample || (!sample->read_chain_ptr && !sample->decoder))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -40,11 +41,14 @@ PlayStream (TFB_SoundSample *sample, ALuint source, ALboolean looping, ALboolean
|
|||||||
if (sample->read_chain_ptr)
|
if (sample->read_chain_ptr)
|
||||||
{
|
{
|
||||||
sample->decoder = sample->read_chain_ptr->decoder;
|
sample->decoder = sample->read_chain_ptr->decoder;
|
||||||
offset = (int) (sample->read_chain_ptr->start_time * (float)ONE_SECOND);
|
offset = (ALint) (sample->read_chain_ptr->start_time * (float)ONE_SECOND);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
offset= 0;
|
offset= 0;
|
||||||
SoundDecoder_Rewind (sample->decoder);
|
if (rewind)
|
||||||
|
SoundDecoder_Rewind (sample->decoder);
|
||||||
|
else
|
||||||
|
offset += (ALint)(SoundDecoder_GetTime (sample->decoder) * (float)ONE_SECOND);
|
||||||
soundSource[source].sample = sample;
|
soundSource[source].sample = sample;
|
||||||
soundSource[source].sample->play_chain_ptr = sample->read_chain_ptr;
|
soundSource[source].sample->play_chain_ptr = sample->read_chain_ptr;
|
||||||
soundSource[source].sample->decoder->looping = looping;
|
soundSource[source].sample->decoder->looping = looping;
|
||||||
@@ -127,7 +131,7 @@ PlayStream (TFB_SoundSample *sample, ALuint source, ALboolean looping, ALboolean
|
|||||||
for ( ; i <sample->num_buffers; ++i)
|
for ( ; i <sample->num_buffers; ++i)
|
||||||
sample->buffer_tag[i] = 0;
|
sample->buffer_tag[i] = 0;
|
||||||
soundSource[source].sbuf_size = pos;
|
soundSource[source].sbuf_size = pos;
|
||||||
soundSource[source].start_time = GetTimeCounter () - offset;
|
soundSource[source].start_time = (ALint)GetTimeCounter () - offset;
|
||||||
soundSource[source].stream_should_be_playing = TRUE;
|
soundSource[source].stream_should_be_playing = TRUE;
|
||||||
alSourcePlay (soundSource[source].handle);
|
alSourcePlay (soundSource[source].handle);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
#ifndef STREAM_H
|
#ifndef STREAM_H
|
||||||
#define STREAM_H
|
#define STREAM_H
|
||||||
|
|
||||||
void PlayStream (TFB_SoundSample *sample, ALuint source, ALboolean looping, ALboolean scope);
|
void PlayStream (TFB_SoundSample *sample, ALuint source, ALboolean looping,
|
||||||
|
ALboolean scope, ALboolean rewind);
|
||||||
void StopStream (ALuint source);
|
void StopStream (ALuint source);
|
||||||
void PauseStream (ALuint source);
|
void PauseStream (ALuint source);
|
||||||
void ResumeStream (ALuint source);
|
void ResumeStream (ALuint source);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ static int tcur; //currently playing subtitle track
|
|||||||
static int cur_page = 0; //current page of subtitle track
|
static int cur_page = 0; //current page of subtitle track
|
||||||
static int no_page_break = 0;
|
static int no_page_break = 0;
|
||||||
static int no_voice;
|
static int no_voice;
|
||||||
|
static int track_pos_changed = 0; // set whenever ff, frev is enabled
|
||||||
|
|
||||||
|
|
||||||
#define MAX_CLIPS 50
|
#define MAX_CLIPS 50
|
||||||
@@ -71,12 +72,14 @@ advance_track (int channel_finished)
|
|||||||
{
|
{
|
||||||
if (channel_finished <= 0)
|
if (channel_finished <= 0)
|
||||||
{
|
{
|
||||||
if (sound_sample->decoder)
|
if (sound_sample->read_chain_ptr || sound_sample->decoder)
|
||||||
{
|
{
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
PlayStream (sound_sample,
|
PlayStream (sound_sample,
|
||||||
SPEECH_SOURCE, AL_FALSE,
|
SPEECH_SOURCE, AL_FALSE,
|
||||||
speechVolumeScale != 0.0f);
|
speechVolumeScale != 0.0f,
|
||||||
|
!track_pos_changed);
|
||||||
|
track_pos_changed = 0;
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
}
|
}
|
||||||
else if (channel_finished == 0)
|
else if (channel_finished == 0)
|
||||||
@@ -89,14 +92,14 @@ advance_track (int channel_finished)
|
|||||||
void
|
void
|
||||||
ResumeTrack ()
|
ResumeTrack ()
|
||||||
{
|
{
|
||||||
if (sound_sample && sound_sample->decoder)
|
if (sound_sample && sound_sample->read_chain_ptr)
|
||||||
{
|
{
|
||||||
ALint state;
|
ALint state;
|
||||||
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
alGetSourcei (soundSource[SPEECH_SOURCE].handle, AL_SOURCE_STATE, &state);
|
alGetSourcei (soundSource[SPEECH_SOURCE].handle, AL_SOURCE_STATE, &state);
|
||||||
|
|
||||||
if (!soundSource[SPEECH_SOURCE].stream_should_be_playing &&
|
if (!track_pos_changed && !soundSource[SPEECH_SOURCE].stream_should_be_playing &&
|
||||||
state == AL_PAUSED)
|
state == AL_PAUSED)
|
||||||
{
|
{
|
||||||
ResumeStream (SPEECH_SOURCE);
|
ResumeStream (SPEECH_SOURCE);
|
||||||
@@ -425,31 +428,90 @@ PauseTrack ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FastReverse ()
|
recompute_track_pos (TFB_SoundSample *sample, TFB_SoundChain *first_chain, ALint offset)
|
||||||
|
{
|
||||||
|
TFB_SoundChain *cur_chain = first_chain;
|
||||||
|
while (cur_chain->next &&
|
||||||
|
(ALint)(cur_chain->next->start_time * (float)ONE_SECOND) < offset)
|
||||||
|
cur_chain = cur_chain->next;
|
||||||
|
if (cur_chain->tag.type)
|
||||||
|
DoTrackTag (&cur_chain->tag);
|
||||||
|
if ((ALint)((cur_chain->start_time + cur_chain->decoder->length) * (float)ONE_SECOND) < offset)
|
||||||
|
{
|
||||||
|
sample->read_chain_ptr = NULL;
|
||||||
|
sample->decoder = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sample->read_chain_ptr = cur_chain;
|
||||||
|
SoundDecoder_Seek(sample->read_chain_ptr->decoder,
|
||||||
|
(ALuint)(1000 * (offset / (float)ONE_SECOND - cur_chain->start_time)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FastReverse_Smooth ()
|
||||||
|
{
|
||||||
|
if (sound_sample)
|
||||||
|
{
|
||||||
|
ALint offset;
|
||||||
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
|
PauseStream (SPEECH_SOURCE);
|
||||||
|
track_pos_changed = 1;
|
||||||
|
soundSource[SPEECH_SOURCE].start_time += ACCEL_SCROLL_SPEED;
|
||||||
|
if (soundSource[SPEECH_SOURCE].start_time > (ALint)GetTimeCounter())
|
||||||
|
{
|
||||||
|
soundSource[SPEECH_SOURCE].start_time = GetTimeCounter();
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
offset = GetTimeCounter() - soundSource[SPEECH_SOURCE].start_time;
|
||||||
|
recompute_track_pos(soundSource[SPEECH_SOURCE].sample, first_chain, offset);
|
||||||
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
|
PlayingTrack();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FastReverse_Page ()
|
||||||
{
|
{
|
||||||
if (sound_sample)
|
if (sound_sample)
|
||||||
{
|
{
|
||||||
TFB_SoundChain *prev_chain;
|
TFB_SoundChain *prev_chain;
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
// fprintf(stderr, "playing %s at %d\n",
|
|
||||||
// sound_sample->play_chain_ptr->decoder->filename,
|
|
||||||
// sound_sample->play_chain_ptr->decoder->start_sample);
|
|
||||||
prev_chain = get_previous_chain(first_chain, sound_sample->play_chain_ptr);
|
prev_chain = get_previous_chain(first_chain, sound_sample->play_chain_ptr);
|
||||||
// fprintf(stderr, "now playing %s at %d\n",
|
|
||||||
// prev_chain->decoder->filename, prev_chain->decoder->start_sample);
|
|
||||||
if (prev_chain)
|
if (prev_chain)
|
||||||
{
|
{
|
||||||
sound_sample->read_chain_ptr = prev_chain;
|
sound_sample->read_chain_ptr = prev_chain;
|
||||||
PlayStream (sound_sample,
|
PlayStream (sound_sample,
|
||||||
SPEECH_SOURCE, AL_FALSE,
|
SPEECH_SOURCE, AL_FALSE,
|
||||||
speechVolumeScale != 0.0f);
|
speechVolumeScale != 0.0f, AL_TRUE);
|
||||||
}
|
}
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FastForward ()
|
FastForward_Smooth ()
|
||||||
|
{
|
||||||
|
if (sound_sample)
|
||||||
|
{
|
||||||
|
ALint offset;
|
||||||
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
|
PauseStream (SPEECH_SOURCE);
|
||||||
|
soundSource[SPEECH_SOURCE].start_time -= ACCEL_SCROLL_SPEED;
|
||||||
|
offset = GetTimeCounter() - soundSource[SPEECH_SOURCE].start_time;
|
||||||
|
track_pos_changed = 1;
|
||||||
|
recompute_track_pos(sound_sample, first_chain, offset);
|
||||||
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
|
PlayingTrack();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FastForward_Page ()
|
||||||
{
|
{
|
||||||
if (sound_sample)
|
if (sound_sample)
|
||||||
{
|
{
|
||||||
@@ -462,7 +524,7 @@ FastForward ()
|
|||||||
sound_sample->read_chain_ptr = cur_ptr->next;
|
sound_sample->read_chain_ptr = cur_ptr->next;
|
||||||
PlayStream (sound_sample,
|
PlayStream (sound_sample,
|
||||||
SPEECH_SOURCE, AL_FALSE,
|
SPEECH_SOURCE, AL_FALSE,
|
||||||
speechVolumeScale != 0.0f);
|
speechVolumeScale != 0.0f, AL_TRUE);
|
||||||
}
|
}
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
}
|
}
|
||||||
@@ -620,22 +682,24 @@ GetSoundData (void *data)
|
|||||||
|
|
||||||
// tells current position of streaming speech
|
// tells current position of streaming speech
|
||||||
int
|
int
|
||||||
GetSoundInfo (int *length, int *offset)
|
GetSoundInfo (int max_len)
|
||||||
{
|
{
|
||||||
|
ALuint length, offset;
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
if (soundSource[SPEECH_SOURCE].sample)
|
if (soundSource[SPEECH_SOURCE].sample)
|
||||||
{
|
{
|
||||||
*length = (int) (soundSource[SPEECH_SOURCE].sample->length * (float)ONE_SECOND);
|
length = (ALuint) (soundSource[SPEECH_SOURCE].sample->length * (float)ONE_SECOND);
|
||||||
*offset = (int) (GetTimeCounter () - soundSource[SPEECH_SOURCE].start_time);
|
offset = (ALuint) (GetTimeCounter () - soundSource[SPEECH_SOURCE].start_time);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*length = 1;
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
*offset = 0;
|
return (0);
|
||||||
}
|
}
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
|
if (offset > length)
|
||||||
return 1;
|
return max_len;
|
||||||
|
return (int)(max_len * offset / length);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -128,13 +128,11 @@ GetSoundData (char* data)
|
|||||||
|
|
||||||
// Status: Unimplemented
|
// Status: Unimplemented
|
||||||
int
|
int
|
||||||
GetSoundInfo (int *length, int *offset)
|
GetSoundInfo (int length)
|
||||||
// Umm... How does it know which sound?
|
// Umm... How does it know which sound?
|
||||||
{
|
{
|
||||||
//fprintf (stderr, "Unimplemented function activated: GetSoundInfo()\n");
|
//fprintf (stderr, "Unimplemented function activated: GetSoundInfo()\n");
|
||||||
*length = 1;
|
return 0;
|
||||||
*offset = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status: Unimplemented
|
// Status: Unimplemented
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ PauseTrack ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FastReverse ()
|
FastReverse_Page ()
|
||||||
{
|
{
|
||||||
JumpTrack (0);
|
JumpTrack (0);
|
||||||
no_voice = 0;
|
no_voice = 0;
|
||||||
@@ -193,7 +193,23 @@ FastReverse ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FastForward ()
|
FastReverse_Smooth ()
|
||||||
|
{
|
||||||
|
JumpTrack (0);
|
||||||
|
no_voice = 0;
|
||||||
|
tcur = 0;
|
||||||
|
ResumeTrack ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FastForward_Page ()
|
||||||
|
{
|
||||||
|
JumpTrack (0);
|
||||||
|
// no_voice = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FastForward_Smooth ()
|
||||||
{
|
{
|
||||||
JumpTrack (0);
|
JumpTrack (0);
|
||||||
// no_voice = 0;
|
// no_voice = 0;
|
||||||
|
|||||||
@@ -19,16 +19,20 @@
|
|||||||
#ifndef TRACKPLAYER_H
|
#ifndef TRACKPLAYER_H
|
||||||
#define TRACKPLAYER_H
|
#define TRACKPLAYER_H
|
||||||
|
|
||||||
|
#define ACCEL_SCROLL_SPEED 30
|
||||||
|
|
||||||
void ResumeTrack();
|
void ResumeTrack();
|
||||||
void PauseTrack();
|
void PauseTrack();
|
||||||
COUNT PlayingTrack();
|
COUNT PlayingTrack();
|
||||||
void JumpTrack(int abort);
|
void JumpTrack(int abort);
|
||||||
void FastForward();
|
void FastForward_Smooth();
|
||||||
void FastReverse();
|
void FastForward_Page();
|
||||||
|
void FastReverse_Smooth();
|
||||||
|
void FastReverse_Page();
|
||||||
void StopTrack();
|
void StopTrack();
|
||||||
void SpliceTrack(UNICODE *filespec, UNICODE *textspec, UNICODE *TimeStamp);
|
void SpliceTrack(UNICODE *filespec, UNICODE *textspec, UNICODE *TimeStamp);
|
||||||
void SpliceMultiTrack (UNICODE *TrackNames[], UNICODE *TrackText);
|
void SpliceMultiTrack (UNICODE *TrackNames[], UNICODE *TrackText);
|
||||||
int GetSoundData (void *data);
|
int GetSoundData (void *data);
|
||||||
int GetSoundInfo (int *len, int *offs);
|
int GetSoundInfo (int max_len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -56,15 +56,13 @@ SetSliderImage (FRAME f)
|
|||||||
void
|
void
|
||||||
Slider (void)
|
Slider (void)
|
||||||
{
|
{
|
||||||
int len, offs;
|
int offs;
|
||||||
|
static int last_offs = -1;
|
||||||
|
|
||||||
if (GetSoundInfo (&len, &offs))
|
if ((offs = GetSoundInfo (sliderSpace)) != last_offs)
|
||||||
{
|
{
|
||||||
if (offs > len)
|
last_offs = offs;
|
||||||
offs = len;
|
buttonStamp.origin.x = sliderStamp.origin.x + offs;
|
||||||
if (len == 0)
|
|
||||||
len = 1;
|
|
||||||
buttonStamp.origin.x = sliderStamp.origin.x + sliderSpace * offs / len;
|
|
||||||
BatchGraphics ();
|
BatchGraphics ();
|
||||||
DrawStamp (&sliderStamp);
|
DrawStamp (&sliderStamp);
|
||||||
DrawStamp (&buttonStamp);
|
DrawStamp (&buttonStamp);
|
||||||
|
|||||||
+10
-1
@@ -90,7 +90,8 @@ main (int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
CSCAN_OPT = 1000,
|
CSCAN_OPT = 1000,
|
||||||
MENU_OPT,
|
MENU_OPT,
|
||||||
FONT_OPT
|
FONT_OPT,
|
||||||
|
SCROLL_OPT
|
||||||
};
|
};
|
||||||
|
|
||||||
int option_index = 0, c;
|
int option_index = 0, c;
|
||||||
@@ -115,6 +116,7 @@ main (int argc, char *argv[])
|
|||||||
{"cscan", 1, NULL, CSCAN_OPT},
|
{"cscan", 1, NULL, CSCAN_OPT},
|
||||||
{"menu", 1, NULL, MENU_OPT},
|
{"menu", 1, NULL, MENU_OPT},
|
||||||
{"font", 1, NULL, FONT_OPT},
|
{"font", 1, NULL, FONT_OPT},
|
||||||
|
{"scroll", 1, NULL, SCROLL_OPT},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -230,6 +232,12 @@ main (int argc, char *argv[])
|
|||||||
(char *)long_options[option_index].name)) != -1)
|
(char *)long_options[option_index].name)) != -1)
|
||||||
optWhichFonts = val;
|
optWhichFonts = val;
|
||||||
break;
|
break;
|
||||||
|
case SCROLL_OPT:
|
||||||
|
if ((val = Check_PC_3DO_opt (optarg,
|
||||||
|
OPT_PC | OPT_3DO,
|
||||||
|
(char *)long_options[option_index].name)) != -1)
|
||||||
|
optSmoothScroll = val;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf ("\nOption %s not found!\n", long_options[option_index].name);
|
printf ("\nOption %s not found!\n", long_options[option_index].name);
|
||||||
case '?':
|
case '?':
|
||||||
@@ -253,6 +261,7 @@ main (int argc, char *argv[])
|
|||||||
printf(" --cscan : coarse-scan display, pc=text, 3do=hieroglyphs (default 3do)\n");
|
printf(" --cscan : coarse-scan display, pc=text, 3do=hieroglyphs (default 3do)\n");
|
||||||
printf(" --menu : menu type, pc=text, 3do=graphical (default 3do)\n");
|
printf(" --menu : menu type, pc=text, 3do=graphical (default 3do)\n");
|
||||||
printf(" --font : font types and colors (default 3do)\n");
|
printf(" --font : font types and colors (default 3do)\n");
|
||||||
|
printf(" --scroll : ff/frev during comm. pc=per-page, 3do=smooth (default pc)\n");
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user