Skip to content

Conversation

@murphlab
Copy link
Contributor

It is possible to create instances of the Note struct that represent values outside of the 0-127 MIDI note range. In such a case, accessing the Note.noteNumber calculated property may result in either an infinite loop or a crash. If the octave is set to less than -2, the following gets stuck in an infinite loop:

 while !octaveBounds.contains(note) {
             note += 12
}

Also, if the final calculated note value is greater than 127, it will cause a crash when being cast to Int8 prior to being returned.

The fix:

  • Add early bounds checking for octave values outside -2 to 8 range. This fixes the infinite loop.
  • Add final bounds checking to ensure note values are within MIDI range. Prevents crash when casting to Int8.
  • Add test to NoteTests.

- Add early bounds checking for octave values outside -2 to 8 range. Fixes infinite loop for octaves below -2
- Add final bounds checking to ensure note values are within MIDI range. Prevents crash on cast to Int8 for values > 127
- Add test coverage
let gSharp8 = Note(.G, accidental: .sharp, octave: 8)
XCTAssertEqual(gSharp8.noteNumber, 127)

let c9 = Note(.C, octave: 9)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm following what appears to be a well established convention in the tests for identifiers referring to notes

let cFlatMinus3 = Note(.C, accidental: .flat, octave: -3)
XCTAssertEqual(cFlatMinus3.noteNumber, 0)

let a8 = Note(.A, octave: 8)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm following what appears to be a well established convention in the tests for identifiers referring to notes


let gSharp8 = Note(.G, accidental: .sharp, octave: 8)
XCTAssertEqual(gSharp8.noteNumber, 127)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm following the spacing convention established in other tests in this file, where assertion statements
are grouped with their supporting setup statements using blank lines. This convention
helps clarify the logical grouping and makes the test structure more readable.


let a8 = Note(.A, octave: 8)
XCTAssertEqual(a8.noteNumber, 127)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm following the spacing convention established in other tests in this file, where assertion statements
are grouped with their supporting setup statements using blank lines. This convention
helps clarify the logical grouping and makes the test structure more readable.


let cFlatMinus3 = Note(.C, accidental: .flat, octave: -3)
XCTAssertEqual(cFlatMinus3.noteNumber, 0)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm following the spacing convention established in other tests in this file, where assertion statements
are grouped with their supporting setup statements using blank lines. This convention
helps clarify the logical grouping and makes the test structure more readable.


let bMinus3 = Note(.B, octave: -3)
XCTAssertEqual(bMinus3.noteNumber, 0)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm following the spacing convention established in other tests in this file, where assertion statements
are grouped with their supporting setup statements using blank lines. This convention
helps clarify the logical grouping and makes the test structure more readable.

@aure aure self-requested a review August 28, 2025 17:51
@aure aure merged commit 47aaabd into AudioKit:main Aug 28, 2025
3 of 4 checks passed
@murphlab murphlab deleted the bugfix-note-bounds branch August 28, 2025 17:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants