Документация Engee

Ноты

Информация о нотах в MIDI-файлах обычно кодируется посредством событий NOTEON и NOTEOFF. Однако информация о музыкальной ноте не ограничивается началом и концом; эта информация помещается в типы Note и Notes. Эти две структуры играют центральную роль в работе JuliaMusic. Кроме того, все события нот в MIDITrack можно получить с помощью функции getnotes.

Note(pitch, velocity, position, duration, channel = 0) <: AbstractNote

Изменяемая структура данных, описывающая музыкальную ноту. При объединении нескольких нот образуется структура Notes, которую возвращает функция getnotes.

Если канал channel ноты имеет значение 0 (по умолчанию), он не отображается.

Создать объект Note можно также с помощью следующего конструктора с именованными аргументами:

Note(pitch, position; velocity = 100, duration = 960, channel = 0)
Note(pitch_name::String; position = 0, velocity = 100, duration = 960, channel = 0)

Поля:

  • pitch::UInt8: высота тона, начиная с C-1 = 0; на каждый полутон добавляется единица. Используйте функции name_to_pitch и pitch_to_name for integer and string representations.

  • velocity::UInt8: динамическая интенсивность. Не может быть больше 127 (0x7F).

  • position::UInt: позиция с начала дорожки в абсолютном времени (в импульсах).

  • duration::UInt: длительность в импульсах.

  • channel::UInt8 = 0: канал дорожки, в котором воспроизводится нота. Не может быть больше 127 (0x7F).

Notes(note_vector, tpq = 960) -> Notes
Notes(notes_string::String, tpq::Int = 960) -> Notes

Структура данных, описывающая коллекцию музыкальных нот с указанием тиков на четверть ноты (чтобы нотам можно было приписать ритмическое значение).

Ноты можно инициализировать строкой; имена нот разделяются пробелами.

Notes("C2 F3 D#6")

Notes допускает итерацию и доступ посредством note_vector. Это устраняет необходимость в пользовательских функциях итерации или поиска. Например, получить ноту максимальной высоты можно так:

max_pitch, index_max = findmax(n -> n.pitch, notes)
max_pitch_note = notes[index_max]
getnotes(midi::MIDIFile [, trackno])

Находит все события NoteOnEvent и NoteOffEvent в дорожке trackno midi (по умолчанию 1 или 2), которые соответствуют одному и тому же значению ноты (высоте тона), и преобразует их в тип данных Note. Есть особые случаи, когда NoteOffEvent фактически кодируется как NoteOnEvent с нулевой силой воспроизведения, однако функция getnotes учитывает это.

Обратите внимание, что первая дорожка midi обычно не содержит нот, поэтому функция по умолчанию использует дорожку 2.

getnotes(track::MIDITrack, tpq = 960)

Находит ноты непосредственно в track, также передавая количество импульсов на четвертную ноту.

Возвращает Notes{Note}, задавая количество импульсов на четвертную ноту в tpq. Определить экспортированное значение количества импульсов на четвертную ноту в исходном файле MIDIFile можно посредством midi.tpq.


Если у вас есть ноты, которые вы хотите добавить в дорожку, используйте следующий код:

addnotes!(track::MIDITrack, notes)

Добавляет заданные notes в заданный track, выполняя внутри все переводы из абсолютного времени в относительное.


Наконец, с помощью функции getnotnotes(track) можно получить все события TrackEvents, отличные от NOTEON и NOTEOFF.

Пример записи

using MIDI
C = Note(60, 96, 0, 192)
E = Note(64, 96, 48, 144)
G = Note(67, 96, 96, 96)

inc = 192
file = MIDIFile()
track = MIDITrack()
notes = Notes() # tpq автоматически устанавливается в значение 960

push!(notes, C)
push!(notes, E)
push!(notes, G)

# Ноты на одну октаву выше
C = Note(60 + 12, 96, C.position+inc, 192)
E = Note(64 + 12, 96, E.position+inc, 144)
G = Note(67 + 12, 96, G.position+inc, 96)

addnotes!(track, notes)
addtrackname!(track, "simple track")
push!(file.tracks, track)
save("test.mid", file)

Пример считывания

using MIDI
midi = load(testmidi())
MIDIFile (format=1, tpq=960) with tracks:
 American Rock Beat 06 Tom
 Drums
 Bass
 ORIGINAL
