Other Script RGSS FmodEx extension

Started by 塗 ゆり May 24th, 2015 5:27 AM
  • 32356 views
  • 107 replies

塗 ゆり

Scripter / RGSS Modder

Age 26
Non-binary
France
Seen 10 Hours Ago
Posted 1 Week Ago
107 posts
9.1 Years
Introduction
Hi, I present one of the first scripts that uses the RGSS Linker !
This script is a rewrite of Audio module to use the C/C++ functions coded in the RGSS FmodEx.dll and RGSS Linker.dll DLLs.
RGSS FmodEx.dll depends on fmodex.dll, therefore to avoid the dependences problems, I included the file in the following archive : http://www.mediafire.com/download/jrlci7hwh5z0zhe/Fichiers+DLL+FmodEX.zip
You must paste these files in your project's root and everything should be fine.

Update of the DLL :
http://www.mediafire.com/file/knt7ran4nhbw0sq/RGSS_FmodEx.dll
http://www.mediafire.com/file/vj64d7cuwj2ct27/fmodex.dll

Note : This files were analysed by Kapersky and doesn't contain viruses, if a virus is found by your antivirus, it's a false positive.
The RGSS Linker is a bit special, it links RGSS functions in dynamic way by using static metric. Some AV such as Avast have difficulties with that and panick for nothing.

Contents
Here are links to the different parts of this post :
¤ RGSS Linker Script
¤ Audio (FmodEx) Script
¤ FmodEx::Sound class methods
¤ FmodEx module methods
¤ Credits

RGSS Linker script
This script permit to define the necessaries methods for the good function of the next script.
Your project must use RGSS104E.dll for that script function properly.
#===
#RGSS Linker (Kernel)
#  Function that helps the load of extentions using RGSS Linker.
#---
#© 2015 - Nuri Yuri (塗 ゆり)
#===
module Kernel
  unless @RGSS_Linker #>To avoid the RGSS Reset problem
     
  @RGSS_Linker = {:core => Win32API.new("RGSS Linker.dll","RGSSLinker_Initialize","p","i")}
  Win32API.new("kernel32","GetPrivateProfileString","ppppip","i").call("Game","Library",0,lib_name = "\x00"*32,32,".//Game.ini")
  raise LoadError, "Failed to load RGSS Linker." unless(@RGSS_Linker[:core].call(lib_name)==1)
  lib_name = nil
  module_function
  #===
  #>Kernel.load_module
  #  Helps to load a RGSS extension
  #---
  #I : module_filename : String : Name of the file which contains the extension
  #    module_function : String : Name of the function that will load the extension
  #===
  def load_module(module_filename, module_function)
    return if @RGSS_Linker[module_filename]
    mod = @RGSS_Linker[module_filename] = Win32API.new(module_filename, module_function, "", "")
    mod.call
  end
   
  end #>unless @RGSS_Linker
end

