@@ -0,0 +1,2 @@ | |||||
# This makes the repo play nice with git on Windows | |||||
* text=auto |
@@ -0,0 +1,8 @@ | |||||
cmake-build-debug | |||||
*.o | |||||
CMakeFiles/ | |||||
CMakeCache.txt | |||||
Makefile | |||||
cmake_install.cmake | |||||
example | |||||
.idea/ |
@@ -0,0 +1,19 @@ | |||||
cmake_minimum_required(VERSION 3.24) | |||||
project(midi_note_id_utils C) | |||||
set(CMAKE_C_STANDARD 11) | |||||
include_directories(.) | |||||
add_executable(test-note-names | |||||
test-note-names.c | |||||
midi-utils.c | |||||
midi-utils.h) | |||||
add_custom_command( | |||||
TARGET test-note-names POST_BUILD | |||||
COMMAND ${CMAKE_COMMAND} -E copy | |||||
"${CMAKE_HOME_DIRECTORY}/cases.txt" | |||||
$<TARGET_FILE_DIR:test-note-names> | |||||
) |
@@ -0,0 +1,36 @@ | |||||
C0 0 | |||||
C#0 1 | |||||
D0 2 | |||||
D#0 3 | |||||
E0 4 | |||||
F0 5 | |||||
F#0 6 | |||||
G0 7 | |||||
G#0 8 | |||||
A0 9 | |||||
A#0 10 | |||||
B0 11 | |||||
C1 12 | |||||
C2 24 | |||||
C3 36 | |||||
C4 48 | |||||
C5 60 | |||||
A5 69 | |||||
C6 72 | |||||
C7 84 | |||||
C8 96 | |||||
C9 108 | |||||
C10 120 | |||||
G10 127 | |||||
C11 132 | |||||
C12 144 | |||||
C13 156 | |||||
C14 168 | |||||
C15 180 | |||||
C16 192 | |||||
C17 204 | |||||
C18 216 | |||||
C19 228 | |||||
C20 240 | |||||
C21 252 | |||||
D#21 255 |
@@ -0,0 +1,81 @@ | |||||
#include "midi-utils.h" | |||||
char* MIDI_GetNoteName(unsigned char midi_note) { | |||||
static const char* pitch_names[] = { | |||||
"C", | |||||
"C#", | |||||
"D", | |||||
"D#", | |||||
"E", | |||||
"F", | |||||
"F#", | |||||
"G", | |||||
"G#", | |||||
"A", | |||||
"A#", | |||||
"B" | |||||
}; | |||||
const unsigned char pitch_class = midi_note % 12; | |||||
const unsigned char octave = midi_note / 12; | |||||
static char note_name[8]; | |||||
sprintf(note_name, "%s%u", pitch_names[pitch_class], octave); | |||||
return note_name; | |||||
} | |||||
unsigned char MIDI_GetNoteFromName(const char* name) { | |||||
char name_copy[8]; | |||||
strcpy(name_copy, name); | |||||
_strlwr(name_copy); | |||||
unsigned char octave = 0; | |||||
unsigned char has_accidental = name_copy[1] == '#' || name_copy[1] == 'b'; | |||||
unsigned char octave_start = has_accidental ? 2 : 1; | |||||
unsigned char pitch_class; | |||||
char octave_offset = 0; | |||||
for (unsigned char i = octave_start; '0' <= name_copy[i] && name_copy[i] <= '9'; i += 1) { | |||||
octave *= 10; | |||||
octave += name_copy[i] - '0'; | |||||
} | |||||
if (strstr(name_copy, "c#") || strstr(name_copy, "db")) { | |||||
pitch_class = 1; | |||||
} else if (strstr(name_copy, "d#") || strstr(name_copy, "eb")) { | |||||
pitch_class = 3; | |||||
} else if (strstr(name_copy, "fb")) { | |||||
pitch_class = 4; | |||||
} else if (strstr(name_copy, "e#")) { | |||||
pitch_class = 5; | |||||
} else if (strstr(name_copy, "f#") || strstr(name_copy, "gb")) { | |||||
pitch_class = 6; | |||||
} else if (strstr(name_copy, "g#") || strstr(name_copy, "ab")) { | |||||
pitch_class = 8; | |||||
} else if (strstr(name_copy, "a#") || strstr(name_copy, "bb")) { | |||||
pitch_class = 10; | |||||
} else if (strstr(name_copy, "cb")) { | |||||
pitch_class = 11; | |||||
octave_offset = -1; | |||||
} else if (strstr(name_copy, "b#")) { | |||||
pitch_class = 0; | |||||
octave_offset = 1; | |||||
} else if (strstr(name_copy, "c")) { | |||||
pitch_class = 0; | |||||
} else if (strstr(name_copy, "d")) { | |||||
pitch_class = 2; | |||||
} else if (strstr(name_copy, "e")) { | |||||
pitch_class = 4; | |||||
} else if (strstr(name_copy, "f")) { | |||||
pitch_class = 5; | |||||
} else if (strstr(name_copy, "g")) { | |||||
pitch_class = 7; | |||||
} else if (strstr(name_copy, "a")) { | |||||
pitch_class = 9; | |||||
} else if (strstr(name_copy, "b")) { | |||||
pitch_class = 11; | |||||
} else { | |||||
return 255u; | |||||
} | |||||
return ((octave * 12) + octave_offset) + pitch_class; | |||||
} |
@@ -0,0 +1,18 @@ | |||||
#ifndef MIDI_UTILS_H | |||||
#define MIDI_UTILS_H | |||||
#include <stdio.h> | |||||
#include <string.h> | |||||
#define MIDI_MESSAGE_NOTEON 0x90u | |||||
#define MIDI_MESSAGE_NOTEOFF 0x80u | |||||
#define MIDI_CC_SUSTAIN 0x40u | |||||
#define MIDI_CC_SOSTENUTO 0x42u | |||||
#define MIDI_CC_UNACORDA 0x43u | |||||
char* MIDI_GetNoteName(unsigned char); | |||||
unsigned char MIDI_GetNoteFromName(const char*); | |||||
#endif |
@@ -0,0 +1,26 @@ | |||||
#include <stdio.h> | |||||
#include <assert.h> | |||||
#include "midi-utils.h" | |||||
int main(void) { | |||||
FILE* f = fopen("cases.txt", "r"); | |||||
if (!f) { | |||||
return -1; | |||||
} | |||||
char read_note_name[255] = ""; | |||||
unsigned int read_note_value; | |||||
while (!feof(f)) { | |||||
fscanf(f, "%s %d\n", read_note_name, &read_note_value); | |||||
unsigned int actual_note_value = MIDI_GetNoteFromName(read_note_name); | |||||
printf("MIDI_GetNoteFromName(\"%s\")...", read_note_name); | |||||
assert(read_note_value == actual_note_value); | |||||
printf("OK!\n"); | |||||
printf("MIDI_GetNoteName(%d)...", read_note_value); | |||||
assert(!strcmp(MIDI_GetNoteName(read_note_value), read_note_name)); | |||||
printf("OK!\n"); | |||||
} | |||||
fclose(f); | |||||
return 0; | |||||
} |