class ZXUtils::MusicBox::Song::SongModule
MusicBox
Song
SongModule
¶ ↑
An instance of this class can be created by calling Song.to_module
instance method of the compiled song.
The instance of this class can produce an instance of PlayerModule
or a Z80::Program
.
Example:
require 'zxutils/ay_music' require 'zxlib/basic' require_relative 'examples/test_music' class Music include Z80 include Z80::TAP include ZXUtils MusicData = TestMusic.new.to_program macro_import MathInt macro_import Utils::SinCos import ZXLib::Sys, macros: true macro_import ZXLib::AYSound macro_import AYMusic with_saved :start, :exx, hl, ret: :after_ei do call make_sincos ay_expand_notes( music.notes, octaves:8 ) ay_music_tone_progress_table_factory( music.fine_tones ) ay_music_note_to_fine_tone_cursor_table_factory( music.note_to_cursor, play: music.play ) di call music.init dw track_a, track_b, track_c forever ei halt di push iy call music.play pop iy key_pressed? jr Z, forever ay_init end make_sincos create_sincos_from_sintable music.sincos, sintable:sintable sintable bytes neg_sintable256_pi_half_no_zero_lo song import MusicData song_end label import AYMusic, :music, override: { index_table: index_table } music_end label NOTES = ay_tone_periods(min_octave:0, max_octave:0) dw NOTES[11]*2 notes dw NOTES end music = Music.new 0x8000 puts music.debug program = ZXLib::Basic.parse_source <<-EOC 10 RANDOMIZE USR #{music[:start]} 9998 STOP: GO TO 10 9999 CLEAR #{music.org-1}: LOAD ""CODE: RUN EOC puts program.to_source escape_keywords: true program.save_tap "music", line: 9999 music.save_tap "music", append: true Z80::TAP.parse_file('music.tap') do |hb| puts hb.to_s end
Attributes
A compiled song module body as a binary string.
An array containing descriptors of each of the indexed items.
An array containing offset ranges determining the position within the SongModule.code
each of the indexed items.
An array containing offset ranges determining the position within the SongModule.code
each of the three channel tracks.
Public Instance Methods
Returns an instance of the PlayerModule
from the compiled SongModule
instance.
# File lib/zxutils/music_box/song.rb, line 345 def to_player_module PlayerModule.new(*@track_offsets.map(&:first), @index_offsets.map(&:first), @code) end
Returns an ad-hoc Z80::Program
class containing the compiled SongModule
.
The returned program exports the following labels:
-
track_a
-
track_b
-
track_c
-
index_table
That can be passed to the the ZXUtils::AYMusic
engine. For the complete example, see SongModule
.
Additionally these label namespaces are also being exported:
-
track
-
instrument
-
envelope
-
chord
-
mask
And each song's item is being sub-labeled in the according namespaces, so you can identify them in the debug
output or use it for some other purpose.
# File lib/zxutils/music_box/song.rb, line 367 def to_program code = @code track_offsets = @track_offsets index_offsets = @index_offsets index_items = @index_items index_labels = Array.new(index_offsets.length) Class.new do include Z80 include Z80::TAP export :auto track_a data code.slice(track_offsets[0]) track_b data code.slice(track_offsets[1]) track_c data code.slice(track_offsets[2]) index_items.zip(index_offsets). sort_by {|item, _| "#{item.type}.#{item.name}"}. chunk {|item, _| item.type}. each do |type, items| isolate type do items.each do |item, offsets| index_labels[item.index - 1] = define_label item.name, data(code.slice(offsets)) end end end raise "sanity error" if index_labels.length != index_offsets.length or index_labels.any?(&:nil?) index_table words index_labels end end