Play one sound right after another without gaps

Monkey Forums/Monkey Programming/Play one sound right after another without gaps

lom(Posted 2015) [#1]
I have two parts of music track: 1 - intro (should play only once), 2 -loop.
I want to play intro first and then right after it stops I want to play a loop part without any gaps.
Here's what I'm doing:
if music_is_playing=false
PlaySound intro,music_channel
music_is_playing=true
endif
if music_is_playing=true and ChannelState (music_channel)=0 Then PlaySound loop,music_channel,1


It works but it seems like the loop starts playing after a small pause, it's very noticeable.
How to make it play right after the intro without any gaps?


tiresius(Posted 2015) [#2]
I seem to remember that mp3 format has built-in pause at the end. Are these mp3? Can you try ogg (which has no pause) ?


lom(Posted 2015) [#3]
tiresius,
I'm using OGG


golomp(Posted 2015) [#4]
Hi lom,
Did you tryed with shorter music file ?


abakobo(Posted 2015) [#5]
you probably have to use very hi fps because 5ms is noticeable with sound and the fps of sound is generaly 44100fps! and 5ms would be 200fps... I don't know how huge is the gap and what you mean by very noticeable... As they are from the same music you'll surely need very hi fps for it to sound good! May be using sound that fit exacly 16.666ms "cakes" if you are at 60fps would work?
You could try hi fps without graphics to see if it works better.. but i don't think mojo is adapted to create "trackers". It would need two different "render" updates..
It would be probably easier to start the loop before the intro ends and have a kind of reverb at the end of your intro so there won't be silence between them (using millisecs difference to know when to start the loop).


ImmutableOctet(SKNG)(Posted 2015) [#6]
I haven't messed with sound in Monkey for a while, but I wonder if an "asynchronous" approach would be better for Mojo's audio functionality. To put it simply, my idea is to use a call-back system akin to the async-classes for audio behavior. Then, you could have one or more interfaces which would be used to pass an object (Usually the 'App' object) into Mojo. From there, when the channel state changes, it could use the methods of those/that interface(s) as call-backs.

The only option I see for this without a semi-noticeable delay would be to just play your intro and main song at the same time, then simply have the main song contain blank audio for that section. The issue then becomes about looping the audio, so this doesn't really make much sense to begin with. This system does work for multiple "audio-layers" at one time, even if it is inefficient (Good compression or not). Crypt of the NecroDancer uses a system like this for the Shop Keeper's vocals (Even though, technically, it could be done dynamically using what they already have set up for the beat-detection); I'm not sure if this has changed with newer versions.

Besides a call-back system, the only other option is a terribly inefficient, external polling system for the channel state. Or you know, you could always deal with the slight delay. I don't think this would be hard for Mark to add, though. There's apparently problems with this idea on Android, though (At least from what the documentation says). A more abstracted interface-model would probably be needed for targets that have issues with this. In other words, an interface with a "SoundStopped" method, as opposed to the "OnSoundStateChange" idea.

EDIT 01: For the record, I'm not talking about audio loading, I'm talking about playing the audio.
EDIT 02: After a couple of minutes, I found the culprit; I can't technically say what it is because the Android Mojo implementation is commercial, but it basically doesn't allow for this kind of thing. There are options available for this on Android, though. Again, this is referring to Mojo's native code, so it's not something that's directly an option for you. (Unless you want to write your own audio API)


abakobo(Posted 2015) [#7]

It would be probably easier to start the loop before the intro ends and have a kind of reverb at the end of your intro so there won't be silence between them (using millisecs difference to know when to start the loop).



You can find an example here: http://turdus.be/monkeyx_example/soundintroloop.rar
(don't know if it is possible to upload on the forum...)

Listen to the two different intro's alone and run the example changing the intro files. Change the intro_length varibale to ear more reverb and get a "suspend" effect that can be cool too. If you have created the music yourself with a daw it will be easy to reproduce the logic. If not, it's possible to add a reverb at the end with a daw but it will be a "cheaper" effect as the reverb will involve all the sound (master track).
Notice it's more a more a musical solution than a programming solution. This is due to mojo's limits with audio.
The intro is short enough to play with android target. the loop should have been faded at short beginning and short end so it doesn't tick (may be with PlaySound it would work better but not compatible with Android for long loops)


lom(Posted 2015) [#8]
Thanks for responses.
I'm targeting desktop target, working with 60 fps

golomp,
yes, I tried different files with different length, result is the same.

abakobo,
The intro should sound seamless with the looping part, so you couldn't hear where it actually ends and where the loop starts. Right now I can clearly hear a short silent part.
I've tried to add silense at the beginning of the intro but result is the same.

Thanks for your example, I'll check it out!

ImmutableOctet(SKNG),
Writing my own audio API would be a problem for me=)
I guess I should just deal with current Monkey abilities.
I think Mark should add more advanced sound tracking commands at least for desktop target.


skid(Posted 2015) [#9]
I think the problem you have is with ChannelState.

As you already know duration of first track you could use a timer and start the loop on a second channel when first track ends without relying on polling ChannelState.

You can start it a bit early for a bit of overlap which will be a lot less noticeable than having a gap.

pseudo code (use integers so period calculation wraps correctly for all system clocks)

  PlaySound intro
  startTime=MilliSecs()+180000 ' 180.000 seconds for intro

...

  if not introIsFinished
    timeToFinishIntro=startTime-MilliSecs()
    if timeToFinishIntro<30 ' bit of overlap
      PlaySound loop
      introIsFinished=true
   endif
 endif



abakobo(Posted 2015) [#10]
using the same chanel is for sure a bad option in this case...


Samah(Posted 2015) [#11]
This is a perfect opportunity to use BASS, but I don't believe anyone has externed it yet for Monkey. I could be wrong?
http://www.un4seen.com/

Note that BASS is free for non-commercial use, but the commercial license is pretty exorbitant. You might be able to get around this by making your app free to download, but with in-app purchases.


Nobuyuki(Posted 2015) [#12]
This is a perfect opportunity to use BASS, but I don't believe anyone has externed it yet for Monkey. I could be wrong?

https://github.com/JochenHeizmann/monkeybass

Wrapped, but only for android. You'll have to write your own glue for the other platforms. I don't dig the licensing so much, but it's gotten better over time. Back when BASS's only general-purpose competitor was fmod EX, the licensing costs made sense. Nowadays you can get away with using fmod Studio for free if your commercial project has a sub-6-figure budget. Though if you want support for tracker formats, BASS or libmodplug's probably the way to go....


Why0Why(Posted 2015) [#13]
Definitely ouch on the prices, especially if you need multiple platforms.


lom(Posted 2015) [#14]
I decided to use overlapping for intro and loop playback. It's noticeable though, but at least there's no gap now.
Samah,
BASS prices are not very friendly


abakobo(Posted 2015) [#15]
If you send me the sounds (or daw projects) i can try to make a reverb at the end of you intro if you're not comfortable with daw and sounds.


golomp(Posted 2015) [#16]
+1
i also the issue come from sound files


lom(Posted 2015) [#17]
abakobo,
Thanks, but I'm satisfied with result, it's not perfect but seems ok:)


EdzUp(Posted 2015) [#18]
Couldn't ya just edit the sound and add the looping track to the end twice?


golomp(Posted 2015) [#19]
Maybe the solution is not to use Music function but only Sound functions ?