# Дорожка номер 3 — это квантованная басовая MIDI-дорожка.
bass = midi.tracks[3]
notes = getnotes(bass, midi.tpq)
println("Notes of track $(trackname(bass)):")
notes
177 Notes with tpq=960
 Note A♯2 | vel = 95  | pos = 7680, dur = 690
 Note A♯2 | vel = 71  | pos = 9280, dur = 308
 Note G♯2 | vel = 52  | pos = 9600, dur = 668
 Note G♯2 | vel = 58  | pos = 11200, dur = 338
 Note G2  | vel = 71  | pos = 11520, dur = 701
 Note G♯2 | vel = 83  | pos = 13120, dur = 281
 Note G2  | vel = 73  | pos = 13440, dur = 855
  ⋮
 Note F♯1 | vel = 73  | pos = 185280, dur = 878
 Note F1  | vel = 85  | pos = 186240, dur = 964
 Note A1  | vel = 88  | pos = 187200, dur = 904
 Note A♯1 | vel = 81  | pos = 188160, dur = 900
 Note B1  | vel = 77  | pos = 189120, dur = 945
 Note C2  | vel = 83  | pos = 190080, dur = 847
 Note F2  | vel = 90  | pos = 191040, dur = 713

Преобразования

name_to_pitch(name::String) -> Int

Возвращает значение высоты тона заданного имени ноты, которое может иметь вид capital_letter*sharp*octave, где:

  • capital_letter: от "A" до "G".

  • sharp: один из символов "#" "♯" "b" "♭" или "".

  • octave: любое целое число (в виде строки); номер октавы (октава — это 12 нот). Если не указано, предполагается значение "5".

Можно определить, например, name_to_pitch("C4") === 60 (то есть строка "C4", представляющая ноту до первой октавы, соответствует высоте тона 60).

pitch_to_name(pitch; flat=false) -> String

Return the name of the pitch, e.g. F5, A♯3 etc. in modern notation given the pitch value in integer. When flat=true, accidentals are printed as flats, e.g. A♯3 is printed as B♭3.

Возвращает название тональности, например, F5, A♯3 и т.д. в современной нотации, учитывая значение тональности в целых числах. Если flat=true, то авариации печатаются как бемоли, например, A♯3 печатается как B♭3.

Напоминание: нота до первой октавы имеет высоту 60 и отображается как C4.

note_to_fundamental(note(s))

Возвращает String или Vector{String} с основной высотой нот (то есть без информации об октаве).

hz_to_pitch(hz::Real, A4::Real = 440) -> pitch::Int

Функция, обратная pitch_to_hz.

pitch_to_hz(pitch::Integer, A4::Real = 440) -> hz::Real

Возвращает значение частоты заданной миди-ноты, опционально задавая ссылку на середину A. См. https://en.wikipedia.org/wiki/Pianokeyfrequencies and https://librosa.org/doc/main/modules/librosa/core/convert.html#midito_hz.

NamedNote

Нота с определенным именем. Для этого типа требуется MusicManipulations.jl.

NamedNote(name, velocity, position, duration, channel = 0) <: AbstractNote

Изменяемая структура данных, описывающая музыкальную ноту с определенным именем высоты тона. При объединении нескольких нот образуется структура Notes, которую возвращает функция getnotes.

Если канал channel ноты имеет значение 0 (по умолчанию), он не отображается.

Создать объект NamedNote можно также с помощью следующего конструктора с именованными аргументами:

NamedNote(pitch_name::String; position = 0, velocity = 100, duration = 960, channel = 0)
NamedNote(n::Note; pitch_name::String = "")

Notes{NamedNote} инициализируется на основе строки с именами высоты тона, разделенными пробелами.

NamedNotes(notes_string::String; tpq::Int = 960)
# NamedNotes("C#6 Db5 E4")

Преобразует NamedNote в Note:

Note(n::NamedNote)

Внимание! Для сравнения NamedNote используются атрибуты name_to_pitch(name), duration, position, channel, velocity. Поэтому:

NamedNote("Db5") == NamedNote("C#5")
# true

Поля:

  • name::String: имя высоты тона в верхнем регистре.

  • velocity::UInt8: динамическая интенсивность. Не может быть больше 127 (0x7F).

  • position::UInt: позиция с начала дорожки в абсолютном времени (в импульсах).

  • duration::UInt: длительность в импульсах.

  • channel::UInt8 = 0: канал дорожки, в котором воспроизводится нота. Не может быть больше 127 (0x7F).