KSoundFontMenu - kyonides - 05-24-2024
KSoundFontMenu
HiddenChest Exclusive!
XP + VX + ACE Related
by Kyonides
This scriptlet allows you to actually play a specific MIDI melody AND change the current synthesizer's SoundFont!
All of these scripts will only work by running the HiddenChest binary executable.
There are certain consideration to take in consideration before using it:
- The MIDI file should be playing BEFORE you proceed to call Setup.choose_soundfont(index)
Otherwise the change would be ignored by the internal system.
- Some scenes might take advantage of setting the current soundfont again, no filename change involved here, to make sure it will be using the selected soundfont.
Yet, it is not mandatory because this apparent issue could have been caused by using some soundfonts with similar sound sets.
- The change may take a couple of seconds to take effect.
That is why I added the "Processing New SF..." label to the KSoundFont module.
Extra Step
Add the following lines to your Game.ini file:
Code: SoundFontWin=C:/Audio/SF2/GMGSx.sf2
SoundFontLnx=/home/user/Maker/GMGSx.sf2
SoundFontPathWin=C:/Music/SF2
SoundFontPathLnx=/home/user/Music/SF2
These lines will allow the HiddenChest engine find your custom SoundFonts on both Windows & Linux!
Keep in mind that HiddenChest has always been a cross-platform engine.
Script Calls
Open the KSoundFont::Menu Scene depending on your RM Editor:
Code: $scene = KSoundFont::Menu.new
SceneManager(KSoundFont::Menu)
Select Your Favorite SoundFont - All Versions:
Code: Game.choose_soundfont(index)
Getting and Saving the Index of Your Favorite SoundFont
Code: $game_system.soundfont_index
$game_system.soundfont_index = Number
Getting a SoundFont (Full Path) Based on its Current Position:
Code: Game.soundfonts[index]
Default SoundFont (if it Exists):
Default SoundFont Directory (It Should Exist if you ever pretend to add 2+ SoundFonts):
Code: System::SOUNDFONT_DIR
Scripts Section
Script For RMXP Editor
Code: # * KSoundFontMenu XP * #
# Scripter : Kyonides Arkanthes
# 2024-06-03
# Note: It seems like the MIDI file should be playing BEFORE you proceed to call
# Game.choose_soundfont while loading a save game. Otherwise, the MIDI
# synthetizer might ignore your request at that specific point.
# Calling the same method at the beginning of KSoundFont::Menu ensures it
# will always play the MIDI using the chosen soundfont.
# * Script Call * #
# $scene = KSoundFont::Menu.new
module KSoundFont
START_SF = [0]
TITLE = "Select a SoundFont"
THIS_SOUNDFONT = "Current SoundFont"
DELAY_MESSAGE = "Processing New SF..."
NO_SOUNDFONT = "No SoundFont"
TRANSPARENT = Color.new(0, 0, 0, 0)
class PathsWindow < Window_Command
def initialize(w, paths)
@paths = paths
commands = paths.map {|fn| fn.split(/[\/|\\]/)[-1].sub(".sf2", "") }
super(w, commands)
end
def path
@paths[@index]
end
def name
@commands[@index]
end
end
class SmallInfoWindow < Window_Base
def initialize(wx, wy, w, h)
super
self.contents = Bitmap.new(w - 32, h - 32)
contents.font.color = system_color
contents.draw_text(0, 0, w - 32, 32, THIS_SOUNDFONT, 1)
contents.font.color = normal_color
end
def set_text(text)
contents.fill_rect(0, 32, width - 32, 32, TRANSPARENT)
contents.draw_text(0, 32, width - 32, 32, text, 1)
end
end
class Menu
def main
@timer = 0
pos = $game_system.soundfont_index
Game.choose_soundfont(pos)
soundfonts = Game.soundfonts
gs_indexes = $game_system.soundfont_indexes
if gs_indexes.any?
@indexes = gs_indexes.sort
if @indexes.size < soundfonts.size
soundfonts = @indexes.map{|n| soundfonts[n] }
end
end
@total = soundfonts.size
@full_list = Game.soundfonts.size == @total
soundfont = soundfonts[pos]
dialog_box soundfont
if soundfonts.any?
soundfont = soundfont.split(/[\/|\\]/)[-1].sub(".sf2", "")
else
soundfont = NO_SOUNDFONT
end
@help_window = Window_Help.new
@help_window.set_text(TITLE, 1)
@command_window = PathsWindow.new(192, soundfonts)
@command_window.y = 64
@command_window.index = pos
@info_window = SmallInfoWindow.new(192, @command_window.y, 240, 96)
@info_window.set_text(soundfont)
Graphics.transition
loop do
Graphics.update
Input.update
update
break if $scene != self
end
Graphics.freeze
@info_window.dispose
@command_window.dispose
@help_window.dispose
end
def update
if @timer > 0
@timer -= 1
if @timer == 0
@info_window.set_text(@command_window.name)
end
return
end
@command_window.update
if Input.trigger?(Input::B) or Input.double_right_click?
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
return
elsif Input.trigger?(Input::C) or Input.double_left_click?
if @total < 2
$game_system.se_play($data_system.buzzer_se)
return
end
$game_system.se_play($data_system.decision_se)
n = @command_window.index
n = @indexes[n] unless @full_list
$game_system.soundfont_index = n
@info_window.set_text(DELAY_MESSAGE)
@timer = Graphics.frame_rate * 2
elsif Input.trigger?(Input::SHIFT)
$game_system.se_play($data_system.cursor_se)
Graphics.screenshot
end
end
end
end
class Game_System
alias :kyon_soundfont_menu_gm_sys_init :initialize
def initialize
kyon_soundfont_menu_gm_sys_init
self.soundfont_index = find_soundfont_index
@soundfont_indexes = KSoundFont::START_SF.dup
end
def find_soundfont_index
Game.soundfont_index || 0
end
def soundfont_index
@soundfont_index ||= find_soundfont_index
end
def soundfont_index=(n)
Game.choose_soundfont(n)
@soundfont_index = n
end
def soundfont_indexes
@soundfont_indexes ||= []
end
end
class Scene_Load
alias :kyon_soundfont_menu_scn_ld_rsd :read_save_data
def read_save_data(file)
kyon_soundfont_menu_scn_ld_rsd(file)
$game_system.bgm_play($game_system.playing_bgm)
Game.choose_soundfont($game_system.soundfont_index)
end
end
Script for RMVX Editor
Code: # * KSoundFontMenu VX * #
# Scripter : Kyonides Arkanthes
# 2024-06-03
# Note: It seems like the MIDI file should be playing BEFORE you proceed to call
# Game.choose_soundfont while loading a save game. Otherwise, the MIDI
# synthetizer might ignore your request at that specific point.
# Calling the same method at the beginning of KSoundFont::Menu ensures it
# will always play the MIDI using the chosen soundfont.
# * Script Call * #
# $scene = KSoundFont::Menu.new
module KSoundFont
START_SF = [0]
TITLE = "Select a SoundFont"
THIS_SOUNDFONT = "Current SoundFont"
DELAY_MESSAGE = "Processing New SF..."
NO_SOUNDFONT = "No SoundFont"
TRANSPARENT = Color.new(0, 0, 0, 0)
class PathsWindow < Window_Command
def initialize(w, paths)
@paths = paths
commands = paths.map {|fn| fn.split(/[\/|\\]/)[-1].sub(".sf2", "") }
super(w, commands)
end
def path
@paths[@index]
end
def name
@commands[@index]
end
end
class SmallInfoWindow < Window_Base
def initialize(wx, wy, w, h)
super
self.contents = Bitmap.new(w - 32, h - 32)
contents.font.color = system_color
contents.draw_text(0, 0, w - 32, 32, THIS_SOUNDFONT, 1)
contents.font.color = normal_color
end
def set_text(text)
contents.fill_rect(0, 32, width - 32, 32, TRANSPARENT)
contents.draw_text(0, 32, width - 32, 32, text, 1)
end
end
class Menu
def main
@timer = 0
pos = $game_system.soundfont_index
Game.choose_soundfont(pos)
soundfonts = Game.soundfonts
gs_indexes = $game_system.soundfont_indexes
if gs_indexes.any?
@indexes = gs_indexes.sort
if @indexes.size < soundfonts.size
soundfonts = @indexes.map{|n| soundfonts[n] }
end
end
@total = soundfonts.size
@full_list = Game.soundfonts.size == @total
soundfont = soundfonts[pos]
if soundfonts.any?
soundfont = soundfont.split(/[\/|\\]/)[-1].sub(".sf2", "")
else
soundfont = NO_SOUNDFONT
end
@help_window = Window_Help.new
@help_window.set_text(TITLE, 1)
hwy = @help_window.height
@command_window = PathsWindow.new(192, soundfonts)
@command_window.y = hwy
@command_window.index = pos
@info_window = SmallInfoWindow.new(192, hwy, 240, 96)
@info_window.set_text(soundfont)
Graphics.transition
loop do
Graphics.update
Input.update
update
break if $scene != self
end
Graphics.freeze
@info_window.dispose
@command_window.dispose
@help_window.dispose
end
def update
if @timer > 0
@timer -= 1
if @timer == 0
@info_window.set_text(@command_window.name)
end
return
end
@command_window.update
if Input.trigger?(Input::B) or Input.double_right_click?
Sound.play_cancel
$scene = Scene_Map.new
return
elsif Input.trigger?(Input::C) or Input.double_left_click?
return Sound.play_buzzer if @total < 2
Sound.play_decision
n = @command_window.index
n = @indexes[n] unless @full_list
$game_system.soundfont_index = n
@info_window.set_text(DELAY_MESSAGE)
@timer = Graphics.frame_rate * 2
elsif Input.trigger?(Input::SHIFT)
Sound.play_cursor
Graphics.screenshot
end
end
end
end
class Game_System
alias :kyon_soundfont_menu_gm_sys_init :initialize
def initialize
kyon_soundfont_menu_gm_sys_init
self.soundfont_index = find_soundfont_index
@soundfont_indexes = KSoundFont::START_SF.dup
end
def find_soundfont_index
Game.soundfont_index || 0
end
def soundfont_index
@soundfont_index ||= find_soundfont_index
end
def soundfont_index=(n)
Game.choose_soundfont(n)
@soundfont_index = n
end
def soundfont_indexes
@soundfont_indexes ||= []
end
end
class Scene_File
alias :kyon_soundfont_menu_scn_fl_rsd :read_save_data
def read_save_data(file)
kyon_soundfont_menu_scn_fl_rsd(file)
@last_bgm.play
Game.choose_soundfont($game_system.soundfont_index)
end
end
Script for RMVX ACE Editor
Code: # * KSoundFontMenu ACE * #
# Scripter : Kyonides Arkanthes
# 2024-06-03
# Note: It seems like the MIDI file should be playing BEFORE you proceed to call
# Game.choose_soundfont while loading a save game. Otherwise, the MIDI
# synthetizer might ignore your request at that specific point.
# Calling the same method at the beginning of KSoundFont::Menu ensures it
# will always play the MIDI using the chosen soundfont.
# * Script Call * #
# SceneManager(KSoundFont::Menu)
module KSoundFont
START_SF = [0]
TITLE = "Select a SoundFont"
THIS_SOUNDFONT = "Current SoundFont"
DELAY_MESSAGE = "Processing New SF..."
NO_SOUNDFONT = "No SoundFont"
TRANSPARENT = Color.new(0, 0, 0, 0)
class HelpWindow < Window_Help
def set_text(text, align)
return if text == @text and align == @align
@text = text
@align = align
refresh
end
def refresh
contents.clear
draw_text(contents.rect, @text, @align)
end
end
class PathsWindow < Window_Selectable
def initialize(w, paths)
@paths = paths
@commands = paths.map {|fn| fn.split(/[\/|\\]/)[-1].sub(".sf2", "") }
@item_max = @commands.size
h = @item_max * line_height + line_height
super(0, 0, w, h)
return if @item_max == 0
refresh
self.active = true
end
def draw_all_items
@item_max.times do |n|
rect = @area[n] ||= item_rect_for_text(n)
draw_text(rect, @commands[n])
end
end
def process_handling
end
def path
@paths[@index]
end
def name
@commands[@index]
end
attr_reader :item_max
end
class SmallInfoWindow < Window_Base
def initialize(wx, wy, w, h)
super
self.contents = Bitmap.new(w - 32, h - 32)
contents.font.color = system_color
contents.draw_text(0, 0, w - 32, 32, THIS_SOUNDFONT, 1)
contents.font.color = normal_color
end
def set_text(text)
contents.fill_rect(0, 32, width - 32, 32, TRANSPARENT)
contents.draw_text(0, 32, width - 32, 32, text, 1)
end
end
class Menu < Scene_Base
def start
super
@timer = 0
pos = $game_system.soundfont_index
Game.choose_soundfont(pos)
soundfonts = Game.soundfonts
gs_indexes = $game_system.soundfont_indexes
if gs_indexes.any?
@indexes = gs_indexes.sort
if @indexes.size < soundfonts.size
soundfonts = @indexes.map{|n| soundfonts[n] }
end
end
@total = soundfonts.size
@full_list = Game.soundfonts.size == @total
soundfont = soundfonts[pos]
if soundfonts.any?
soundfont = soundfont.split(/[\/|\\]/)[-1].sub(".sf2", "")
else
soundfont = NO_SOUNDFONT
end
@help_window = HelpWindow.new
@help_window.set_text(TITLE, 1)
hwy = @help_window.height
@command_window = PathsWindow.new(192, soundfonts)
@command_window.y = hwy
@command_window.index = pos
@info_window = SmallInfoWindow.new(192, hwy, 240, 96)
@info_window.set_text(soundfont)
end
def update
Graphics.update
Input.update
if @timer > 0
@timer -= 1
if @timer == 0
@info_window.set_text(@command_window.name)
end
return
end
@command_window.update
if Input.trigger?(:B) or Input.double_right_click?
Sound.play_cancel
SceneManager.return
return
elsif Input.trigger?(:C) or Input.double_left_click?
return Sound.play_buzzer if @total < 2
Sound.play_ok
n = @command_window.index
n = @indexes[n] unless @full_list
$game_system.soundfont_index = n
@info_window.set_text(DELAY_MESSAGE)
@timer = Graphics.frame_rate * 2
elsif Input.trigger?(:SHIFT)
Sound.play_cursor
Graphics.screenshot
end
end
end
end
class Game_System
alias :kyon_soundfont_menu_gm_sys_init :initialize
alias :kyon_soundfont_menu_gm_sys_on_after_load :on_after_load
def initialize
kyon_soundfont_menu_gm_sys_init
self.soundfont_index = find_soundfont_index
@soundfont_indexes = KSoundFont::START_SF.dup
end
def find_soundfont_index
Game.soundfont_index || 0
end
def soundfont_index
@soundfont_index ||= find_soundfont_index
end
def soundfont_index=(n)
Game.choose_soundfont(n)
@soundfont_index = n
end
def soundfont_indexes
@soundfont_indexes ||= []
end
def on_after_load
kyon_soundfont_menu_gm_sys_on_after_load
Game.choose_soundfont($game_system.soundfont_index)
end
end
Screenshots
Terms & Conditions
Free for any kind of game running on the HiddenChest engine.
Due credit is mandatory.
Don't post the contents of this topic anywhere else!
You better paste a link to this thread and make them come here instead.
That's it!
RE: KSoundFontMenu - kyonides - 05-27-2024
Small But Important Update
Because HiddenChest version 1.1.71 has been released for both Windows & Linux, I was in dire need of updating these scripts to replace all the old references to the deprecated Setup module. All of its methods have now been merged with the Game module's.
I have also edited the first post to reflect all of these changes.
RE: KSoundFontMenu - kyonides - 06-03-2024
Small Update
I've updated all of my scripts to make sure it will find the soundfonts as first intended. The problem was caused by not clearly defining the condition that would split the list or the default soundfont or even the last selected one.
There's also a need to tell you that you'd need to upgrade HiddenChest to version 1.1.76 or later because that's the first release that finally included a fix involving finding the SoundFontPath on both Windows & Linux.
|