Hi,
ich möchte mehrere Midi-Files anhand einer Liste von Midi-Instrumenten ausgeben.
Der folgende Code funktioniert:
\version "2.20.0"
\language "deutsch"
mus=\relative c'' { c4 c c c c }
make-score =
#(define-scheme-function (instrument)(string?)
#{
\score {
\new Staff
{
\set Staff.midiInstrument = $instrument
\mus
}
\midi {
\tempo 4=180
\context {
\Score
midiMinimumVolume = #0.1
midiMaximumVolume = #0.99
}
}
}
#})
Nun möchte ich mehrere Instrumente in einem Rutsch ausprobieren und habe dazu folgendes geschrieben:
\version "2.20.0"
\language "deutsch"
mus=\relative c'' { c4 c c c c }
make-midi-list =
#(define-scheme-function (instrumentlist mus)(list? ly:music?)
(map (lambda (p)
#{
\score {
\new Staff
{
\set Staff.midiInstrument = $p
$mus
}
\midi {
\tempo 4=180
\context {
\Score
midiMinimumVolume = #0.1
midiMaximumVolume = #0.99
}
}
}
#}) instrumentlist))
\make-midi-list #'( "acoustic grand" "bright acoustic") \mus
was zur folgenden Fehlermeldung führt:
error: bad expression type
Ersetze ich define-scheme-function durch define-void-function so wird keine Fehlermeldung, aber auch keine Ausgabe erzeugt.
Wahrscheinlich irgend ein blöder Fehler, ich komme aber nicht dahinter. Was mache ich falsch?
Hallo Manuela,
schauen wir erstmal was falsch läuft.
(Alle Beispiele für 2.20.0 und mit mus = \relative c'' { c4 c c c c } )
\displayScheme \make-midi-list #'( "acoustic grand" "bright acoustic") \mus
führt zu
(list #<Score> #<Score>)
LilyPond kann aber nichts mit einer bloßen Liste auf toplevel-Niveau anfangen.
Ich kann Deinen code unverändert ans laufen kriegen, wenn ich den Aufruf so verändere, daß die Liste aufgelöst wird.
$@(make-midi-list '( "acoustic grand" "bright acoustic") mus)
Jetzt erscheinen die scores einzeln auf toplevel-Niveau und werden der internen Liste mit Namen
toplevel-scores hinzugefügt.
Natürlich werden sie als midi-scores nicht gedruckt. Die erwähnte interne Liste kann übrigens mittels
#(pretty-print (ly:parser-lookup 'toplevel-scores))
(gesetzt ans Ende eines files) eingesehen werden.
Man kann die scores auch mittels add-score direkt dieser Liste hinzufügen. Dann braucht man aber keine scheme-function, eine void-function wäre angemessener. Auch soll die void-function ja keine eigene Liste ausgeben, sondern man iteriert über die "instrumentlist" um add-score anzuwenden , also for-each statt map.
Führt zu:
make-midi-list-harm-I =
#(define-void-function (instrumentlist mus)(list? ly:music?)
(for-each
(lambda (p)
(add-score
#{
\score {
\new Staff
{
\set Staff.midiInstrument = $p
$mus
}
\midi {
\tempo 4=180
\context {
\Score
midiMinimumVolume = #0.1
midiMaximumVolume = #0.99
}
}
}
#}))
instrumentlist))
\make-midi-list-harm-I #'( "acoustic grand" "bright acoustic") \mus
Allerdings ist es so, daß all diese midis file-name.midi, file-name-1.midi, file-name-2.midi etc heißen.
Besser fände ich den Namen so zu verändern, daß er eine Referenz zum benutzten midiInstrument hat und optional einen eigenen base-name bekommt.
Also etwas wie my-name-or-file-name-midiInstrumentName.midi
Um dahin zu kommen sollte man sich klar machen, daß jede \midi {}-Angabe ein eigenes output-file erzeugt, anders gesprochen ein book.
Also kann man ja gleich ein book mittels einer void-function erstellen, die den gewünschten Namen berücksichtigt.
Führt zu:
make-midi-list-harm-II =
#(define-void-function (name score tempo-list)((string? #f) ly:score? list?)
(for-each
(lambda (instrument)
(ly:book-process
(apply
ly:make-book
$defaultpaper
$defaultheader
(list score))
$defaultpaper
#{
\midi {
\tempo 4 = 180
\context {
\Score
midiMinimumVolume = #0.1
midiMaximumVolume = #0.99
}
\context {
\Staff
midiInstrument = #instrument
}
}
#}
(format #f "~a-~a"
(or name (ly:parser-output-name))
(string-join (string-split instrument #\SPACE) "-"))))
tempo-list))
\make-midi-list-harm-II
\score { \new Staff { $mus } }
#'( "acoustic grand" "bright acoustic")
\make-midi-list-harm-II
"atest-102-x"
\score { \new Staff { $mus } }
#'( "acoustic grand" "bright acoustic")
Der erste Aufruf (ohne Angabe des base-names) führt zu midis mit dem default file-name (bei mir atest-102).
Der zweite Aufruf setzt "atest-102-x" an den Anfang des Namens, gefolgt vom midiInstrument-Name (eventuelle Leerzeichen werden durch "-" ersetzt)
Zitat von: terminal
$ lilypond atest-102.ly
GNU LilyPond 2.20.0
Processing `atest-102.ly'
Parsing...
Interpreting music...
MIDI output to `atest-102-acoustic-grand.midi'...
Interpreting music...
MIDI output to `atest-102-bright-acoustic.midi'...
Interpreting music...
MIDI output to `atest-102-x-acoustic-grand.midi'...
Interpreting music...
MIDI output to `atest-102-x-bright-acoustic.midi'...
Success: compilation successfully completed
HTH,
Harm
Vielen lieben Dank Harm. :) :) :)
Wen der Name des Midi-Files den Instrumentnamen enthält, ist das natürlich noch viel besser als ich gedacht hätte. Ich war der Meinung, das geht nicht (habe irgendwo in der Mailingliste gelesen, vermutlich missverstanden).
Ich probier das heute abend mal aus und melde mich dann nochmal
Funktioniert 1a! Super, danke!!!
Ich habe eine kleine Änderung angebracht, sodass die Dateien fortlaufend numeriert werden.
Die Idee dabei ist, dass jede Mididatei mit der Nummer ihres Instruments versehen ist.
\version "2.20.0"
\language "deutsch"
mus=\relative c'' { c4 c c c c }
#(define myzahl 0)
make-midi-list-harm-II =
#(define-void-function (name score tempo-list)
((string? #f) ly:score? list?)
(for-each
(lambda (instrument)
(set! myzahl (+ myzahl 1))
(ly:book-process
(apply
ly:make-book
$defaultpaper
$defaultheader
(list score))
$defaultpaper
#{
\midi {
\tempo 4 = 180
\context {
\Score
midiMinimumVolume = #0.1
midiMaximumVolume = #0.99
}
\context {
\Staff
midiInstrument = #instrument
}
}
#}
(format #f "~3,'0d_~a"
myzahl
(string-join (string-split instrument #\SPACE) "_"))))
tempo-list))
Hallo Manuela,
anstatt myZahl toplevel zu definieren und dann hochzuzählen, kannst Du Dich auch auf die Länge der Liste beziehen und iota verwenden.
Auch hast Du die Funktionalität die für die "name"-Variable da war entfernt, die (jetzt nutzlose) Variable aber drin gelassen.
Ich würde da lieber eine Wahlmöglichkeit haben. Führt zu:
\version "2.20.0"
\language "deutsch"
mus=\relative c'' { c4 c c c c }
make-midi-list-harm-III =
#(define-void-function (name score instrument-list)
((string? #f) ly:score? list?)
(for-each
(lambda (index instrument)
(ly:book-process
(apply
ly:make-book
$defaultpaper
$defaultheader
(list score))
$defaultpaper
#{
\midi {
\tempo 4 = 180
\context {
\Score
midiMinimumVolume = #0.1
midiMaximumVolume = #0.99
}
\context {
\Staff
midiInstrument = #instrument
}
}
#}
(format #f "~3,'0d~a_~a"
index
(if name (format #f "_~a" name) "")
(string-join (string-split instrument #\SPACE) "_"))))
(iota (length instrument-list) 1 1)
instrument-list))
\make-midi-list-harm-III
\score { \new Staff { $mus } }
#'( "acoustic grand" "bright acoustic")
\make-midi-list-harm-III
"foo"
\score { \new Staff { $mus } }
#'( "acoustic grand" "bright acoustic")
\make-midi-list-harm-III
#(ly:parser-output-name)
\score { \new Staff { $mus } }
#'( "acoustic grand" "bright acoustic")
->
Zitat von: terminal
Interpreting music...
MIDI output to `001_acoustic_grand.midi'...
Interpreting music...
MIDI output to `002_bright_acoustic.midi'...
Interpreting music...
MIDI output to `001_foo_acoustic_grand.midi'...
Interpreting music...
MIDI output to `002_foo_bright_acoustic.midi'...
Interpreting music...
MIDI output to `001_atest-102_acoustic_grand.midi'...
Interpreting music...
MIDI output to `002_atest-102_bright_acoustic.midi'...
Gruß,
Harm
Danke Harm :) :) :)
Ich hatte den falschen Code gepostet, hier ist der von mir tatsächlich verwendete (mitsamt einer Liste aller Midi-Instrumente) (https://lilypond.miraheze.org/wiki/Midi_Beispieldatei_erzeugen)
und hier eine Seite mit den Midiinstrumenten #1-32 (https://lilypond.miraheze.org/wiki/Midi_Beispieldateien)