Audio module Script (FmodEx)
This script must be placed after the RGSS Linker script otherwise it won't work.
#===
#Audio (FmodEx)
#  A rewrite of Audio module to integrate FmodEx
#---
#© 2015 - Nuri Yuri (塗 ゆり)
#© 2015 - GiraPrimal : Concept of LOOP_TABLE
#---
#Script written by the menbers of the Community Script Project
#===
module Audio
  LOOP_TABLE = [
  # [ "Audio/xxx/File_name", begin, end ]
  # Add here

  
  # Note : Renember to add a comma after each ]
  #       (except for the last line and the below ]).
  ]
  #---
  #>Puts the file names in lowercase to improve the search
  #---
  LOOP_TABLE.each do |i| i[0].downcase! end
   
  unless @bgm_play #>To avoid the RGSSReset problem
  #===
  #>Load and initialize FmodEx
  #===
  Kernel.load_module("RGSS FmodEx.dll","Init_FmodEx")
  ::FmodEx.init(32)
  #---
  #>Indication of the default lib'
  #---
  @library = ::FmodEx
  #---
  #>Saving the RGSS functions
  #---
  @bgm_play = method(:bgm_play)
  @bgm_fade = method(:bgm_fade)
  @bgm_stop = method(:bgm_stop)
  @bgs_play = method(:bgs_play)
  @bgs_fade = method(:bgs_fade)
  @bgs_stop = method(:bgs_stop)
  @me_play = method(:me_play)
  @me_fade = method(:me_fade)
  @me_stop = method(:me_stop)
  @se_play = method(:se_play)
  @se_stop = method(:se_stop)
  #---
  #>Volumes definition
  #---
  @master_volume = 100
  @sfx_volume = 100
  #===
  #>Extensions supported by FmodEx
  #===
  EXT = ['.ogg', '.mp3', '.wav', '.mid', '.aac', '.wma', '.it', '.xm', '.mod', '.s3m', '.midi']
  #===
  #>Creation/definition of the functions
  #===
  module_function
  def bgm_play(file_name, volume = 100, pitch = 100)
    volume = volume * @master_volume / 100
    return @bgm_play.call(file_name, volume, pitch) if(@library != ::FmodEx)
    filename = check_file(file_name)
    bgm = ::FmodEx.bgm_play(filename, volume, pitch)
    loop_audio(bgm, file_name)
  end
  def bgm_fade(time)
    return @bgm_fade.call(time) if(@library != ::FmodEx)
    ::FmodEx.bgm_fade(time)
  end
  def bgm_stop
    return @bgm_stop.call if(@library != ::FmodEx)
    ::FmodEx.bgm_stop
  end
  def bgs_play(file_name, volume = 100, pitch = 100)
    volume = volume * @sfx_volume / 100
    return @bgs_play.call(file_name, volume, pitch) if(@library != ::FmodEx)
    filename = check_file(file_name)
    bgs = ::FmodEx.bgs_play(filename, volume, pitch)
    loop_audio(bgs, file_name)
  end
  def bgs_fade(time)
    return @bgs_fade.call(time) if(@library != ::FmodEx)
    ::FmodEx.bgs_fade(time)
  end
  def bgs_stop
    return @bgs_stop.call if(@library != ::FmodEx)
    ::FmodEx.bgs_stop
  end
  def me_play(file_name, volume = 100, pitch = 100)
    volume = volume * @master_volume / 100
    return @me_play.call(file_name, volume, pitch) if(@library != ::FmodEx)
    file_name = check_file(file_name)
    ::FmodEx.me_play(file_name, volume, pitch)
  end
  def me_fade(time)
    return @me_fade.call(time) if(@library != ::FmodEx)
    ::FmodEx.me_fade(time)
  end
  def me_stop
    return @me_stop.call if(@library != ::FmodEx)
    ::FmodEx.me_stop
  end
  def se_play(file_name, volume = 100, pitch = 100)
    volume = volume * @sfx_volume / 100
    return @se_play.call(file_name, volume, pitch) if(@library != ::FmodEx)
    file_name = check_file(file_name)
    ::FmodEx.se_play(file_name, volume, pitch)
  end
  def se_stop
    return @se_stop.call if(@library != ::FmodEx)
    ::FmodEx.se_stop
  end
  #===
  #>check_file
  #  Check the presence of the file and return the filename
  #  /!\ Doesn't correct the mistake
  #====
  def check_file(file_name)
    return file_name if File.exist?(file_name)
    EXT.each do |ext|
      filename = file_name+ext
      return filename if File.exist?(filename)
    end
    return file_name
  end
  #===
  #>loop_audio
  # Function that automatically call the set_loop_points
  #===
  def loop_audio(sound, file_name)
    filename = file_name.downcase
    LOOP_TABLE.each do |i|
      if(i[0] == filename)
        return sound.set_loop_points(i[1], i[2])
      end
    end
  end
  end
end
Note : The begin and end contained in LOOP_TABLE must be in milliseconds. They apply only for the BGM and BGS.

FmodEx::Sound methods
Here are the methods of the FmodEx::Sound class.
At the exception of initialize, the following methods can return nil.
Think check if the result is not nil before using them in calculations.

