Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Sources/CAudioKitEX/Sequencing/SequencerEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ void process(AUAudioFrameCount frameCount) {
for (auto& event : events) {
// go through every event
int triggerTime = beatToSamples(event.beat);

if (currentEndSample > lengthInSamples() && data->settings.loopEnabled) {
// this buffer extends beyond the length of the loop and looping is on
int loopRestartInBuffer = (int)(lengthInSamples() - currentStartSample);
Expand All @@ -188,14 +187,18 @@ void process(AUAudioFrameCount frameCount) {
offset, event.beat);
}
} else if (currentStartSample == 0 && triggerTime == lengthInSamples() && data->settings.loopEnabled) {
// this event handles the case of skipped last note
// this event handles the case of skipped last note
sendMidiData(event.status, event.data1, event.data2,
0, event.beat);
} else if (currentStartSample <= triggerTime && triggerTime < currentEndSample) {
// this event is supposed to trigger between currentStartSample and currentEndSample
int offset = (int)(triggerTime - currentStartSample);
sendMidiData(event.status, event.data1, event.data2,
offset, event.beat);
} else if (currentEndSample >= lengthInSamples() && triggerTime > lengthInSamples() && data->settings.loopEnabled) {
// event is happens outside loop window, schedule it at the end of frames
sendMidiData(event.status, event.data1, event.data2,
frameCount, event.beat);
}

}
Expand Down
4 changes: 3 additions & 1 deletion Tests/AudioKitEXTests/SequenceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ class NoteEventSequenceTests: XCTestCase {
newNote.noteOff.data2 = 127
newNote.noteOff.beat = 2.0

XCTAssertEqual(seq, NoteEventSequence(notes: [newNote], events: [], totalDuration: 1.0))
XCTAssertEqual(seq, NoteEventSequence(notes: [newNote], events: [], totalDuration: 2.0))
// Even though note duration is 1.0, there is space at beginning of track since note position also 1.0.
// Total duration should be 2.0
}

func testRemoveNote() {
Expand Down
44 changes: 24 additions & 20 deletions Tests/AudioKitEXTests/SequencerEngineTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ class SequencerEngineTests: XCTestCase {
}

// events that start late in the loop are stopped after the engine is destroyed
// Or at the end of the loop before new note events occur
func testShortNotesAcrossLoop() {

var seq = NoteEventSequence()
Expand All @@ -239,26 +240,29 @@ class SequencerEngineTests: XCTestCase {

/// 6 render calls at 120bpm, 44100 buffersize is 12 beats, default loop is 4 beats
let events = observerTest(sequence: seq, renderCallCount: 6)
XCTAssertEqual(events.count, 30)

XCTAssertEqual(events.map { $0.noteNumber! }, [60, 62, 65, 60, 62, 65,
60, 64, 67, 60, 62, 65, 60, 62, 65,
60, 64, 67, 60, 62, 65, 60, 62, 65,
60, 64, 67,
67, 64, 60]) // engine destroyed

XCTAssertEqual(events.compactMap { $0.status!.type }, [.noteOn, .noteOn, .noteOn, .noteOff, .noteOff, .noteOff,
.noteOn, .noteOn, .noteOn, .noteOn, .noteOn, .noteOn,
.noteOff, .noteOff, .noteOff, .noteOn, .noteOn, .noteOn,
.noteOn, .noteOn, .noteOn, .noteOff, .noteOff, .noteOff,
.noteOn, .noteOn, .noteOn,
.noteOff, .noteOff, .noteOff]) // engine destroyed
XCTAssertEqual(events.map { $0.timeStamp }, [0, 0, 0, 0, 0, 0,
43658, 43658, 43658, 0, 0, 0,
0, 0, 0, 43658, 43658, 43658,
0, 0, 0, 0, 0, 0,
43658, 43658, 43658,
1, 1, 1]) // engine destroyed
XCTAssertEqual(events.count, 36)

XCTAssertEqual(events.map { $0.noteNumber! }, [60, 62, 65, 60, 62, 65, // First 3 notes on and off
60, 64, 67, 60, 64, 67, // Second 3 notes on and off
60, 62, 65, 60, 62, 65, // Loop #2 first 3 notes on/off
60, 64, 67, 60, 64, 67, // Loop #2 second 3 on/off
60, 62, 65, 60, 62, 65, // Loop #3 first 3 on/off
60, 64, 67, 60, 64, 67]) // Loop #3 second 3 on/off
// Engine cleans up remaining active note events, but there shouldn't be any since they're all handled before loop ends

XCTAssertEqual(events.compactMap { $0.status!.type }, [.noteOn, .noteOn, .noteOn, .noteOff, .noteOff, .noteOff, // First 3
.noteOn, .noteOn, .noteOn, .noteOff, .noteOff, .noteOff, // Second 3
.noteOn, .noteOn, .noteOn, .noteOff, .noteOff, .noteOff, // First 3
.noteOn, .noteOn, .noteOn, .noteOff, .noteOff, .noteOff, // Second 3
.noteOn, .noteOn, .noteOn, .noteOff, .noteOff, .noteOff, // First 3
.noteOn, .noteOn, .noteOn, .noteOff, .noteOff, .noteOff]) // Second 3
// Engine cleans up remaining active note events, but there shouldn't be any since they're all handled before loop ends
XCTAssertEqual(events.map { $0.timeStamp }, [0, 0, 0, 0, 0, 0, // First render call
43658, 43658, 43658, 44100, 44100, 44100, // Second
0, 0, 0, 0, 0, 0, // Third
43658, 43658, 43658, 44100, 44100, 44100, // Fourth
0, 0, 0, 0, 0, 0, // Fifth
43658, 43658, 43658, 44100, 44100, 44100,]) // Sixth
}
}
#endif
2 changes: 1 addition & 1 deletion Tests/AudioKitEXTests/ValidatedMD5s.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ let validatedMD5s: [String: String] = [
"-[SequencerTrackTests testLoop]": "3a7ebced69ddc6669932f4ee48dabe2b",
"-[SequencerTrackTests testOneShot]": "3fbf53f1139a831b3e1a284140c8a53c",
"-[SequencerTrackTests testTempo]": "1eb7efc6ea54eafbe616dfa8e1a3ef36",
"-[SequencerTrackTests testNoteBounds]": "f3b3935e30380367c15652c0a76a8a57",
"-[SequencerTrackTests testNoteBounds]": "a044a6482a0329a20ca84a446d599e0b",
"-[DryWetMixerTests testBalance0]": "789c1e77803a4f9d10063eb60ca03cea",
"-[DryWetMixerTests testBalance1]": "3932bc5d49cbefd4a9dd587d16f4b81c",
"-[DryWetMixerTests testDefault]": "45a639729d8698a28f134bbe4ccc9d6c",
Expand Down
Loading