Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MTS pitch and SysEx format conversion methods #7

Merged
merged 5 commits into from
Nov 16, 2023
Merged

Conversation

vsicurella
Copy link
Member

MTS methods - "mtsToFrequency" is covered by "mtof" as the math is exactly the same!

I think I've actually set this PR up right this time lol

@@ -38,6 +41,33 @@ describe('MIDI to frequency converter', () => {
});
});

describe('Frequency to MTS converter', () => {
it('converts a known value', () => {
Copy link
Member

Choose a reason for hiding this comment

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

Should be it('converts known values', ...). This test case is doing multiple things.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, I didn't connect the dots on that one.

Copy link
Member

Choose a reason for hiding this comment

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

No problem. For the smoothest experience it would be nice if this it case was broken into multiple invididual test cases. Now if the first expect fails the rest won't run and you have to run the unit tests multiple times when things eventually break.

})

describe("Frequency to MTS sysex value", () => {
it('converts a known value', () => {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
it('converts a known value', () => {
it('converts known values', () => {

})

describe("MTS data hex string converter", () => {
it('converts a known value', () => {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
it('converts a known value', () => {
it('converts known values', () => {

* @returns Frequency in Hertz.
*/
export function mtof(index: number) {
return 440 * Math.pow(2, (index - MIDI_NOTE_NUMBER_OF_A4) / 12);
}

function mtsRound(mtsValue: number): number {
return Math.round(mtsValue * 100000) / 100000;
Copy link
Member

Choose a reason for hiding this comment

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

How critical is it that this result is stable? Javascript's number type cannot represent decimals exactly under the hood.

Copy link
Member Author

@vsicurella vsicurella Jun 27, 2023

Choose a reason for hiding this comment

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

I think not very much. Currently there's no use case in SW for the mtsValue to be 128 or higher, but at the most, if for some reason someone used it in an MPE-style of tuning the upper bound would be 1920 or 2048. It only needs two-places of precision too.
I originally wanted to round to closest possible value in the three-byte representation which is why I made it a separate method. Decided it wasn't worth the debugging for now, but I kept the abstraction in.

@frostburn
Copy link
Member

Please do npm run fix. Some of the changes do not conform to the style specs.

@frostburn
Copy link
Member

What's the status of this PR? I'm still getting a local diff when I do npm run fix.

@vsicurella
Copy link
Member Author

The new commits make the tests tighter, fix some rounding errors, and fixes the code style! :)

let lsb = mtsBytes[2];

const noteNumber = mtsBytes[0] > 0x7f ? 0x7f : mtsBytes[0];
if (noteNumber == 0x7f) {
Copy link
Member

Choose a reason for hiding this comment

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

Prefer ===.

@frostburn
Copy link
Member

npm test fails.
npm run fix produces a diff.
I guess I need to set up some automatic checks in this repository too.

* @returns Uint8Array 3-byte of 7-bit MTS data
*/
export function mtsToMtsBytes(mtsValue: number): Uint8Array {
const noteNumber = Math.trunc(mtsValue);
Copy link
Member

Choose a reason for hiding this comment

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

Is there a test where mtsValue is negative? I'm wondering if we should worry about Math.trunc rounding towards zero instead of negative infinity. SW can produce silly scales with nanohertz frequencies.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fair call, I think that would only happen with bad usage but it would be good practice to clamp it to 0 otherwise you could be producing junk byte data.

@frostburn
Copy link
Member

Automated tests pass. Code seems fine. 👍 Feel free to merge if negative MTS values are nothing to worry about.

@vsicurella vsicurella merged commit a3c0987 into main Nov 16, 2023
1 check passed
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