You can create a sound independently of the BGM, BGS, ME and SE by using the "new" method of FmodEx::Sound (with the arguments of the initialize method).
initialize(filename, volume = 100, pitch = 100, position = 0, looping = true, streaming = true, *args)
Initialize a sound.
Arguments : filename, volume, pitch, position, looping, streaming, memory_data, dls_file_name
Optional from volume (include)
If the position is less than 0, sound will initially paused.
memory_data corresponds at a string/channel who contains the file data.
dls_file_name is the name of the dls file used to read the midis.

stop
Stop the sound (automatically release the channel and the sound)
Return true if the stop was made, false if stop isn't possible.
Raise a FmodEx::Error exception if FmodEx fails and no Fade Thread is associated with sound.

fade(time_ms)
Fade out of a sound.
The user indicate the time in milliseconds.
Return true if the sound fade was triggered, false if not.

pause(pause_state)
Pausing a sound.
The user indicates if he wants the sound to be paused (true) or played (false).
Returns requested pause status, or nil if it is not possible.
Raises a FmodEx :: Error exception if FmodEx can not paused the sound.

paused?
Retrieve the "pause" status of a sound.
Return true if the sound is in pause, false if not.
Raise a FmodEx::Error exception if FmodEx cannot retrieve the status.

set_loop_points(begin_pt, end_pt)
Indicate the loop points of the sound.
If the sound is looped, the user can indicate the begin and end of the loop in milliseconds.
Returns true if this was done, nil if this is not possible.
Raise a FmodEx::Error exception if FmodEx cannot save the loop points.

set_looping(state)
Indicate the loop possibility.
The user indicates if he wants the sound is looped (true) or not (false)
Returns the requested status, nil if is not possible.
Raise a FmodEx::Error exception if FmodEx cannot modify the sound status.

looping?
Return if the sound is looped or not.
Raise a FmodEx::Error exception if FmodEx cannot retrieve the status.

set_position(position_ms)
Indicates the playing position of a sound.
The user indicate the playing position in milliseconds.
Return the requested position if it cannot save.
Raise a FmodEx::Error exception if FmodEx cannot modify the position.

get_position
Return the actual position of the sound playing.
Raise a FmodEx::Error exception if FmodEx fails.

set_volume(volume)
Indication of sound volume.
The user indicates the desired volume between 0 and 100.
Returns the requested volume if realized.
Raise a FmodEx::Error exception if FmodEx fails.

get_volume
Returns the sound volume.
Raise a FmodEx::Error exception if FmodEx cannot retrieve the volume.

set_frequency(frequency)
Indicate the sound frequency.
Return the indicated frequency if it was realized.
Raise a FmodEx::Error exception if FmodEx cannot change the sound frequency.

get_frequency
Retrieve the sound frequency .
Raise a FmodEx::Error exception if FmodEx cannot retrieve the sound playing frequency.

set_pan(pan)
Indicates the sound pan (-100 = Left, 0 = Center, 100 = right)
Return the requested value.
Raise a FmodEx::Error exception if FmodEx cannot modify the pan.

get_pan
Retrieve sound pan.
Raise a FmodEx::Error exception if FmodEx cannot retrieve the pan.

playing?
Is FmodEx currently playing the sound ?
Return true if is the case.
Raise a FmodEx::Error exception if FmodEx cannot know what it does of the sound.

length
Retrieve the sound temporal length in milliseconds.
Raise a FmodEx::Error exception if FmodEx cannot retrieve the sound length.

FmodEx module methods

FmodEx.init(nb_of_channels)
FmodEx initialisation.
nb_of_channels indicate the desired number of channels.
Return true if is succeed, false if already initialized.
Raise a FmodEx::Error exception if FmodEx fails in its task.

FmodEx.bgm_play(filename, volume = 100, pitch = 100, streaming = true, *args)
Play a ME.
Returns the ME sound playing.
Arguments : filename [,volume [, pitch [, streaming [, memory [, dls]]]]]
memory is the string that contain the file in RAM.
dls_file_name is the name of the dls file used to read the midis.

