Skip to content

Commit

Permalink
realtime midi output now buffers past the end of the longest event du…
Browse files Browse the repository at this point in the history
…ration
  • Loading branch information
adamjmurray committed Jul 9, 2013
1 parent 64367cc commit 4eaea09
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
5 changes: 4 additions & 1 deletion lib/mtk/io/midi_output.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,10 @@ def play(anything, options={})
end
end

end_time = timeline.times.last + trailing_buffer
end_time = timeline.times.last
final_events = timeline[end_time]
max_length = final_events.inject(0) {|max,event| len = event.length; max > len ? max : len } || 0
end_time += max_length + trailing_buffer
@scheduler.at(end_time) { @scheduler.stop }

thread = @scheduler.run
Expand Down
26 changes: 25 additions & 1 deletion spec/mtk/io/midi_output_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class MockOuput < MTK::IO::MIDIOutput
let(:scheduler) do
scheduler = mock(:scheduler)
Gamelan::Scheduler.stub(:new).and_return scheduler
scheduler.stub(:stop).and_return :stop_scheduler
scheduler
end

Expand All @@ -28,13 +29,15 @@ def timeline_with_param_event(event_type, event_options={})
end

def should_be_scheduled timed_data
explicitly_expected_stop_scheduler = false
timed_data.each do |time,data|
explicitly_expected_stop_scheduler = true if data == :stop_scheduler
scheduler.should_receive(:at) do |scheduled_time,&callback|
scheduled_time.should == time
callback.yield.should == data
end
end
scheduler.should_receive(:at) # end time, don't care about this here...
scheduler.should_receive(:at) unless explicitly_expected_stop_scheduler # auto-handle stop_schedulerer if needed
scheduler.should_receive(:run).and_return mock(:thread,:join=>nil)
end

Expand Down Expand Up @@ -97,6 +100,27 @@ def should_be_scheduled timed_data
subject.play [ MTK::Events::Timeline.from_h( 0 => Note(C4,fff,1) ), MTK::Events::Timeline.from_h( 2 => Note(G4,fff,1) )]
end


it "stops the scheduler 2 beats after the last event" do
should_be_scheduled 0 => [:note_on, 60, 127, 0],
1 => [:note_off, 60, 127, 0],
3 => :stop_scheduler
subject.play MTK::Events::Timeline.from_h( 0 => Note(C4,fff,1) )
end

it "stops the scheduler 2 beats after the longest of simultaneous final events" do
should_be_scheduled [
[0, [:note_on, 60, 127, 0]],
[1, [:note_off, 60, 127, 0]],
[0, [:note_on, 62, 127, 0]],
[3.5,[:note_off, 62, 127, 0]],
[0, [:note_on, 64, 127, 0]],
[2, [:note_off, 64, 127, 0]],
[5.5, :stop_scheduler]
]
subject.play MTK::Events::Timeline.from_h( 0 => [Note(C4,fff,1), Note(D4,fff,3.5), Note(E4,fff,2)] )
end

end

end

0 comments on commit 4eaea09

Please sign in to comment.