Class: Musa::MIDIVoices::MIDIVoice Private
- Defined in:
- lib/musa-dsl/midi/midi-voices.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Individual MIDI channel voice with sequencer-synchronized note management.
Manages the state of a single MIDI channel including active notes, controller values, and sustain pedal. All note scheduling is tied to the sequencer clock, ensuring proper timing in fast-forward mode or during quantized playback.
Supports indefinite notes (manual note-off), automatic note-off scheduling, callbacks on note stop, and fast-forward mode for silent state updates.
Instance Attribute Summary collapse
-
#active_pitches ⇒ Array<Hash>
readonly
private
Metadata for each of the 128 MIDI pitches.
-
#channel ⇒ Integer
readonly
private
MIDI channel number (0-15).
-
#do_log ⇒ Boolean
private
Whether this voice logs every emitted message.
-
#name ⇒ String?
private
Optional name used in log messages.
-
#output ⇒ #puts?
readonly
private
MIDI destination.
-
#sequencer ⇒ Musa::Sequencer::Sequencer
readonly
private
Sequencer driving this voice.
-
#tick_duration ⇒ Rational
readonly
private
Duration (in bars) of a sequencer tick; used to schedule note offs.
Instance Method Summary collapse
-
#all_notes_off ⇒ void
private
Sends an immediate all-notes-off message on this channel and resets internal state.
-
#controller ⇒ ControllersControl
private
MIDI CC manager for this voice.
-
#fast_forward=(enabled) ⇒ void
private
Turns fast-forward on/off for this voice.
-
#fast_forward? ⇒ Boolean
private
True when in fast-forward mode (notes registered but not emitted).
-
#initialize(sequencer:, output:, channel:, name: nil, do_log: nil) ⇒ MIDIVoice
constructor
private
A new instance of MIDIVoice.
-
#log(msg) ⇒ void
private
Logs a message tagging the current voice.
-
#note(pitchvalue = nil, pitch: nil, velocity: nil, duration: nil, duration_offset: nil, note_duration: nil, velocity_off: nil) ⇒ NoteControl?
private
Plays one or several MIDI notes.
-
#sustain_pedal ⇒ Integer?
private
Current sustain pedal value.
-
#sustain_pedal=(value) ⇒ Object
private
Sets the sustain pedal state.
-
#to_s ⇒ String
private
Human-readable voice description.
Constructor Details
#initialize(sequencer:, output:, channel:, name: nil, do_log: nil) ⇒ MIDIVoice
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of MIDIVoice.
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 203 def initialize(sequencer:, output:, channel:, name: nil, do_log: nil) do_log ||= false @sequencer = sequencer @output = output @channel = channel @name = name @do_log = do_log @tick_duration = Rational(1, @sequencer.) @controllers_control = ControllersControl.new(@output, @channel) @active_pitches = [] fill_active_pitches @active_pitches @sequencer.logger.warn 'voice without output' unless @output self end |
Instance Attribute Details
#active_pitches ⇒ Array<Hash> (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns metadata for each of the 128 MIDI pitches. Mainly used internally.
194 195 196 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 194 def active_pitches @active_pitches end |
#channel ⇒ Integer (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns MIDI channel number (0-15).
191 192 193 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 191 def channel @channel end |
#do_log ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns whether this voice logs every emitted message.
182 183 184 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 182 def do_log @do_log end |
#name ⇒ String?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns optional name used in log messages.
179 180 181 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 179 def name @name end |
#output ⇒ #puts? (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns MIDI destination. When nil the voice becomes silent.
188 189 190 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 188 def output @output end |
#sequencer ⇒ Musa::Sequencer::Sequencer (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns sequencer driving this voice.
185 186 187 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 185 def sequencer @sequencer end |
#tick_duration ⇒ Rational (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns duration (in bars) of a sequencer tick; used to schedule note offs.
197 198 199 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 197 def tick_duration @tick_duration end |
Instance Method Details
#all_notes_off ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Sends an immediate all-notes-off message on this channel and resets internal state.
291 292 293 294 295 296 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 291 def all_notes_off @active_pitches.clear fill_active_pitches @active_pitches @output.puts MIDIEvents::ChannelMessage.new(0xb, @channel, 0x7b, 0) end |
#controller ⇒ ControllersControl
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns MIDI CC manager for this voice.
272 273 274 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 272 def controller @controllers_control end |
#fast_forward=(enabled) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Turns fast-forward on/off for this voice.
When disabling it, pending notes that were held silently are sent again so the synth is in sync with the sequencer state.
231 232 233 234 235 236 237 238 239 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 231 def fast_forward=(enabled) if @fast_forward && !enabled (0..127).each do |pitch| @output.puts MIDIEvents::NoteOn.new(@channel, pitch, @active_pitches[pitch][:velocity]) unless @active_pitches[pitch][:note_controls].empty? end end @fast_forward = enabled end |
#fast_forward? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns true when in fast-forward mode (notes registered but not emitted).
242 243 244 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 242 def fast_forward? @fast_forward end |
#log(msg) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Logs a message tagging the current voice.
302 303 304 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 302 def log(msg) @sequencer.logger.info('MIDIVoice') { "voice #{name || @channel}: #{msg}" } if @do_log end |
#note(pitchvalue = nil, pitch: nil, velocity: nil, duration: nil, duration_offset: nil, note_duration: nil, velocity_off: nil) ⇒ NoteControl?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Plays one or several MIDI notes.
256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 256 def note(pitchvalue = nil, pitch: nil, velocity: nil, duration: nil, duration_offset: nil, note_duration: nil, velocity_off: nil) pitch ||= pitchvalue if pitch velocity ||= 63 duration_offset ||= -@tick_duration note_duration ||= [0, duration + duration_offset].max velocity_off ||= 63 NoteControl.new(self, pitch: pitch, velocity: velocity, duration: note_duration, velocity_off: velocity_off).note_on end end |
#sustain_pedal ⇒ Integer?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns current sustain pedal value.
284 285 286 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 284 def sustain_pedal @controllers_control[:sustain_pedal] end |
#sustain_pedal=(value) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Sets the sustain pedal state.
279 280 281 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 279 def sustain_pedal=(value) @controllers_control[:sustain_pedal] = value end |
#to_s ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns human-readable voice description.
307 308 309 |
# File 'lib/musa-dsl/midi/midi-voices.rb', line 307 def to_s "voice #{@name} output: #{@output} channel: #{@channel}" end |