FmodEx.bgm_stop
Stop a BGM.

FmodEx.bgm_fade(time_ms)
Fade the BGM out.
time_ms is the fade out time in milliseconds.

FmodEx.bgm_sound
Retrieve the object FmodEx::Sound of BGM.
Can be nil if no BGM is played.

FmodEx.bgs_play(filename, volume = 100, pitch = 100, streaming = true, *args)
Play a BGS.
Returns the BGS sound playing.
Arguments : filename [,volume [, pitch [, streaming [, memory [, dls]]]]]
memory is the string that contain the file in RAM.
dls_file_name is the name of the dls file used to read the midis.

FmodEx.bgs_stop
Stop a BGS.

FmodEx.bgs_fade(time_ms)
Fade the BGS out.
time_ms is the fade out time in milliseconds.

FmodEx.bgs_sound(filename, volume = 100, pitch = 100, streaming = true, *args)
Retrieve the object FmodEx::Sound of BGS.
Can be nil if no BGS is played.

FmodEx.me_play
Play a ME.
Returns the ME sound.
Arguments : filename [,volume [, pitch [, streaming [, memory [, dls]]]]]
memory is the string that contain the file in RAM.
dls_file_name is the name of the dls file used to read the midis.

FmodEx.me_stop
Stop a ME.

FmodEx.fade_out(time_ms)
Fade the ME out.
time_ms is the fade out time in milliseconds.

FmodEx.me_sound
Retrieve the object FmodEx::Sound of ME.
Can be nil if no ME is played.

FmodEx.se_play(filename, volume = 100, pitch = 100, streaming = true, *args)
Play a SE.
Returns the SE sound.
Arguments : filename [,volume [, pitch [, streaming [, memory [, dls]]]]]
memory is the string that contain the file in RAM.
dls_file_name is the name of the dls file used to read the midis.

FmodEx.se_stop
Stops the SE.

Credits
FIRELIGHT TECHNOLOGIES PTY LTD. - FMOD Ex API
Enterbrain - RGSS
Nuri Yuri - RGSS Linker, RGSS FmodEx, Audio (FmodEx)
GiraPrimal - LOOP_TABLE


Voilà, I think that the thing is complete, if you want use the RGSS linker, follow this link : https://github.com/NuriYuri/RGSS-Linker
Original topic : https://pokemonworkshop.com/forum/index.php?topic=542.msg8417#msg8417
Translator :
KaiserYoshi
(He asked to post this script here :p)

塗 ゆり

Scripter / RGSS Modder

Age 26
Non-binary
France
Seen 10 Hours Ago
Posted 1 Week Ago
107 posts
9.1 Years
@KillerMapper : KaiserYoshi tried and said it worked (that's why he asked me to post that here ^^)
Édit : J'ai fait un test sur Essentials et ...... ça marche !!!! Mille mercis !!! (Je peux poster cette méthode sur le forum d'Essentials ?)
I tried with PSP and Pokémon SDK, it worked ^^ (It's made to work with RMXP projet that use RGSS104E.dll and the normal Audio module).
There's probably a little adaptation to do if I remember there's a volume setting in Essentials so the Audio module is probably overwritten somewhere.

@Franzo : Don't put the ".ogg" at the end of the file and the Audio module will find the file itself ^^
The LOOPLENGTH and LOOPSTART tag will be considered for anyformat as long as you set a number that fit in a "long" and that the numer is in "Sample".

KillerMapper

Helix Follower

Male
Paris
Seen August 27th, 2018
Posted January 1st, 2017
200 posts
5.7 Years
Ok tried it and works perfectly. Finally.

I just had a problem with RGSS104E.dll, since I use RPG Maker 1.02 the game will always look for RGSS102E.dll (and Game.ini always resets the value Library to RGSS102E.dll when saving my project). I just renamed RGSS104E.dll to RGSS102E.dll, I hope it won't mess somewhere.
Praise Helix.

Erassus

Hunter

Age 29
Male
Chile
Seen January 22nd, 2017
Posted January 2nd, 2017
50 posts
5.3 Years
Works like a charm!

However, what do you recommended?

MP3 or OGG files to loop?

Ogg files are perfect to save space in the project and also the tag loop is a plus, but i was wondering is there any noticeable quality between 128kbps to 256/320 kbps? and MP3?

Other question, it seems the audio files above 10mb, RPG maker XP taken one or two seconds to initialize in the battles (with o without fmod). If is not, i'm hallucinating.

Thanks for the script, i hope the ME sounds can be looped, is the only thing missing to make Fmod perfect.

KillerMapper

Helix Follower

Male
Paris
Seen August 27th, 2018
Posted January 1st, 2017
200 posts
5.7 Years
I tried looped ME (the ones when a trainer spots you) and it didn't work. I had to replace them by BGMs (and restore manually the map BGM in each event since I don't know in the scripts how to get the current map BGM).

