Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » Audio Stream: Seeking doesn't work

Credits go to Edgar Reynaldo and Peter Hull for helping out!
This thread is locked; no one can reply to it. rss feed Print
Audio Stream: Seeking doesn't work
schollexpos
Member #16,751
October 2017

Hello,
I have started to work on a "smart" music system. I just have different versions of a song, and every time, the player level increases, the corresponding version of a song gets to play. All versions are stored in one audio file and thus in one stream, I only readjust the position and the looping points. To avoid straight cuts but also not having to wait through the entire length of the song to change it, the game knows the position of the sections in the song, and then waits for the current section to end and then jumps to the next section, but this time of course in the new version of the song.

But the simple call to al_seek_audio_stream_secs() fails. I have tried stopping the song before the call, or disabling the looping of the song, but with no luck. Does anyone know why the function could return false? Changing the looping points works without a problem.

The basic structure of my code:
I have an Audio Manager that recieves a Message from the Gameplay section, when a level-up occurs. This AudioManager has an object containing the ALLEGRO_STREAM of the currently playing track. With this it computes the amount of seconds to wait until the current section ends and where to jump to, and then starts an ALLEGRO_THREAD that waits and then calls the stream functions mentioned above. The thread doesn't seem to be a problem, the seeking fails even without it (the rest of my code is single threaded).

Thanks in advance!

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

schollexpos
Member #16,751
October 2017

Hello Edgar, thanks for your quick reply!
Here, is a condensed example:

#SelectExpand
1int main() { 2 al_init(); 3 4 al_install_keyboard(); 5 6 ALLEGRO_EVENT_QUEUE *queue = al_create_event_queue(); 7 8 ALLEGRO_DISPLAY *display = nullptr; 9 int requiredFlags = ALLEGRO_OPENGL | ALLEGRO_PROGRAMMABLE_PIPELINE; 10 al_set_new_display_flags(requiredFlags); 11 12 display = al_create_display(1280, 720); 13 al_register_event_source(queue, al_get_display_event_source(display)); 14 al_register_event_source(queue, al_get_keyboard_event_source()); 15 16 if(!al_install_audio()) { 17 std::cout << "[ERR.] Failed to load the Audio System!" << std::endl; 18 return 0; 19 } else { 20 std::cout << "Loaded the Audio System!" << std::endl; 21 } 22 al_init_acodec_addon(); 23 24 ALLEGRO_VOICE *voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2); 25 26 if(!voice) { 27 std::cout << "Failed to create Voice!" << std::endl; 28 exit(-1); 29 } 30 31 ALLEGRO_MIXER *mix_final = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2); 32 33 al_reserve_samples(16); 34 35 al_attach_mixer_to_voice(mix_final, voice); 36 37 ALLEGRO_AUDIO_STREAM *stream = al_load_audio_stream("res/theme.ogg", 4, 2048); 38 al_attach_audio_stream_to_mixer(stream, mix_final); 39 al_set_audio_stream_playmode(stream, ALLEGRO_PLAYMODE_LOOP); 40 al_set_audio_stream_loop_secs(stream, 0, 47.2); 41 42 bool running = true; 43 while(running) { 44 ALLEGRO_EVENT ev; 45 al_wait_for_event(queue, &ev); 46 do { 47 switch(ev.type) { 48 case ALLEGRO_EVENT_DISPLAY_CLOSE: 49 running = false; 50 break; 51 case ALLEGRO_EVENT_KEY_DOWN: 52 if(ev.keyboard.keycode == ALLEGRO_KEY_N) { 53 std::cout << "We should get something here" << std::endl; 54 al_seek_audio_stream_secs(stream, 60); 55 } 56 } 57 } while(al_get_next_event(queue, &ev)); 58 } 59 60 return 0; 61}

I'm amazed that the problem is not some kind of side effect from somewhere else in my engine ;D The console shows the output when pressing N, but the audio stream plays as if nothing had happened.

The audio file is over 5 minutes long, so I'm not trying to go over it's length here. I'm developing on Windows with Visual Studio 2017 and Allegro 5.2.5.2

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

schollexpos
Member #16,751
October 2017

The Music kind of gives away what I'm working on :P

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

What I'm getting at is that the ogg container that holds the audio file has a stream adjuster. I don't know if they're common for all formats. Can you load the file in VLC and tell me what the audio codec in use is?

EDIT
Did you ever call al_set_audio_stream_playing(true) or false?? I don't see that in the example.

schollexpos
Member #16,751
October 2017

The codec is just plain Vorbis Audio, according to VLC. I've exported the file from audacity, so I don't think there should be anything wrong about it(?)

No I haven't, I've relied on al_load_audio_stream automatically starting the file. But now I've tried to setting the stream to play manually, that didn't change anything.

Edit:
I've tried to replace my music file with the menu music from the allegro skater demo, but al_seek_audio_stream_secs() still returns false

Peter Hull
Member #1,136
March 2001

I had a very quick look at the Allegro code. It seems that you can only seek to within the loop you set in al_set_audio_stream_loop_secs. You set that to 0..47.2secs then tried to seek outside it. You could maybe try resetting the loop to whatever and then seeking.

Relevant part is here:
https://github.com/liballeg/allegro5/blob/50460b7fc48d6bafff2db309fe3cd5def80e3863/addons/acodec/ogg.c#L309-L319

static bool ogg_stream_seek(ALLEGRO_AUDIO_STREAM *stream, double time)
{
   AL_OV_DATA *extra = (AL_OV_DATA *) stream->extra;
   if (time >= extra->loop_end)
      return false;
#ifndef TREMOR
   return (lib.ov_time_seek_lap(extra->vf, time) != -1);
#else
   return lib.ov_time_seek(extra->vf, time*1000) != -1;
#endif
}

schollexpos
Member #16,751
October 2017

Of course, that was it! I haven't even thought about that I should be changing the loop-points first and only seek after that. Thank you!

Peter Hull
Member #1,136
March 2001

Strangely it's OK to seek before the looped section (you can see in the code snippet there's no check against loop_start) - in which case it plays through to the loop end and then starts to repeat. I don't know if that's a bug or useful behaviour, what do you think?

Go to: