• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Getting looped musics in Essentials (done!)

KillerMapper

Helix Follower
200
Posts
9
Years
  • We finally have a way to get looped music in Essentials with FMod!

    Some people, including me, tried to use FMod for more controls over the sound, especially for the looping points which allow to have correctly looped music. RPG Maker VX ACE can do it using loop tags in audio files such as OGG but unfortunately RPG Maker XP doesn't. FMod is probably the best way to do it.

    People from Community Script Project made a new script with FMod and this one is actually working fine with Essentials (unless you made some script change in the sound domain, maybe. Just try). You can grab it here:
    http://www.pokecommunity.com/showthread.php?t=349496

    Install it following the instructions. Now to get looped musics, you can use GiraPrimal's table (see the topic or look in the FMod script to figure out how do use it).
    Or you can use the tags in OGG (maybe other formats are supported, I don't know). See here to know how to do that: http://www.rpgmakervxace.net/topic/3825-make-looping-bgm-part-1-ogg-vorbis/ . This method works perfectly and only requires Audacity which is free.

    Now you can enjoy correctly looped BGMs in your game!

    Big thanks for Nuri Yuri and CSP for this script!

    Older and original post:
    Spoiler:
     
    Last edited:

    Luka S.J.

    Jealous Croatian
    1,270
    Posts
    15
    Years
  • Ok, so first off, FMod is a great tool to use if you want good Audio in your games. The seamless looping is a huge point many RMXP games lack. Not to mention you can isolate Audio channels and split BGM tracks into instruments, getting perfect control of what to play, and when. You can swap BGMs to the precision of a millisecond with it, and other neat things. I use FMod...a lot, granted it may not be for a Pokemon Essentials project, but I think the same thing could apply.

    The way I've arranged looping points is not by having a table...yuck...that would require you to have to manually go through the song, and seek the loop position. The way I've set it up, is that you have two BGM tracks. One that has the full song, and one that is just the little intro of the song. The game then returns the length of the intro and full BGM in milliseconds, and sets those two values as the loop beginning and loop end respectively. This makes setting the loop points automatic, and does not require you to fill in a table. If you're making your own music, that's even better since you have full control over which sections you're exporting into the music file when compiling it (something I like and do a lot).
    Code:
    module Audio
      def Audio.bgm_fade(time)
        return if @me_playing or !FMod::bgm_playing?
        @bgm_fading_out = true
        time = time * 1.0
        @bgm_fade_decrement = FMod::bgm_volume / (time * Graphics.frame_rate)
      end
    end
    
    def pbBGMPlay(param,volume=100,pitch=nil)
      return if !param
      param=pbResolveAudioFile(param,volume,pitch)
      
      first=getPlayTime("Audio/BGM/"+param.name+"_intro")
    
      second=getPlayTime("Audio/BGM/"+param.name)
        
      FMod.bgm_play("Audio/BGM/"+param.name,volume,param.pitch)
      FMod.bgm_set_loop_points(first*1000, second*1000)
    end
    
    def pbCueBGM(bgm,seconds=1.0,volume=100,pitch=nil)
      return if !bgm
      bgm=pbResolveAudioFile(bgm,volume,pitch)
      playingBGM=FMod.bgm_name
      return if bgm.name==playingBGM
      if playingBGM && FMod.bgm_volume>0
        Audio.bgm_fade(seconds/8)
        if !$PokemonTemp.cueFrames
          $PokemonTemp.cueFrames=(seconds*Graphics.frame_rate)+2
        end
        $PokemonTemp.cueBGM=bgm
      else
        pbBGMPlay(bgm)
      end
    end
    This is how I have set up my calls and transitions for the bgm. And I'd assume that it would work for Essentials too, since the original Audio set-up I used from my project was similar to what is used in Essentials. I adjusted it a bit to work with the $PokemonTemp from Essentials, but I haven't actually tested it out. It might need some further tinkering to use flawlessly, but I think it's a good starting point.
     
    Last edited:

    KillerMapper

    Helix Follower
    200
    Posts
    9
    Years
  • Thanks for you help. Your method is nice. I tried to implement it but I ran into a first error while loading my savegame (game menu loaded fine since there is no music here):

    Code:
    Exception: NoMethodError
    Message: undefined method `bgm_play' for FMod:Module
    LoopMusic:17:in `pbBGMPlay'
    Game_Map_:127:in `autoplay'
    PokemonField:2112:in `pbAutoplayOnSave'
    PokemonLoad:398:in `pbStartLoadScreen'
    PokemonLoad:326:in `loop'
    PokemonLoad:459:in `pbStartLoadScreen'
    Main:6:in `main'
    Main:49:in `mainFunctionDebug'
    Main:27:in `mainFunction'
    Main:27:in `pbCriticalCode'
    (I put your scrip into a section named LoopMusic)

    I fixed this one by replacing the FMod script given by KaiserYoshi (which has been modified by GiraPrimal) by another one I found in a RMXP project I had on my computer.
    The game launched fine, the music loops correctly but at a changemap I ran into another error:

    Code:
    Exception: NoMethodError
    Message: undefined method `bgm_name' for FMod:Module
    LoopMusic:24:in `pbCueBGM'
    Game_Map_:109:in `autoplayAsCue'
    PokemonField:2103:in `pbAutoplayOnTransition'
    PokemonMap:790:in `setCurrentMap'
    Game_Map_:424:in `update'
    Scene_Map:37:in `updateMaps'
    Scene_Map:36:in `each'
    Scene_Map:36:in `updateMaps'
    Scene_Map:102:in `update'
    Scene_Map:101:in `loop'

    My FMod script doesn't have bgm_name, and a ctrl+shift+F shows me that bgm_name is only in your script and in the Audio script as Audio_bgm_name. Can you show me the FMod script you use?

    This tutorial has a dead link for the script.
     
    Last edited:

    Luka S.J.

    Jealous Croatian
    1,270
    Posts
    15
    Years
  • I just use the standard FMod script that was on the HBGames forums. It is pretty much the same thing as what you have (without that part of the code with the loop tables). I have made a lot of adjustments to it, of course, to suit my needs and my style of usage. I just don't exactly remember what I changed/added.
    Code:
    module FMod
      #--------------------------------------------------------------------------
      # * Gets Current BGM name
      #-------------------------------------------------------------------------- 
      def self.bgm_name
        return nil if !@fmod_bgm
        return @fmod_bgm.name
      end
    end
    I may or may not have added that BGM name retrieval portion, I honestly don't remember. I know that I added a lot of channel manipulation, pitch altering, and other shenanigans to it, so I apologize that something was missing. But like I said, this is what I used in my project, and I haven't tested it in Essentials.

    I derped hard. No idea why I put the SoundFile class there.
     
    Last edited:

    KillerMapper

    Helix Follower
    200
    Posts
    9
    Years
  • Don't worry, it's fine! :p

    So I can now change map, but I have now the sames problems that I had few months ago with FMod: battle musics randomly not playing (or just for some frames, not even a second), same for some maps BGM. All BGM plays normally without FMod (not looping of course).

    There is something between Essentials and FMod that makes it not working, and I never found why...
     
    11
    Posts
    9
    Years
  • I have an idea : the problem come to the fade isn 't it ? Why not add a little delay before the BGM/BGS play in the FModex ?
    And thanks for the attention for this problem.

    Regards KaiserYoshi
     

    Luka S.J.

    Jealous Croatian
    1,270
    Posts
    15
    Years
  • I already addressed the issue with the fading in pbCueBGM (as far as I am aware). The only difference I can see with the battle BGM manipulation is that it uses $game_system to pause and resume the music.
    Code:
    class Game_System
      
      def bgm_pause(fadetime=0.0) 
        pos=FMod.bgm_position rescue 0
        if fadetime>0.0
          Audio.bgm_fade(fadetime)
        end
        @bgm_position=pos
        @bgm_paused=true
      end
    
      def bgm_resume(bgm) 
        if @bgm_paused
          return false if !FileTest.audio_exist?("Audio/BGM/"+ bgm.name)
          @playing_bgm = bgm==nil ? nil : bgm.clone
          first=getPlayTime("Audio/BGM/"+bgm.name+"_intro")
          second=getPlayTime("Audio/BGM/"+bgm.name)
          
          FMod.bgm_play("Audio/BGM/"+bgm.name,bgm.volume,bgm.pitch,@bgm_position)
          FMod.bgm_set_loop_points(first*1000, second*1000)
          
          @bgm_position=0
          @bgm_paused=false
        end
      end
    
    end
    Just something I threw together quickly. Try it out.
     
    11
    Posts
    9
    Years
  • I don't see that, i'm sorry.
    For avoid an error, this script : places above main or replaces in game system ? (sorry for my low level)

    Regards KaiserYoshi
     

    KillerMapper

    Helix Follower
    200
    Posts
    9
    Years
  • I added your latest code.

    So far, the issues I still have:
    -the map I load plays a looped BGM fine. When I change map, it will play its BGM, but another map won't play it. It's random, not map or music related. Also if I do quickly chamgmaps like map A > map B > map A > map B, (where map B BGM fails), it will eventually play map B's BGM.
    - BGM in battles sometimes stop playing quickly after it start.

    It's not specifically related to the Cue script since battle doesn't use it.

    Do you think it would be possible to keep the minimal code from FMod to only get the loop points?
    Maybe we should try to check all the methods used by Essentials and replaced by FMod, and see what changed compared to Audio...
     
    Last edited:

    KillerMapper

    Helix Follower
    200
    Posts
    9
    Years
  • I think the best thing to do now it to make FMod compatible with Essentials. I just made a new and unmodified Essentials project (V15.1) and add the FMod script Luka linked. Then I made some tests:
    - map BGM works, they fade out correctly. Sometimes it won't play, but it's very rare, 99% of time it will play.
    - battles BGM are broken, the BGM either doesn't play or plays for less than a second. Sometimes, it will play correctly. This is for wild, trainer, safari, event battles. I noticed double battles are less buggy, I got the best results here. But I can't tell you why.
    - other BGMs seem to work. I tried Pokémon evolution and it played nicely.
    - about other sounds (BGS, ME and SE), I didn't noticed problems.

    I used the musics provided by Essentials, so MIDI format. I didn't tried other formats yet (OGG, VAW, MP3... even if I aim to use OGG most of time).

    Now to find why battles BGM don't work properly...
     

    KillerMapper

    Helix Follower
    200
    Posts
    9
    Years
  • I just found this post on Reddit (by IIcolour_Spectrum): http://www.reddit.com/r/PokemonRMXP/comments/1tstpf/tutorial_give_evented_encounters_unique_music/

    The thing to know is that ME pauses BGM when played. IIcolour_Spectrum uses this to get looped musics on a specific battle event (like a legendary). The music is made of 2 files: the intro part (as a ME) and the loop part (the BGM). The BGM is played, immediately followed by the ME if it's defined. The ME will immediately pause the BGM, play itself and then resume the BGM when it's finished.
    Maybe it's possible to get it working for all the musics, using Luka's idea (checking if xxx_intro exists). That could be a Fmod-free alternative.
     

    Erassus

    I'm back.
    50
    Posts
    9
    Years
  • The best way (actually what im using) is a BGM looped .OGG file with a bitrate of 128 kbps, around 100~900 KB per file.
    Using a Intro ME/SE (depends or script or event) to the transition of the battle music.

    I would post later an example, if i have time.

    Intro of the Loop file, that takes around 5~10 seconds i think. Then the BGM file.

    This only works for Battle BGM's, for Maps BGM, i think is not necessary intro's if you managed as well the looped file.

    An example of BGM looped file that doesn't need intro cut: http://vocaroo.com/i/s18G0gzdXPst
     

    KillerMapper

    Helix Follower
    200
    Posts
    9
    Years
  • Some map BGM still have intro+loop parts. The gym theme for example. For now I get rid of the intro parts, but I'd like to get them.
     

    Luka S.J.

    Jealous Croatian
    1,270
    Posts
    15
    Years
  • Using an intro ME + BGM (as the main loop), is a terrible idea, and you'll never get that seamless transition that you would with FMod. Believe me, I know. I already tried that idea for my previous project. Using FMod is still your best bet, for properly looped ost.
     

    KillerMapper

    Helix Follower
    200
    Posts
    9
    Years
  • I would like to use FMod but I can't get it working correctly. It either messes up the battle BGM or the map BGM. I don't know how to fix this.
     

    KillerMapper

    Helix Follower
    200
    Posts
    9
    Years
  • http://www.pokecommunity.com/showthread.php?t=349496

    This works with Essential. I can finally have looped musics in Essential!
    LOOPSTART and LOOPLENGTH metadata tags added in oggs works with this script, so I don't even need to bother with multiple files. A simple tagged oggs is now enough.

    I'm edited the first post to resume all the information.

    Thanks everybody who helped to achieve this.
     
    Last edited:
    1
    Posts
    7
    Years
    • Seen Dec 26, 2019
    There is a bug in FModEx. Sometimes my BGM is cut.

    change the "se_play" method to the following will fix it:

    def self.se_play(name, volume=100, pitch=100)
    if @fmod_se.size > @fmod.maxChannels
    Audio.se_clean
    if @fmod_se.size > @fmod.maxChannels
    #msgbox_p 0
    se = @fmod_se.shift
    #msgbox_p se
    self.stop(se) if self.playing?(se)
    end
    end
    # Load SE into memory and play it
    @fmod_se << self.play(name, volume, pitch, 0, false, false)
    end
     
    Back
    Top