I think OGG is better than MP3, for quality, disk usage and license (ogg is free-use while mp3 is proprietary format). MP3 is only used because everybody call the musics "MP3", but OGG deserves to replace it IMO.
Praise Helix.

塗 ゆり

Scripter / RGSS Modder

Age 26
Non-binary
France
Seen 10 Hours Ago
Posted 1 Week Ago
107 posts
9.1 Years
@KillerMapper : Did you tried this :
FmodEx.me_play("Audio/ME/filename.ogg").set_looping(true)
?
FmodEx.me_play automatically unloop ME because it's supposed to pause BGM while playing. (It's better to pause BGM FmodEx.bgm_sound.pause and play a new sound
@tmp_sound = FmodEx::Sound.new("Audio/ME/filename.ogg")
and stop it before launching the battle @tmp_sound.stop)

@Erassus : Even if the File weight more than 10 MB FmodEx plays it instantly (because it's played in streaming).
Proof : https://www.youtube.com/watch?v=HDC8ZRVjt1c&feature=youtu.be

For the audio quality, there's a huge difference between 128kbps and 256kbps, 128kbps is mukty has psyduck, 256kbps is acceptable, 192kbps is the minimum acceptable ^^
For the difference between OGG and MP3 I don't really know and to be frank I don't care as long as I can listen to the music x)

If you're affraid of the weight, you can make two version of your Audio folder. One in 192kpbs, one in 320kpbs and let the player choose (before download or in a separate download) the quality of the Audio for its own playing experience :3

Erassus

Hunter

Age 29
Male
Chile
Seen January 22nd, 2017
Posted January 2nd, 2017
50 posts
5.3 Years
I found a weird thing.

The script works well with trainer BGM's and map BGM's, all fine.

But with Wild pokemons, doesnt work, i fixed that adding the ".ogg" extension in the LOOP_TABLE of the script, and making sure in the Metadata.txt of Pokemon Essentials have the extension as well.

However, the other lines added in the table, doesnt have the extension of the music file (trainers and maps) and works well, only for wild battle pokemon is needed the extension.

Not sure is a bug or not, but is a little detail.

Edit: I derped.

Because, this happen if you have tipped in Metadata "WildBattleBGM=example.ogg"

and in the Loop table without extension.

Nevermind, thanks!

Edit2: This also happens in TrainerTypes.txt - For others, make sure the filename with or without extension is the same in loop table.


Edit3: (i found what was causing my problem) For anyone who is making files with the exact miliseconds end for the loop part.

Example Loop wanted: 12980, 63497

make sure the file have 64000 or 65000 of length, otherwise, doesnt work if the file have 63497 same as when the loop end.
Age 26
Male
Brisbane, Australia
Seen June 19th, 2019
Posted May 31st, 2015
495 posts
12.7 Years
Normal map BGM works perfectly, but anything in PBS/metadata keeps throwing me a "file not found" error from fmod.
I tried adding the entry to the file in the fmod table, still nothing.

Current file I'm trying to test is an .ogg named "Wild Pokémon" (with the 'é'). In both metadata and fmod table I've tried with and without the file extension, still "file not found".

塗 ゆり

