From a40f9a695b2af2544a08cab7f5331e2da77f0943 Mon Sep 17 00:00:00 2001 From: ghaushe Date: Wed, 29 Jan 2003 03:50:33 +0000 Subject: [PATCH] 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 --- sc2/ChangeLog | 1 + sc2/TODO | 2 - sc2/doc/users/manual.txt | 9 +- sc2/src/options.c | 1 + sc2/src/options.h | 1 + sc2/src/sc2code/comm.c | 30 +++-- .../libs/sound/mixsdl/decoders/decoder.c | 75 +++++++++++-- .../libs/sound/mixsdl/decoders/decoder.h | 2 + sc2/src/sc2code/libs/sound/mixsdl/music.c | 2 +- sc2/src/sc2code/libs/sound/mixsdl/sound.h | 2 +- sc2/src/sc2code/libs/sound/mixsdl/stream.c | 14 ++- sc2/src/sc2code/libs/sound/mixsdl/stream.h | 3 +- .../sc2code/libs/sound/mixsdl/trackplayer.c | 103 +++++++++++++---- .../libs/sound/openal/decoders/decoder.c | 68 ++++++++++-- .../libs/sound/openal/decoders/decoder.h | 2 + sc2/src/sc2code/libs/sound/openal/music.c | 3 +- sc2/src/sc2code/libs/sound/openal/sound.h | 2 +- sc2/src/sc2code/libs/sound/openal/stream.c | 14 ++- sc2/src/sc2code/libs/sound/openal/stream.h | 3 +- .../sc2code/libs/sound/openal/trackplayer.c | 104 ++++++++++++++---- sc2/src/sc2code/libs/sound/sdl/sound.c | 6 +- sc2/src/sc2code/libs/sound/sdl/trackplayer.c | 20 +++- sc2/src/sc2code/libs/sound/trackplayer.h | 10 +- sc2/src/sc2code/oscill.c | 12 +- sc2/src/starcon2.c | 11 +- 25 files changed, 399 insertions(+), 101 deletions(-) diff --git a/sc2/ChangeLog b/sc2/ChangeLog index 0cec2dac3..cb43e3539 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,5 @@ 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 sound module "mixsdl" (experimental) -fOSSiL - Fixed overlapping subtitle text while switch tracks -PhracturedBlue diff --git a/sc2/TODO b/sc2/TODO index 0a951dad4..f524d5608 100644 --- a/sc2/TODO +++ b/sc2/TODO @@ -101,8 +101,6 @@ Implementation bugs (low priority): vux001.ogg utwig072.ogg umgah027.ogg talkp068.ogg spaho007.ogg syree012.ogg syree021.ogg syree028.ogg syree069.ogg orz000.ogg - 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. - Slider doesn't track the audio very well Stuff still to do (large): diff --git a/sc2/doc/users/manual.txt b/sc2/doc/users/manual.txt index 540be5608..e3bbaaa24 100644 --- a/sc2/doc/users/manual.txt +++ b/sc2/doc/users/manual.txt @@ -116,7 +116,14 @@ Use PC style fonts and colors. --font 3do 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 diff --git a/sc2/src/options.c b/sc2/src/options.c index 714350e8d..fd538346d 100644 --- a/sc2/src/options.c +++ b/sc2/src/options.c @@ -32,6 +32,7 @@ int optWhichMusic = OPT_3DO; int optWhichCoarseScan = OPT_3DO; int optWhichMenu = OPT_3DO; int optWhichFonts = OPT_3DO; +int optSmoothScroll = OPT_PC; char *configDir, *saveDir, *meleeDir; BOOLEAN optSubtitles = TRUE; diff --git a/sc2/src/options.h b/sc2/src/options.h index f1cf0d7aa..8f3464ab8 100644 --- a/sc2/src/options.h +++ b/sc2/src/options.h @@ -34,6 +34,7 @@ extern int optWhichMusic; extern int optWhichCoarseScan; extern int optWhichMenu; extern int optWhichFonts; +extern int optSmoothScroll; extern BOOLEAN optSubtitles; diff --git a/sc2/src/sc2code/comm.c b/sc2/src/sc2code/comm.c index 8a0584aa3..2fe831ebc 100644 --- a/sc2/src/sc2code/comm.c +++ b/sc2/src/sc2code/comm.c @@ -1220,27 +1220,41 @@ SpewPhrases (COUNT wait_track) if (which_track) { - if (InputState != LastInputState && GetInputXComponent (InputState) > 0) + if (GetInputXComponent (InputState) > 0) { SetSliderImage (SetAbsFrameIndex (ActivityFrame, 3)); - FastForward (); + if (optSmoothScroll == OPT_PC && InputState != LastInputState) + FastForward_Page (); + else if (optSmoothScroll == OPT_3DO) + FastForward_Smooth (); ContinuityBreak = TRUE; CommData.AlienFrame = 0; } - else if (InputState != LastInputState && GetInputXComponent (InputState) < 0) + else if (GetInputXComponent (InputState) < 0) { Rewind: SetSliderImage (SetAbsFrameIndex (ActivityFrame, 4)); - FastReverse (); + if (optSmoothScroll == OPT_PC && InputState != LastInputState) + FastReverse_Page (); + else if (optSmoothScroll == OPT_3DO) + FastReverse_Smooth (); ContinuityBreak = TRUE; CommData.AlienFrame = 0; } - else if (InputState != LastInputState && ContinuityBreak) + else if (ContinuityBreak) { SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2)); if ((which_track = PlayingTrack ()) - && which_track <= wait_track) ; -// ResumeTrack (); + && which_track <= wait_track) + { + if (optSmoothScroll == OPT_3DO) + ResumeTrack (); + } + else + { + CommData.AlienFrame = F; + return (FALSE); + } ContinuityBreak = FALSE; } 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; silence_length = 0; 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) { diff --git a/sc2/src/sc2code/libs/sound/mixsdl/decoders/decoder.c b/sc2/src/sc2code/libs/sound/mixsdl/decoders/decoder.c index 418e3f9ef..457533eff 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/decoders/decoder.c +++ b/sc2/src/sc2code/libs/sound/mixsdl/decoders/decoder.c @@ -441,8 +441,9 @@ uint32 SoundDecoder_Decode (TFB_SoundDecoder *decoder) return decoded_bytes; } case SOUNDDECODER_BUF: + decoder->buffer = (char *)decoder->data + decoder->pos; decoder->error = SOUNDDECODER_EOF; - return (decoder->buffer_size); + return (decoder->buffer_size - decoder->pos); default: { 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) { - decoder->type = SOUNDDECODER_BUF; - decoder->error = SOUNDDECODER_OK; /* WAVs are loaded in little-endian order * may need to do a word-swap @@ -480,6 +479,10 @@ uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder) SoundDecoder_SwapWords ( decoder->buffer, decoder->buffer_size); } + decoder->type = SOUNDDECODER_BUF; + decoder->data = decoder->buffer; + decoder->pos = 0; + decoder->error = SOUNDDECODER_OK; } else { @@ -545,6 +548,8 @@ uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder) ov_clear (vf); HFree (vf); decoder->type = SOUNDDECODER_BUF; + decoder->data = decoder->buffer; + decoder->pos = 0; decoder->error = SOUNDDECODER_OK; return decoded_bytes; @@ -562,18 +567,26 @@ uint32 SoundDecoder_DecodeAll (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) { case SOUNDDECODER_WAV: { - fprintf (stderr, "SoundDecoder_Rewind(): unimplemented for wav\n"); + fprintf (stderr, "SoundDecoder_Seek(): unimplemented for wav\n"); break; } case SOUNDDECODER_MOD: { MODULE *mod = (MODULE *)decoder->data; Player_Start (mod); + if (seekTime) + fprintf (stderr, "SoundDecoder_Seek(): non-zero seek positions not supported for mod\n"); Player_SetPosition (0); //fprintf (stderr, "SoundDecoder_Rewind(): rewound %s\n", decoder->filename); decoder->error = SOUNDDECODER_OK; @@ -582,29 +595,34 @@ void SoundDecoder_Rewind (TFB_SoundDecoder *decoder) case SOUNDDECODER_OGG: { int err; + uint32 pcm_pos = 0; 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; } if (decoder->format == decoder_formats.mono16) - decoder->pos = decoder->start_sample * 2; + decoder->pos = (pcm_pos + decoder->start_sample) * 2; 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; return; } case SOUNDDECODER_BUF: { + decoder->pos = seekTime * decoder->frequency * + (decoder->format == decoder_formats.mono16 ? 2 : 4) / 1000; decoder->error = SOUNDDECODER_OK; return; } default: { - fprintf (stderr, "SoundDecoder_Rewind(): unknown type %d\n", decoder->type); + fprintf (stderr, "SoundDecoder_Seek(): unknown type %d\n", decoder->type); break; } } @@ -655,4 +673,41 @@ void SoundDecoder_Free (TFB_SoundDecoder *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 diff --git a/sc2/src/sc2code/libs/sound/mixsdl/decoders/decoder.h b/sc2/src/sc2code/libs/sound/mixsdl/decoders/decoder.h index d714eea67..c177453e1 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/decoders/decoder.h +++ b/sc2/src/sc2code/libs/sound/mixsdl/decoders/decoder.h @@ -86,6 +86,8 @@ TFB_SoundDecoder* SoundDecoder_Load (char *filename, uint32 buffer_size, uint32 startTime, uint32 runTime); uint32 SoundDecoder_Decode (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_Free (TFB_SoundDecoder *decoder); diff --git a/sc2/src/sc2code/libs/sound/mixsdl/music.c b/sc2/src/sc2code/libs/sound/mixsdl/music.c index d5e053783..467a5fa3c 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/music.c +++ b/sc2/src/sc2code/libs/sound/mixsdl/music.c @@ -35,7 +35,7 @@ PLRPlaySong (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE Priority) { LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); PlayStream ((*pmus), MUSIC_SOURCE, Continuous, - speechVolumeScale == 0.0f); + speechVolumeScale == 0.0f, true); UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); curMusicRef = MusicRef; diff --git a/sc2/src/sc2code/libs/sound/mixsdl/sound.h b/sc2/src/sc2code/libs/sound/mixsdl/sound.h index db0e3432c..aec025261 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/sound.h +++ b/sc2/src/sc2code/libs/sound/mixsdl/sound.h @@ -72,7 +72,7 @@ typedef struct tfb_soundsource mixSDL_Object handle; bool stream_should_be_playing; Mutex stream_mutex; - uint32 start_time; + sint32 start_time; // for oscilloscope void *sbuffer; diff --git a/sc2/src/sc2code/libs/sound/mixsdl/stream.c b/sc2/src/sc2code/libs/sound/mixsdl/stream.c index 340c9a5be..2ac93f46e 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/stream.c +++ b/sc2/src/sc2code/libs/sound/mixsdl/stream.c @@ -26,9 +26,10 @@ bool speech_advancetrack = FALSE; 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)) return; @@ -37,11 +38,14 @@ PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope) if (sample->read_chain_ptr) { 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 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->play_chain_ptr = sample->read_chain_ptr; soundSource[source].sample->decoder->looping = looping; @@ -108,7 +112,7 @@ PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope) for ( ; i num_buffers; ++i) sample->buffer_tag[i] = 0; 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; mixSDL_SourcePlay (soundSource[source].handle); } diff --git a/sc2/src/sc2code/libs/sound/mixsdl/stream.h b/sc2/src/sc2code/libs/sound/mixsdl/stream.h index fb3468f7d..199a73ced 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/stream.h +++ b/sc2/src/sc2code/libs/sound/mixsdl/stream.h @@ -20,7 +20,8 @@ #ifndef 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 PauseStream (uint32 source); void ResumeStream (uint32 source); diff --git a/sc2/src/sc2code/libs/sound/mixsdl/trackplayer.c b/sc2/src/sc2code/libs/sound/mixsdl/trackplayer.c index f82dab742..b0518c2ff 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/trackplayer.c +++ b/sc2/src/sc2code/libs/sound/mixsdl/trackplayer.c @@ -31,6 +31,7 @@ static int tcur; //currently playing subtitle track static int cur_page = 0; //current page of subtitle track static int no_page_break = 0; static int no_voice; +static int track_pos_changed = 0; // set whenever ff, frev is enabled #define MAX_CLIPS 50 @@ -72,12 +73,13 @@ advance_track (int channel_finished) { if (channel_finished <= 0) { - if (sound_sample->decoder) + if (sound_sample->read_chain_ptr || sound_sample->decoder) { LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); PlayStream (sound_sample, SPEECH_SOURCE, false, - speechVolumeScale != 0.0f); + speechVolumeScale != 0.0f, !track_pos_changed); + track_pos_changed = 0; UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } else if (channel_finished == 0) @@ -90,14 +92,14 @@ advance_track (int channel_finished) void ResumeTrack () { - if (sound_sample && sound_sample->decoder) + if (sound_sample && sound_sample->read_chain_ptr) { uint32 state; LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); 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) { ResumeStream (SPEECH_SOURCE); @@ -426,31 +428,90 @@ PauseTrack () } 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) { TFB_SoundChain *prev_chain; 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); -// fprintf(stderr, "now playing %s at %d\n", -// prev_chain->decoder->filename, prev_chain->decoder->start_sample); if (prev_chain) { sound_sample->read_chain_ptr = prev_chain; PlayStream (sound_sample, SPEECH_SOURCE, false, - speechVolumeScale != 0.0f); + speechVolumeScale != 0.0f, true); } UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } } 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) { @@ -463,7 +524,7 @@ FastForward () sound_sample->read_chain_ptr = cur_ptr->next; PlayStream (sound_sample, SPEECH_SOURCE, false, - speechVolumeScale != 0.0f); + speechVolumeScale != 0.0f, true); } UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } @@ -621,22 +682,24 @@ GetSoundData (void *data) // tells current position of streaming speech int -GetSoundInfo (int *length, int *offset) +GetSoundInfo (int max_len) { + uint32 length, offset; LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); if (soundSource[SPEECH_SOURCE].sample) { - *length = (int) (soundSource[SPEECH_SOURCE].sample->length * (float)ONE_SECOND); - *offset = (int) (GetTimeCounter () - soundSource[SPEECH_SOURCE].start_time); + length = (uint32) (soundSource[SPEECH_SOURCE].sample->length * (float)ONE_SECOND); + offset = (uint32) (GetTimeCounter () - soundSource[SPEECH_SOURCE].start_time); } else { - *length = 1; - *offset = 0; + UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); + return (0); } UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); - - return 1; + if (offset > length) + return max_len; + return (int)(max_len * offset / length); } #endif diff --git a/sc2/src/sc2code/libs/sound/openal/decoders/decoder.c b/sc2/src/sc2code/libs/sound/openal/decoders/decoder.c index a35262321..177b1c642 100644 --- a/sc2/src/sc2code/libs/sound/openal/decoders/decoder.c +++ b/sc2/src/sc2code/libs/sound/openal/decoders/decoder.c @@ -392,8 +392,9 @@ ALuint SoundDecoder_Decode (TFB_SoundDecoder *decoder) return decoded_bytes; } case SOUNDDECODER_BUF: + decoder->buffer = (char *)decoder->data + decoder->pos; decoder->error = SOUNDDECODER_EOF; - return (decoder->buffer_size); + return (decoder->buffer_size - decoder->pos); default: { 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) { decoder->type = SOUNDDECODER_BUF; + decoder->data = decoder->buffer; + decoder->pos = 0; decoder->error = SOUNDDECODER_OK; } else @@ -483,6 +486,8 @@ ALuint SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder) ov_clear (vf); HFree (vf); decoder->type = SOUNDDECODER_BUF; + decoder->data = decoder->buffer; + decoder->pos = 0; decoder->error = SOUNDDECODER_OK; return decoded_bytes; @@ -500,18 +505,26 @@ ALuint SoundDecoder_DecodeAll (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) { case SOUNDDECODER_WAV: { - fprintf (stderr, "SoundDecoder_Rewind(): unimplemented for wav\n"); + fprintf (stderr, "SoundDecoder_Seek(): unimplemented for wav\n"); break; } case SOUNDDECODER_MOD: { MODULE *mod = (MODULE *)decoder->data; Player_Start (mod); + if (seekTime) + fprintf (stderr, "SoundDecoder_Seek(): non-zero seek positions not supported for mod\n"); Player_SetPosition (0); //fprintf (stderr, "SoundDecoder_Rewind(): rewound %s\n", decoder->filename); decoder->error = SOUNDDECODER_OK; @@ -520,18 +533,22 @@ void SoundDecoder_Rewind (TFB_SoundDecoder *decoder) case SOUNDDECODER_OGG: { int err; + unsigned long pcm_pos = 0; 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); break; } if (decoder->format == AL_FORMAT_MONO16) - decoder->pos = decoder->start_sample * 2; + decoder->pos = (pcm_pos + decoder->start_sample) * 2; 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; return; } @@ -542,7 +559,7 @@ void SoundDecoder_Rewind (TFB_SoundDecoder *decoder) } default: { - fprintf (stderr, "SoundDecoder_Rewind(): unknown type %d\n", decoder->type); + fprintf (stderr, "SoundDecoder_Seek(): unknown type %d\n", decoder->type); break; } } @@ -593,4 +610,41 @@ void SoundDecoder_Free (TFB_SoundDecoder *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 diff --git a/sc2/src/sc2code/libs/sound/openal/decoders/decoder.h b/sc2/src/sc2code/libs/sound/openal/decoders/decoder.h index 2b21ea756..d8c23fcdf 100644 --- a/sc2/src/sc2code/libs/sound/openal/decoders/decoder.h +++ b/sc2/src/sc2code/libs/sound/openal/decoders/decoder.h @@ -73,6 +73,8 @@ void SoundDecoder_Uninit (void); TFB_SoundDecoder* SoundDecoder_Load (char *filename, ALuint buffer_size, unsigned long startTime, unsigned long runTime); ALuint SoundDecoder_Decode (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_Free (TFB_SoundDecoder *decoder); diff --git a/sc2/src/sc2code/libs/sound/openal/music.c b/sc2/src/sc2code/libs/sound/openal/music.c index a2541f00c..3aed992b7 100644 --- a/sc2/src/sc2code/libs/sound/openal/music.c +++ b/sc2/src/sc2code/libs/sound/openal/music.c @@ -35,7 +35,8 @@ PLRPlaySong (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE Priority) { LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); 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); curMusicRef = MusicRef; diff --git a/sc2/src/sc2code/libs/sound/openal/sound.h b/sc2/src/sc2code/libs/sound/openal/sound.h index bc1bf097e..03dad57f4 100644 --- a/sc2/src/sc2code/libs/sound/openal/sound.h +++ b/sc2/src/sc2code/libs/sound/openal/sound.h @@ -81,7 +81,7 @@ typedef struct tfb_soundsource ALuint handle; BOOLEAN stream_should_be_playing; Mutex stream_mutex; - ALuint start_time; + ALint start_time; // for oscilloscope void *sbuffer; diff --git a/sc2/src/sc2code/libs/sound/openal/stream.c b/sc2/src/sc2code/libs/sound/openal/stream.c index 126c05daf..b0a110c07 100644 --- a/sc2/src/sc2code/libs/sound/openal/stream.c +++ b/sc2/src/sc2code/libs/sound/openal/stream.c @@ -29,10 +29,11 @@ BOOLEAN speech_advancetrack = FALSE; 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 offset = 0; + ALint offset = 0; if (!sample || (!sample->read_chain_ptr && !sample->decoder)) return; @@ -40,11 +41,14 @@ PlayStream (TFB_SoundSample *sample, ALuint source, ALboolean looping, ALboolean if (sample->read_chain_ptr) { 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 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->play_chain_ptr = sample->read_chain_ptr; soundSource[source].sample->decoder->looping = looping; @@ -127,7 +131,7 @@ PlayStream (TFB_SoundSample *sample, ALuint source, ALboolean looping, ALboolean for ( ; i num_buffers; ++i) sample->buffer_tag[i] = 0; 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; alSourcePlay (soundSource[source].handle); } diff --git a/sc2/src/sc2code/libs/sound/openal/stream.h b/sc2/src/sc2code/libs/sound/openal/stream.h index dfb482b67..52efddd3e 100644 --- a/sc2/src/sc2code/libs/sound/openal/stream.h +++ b/sc2/src/sc2code/libs/sound/openal/stream.h @@ -20,7 +20,8 @@ #ifndef 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 PauseStream (ALuint source); void ResumeStream (ALuint source); diff --git a/sc2/src/sc2code/libs/sound/openal/trackplayer.c b/sc2/src/sc2code/libs/sound/openal/trackplayer.c index 6a860b61f..230d76123 100644 --- a/sc2/src/sc2code/libs/sound/openal/trackplayer.c +++ b/sc2/src/sc2code/libs/sound/openal/trackplayer.c @@ -30,6 +30,7 @@ static int tcur; //currently playing subtitle track static int cur_page = 0; //current page of subtitle track static int no_page_break = 0; static int no_voice; +static int track_pos_changed = 0; // set whenever ff, frev is enabled #define MAX_CLIPS 50 @@ -71,12 +72,14 @@ advance_track (int channel_finished) { if (channel_finished <= 0) { - if (sound_sample->decoder) + if (sound_sample->read_chain_ptr || sound_sample->decoder) { LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); PlayStream (sound_sample, SPEECH_SOURCE, AL_FALSE, - speechVolumeScale != 0.0f); + speechVolumeScale != 0.0f, + !track_pos_changed); + track_pos_changed = 0; UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } else if (channel_finished == 0) @@ -89,14 +92,14 @@ advance_track (int channel_finished) void ResumeTrack () { - if (sound_sample && sound_sample->decoder) + if (sound_sample && sound_sample->read_chain_ptr) { ALint state; LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); 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) { ResumeStream (SPEECH_SOURCE); @@ -425,31 +428,90 @@ PauseTrack () } 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) { TFB_SoundChain *prev_chain; 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); -// fprintf(stderr, "now playing %s at %d\n", -// prev_chain->decoder->filename, prev_chain->decoder->start_sample); if (prev_chain) { sound_sample->read_chain_ptr = prev_chain; PlayStream (sound_sample, SPEECH_SOURCE, AL_FALSE, - speechVolumeScale != 0.0f); + speechVolumeScale != 0.0f, AL_TRUE); } UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } } 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) { @@ -462,7 +524,7 @@ FastForward () sound_sample->read_chain_ptr = cur_ptr->next; PlayStream (sound_sample, SPEECH_SOURCE, AL_FALSE, - speechVolumeScale != 0.0f); + speechVolumeScale != 0.0f, AL_TRUE); } UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } @@ -620,22 +682,24 @@ GetSoundData (void *data) // tells current position of streaming speech int -GetSoundInfo (int *length, int *offset) +GetSoundInfo (int max_len) { + ALuint length, offset; LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); if (soundSource[SPEECH_SOURCE].sample) { - *length = (int) (soundSource[SPEECH_SOURCE].sample->length * (float)ONE_SECOND); - *offset = (int) (GetTimeCounter () - soundSource[SPEECH_SOURCE].start_time); + length = (ALuint) (soundSource[SPEECH_SOURCE].sample->length * (float)ONE_SECOND); + offset = (ALuint) (GetTimeCounter () - soundSource[SPEECH_SOURCE].start_time); } else { - *length = 1; - *offset = 0; + UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); + return (0); } UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); - - return 1; + if (offset > length) + return max_len; + return (int)(max_len * offset / length); } #endif diff --git a/sc2/src/sc2code/libs/sound/sdl/sound.c b/sc2/src/sc2code/libs/sound/sdl/sound.c index d4af0ab13..d6a8e4ddb 100644 --- a/sc2/src/sc2code/libs/sound/sdl/sound.c +++ b/sc2/src/sc2code/libs/sound/sdl/sound.c @@ -128,13 +128,11 @@ GetSoundData (char* data) // Status: Unimplemented int -GetSoundInfo (int *length, int *offset) +GetSoundInfo (int length) // Umm... How does it know which sound? { //fprintf (stderr, "Unimplemented function activated: GetSoundInfo()\n"); - *length = 1; - *offset = 0; - return 1; + return 0; } // Status: Unimplemented diff --git a/sc2/src/sc2code/libs/sound/sdl/trackplayer.c b/sc2/src/sc2code/libs/sound/sdl/trackplayer.c index 3cb28e92b..74922aa5a 100644 --- a/sc2/src/sc2code/libs/sound/sdl/trackplayer.c +++ b/sc2/src/sc2code/libs/sound/sdl/trackplayer.c @@ -184,7 +184,7 @@ PauseTrack () } void -FastReverse () +FastReverse_Page () { JumpTrack (0); no_voice = 0; @@ -193,7 +193,23 @@ FastReverse () } 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); // no_voice = 0; diff --git a/sc2/src/sc2code/libs/sound/trackplayer.h b/sc2/src/sc2code/libs/sound/trackplayer.h index 0aebfbcc1..5e0e187e3 100644 --- a/sc2/src/sc2code/libs/sound/trackplayer.h +++ b/sc2/src/sc2code/libs/sound/trackplayer.h @@ -19,16 +19,20 @@ #ifndef TRACKPLAYER_H #define TRACKPLAYER_H +#define ACCEL_SCROLL_SPEED 30 + void ResumeTrack(); void PauseTrack(); COUNT PlayingTrack(); void JumpTrack(int abort); -void FastForward(); -void FastReverse(); +void FastForward_Smooth(); +void FastForward_Page(); +void FastReverse_Smooth(); +void FastReverse_Page(); void StopTrack(); void SpliceTrack(UNICODE *filespec, UNICODE *textspec, UNICODE *TimeStamp); void SpliceMultiTrack (UNICODE *TrackNames[], UNICODE *TrackText); int GetSoundData (void *data); -int GetSoundInfo (int *len, int *offs); +int GetSoundInfo (int max_len); #endif diff --git a/sc2/src/sc2code/oscill.c b/sc2/src/sc2code/oscill.c index 33de5ae76..edfe88f61 100644 --- a/sc2/src/sc2code/oscill.c +++ b/sc2/src/sc2code/oscill.c @@ -56,15 +56,13 @@ SetSliderImage (FRAME f) 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) - offs = len; - if (len == 0) - len = 1; - buttonStamp.origin.x = sliderStamp.origin.x + sliderSpace * offs / len; + last_offs = offs; + buttonStamp.origin.x = sliderStamp.origin.x + offs; BatchGraphics (); DrawStamp (&sliderStamp); DrawStamp (&buttonStamp); diff --git a/sc2/src/starcon2.c b/sc2/src/starcon2.c index 199c98500..75db493d8 100644 --- a/sc2/src/starcon2.c +++ b/sc2/src/starcon2.c @@ -90,7 +90,8 @@ main (int argc, char *argv[]) { CSCAN_OPT = 1000, MENU_OPT, - FONT_OPT + FONT_OPT, + SCROLL_OPT }; int option_index = 0, c; @@ -115,6 +116,7 @@ main (int argc, char *argv[]) {"cscan", 1, NULL, CSCAN_OPT}, {"menu", 1, NULL, MENU_OPT}, {"font", 1, NULL, FONT_OPT}, + {"scroll", 1, NULL, SCROLL_OPT}, {0, 0, 0, 0} }; @@ -230,6 +232,12 @@ main (int argc, char *argv[]) (char *)long_options[option_index].name)) != -1) optWhichFonts = val; 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: printf ("\nOption %s not found!\n", long_options[option_index].name); case '?': @@ -253,6 +261,7 @@ main (int argc, char *argv[]) printf(" --cscan : coarse-scan display, pc=text, 3do=hieroglyphs (default 3do)\n"); printf(" --menu : menu type, pc=text, 3do=graphical (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; break; }