Потратив достаточно много времени на изучение lilypond и написание партитур для нескольких голосов, я часто сталкивался с проблемой создания отдельных голосовых файлов midi/mp3 из партитуры. Я был удивлен, обнаружив, что это еще не функция или что ни у кого не было простого способа сделать это, поскольку отдельные голосовые mp3-файлы являются ценным ресурсом для изучения многоголосного произведения!
Хотя можно просто временно удалить другие голоса из партитуры, скомпилировать, переименовать миди, изменить на другой голос, скомпилировать, переименовать и т. д. Это очень быстро становится очень утомительным. Кроме того, я считаю полезным, чтобы другие голоса по-прежнему звучали на низком уровне громкости на заднем плане, чтобы иметь ощущение гармонии.
Поэтому мне нужен способ генерировать эти отдельные голоса из стандартной партитуры с несколькими голосами.
Вот стандартный сценарий lilypond для 4-голосного примера, который можно использовать в качестве тестового файла:
\version "2.18.2"
global = {
\key c \major
\time 4/4
\tempo "Allegro" 2 = 60
}
% Lyrics
verseBass = \lyricmode {Ho Ho Hoo, Ho Ho Hoo !
}
verseTenor = \lyricmode {Ha Ha Haa, Ha Ha Haa !
}
verseAlto = \lyricmode {Huu Hu Hu, Hu Hu Huu !
}
verseSoprano = \lyricmode {Hi Hi Hii, Hi Hi Hii !
}
% Music
voiceBass = \relative c {\global c4 b f'2 d4 g, c2 \bar "|."}
voiceTenor = \relative c' {\global g4 b c2 b4 f g2}
voiceAlto = \relative c' {\global e2 d4 g g b, e2}
voiceSoprano = \relative c'' {\global c8e d4 a2 d4 b c2}
% Score stucture
voicePartBass = \new Staff \with {
instrumentName = "Bass"
shortInstrumentName = "B"
midiInstrument = "violin"
} {
\clef bass \voiceBass
} \addlyrics { \verseBass }
voicePartTenor = \new Staff \with {
instrumentName = "Tenor"
shortInstrumentName = "T"
midiInstrument = "violin"
} {
\clef "G_8" \voiceTenor
} \addlyrics {\verseTenor}
voicePartAlto = \new Staff \with {
instrumentName = "Alto"
shortInstrumentName = "A"
midiInstrument = "violin"
} {
\voiceAlto
} \addlyrics { \verseAlto }
voicePartSoprano = \new Staff \with {
instrumentName = "Soprano"
shortInstrumentName = "S"
midiInstrument = "violin"
} {
\voiceSoprano
} \addlyrics {\verseSoprano}
\score {
<<
\new ChoirStaff << % choirstaff adds the fancy join on voice staves
\voicePartSoprano
\voicePartAlto
\voicePartTenor
\voicePartBass
>>
>>
\layout {}
\midi {}
}
Какие выходы
И миди файл со всем.
TL;DR: вы добавляете несколько тегов, и в конце есть bash-скрипт, который автоматизирует генерацию отдельной части midi (только для пользователей Unix, извините: P)
midiMaximumVolume
_В своем стремлении к многоголосному разделению я узнал об опцииmidiMaximumVolume
, которую можно установить в Staff
среде. Установив для этой переменной значение от 0 до 1, можно уменьшить (или полностью подавить) громкость нотоносца, в котором она находится.
Это должно быть установлено для каждого голоса, поэтому это примерно так же утомительно, как удаление музыкальных переменных других частей, а затем вам все равно придется выполнять махинации с компиляцией / переименованием.
Однако это уже большой шаг к автоматизации разделения голосов, поскольку это единственный параметр, на который можно ориентироваться (вместо любых пользовательских \myvoice
переменных, которые можно использовать...)
Кроме того, это позволяет использовать другие голоса на низком уровне громкости в фоновом режиме, установив для них меньшую громкость (например, основной голос на 1, другие на 0,3).
Итак, идея состоит в том, чтобы пометить каждую часть в ее нотоносце именем и тегом, чтобы мы могли легко определить, где ввести параметр громкости, а также имя для каждой части (в основном для именования файлов). Я пошел с чем-то вроде этого:
%#%part:<part_name>
Который подходит к комментарию lilypond. Он должен быть размещен в том месте, где будет установлен параметр громкости. Используя приведенный выше пример, это будет выглядеть так:
% Score stucture
voicePartBass = \new Staff \with {
instrumentName = "Bass"
shortInstrumentName = "B"
midiInstrument = "violin"
} {
%#%part:Bass
\clef bass \voiceBass
} \addlyrics { \verseBass }
voicePartTenor = \new Staff \with {
instrumentName = "Tenor"
shortInstrumentName = "T"
midiInstrument = "violin"
} {
%#%part:Tenor
\clef "G_8" \voiceTenor
} \addlyrics {\verseTenor}
Теперь нам нужно настроить таргетинг на каждый тег и изменить его на соответствующие команды, чтобы использовать его голос в качестве основного голоса с остальными в фоновом режиме, и повторить для всех тегов.
Я превратил это в функцию bash ly2partmidi
(в конце поста).
Теперь вы можете получить функцию и запустить
который генерирует test_<part_name1>.midi
, test_<part_name2>.midi
и т. д. за один раз!
Чтобы модулировать громкость (или тишину) голосов:
$ ly2partmidi <file.ly> <mainvolume> <othervolume>
например. чтобы полностью удалить другие голоса ly2partmidi <file.ly> 1 0
или оставить все голоса, кроме основного 0 1
, по умолчанию используется значение 1 0.3
.
Если мы правильно настроим test.ly
вышеуказанный файл и запустим функцию, она сгенерирует файлы test_Soprano.midi
, и , как и test_Alto.midi
ожидалось .test_Tenor.midi
test_Bass.midi
Вы также можете добавить туда шаг midi2mp3, если хотите.
Баш-функция:
ly2partmidi () {
lyfile=${1}
volumeMain=${2:-1} # level of the 'main' voice of a file
volumeOther=${3:-0.3} # level of the other voices (set to 0 if completely silent)
tagregex="^\s*%#%part:([a-zA-Z0-9_\-]+)"
setvolcmd="\\\set midiMaximumVolume = #"
# find the tags in the .ly file
mapfile -t fulltags < <( grep -Po ${tagregex} ${lyfile} )
tagnames=()
for t in ${fulltags[@]} ; do
t1=$(echo $t | sed -E "s/${tagregex}/\1/")
tagnames+=("$t1")
done
# get unique of each tag
fulltags=($(echo "${fulltags[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
tagnames=($(echo "${tagnames[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
# for each tag...
for i in ${!fulltags[@]}; do
ft=${fulltags[$i]}
t=${tagnames[$i]}
echo -e "\n--- Generating part [$t] ..."
echo -e "\tCopying lilypond script"
# make temp copy of .ly
t_lyfile=${lyfile/.ly/_$t.ly}
cp -f $lyfile $t_lyfile
echo -e "\tReplacing tags with midiVolume cmd"
# replace tags with the midiVolume cmds
sed -i -E "s/${ft}/${setvolcmd}${volumeMain}/g" $t_lyfile
sed -i -E "s/${tagregex}/${setvolcmd}${volumeOther}/g" $t_lyfile
echo -e "\tRunning lilypond engraving to generate midi"
# generate midi
lily_o=${t_lyfile/.ly/}
lilypond -s -dno-print-pages -o $lily_o $t_lyfile
rm $t_lyfile
done
}
Ваше решение, очевидно, работает, но вам не нужны какие-либо компиляции/переименования/полоскания/повторения махинаций.
Вы можете поместить несколько \score
блоков в один файл. Каждый из этих блоков будет набирать музыку в какой-либо файл, если \layout
в нем есть блок, и будет помещать MIDI в какой-либо файл, если в нем есть \midi
блок. Таким образом, вы можете добавить еще один блок оценки, который будет выглядеть следующим образом:
\score {
\new Staff \with {
midiInstrument = "saxophone"
midiMinimumVolume = #1
midiMaximumVolume = #1
} \new Voice \soprano
\new Staff \with {
midiInstrument = "acoustic grand"
midiMinimumVolume = #0.4
midiMaximumVolume = #0.4
} \new Voice \alto
% etc for \tenor and \bass
% NO \layout block!!
\midi {}
}
Это создаст файл your-filename-0.midi
, в котором ваше сопрано играет громкий саксофон, а остальные партии - тихое пианино. Вы не поместили \layout
в него блок, так что он не будет набирать музыку, просто сделает MIDI. Промойте и повторите для остальных трех голосов.
Конечно, вы можете дополнительно автоматизировать это. Я использую эту функцию (которую я спер где-то много лет назад, не помню где):
rehearsalMidi = #
(define-music-function
(parser location name midiInstrument lyrics) (string? string? ly:music?)
#{
\unfoldRepeats <<
\new Staff = "sopran" \new Voice = "sopran" { s1*0\f \sopran }
\new Staff = "alt" \new Voice = "alt" { s1*0\f \alt }
\new Staff = "tenor" \new Voice = "tenor" { s1*0\f \tenor }
\new Staff = "bas" \new Voice = "bas" { s1*0\f \bas }
\context Staff = $name {
\set Score.midiMinimumVolume = #0.5
\set Score.midiMaximumVolume = #0.5
\set Score.tempoWholesPerMinute = #(ly:make-moment 100 4)
\set Staff.midiMinimumVolume = #1.0
\set Staff.midiMaximumVolume = #1.0
\set Staff.midiInstrument = $midiInstrument
}
\new Lyrics \with {
alignBelowContext = $name
} \lyricsto $name $lyrics
>>
#})
Теперь я просто добавляю такие блоки,
\book {
\bookOutputSuffix "sopran"
\score {
\rehearsalMidi "sopran" "soprano sax" \slovaI
\midi { }
}
}
по одному на каждый голос. Три аргумента \rehearsalMidi
: голос, чья партия, инструмент, на котором эта партия должна быть сыграна, и лирика к ней. Поскольку в чешском языке мы называем четыре голоса сопраном , альтом , тенором и басом , я использую эти имена для своих голосов, но вы, несомненно, сможете изменить эту функцию, чтобы она соответствовала вашим потребностям. И просто сделайте имена файлов более красивыми, например , и т book
. д. вместо и т. д.bookOutputSuffix
my-filename-sopran.midi
my-filename-alt.midi
my-filename-0.midi
Кстати, когда вы напишете это один раз, вы можете скопировать и вставить его во всю набранную вами хоровую музыку (что я и делаю уже несколько лет :)).
Какими бы интересными ни были эти ответы, есть хороший аргумент в пользу решения с низким кодом, которое не требует внешних сценариев Bash, программ C или определения новых функций. Он использует две основные функции, встроенные в LilyPond: имена выходных файлов ( https://lilypond.org/doc/v2.22/Documentation/notation/output-file-names ) и включает ( https://lilypond.org/doc/ v2.22/Документация/обозначение/включая-lilypond-файлы ).
Рассмотрим следующую иерархию каталогов:
┌─ base
├─┬─ music
│ └─── example.ily
│
├─┬─ score
│ └─┬─ audio.ily
│ ├─ example.ily
│ └─ printed.ily
│
├─┬─ words
│ └─── example.ily
│
└─── compile.ly
Содержимое вашей базовой папки состоит всего из трех каталогов ( music
, words
, score
) и одного файла компиляции ( compile.ly
).
Внутри ваших папок music
и words
находятся просто .ily
файлы, содержащие, соответственно, вашу музыку и переменные слова.
Внутри вашей score
папки находится один .ily
файл, который использует два \include
оператора для ссылки на два других .ily
файла:
\book
и \score
блок, который приводит только к печатной музыке ( printed.ily
)\book
и \score
блоков, которые приводят только к аудиофайлам ( audio.ily
)Как это выглядит?
compile.ly
\version "2.22.0"
\include "./music/example.ily"
\include "./words/example.ily"
\include "./score/example.ily"
music/example.ily
sop = \relative c' {
c4 d e f
e d e2
}
alt = \relative c' {
e4 f g a
g fis g2
}
ten = \relative c' {
c2 b
a g
}
bas = \relative c {
a2 e'
a, a
}
words/example.ily
sop_words = \lyricmode {
so -- pra -- no
words they are here
}
alt_words = \lyricmode {
al -- to words be
here yo ho
}
ten_words = \lyricmode {
ten -- or
words -- ies
}
bas_words = \lyricmode {
gol -- lum
gol -- lum
}
score/example.ily
\include "./printed.ily"
\include "./audio.ily"
score/printed.ily
\book {
\bookOutputName "my_printed_score"
\score {
<<
\new ChoirStaff <<
\new Voice = "sop" \sop
\new Lyrics \lyricsto sop \sop_words
\new Voice = "alt" \alt
\new Lyrics \lyricsto alt \alt_words
\new Voice = "ten" { \clef "treble_8" \ten }
\new Lyrics \lyricsto ten \ten_words
\new Voice = "bas" { \clef bass \bas }
\new Lyrics \lyricsto bas \bas_words
>>
>>
\layout {}
}
}
score/audio.ily
\book {
\bookOutputName "midi_sop"
\score {
\new Staff \sop
\midi {}
}
}
\book {
\bookOutputName "midi_alt"
\score {
\new Staff \alt
\midi {}
}
}
\book {
\bookOutputName "midi_ten"
\score {
\new Staff \ten
\midi {}
}
}
\book {
\bookOutputName "midi_bas"
\score {
\new Staff \bas
\midi {}
}
}
Как я уже сказал выше, две функции, которые имеют значение здесь, это bookOutputName
и include
.
Используя bookOutputName
, вы можете создать несколько файлов — в этом случае один будет содержать только музыку сопрано, другой — только музыку альта и т. д. Конечно, при желании вы можете добавить другие инструменты и контролировать их громкость. являются и их стерео позиции (левое ухо / правое ухо), среди других вариантов:
\book {
\bookOutputName "midi_sop_bas"
\score {
<<
\new Staff \with {
midiMinimumVolume = #0.8
midiPanPosition = #-1
} \sop
\new Staff \with {
midiMaximumVolume = #0.5
midiPanPosition = #1
} \bas
>>
\midi {}
}
}
(Причиной вызова \include
является закомментировать %
файл \include "./printed.ily"
, когда вы довольны тем, как выглядит музыка, и хотите только настроить то, как она звучит. Компиляция только MIDI без блока макета часто на несколько порядков быстрее.)
В этом случае все, что вам нужно сделать сейчас, это добавить еще несколько блоков \book
, \score
упорядочить и структурировать их так, как вы хотите слышать свои MIDI-файлы, а затем, если вы так склонны, использовать их в \include
утверждениях (или не делайте), чтобы контролировать, какие из них компилируются.
Нанчо Альварес , наборщик LilyPond партитур Томаса Луиса де Виктории ( Partituras de Tomás Luis de Victoria ), написал программу на C, которая разбивает MIDI-дорожки на отдельные MIDI-файлы: splitmidi.c .
РоБ
РоБ
Рамильес