Scripter / RGSS Modder

Age 26
Non-binary
France
Seen 10 Hours Ago
Posted 1 Week Ago
107 posts
9.1 Years
Oh, that's normal, non-ASCII in filename are illegal for a specific reason :
The Filesystem has its own encoding, if you use non-ASCII characters you have a chance that the source encoding and the destination encoding aren't compatible. It happens with the RGSS when the player use a Chinese, Japanese or Arab language setting on its computer.

Just rename the file "Wild_Pokemon.ogg" and it'll work :p
I'll search if there's an API that helps to detect the File System encoding and I'll do a "MultiByteToWideChar" call to find the file ^^ (if FmodEx takes the filename as it).


Edit : I've updated the RGSS FmodEx.dll file, now it seems to take filenames with "é" and other non-ASCII characters.
Files : http://www.mediafire.com/download/jrlci7hwh5z0zhe/Fichiers+DLL+FmodEX.zip
Male
Seen August 3rd, 2015
Posted July 31st, 2015
3 posts
4.8 Years
Hello! I've been trying to get music looping using your script and I just can't get it to work. Initially, I wasn't even able get the music file to appear in the debug menu (and I still can't) and while I was able to get it to appear once I converted it to a different format (.ogg to .mp3), that's unrelated to your script. I tried setting the loop points using both the LOOPSTART and LOOPLENGTH metadata tags and the script's loop table and neither get the file to loop. Is there something else I need to do in order for it to loop?

Thank you in advance.

塗 ゆり

Scripter / RGSS Modder

Age 26
Non-binary
France
Seen 10 Hours Ago
Posted 1 Week Ago
107 posts
9.1 Years
@Juka15 : Screen of the line 10 in your script '^' ?
@The12thGripper : Use the OGG format, I don't know why it can't read metatag of MP3 '^'
Btw the LOOPLENGTH is the length of the loop not the end of the loop.

@lolandbeer : You'll never be able to loop an ME because ME aren't supposed to loop. Use a BGM instead.
Male
Seen August 3rd, 2015
Posted July 31st, 2015
3 posts
4.8 Years
@The12thGripper : Use the OGG format, I don't know why it can't read metatag of MP3 '^'
I've tried that but it doesn't appear in the debug menu (and the PokéGear) nor does it loop in the sound test. I've gotten the file to loop in VX Ace so it's definitely something with FmodEx. I'll trying doing everything from scratch when I'm able to though.

Derxwna Kapsyla

Derxwna "The Badman" Kapsyla

Age 27
Male
Everywhere, yet Nowhere
Seen 1 Day Ago
Posted 3 Days Ago
405 posts
9 Years
I've tried that but it doesn't appear in the debug menu (and the PokéGear) nor does it loop in the sound test. I've gotten the file to loop in VX Ace so it's definitely something with FmodEx. I'll trying doing everything from scratch when I'm able to though.
The reason why it doesn't appear in the Jukebox or Debug Menu related areas is because Essentials does not have it set to display .ogg files by default. This can be easily fixed by modifying the arrays that those lists depend on to add ".OGG" and ".ogg" to them.

This is what the Jukebox section would look like, pre-edit, within the PokemonJukebox script section on Pre-v15 builds:
        when 3
          files=[_INTL("(Default)")]
          Dir.chdir("Audio/BGM/"){
             Dir.glob("*.mp3"){|f| files.push(f) }
             Dir.glob("*.MP3"){|f| files.push(f) }
             Dir.glob("*.mid"){|f| files.push(f) }
             Dir.glob("*.MID"){|f| files.push(f) }     
          }
What you'll want to do is this, I've italicized and underline the lines you need to add:
        when 3
          files=[_INTL("(Default)")]
          Dir.chdir("Audio/BGM/"){
             Dir.glob("*.mp3"){|f| files.push(f) }
             Dir.glob("*.MP3"){|f| files.push(f) }
             Dir.glob("*.mid"){|f| files.push(f) }
             Dir.glob("*.MID"){|f| files.push(f) }     
             Dir.glob("*.ogg"){|f| files.push(f) }
             Dir.glob("*.OGG"){|f| files.push(f) }             
          }
This will fix ogg files not showing up in the Jukebox, but it will not fix files not showing up in the Debug menus. You'll need to do a similar method for that. Just do a Ctrl+Shift+F search for ".MP3", with the Match Case option on. You'll be where you need to be. The Editor requires a little more work, since you have to rename EditorScripts.rxdata to be Scripts.rxdata (Make sure you backup your Scripts.rxdata first! You do NOT want to lose that!). Then it'll be editable from within RPG Maker. When all is said and done, rename it back to EditorScripts.rxdata, restore your original Scripts.rxdata, and viola - Your External Editor, Debug Menus, and Jukebox will now be able to read and identify .ogg files.

As for why it doesn't loop within the Sound Test option, that's because scripts in the game don't do anything outside the game. .ogg files don't have proper RMXP support, and as such they don't loop normally, even within the Sound Test.
-----------------------------------------------------
Development Blog:
For more information, future news, and updates to any projects, the following blogs are where I post information. You can usually hit me with a message there when it comes to bug reports or feedback, or general conversation about something.
Game Projects:
In Progress:
Male
Seen August 3rd, 2015
Posted July 31st, 2015
3 posts
4.8 Years
The reason why it doesn't appear in the Jukebox or Debug Menu related areas is because Essentials does not have it set to display .ogg files by default. This can be easily fixed by modifying the arrays that those lists depend on to add ".OGG" and ".ogg" to them.

This is what the Jukebox section would look like, pre-edit, within the PokemonJukebox script section on Pre-v15 builds:
        when 3
          files=[_INTL("(Default)")]
          Dir.chdir("Audio/BGM/"){
             Dir.glob("*.mp3"){|f| files.push(f) }
             Dir.glob("*.MP3"){|f| files.push(f) }
             Dir.glob("*.mid"){|f| files.push(f) }
             Dir.glob("*.MID"){|f| files.push(f) }     
          }
What you'll want to do is this, I've italicized and underline the lines you need to add:
        when 3
          files=[_INTL("(Default)")]
          Dir.chdir("Audio/BGM/"){
             Dir.glob("*.mp3"){|f| files.push(f) }
             Dir.glob("*.MP3"){|f| files.push(f) }
             Dir.glob("*.mid"){|f| files.push(f) }
             Dir.glob("*.MID"){|f| files.push(f) }     
             Dir.glob("*.ogg"){|f| files.push(f) }
             Dir.glob("*.OGG"){|f| files.push(f) }             
          }
This will fix ogg files not showing up in the Jukebox, but it will not fix files not showing up in the Debug menus. You'll need to do a similar method for that. Just do a Ctrl+Shift+F search for ".MP3", with the Match Case option on. You'll be where you need to be. The Editor requires a little more work, since you have to rename EditorScripts.rxdata to be Scripts.rxdata (Make sure you backup your Scripts.rxdata first! You do NOT want to lose that!). Then it'll be editable from within RPG Maker. When all is said and done, rename it back to EditorScripts.rxdata, restore your original Scripts.rxdata, and viola - Your External Editor, Debug Menus, and Jukebox will now be able to read and identify .ogg files.

As for why it doesn't loop within the Sound Test option, that's because scripts in the game don't do anything outside the game. .ogg files don't have proper RMXP support, and as such they don't loop normally, even within the Sound Test.
Oh wow, thank you! I couldn't find anything when I looked up why .ogg files weren't appearing in the Debug menu and none of my friends could tell me why either so seriously, thank you so much! I'll be giving this a shot now.

My apologies, but the script don't work on my project. See the error:

You know why this error happened?
Because I just Copy and Paste above the Main Script. I am make something wrong.
Can you help me about this error?
EDIT: I'm now having this error. I didn't change any of the scripts and I was able to get it to run before so I have no idea what's wrong.

EDIT 2: If you're having the issue above, try coping and pasting the scripts using the "printer-friendly" version of the page. It fixed the problem for me.