Deutsches Lilypond Forum (Archiv)
Allgemein => Fragen zu Funktionen => Thema gestartet von: Webfox am Sonntag, 7. Juni 2015, 17:44
-
Hallo,
ich lasse bei der Generierung meiner Noten eine MIDI Datei erzeugen. Diese enthält dann natürlich immer alle Noten. Ist es möglich, dass Lilypond pro Takt jeweils eine MIDI Datei erzeugt?
Ich habe leider keinen Beispielcode, da ich gar keinen Ansatz habe, ob das geht und auch nichts dazu finden konnte.
-
Du könntest evtl. irgendwie mit clip-regions arbeiten, siehe NR 3.4.1.
Meine Idee dazu wäre, eine Schleife zu bauen, die pro Takt einen \score mit entsprechendem \midi-Block baut.
Ok, getestet, das geht schon mal nicht. Nicht mit midi. Irgendwas mit \set Score.skipTypesetting könnte gehen, laut Dokumentation (NR 3.4.2) wirkt das auch auf midi. Das mit der Schleife könnte auch weiterhin gehen, man kann ja eine Extrastimme haben, die nur diese skipTypesetting-Befehle enthält.
Wie das aber genau aussehen könnte, dazu fehlen mir die nötigen scheme-Kenntnisse.
-
Lieber Webfox,
ich habe mal in meiner Sammlung von MIDI Utilities nachgeschaut, ob es so etwas nicht fertig gibt und bin dabei darüber gestolpert, dass dein Ansinnen nicht ganz trivial ist.
Konkret stellt sich mir die Frage, wie soll mit Noten (oder besser Ereignissen) verfahren werden, die über eine "Schnittgrenze" hinausragen ?
Es gibt offensichtlich mind. 2 Lösungen:
- Alle Ereignisse werden unverändert belassen und es wird nach Startzeitpunkt getrennt. In der Folge lassen sich die so erzeugten Schnippsel mit einer entsprechenden Mergefunktion wieder zum Original zusammenbauen. Allerdings wären so erzeugte Schnippsel u.U. zeitlich überlappend.
- Überhängede Ereignisse werden entsprechend verkürzt und ggf. in den nachfolgenden Schnippsel entsprechend verkürzt repliziert (solange, bis das Ereignis komplett vrearbeitet ist. Diese Schnippsel wären zeitlich disjunkt, aber eine Rückführung in das Original wäre nicht simpel machbar, weil z.B. eine lang ausgehaltene Note in mehrere kürzere Noten mit gleicher Gesamtlänge zerlegt worden wäre.
Ich hoffe, obiger Text ist verständlich; ev. gibt es auch noch weitere Dinge zu beachten, die mir gerade nicht einfallen.
Was von dem (oder ggf. ganz anderes) versuchst du zu erreichen ?
Liebe Grüße,
Michael
-
Hallo,
es geht konkret um Schlagzeugnoten. Ich habe immer max. 4 Takte pro System (Zeile) und 12 Systeme pro Seite.
Es wird eine komplette MIDI Datei geschrieben. Ich möchte erreichen, das pro Takt oder zumindest pro System eine gesonderte MIDI Datei geschrieben wird.
Hier mal ein Beispielcode:
\version "2.18.2"
%% Schlagzeugvorlage
%%#(set-default-paper-size "a4" 'landscape)
\header { tagline = ##f }
\layout {
indent = #0
line-width = #160
}
\paper {
fonts = #
(make-pango-font-tree
"Calibri"
"Calibri"
"sans"
(/ (* staff-height pt) 2.5))
print-page-number = ##f
%% Definition von Rändern und Abständen
#(define left-margin (* 3.5 cm))
#(define top-margin (* 1.5 cm))
#(define bottom-margin (* 1.5 cm))
%% Abstände zwischen den Systemen & Verhindern eines weißen Randes am Seitenende
system-system-spacing = #'((padding . 0.4) (basic-distance . 12))
%%page-count = #10 (Seitenzahl kann erzwungen werden - optional)
systems-per-page = #12 %% (Systeme pro Seite können erzwungen werden - optional)
ragged-last-bottom = ##f
ragged-bottom = ##f
}
\score {
\new DrumStaff
\with {
\consists "Parenthesis_engraver"
instrumentName = #"1"
\numericTimeSignature
}
<<
\new DrumVoice
\with {
\stemUp
\override Script.direction = #UP
\override Script.outside-staff-priority = #451
\override TextScript.padding = 2
}
\drummode {
\time 4/4
%---------------Hier beginnt der eigentliche Noten Code------------%
\repeat unfold 1 { sn4^"R" sn4^"L" sn4^"L" sn4^"L" }
\repeat unfold 1 { tomh4^"R" tomh4^"L" tomh4^"R" tomh4^"L" }
\repeat unfold 1 { tommh4^"R" tommh4^"L" tommh4^"L" tommh4^"L" }
\repeat unfold 1 { tomml4^"L" tomml4^"L" tomml4^"R" tomml4^"R" }
\break
\repeat unfold 4 { <hh> 8 <bd hh> 8 <hh> 8 <hh> 8 <bd hh> 8 <hh> 8 <sn hh> 8 <sn hh> 8 }
\repeat unfold 4 { <hh> 8 <hh> 8 <hh> 8 <bd hh> 8 <sn hh> 8 <sn hh> 8 <bd hh> 8 <hh> 8 }
\repeat unfold 4 { <hh> 8 <bd hh> 8 <hh> 8 <sn hh> 8 <bd hh> 8 <sn hh> 8 <hh> 8 <hh> 8 }
\repeat unfold 4 { <hh> 8 <sn hh> 8 <hh> 8 <bd hh> 8 <hh> 8 <hh> 8 <sn hh> 8 <bd hh> 8 }
\break
}
%---------------Hier endet der eigentliche Noten Code------------%
>>
% Notendruck
\layout {}
% MIDI Erzeugung
\midi {
\tempo 4 = 120
}
}
In diesem Muster sind meine Noten geschrieben. Optimal wäre eine MIDI Datei pro Zeile.
Gibt es dafür eine Lösung?
-
Gibt es dafür eine Lösung?
Ich kenne keine out-of-the-box, aber man kann ev. mit geringem Aufwand eine basteln. Ich wüßte nicht, wie ich das in Lilypond mache, dafür kenne ich mich da mit den Internas zu schlecht aus. Aber ich habe eine Vorstellung, wie man die von Lilypond erzeugte MIDI Datei weiter verarbeiten könnte.
Unter Linux wäre das relativ einfach und mit Bordmitteln möglich. Unter Windows gibt es die ganzen notwendigen Tools nicht von Haus aus. Unter OSX ist die Situation diesbezüglich dazwischen - einige der Tools gibt es, andere nicht. Du bist nicht zufällig unter Linux ?
Und falls Windows oder OSX:
Hast du einen C-Compiler installiert und kannst auch damit umgehen ?
(die Frage zielt darauf ab, ein Programm in Source oder als Binary zu verteilen).
Liebe Grüße,
Michael
-
Hallo,
ich bin unter Windows unterwegs und reiner Anwender. Ich habe keinen C-Compiler installiert.
-
so ganz verstehe ich nicht, was hier dahinter steckt! Ich würde in einem solchen Fall einfach die einzelnen Takte in Variablen ablegen und zum Ausdrucken aneinander kleben, statt mir soviel Arbeit zu machen. Also:
barA =\relative c {...}
barB =\relative c {...}
...
barZ =\relative c {...}
music = { \barA \barB .. \barZ }
Ist sowas keine Lösung?
--ingmar
-
Hallo ingmar,
das zu lösende Problem ist, für alle barA...barZ je eine eigene MIDI Datei zu erzeugen. Eine umständliche aber funktionierende Lösung wäre, alle barA...barZ in eigene lilypond Sourcen zu includieren. Dann hätte man z.B. 30 lilypond Dateien, die 30 MIDI Dateien (und entsprechende Layoutschnippsel) erzeugen.
Die Frage ist jetzt, gibt es innerhalb einer einzigen lilypond Datei eine Möglichkeit wie folgt skizziert:
barA =\relative c {...}
barB =\relative c {...}
...
barZ =\relative c {...}
music = { \barA \barB .. \barZ }
#(define allBars '(barA barB ... barZ))
%% define-markup-command ist als Platzhalter gemeint
#(define-markup-command (midiOut layout props l)
"Gebe jedes Element von l in eine eigene MIDI Datei aus"
(if (null? ls)
'()
(let (createMIDI (car l))
(midiOut (cdr l)))))
\midiOut allBars
So in der Art.
createMIDI erzeugt jeweils einen neuen Dateinamen und schreibt den Inhalt. Keine Ahnung, wie das zu bewerkstelligen wäre.
Liebe Grüße,
Michael
-
Hallo
vielen Dank für die neue Anregung!
Ich kann als reiner Anwender hier leider keinen hilfreichen Hinweis geben. Sinnvoll ist eine solche Variablen Lösung in der Tat nur für mich, wenn pro definierter Variable eine MIDI Datei erzeugt wird. So wie bereits von mgd beschrieben.
-
...worauf ich hinauswollte: Die MIDI-Files müssen doch nicht unbedingt alle automatisch erzeugt werden! Mach ein File wie oben beschrieben mit den Einzeltakten, die du dort auch zu einer Partitur zusammenbosselst. Diese File importierst du in 100 andere (fast) identische Minimalfiles, die alle nur ungefähr so aussehen wie unten und unter den Namen MeinMidifileA.ly bis MeinMidifileZ.ly gespeichert werden und entsprechend MeinMidifileA.mid bis MeinMidifileZ.mid erzeugen. Ja, das ist natürlich ne Viertelstunde mechanische Arbeit, aber anschließend hast du doch, was du brauchst, oder?
--ingmar
\import...
\score {
\barA
\midi {}
}
\import...
\score {
\barB
\midi {}
}
\import...
\score {
\barZ
\midi {}
}
-
Hallo zusammen,
1)
das Problem für einen fertigen score ein jeweils neues midi pro Takt auszugeben, halte ich von LilyPond aus für nicht durchführbar. (zumindest nicht mit vertretbarem Aufwand.)
Man kann zwar einzelne Abschnitte extrahieren, z.B. mit
http://lsr.di.unimi.it/LSR/Item?id=542 (http://lsr.di.unimi.it/LSR/Item?id=542)
aber immer genau einen Takt auszuwählen scheitert auch hier viel zu oft.
Siehe folgendes Beispiel:
\version "2.19.21"
{
\shiftDurations #1 #0 \times 2/3 { c'\breve \< d'1~ d' e'\breve \! }
}
Stattdessen brauch man ein tool welches midis "schneiden" kann wie einen Film.
Gibts bestimmt. Auch wenn ich keine Ahnung habe, wo sowas zu finden wäre (eigentlich interessiere ich mich nicht die Bohne für midi)
2)
ingmars rein manuelle Methode funktioniert natürlich.
Aber hier wird auch nicht ein fertiger score in Takte zerlegt, sondern die einzelnen Teile werden separat geschrieben.
3)
Wenn man aber schon einzelne Teile vordefiniert um sie erst später zusammen zu setzen, dann kann man die Sache auch etwas automatisieren.
\version "2.19.21"
%% each part in a seperate variable
mI = { c''1 }
mII = { d''1 }
mIII = { <c' e' g'>1 }
%% collected in a single expression
ml = { \mI \mII \mIII }
%% initially written as a single expression will work as well
%% note the additional {}-brackets
%ml = { { c''1 } { d''1 } { <c' e' g'>1 } }
foo =
#(define-void-function (parser location m)(ly:music?)
(let* ((elts (ly:music-property m 'elements)))
(if (null? elts)
;; do nothing if elts are empty
#f
(let (;; make a midi from every entry of elts
(scores (map (lambda (e) #{ \score { $e \midi {} } #}) elts)))
;; return them, each as a new book
(for-each
(lambda (score name)
(let* ((my-new-book
(ly:make-book
$defaultpaper
$defaultheader
score)))
(ly:book-process
my-new-book
$defaultpaper
$defaultmidi
;; add increasing numbers to the name
(format #f "part-~a" name))))
scores
(iota (length elts) 1 1))))))
%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%
\header { title = "My Title" }
%% default score
\score { \ml }
%% midis
\foo \ml
Gruß,
Harm
-
Nächste Iteration.
Ich habe versucht Harm's Funktion auf das originale Beispiel von Webfox anzuwenden. Dabei ist der folgende Code entstanden:
\version "2.19.21"
foo =
#(define-void-function (parser location m)(ly:music?)
(let* ((elts (ly:music-property m 'elements)))
(if (null? elts)
;; do nothing if elts are empty
#f
(let (;; make a midi from every entry of elts
(scores (map (lambda (e) #{ \score { $e \midi {} } #}) elts)))
;; return them, each as a new book
(for-each
(lambda (score name)
(let* ((my-new-book
(ly:make-book
$defaultpaper
$defaultheader
score)))
(ly:book-process
my-new-book
$defaultpaper
$defaultmidi
;; add increasing numbers to the name
(format #f "part-~a" name))))
scores
(iota (length elts) 1 1))))))
snare = { \drummode { sn4^"R" sn4^"L" sn4^"L" sn4^"L" } }
tomI = { \drummode { tomh4^"R" tomh4^"L" tomh4^"R" tomh4^"L" } }
tomII = { \drummode { tommh4^"R" tommh4^"L" tommh4^"L" tommh4^"L" } }
tomIII = { \drummode { tomml4^"L" tomml4^"L" tomml4^"R" tomml4^"R" } }
hhI = { \drummode { <hh> 8 <bd hh> 8 <hh> 8 <hh> 8 <bd hh> 8 <hh> 8 <sn hh> 8 <sn hh> 8 } }
hhII = { \drummode { <hh> 8 <hh> 8 <hh> 8 <bd hh> 8 <sn hh> 8 <sn hh> 8 <bd hh> 8 <hh> 8 } }
hhIII = { \drummode { <hh> 8 <bd hh> 8 <hh> 8 <sn hh> 8 <bd hh> 8 <sn hh> 8 <hh> 8 <hh> 8 } }
hhIV = { \drummode { <hh> 8 <sn hh> 8 <hh> 8 <bd hh> 8 <hh> 8 <hh> 8 <sn hh> 8 <bd hh> 8 } }
%partI = { \repeat unfold 1 { \snare } }
%partII = { \repeat unfold 1 { \tomI } }
%partIII = { \repeat unfold 1 { \tomII } }
%partIV = { \repeat unfold 1 { \tomIII } \break }
partI = { \snare }
partII = { \tomI }
partIII = { \tomII }
partIV = { \tomIII \break }
partV = { \repeat unfold 4 { \hhI } }
partVI = { \repeat unfold 4 { \hhII } }
partVII = { \repeat unfold 4 { \hhIII } }
partVIII = { \repeat unfold 4 { \hhIV } \break }
drumnotes = {
\snare
\tomI
\tomII
\tomIII
\partI
\partII
\partIII
\partIV
\partV
\partVI
\partVII
\partVIII
}
\score {
\new DrumStaff <<
\new DrumVoice
\time 4/4
\drumnotes
>>
% Notendruck
\layout {}
% MIDI Erzeugung
\midi {
\tempo 4 = 120
}
}
%% midis
\foo \drumnotes
Es werden insgesamt 12 MIDI Dateien part-1.midi ... part-12,midi erzeugt (was ich auch erwarte, denn drumnotes enthält 12 Blöcke). Leider enthalten die ausschließlich die Header Information aber keinerlei Noten Events.
Die von Harm's Code erzeugten MIDI Dateien enthalten jedoch die erwarteten Noten Events, will sagen, i.P. funktioniert das.
Ich verstehe noch zu wenig von der internen Datenrepräsentation von Lilypond um zu wissen, ob vllt. das\drummode { ... } eine andere (clevere) Behandlung innerhalb der Funktion foo erfordert.
Irgendwelche Ideen ?
Liebe Grüße,
Michael
-
Das Problem liegt hier:
(scores (map (lambda (e) #{ \score { $e \midi {} } #}) elts)))
Der score wird gebaut indem ich mich auf default-Setzungen verlasse.
Jedoch gibt folgendes kein sinnvolles midi:
\score {
\drummode { sn4 }
\midi {}
}
Der Context für Drums muß explizit angegeben werden sonst klappt es nicht:
foo =
#(define-void-function (parser location m)(ly:music?)
(let* ((elts (ly:music-property m 'elements)))
; (display-scheme-music elts)
(if (null? elts)
;; do nothing if elts are empty
#f
(let (;; make a midi from every entry of elts
(scores
(map
(lambda (e) #{ \score { \new DrumStaff $e \midi {} } #})
elts)))
;; return them, each as a new book
(for-each
(lambda (score name)
(let* ((my-new-book
(ly:make-book
$defaultpaper
$defaultheader
score)))
(ly:book-process
my-new-book
$defaultpaper
$defaultmidi
;; add increasing numbers to the name
(format #f "part-test-~a" name))))
scores
(iota (length elts) 1 1))))))
Diese Funktion ist so wie sie ist aber noch (stark) verbesserungsfähig ;)
Jedoch habe ich meine Zweifel, ob das jemals wirklich praktikabel wird.
Schon wenn man keine single-Staff-Musik, sondern Klaviernotation per Takt ausgeben will, wird die Eingabe doch sehr mühsam. Von einer ganzen Orchesterpartitur ganz zu schweigen.
Gruß,
Harm
-
Klasse Harm :)
Du hast vollkommen recht, für eine allgemeine MIDI "Schneide-Funktion" ist noch einiges zu tun und vermutlich ist das besser extern direkt auf der MIDI Datei erledigt (auch da ist es im allgemeinen Fall nicht trivial, aber vermutlich einfacher).
Für das ursprünglich von Webfox gepostete Problem, stellt deine Funktion zusammen mit dem Vorschlag von ingmar aber schon eine Lösung da.
Ich habe die Funktion mal in midiOut umbenannt und in das modifizierte originale Beispiel eingefügt:
\version "2.19.21"
midiOut =
#(define-void-function (parser location m)(ly:music?)
(let* ((elts (ly:music-property m 'elements)))
; (display-scheme-music elts)
(if (null? elts)
;; do nothing if elts are empty
#f
(let (;; make a midi from every entry of elts
(scores
(map
(lambda (e) #{ \score { \new DrumStaff $e \midi {} } #})
elts)))
;; return them, each as a new book
(for-each
(lambda (score name)
(let* ((my-new-book
(ly:make-book
$defaultpaper
$defaultheader
score)))
(ly:book-process
my-new-book
$defaultpaper
$defaultmidi
;; add increasing numbers to the name
(format #f "part-test-~a" name))))
scores
(iota (length elts) 1 1))))))
%% Schlagzeugvorlage
%%#(set-default-paper-size "a4" 'landscape)
\header { tagline = ##f }
\layout {
indent = #0
line-width = #160
}
\paper {
fonts = #
(make-pango-font-tree
"Calibri"
"Calibri"
"sans"
(/ (* staff-height pt) 2.5))
print-page-number = ##f
%% Definition von Rändern und Abständen
#(define left-margin (* 3.5 cm))
#(define top-margin (* 1.5 cm))
#(define bottom-margin (* 1.5 cm))
%% Abstände zwischen den Systemen & Verhindern eines weißen Randes am Seitenende
system-system-spacing = #'((padding . 0.4) (basic-distance . 12))
%%page-count = #10 (Seitenzahl kann erzwungen werden - optional)
systems-per-page = #12 %% (Systeme pro Seite können erzwungen werden - optional)
ragged-last-bottom = ##f
ragged-bottom = ##f
}
snare = { \drummode { sn4^"R" sn4^"L" sn4^"L" sn4^"L" } }
tomI = { \drummode { tomh4^"R" tomh4^"L" tomh4^"R" tomh4^"L" } }
tomII = { \drummode { tommh4^"R" tommh4^"L" tommh4^"L" tommh4^"L" } }
tomIII = { \drummode { tomml4^"L" tomml4^"L" tomml4^"R" tomml4^"R" } }
hhI = { \drummode { <hh> 8 <bd hh> 8 <hh> 8 <hh> 8 <bd hh> 8 <hh> 8 <sn hh> 8 <sn hh> 8 } }
hhII = { \drummode { <hh> 8 <hh> 8 <hh> 8 <bd hh> 8 <sn hh> 8 <sn hh> 8 <bd hh> 8 <hh> 8 } }
hhIII = { \drummode { <hh> 8 <bd hh> 8 <hh> 8 <sn hh> 8 <bd hh> 8 <sn hh> 8 <hh> 8 <hh> 8 } }
hhIV = { \drummode { <hh> 8 <sn hh> 8 <hh> 8 <bd hh> 8 <hh> 8 <hh> 8 <sn hh> 8 <bd hh> 8 } }
partI = { \repeat unfold 1 { \snare } }
partII = { \repeat unfold 1 { \tomI } }
partIII = { \repeat unfold 1 { \tomII } }
partIV = { \repeat unfold 1 { \tomIII } \break }
partV = { \repeat unfold 4 { \hhI } }
partVI = { \repeat unfold 4 { \hhII } }
partVII = { \repeat unfold 4 { \hhIII } }
partVIII = { \repeat unfold 4 { \hhIV } \break }
drumnotes = {
\snare
\tomI
\tomII
\tomIII
\partI
\partII
\partIII
\partIV
\partV
\partVI
\partVII
\partVIII
}
\score {
\new DrumStaff
\with {
\consists "Parenthesis_engraver"
instrumentName = #"1"
\numericTimeSignature
}
<<
\new DrumVoice
\with {
\stemUp
\override Script.direction = #UP
\override Script.outside-staff-priority = #451
\override TextScript.padding = 2
}
\time 4/4
\drumnotes
>>
% Notendruck
\layout {}
% MIDI Erzeugung
\midi {
\tempo 4 = 120
}
}
%% midis
\midiOut \drumnotes
Der Name der erzeugten Ausgabedateien ist part-test-#.midi - das kann vorn in der Funktion individuell angepasst werden.
-
Vielen Dank!
Diese Lösung funktioniert für meine Ziele wunderbar.
Ich denke, für die Erzeugung separater MIDI Dateien für Schlagzeugnoten ist das eine sehr gute Lösung.
-
Hallo,
mir ist bei dieser Lösung noch etwas aufgefallen. Die MIDI Dateien sind unterschiedlich lang. Beispielsweise bei Zeilen mit zwei Takten. Einige MIDI Dateien geben ganz genau die zwei Takte aus, andere sind aber doppelt so lang und am Ende einfach nur leer - also zwei Takte mit Noten, zwei Takte leer in einer Datei.
Diese längeren Dateien muss ich immer manuell kürzen.
Habt Ihr eine Idee, warum die generierten MIDI Dateien nicht genau die zwei Takte einer Zeile wiedergeben?
-
Kannst du ein Beispiel liefern ?
-
Hallo,
ja, hier ein Beispiel mit Deinem Code und jeweils einem Takt pro Zeile. Bei den dabei erzeugten MIDI Files sind Part 1,2 und 4 zu lang (letzter Teil leer). Part 3 hat die richtige Länge, nämlich genau einen Takt.
Ich verstehe nicht, warum einige MIDI Files länger sind.
Ich habe auch versucht, mit dem articulate Script bessere Ergebnisse zu erzielen (Dokumentation 3.5.7 Artikuliere-Script). Leider ohne Erfolg.
\version "2.19.21"
midiOut =
#(define-void-function (parser location m)(ly:music?)
(let* ((elts (ly:music-property m 'elements)))
; (display-scheme-music elts)
(if (null? elts)
;; do nothing if elts are empty
#f
(let (;; make a midi from every entry of elts
(scores
(map
(lambda (e) #{ \score { \new DrumStaff $e \midi {} } #})
elts)))
;; return them, each as a new book
(for-each
(lambda (score name)
(let* ((my-new-book
(ly:make-book
$defaultpaper
$defaultheader
score)))
(ly:book-process
my-new-book
$defaultpaper
$defaultmidi
;; add increasing numbers to the name
(format #f "part-test-~a" name))))
scores
(iota (length elts) 1 1))))))
%% Schlagzeugvorlage
%%#(set-default-paper-size "a4" 'landscape)
\header { tagline = ##f }
\layout {
indent = #0
line-width = #160
}
\paper {
fonts = #
(make-pango-font-tree
"Calibri"
"Calibri"
"sans"
(/ (* staff-height pt) 2.5))
print-page-number = ##f
%% Definition von Rändern und Abständen
#(define left-margin (* 3.5 cm))
#(define top-margin (* 1.5 cm))
#(define bottom-margin (* 1.5 cm))
%% Abstände zwischen den Systemen & Verhindern eines weißen Randes am Seitenende
system-system-spacing = #'((padding . 0.4) (basic-distance . 12))
%%page-count = #10 (Seitenzahl kann erzwungen werden - optional)
systems-per-page = #12 %% (Systeme pro Seite können erzwungen werden - optional)
ragged-last-bottom = ##f
ragged-bottom = ##f
}
vewqyPUP= { \drummode { <sn hh> 16 bd16 <hh> 16 bd16 <bd hh> 8 <hh> 16 bd16 <hh> 16 r16 <hh> 16 bd16 <hh> 16 r16 <sn hh> 8}}
vPrwUgJG= { \drummode { <bd hh> 8 <hh> 16 r16 <bd hh> 8 <bd hh> 8 <hh> 16 sn16 <sn hh> 16 sn16 <bd hh> 8 <bd hh> 8}}
ZYqzHclH= { \drummode { <hh> 16 r16 <sn hh> 16 sn16 <hh> 16 bd16 <sn hh> 8 <bd hh> 16 sn16 <sn hh> 16 sn16 <hh> 16 r16 <hh> 16 r16}}
eMvoyDQt= { \drummode { <hh> 16 r16 <bd hh> 8 <bd hh> 8 <bd hh> 16 bd16 <hh> 16 sn16 <hh> 16 r16 <sn hh> 8 <sn hh> 8}}
pxhCnBGx= { \drummode { <bd hh> 16 bd16 <hh> 16 r16 <hh> 16 r16 <sn hh> 16 sn16 <sn hh> 16 bd16 <hh> 16 r16 <sn hh> 8 <hh> 16 sn16}}
partI = { \repeat unfold 1 { \vewqyPUP } \break }
partII = { \repeat unfold 1 { \vPrwUgJG } \break }
partIII = { \repeat unfold 1 { \ZYqzHclH } \break }
partIV = { \repeat unfold 1 { \pxhCnBGx } \break }
drumnotes = {
\partI
\partII
\partIII
\partIV
}
\score {
\new DrumStaff
\with {
\consists "Parenthesis_engraver"
instrumentName = #"1"
\numericTimeSignature
}
<<
\new DrumVoice
\with {
\stemUp
\override Script.direction = #UP
\override Script.outside-staff-priority = #451
\override TextScript.padding = 2
}
\time 4/4
\drumnotes
>>
% Notendruck
\layout {}
% MIDI Erzeugung
\midi {
\tempo 4 = 120
}
}
%% midis
\midiOut \drumnotes
-
Kannst Du mal testen, ob folgendes bei Dir auch zu lang ist?
\score {
{ c''1 }
\midi {}
}
Mir ist nämlich aufgefallen, daß Dein drittes Beispiel als einziges eine Pause am Ende hat. Wenn ich das via Rosegarden öffne dann sehe ich gar keinen vollen Takt und die Rückumwandlung in Noten läßt diese Pause dann auch aus.
Allerdings sind alle anderen Beispiele bei mir exakt einen Takt lang, 4 Sekunden.
Ich hege den Verdacht, daß ein leerer Takt angehängt wird falls keine Pause am Ende da ist, von wem auch immer.
LilyPond selbst scheint aber auszuscheiden.
Gruß,
Harm
-
Hallo!
es lag tatsächlich an meiner DAW Presonus Studio One 2. Offenbar wird dort ein leerer Takt angehängt! Warum konnte ich allerdings nicht herausfinden...
-
Hallo,
ich arbeite noch immer sehr gut mit dieser Lösung, möchte jetzt aber zusätzlich die MIDI Erzeugung nun nicht nur pro Takt, sondern pro Zeile ausgeben.
Das geht sozusagen in die Richtung, die Takte definieren zu können. So wie ich es im Titel dieses Posts ursprünglich erwähnte. Bisher war das nicht nötig. Jetzt erstelle ich Übungen, bei denen es sinnvoll wäre, auch die gesamte Zeile als eine MIDI Datei auszugeben, da eine Zeile einer vollständigen Übung entspricht.
Hier ein Beispielcode für diese Übungen:
\version "2.18.2"
midiOut =
#(define-void-function (parser location m)(ly:music?)
(let* ((elts (ly:music-property m 'elements)))
; (display-scheme-music elts)
(if (null? elts)
;; do nothing if elts are empty
#f
(let (;; make a midi from every entry of elts
(scores
(map
(lambda (e) #{ \score { \new DrumStaff $e \midi {\tempo 4 = 120} } #})
elts)))
;; return them, each as a new book
(for-each
(lambda (score name)
(let* ((my-new-book
(ly:make-book
$defaultpaper
$defaultheader
score)))
(ly:book-process
my-new-book
$defaultpaper
$defaultmidi
;; add increasing numbers to the name
(format #f "~a-test" name))))
scores
(iota (length elts) 1 1))))))
#(define counter 1)
my-staff-count-mod =
\with {
instrumentName = "1"
shortInstrumentName = ""
\override InstrumentName.after-line-breaking =
#(lambda (grob)
(ly:grob-set-property! grob 'text
(format #f "~5a" (number->string counter)))
(set! counter (1+ counter)))
%% Ausrichten und Positionieren der Handsatz Markierung
\override TextScript.padding = 4
%%\once \textLengthOn
%%\once \override TextScript.X-offset = #-0.4
}
%% Schlagzeugvorlage
%%#(set-default-paper-size "a4" 'landscape)
\header { tagline = ##f }
\layout {
indent = #0
line-width = #160
%%\set Score.currentBarNumber = #
}
\paper {
fonts = #
(make-pango-font-tree
"Calibri"
"Calibri"
"sans"
(/ (* staff-height pt) 2.5))
print-page-number = ##f
%% Definition von Rändern und Abständen
#(define left-margin (* 3.5 cm))
#(define top-margin (* 1.5 cm))
#(define bottom-margin (* 1.5 cm))
%% Abstände zwischen den Systemen & Verhindern eines weißen Randes am Seitenende
system-system-spacing = #'((padding . 0.4) (basic-distance . 12))
%%page-count = #10 (Seitenzahl kann erzwungen werden - optional)
systems-per-page = #2 %% (Systeme pro Seite können erzwungen werden - optional)
%%ragged-last-bottom = ##f
%%ragged-bottom = ##f
}
AoBtvPdN= {\drummode { <tomh bd> 8^"L" tommh8^"R" <tomml bd hhp> 8^"R" tomh8^"L" <tomh bd> 8^"L" tomh8^"L" <sn bd hhp> 8^"L" tommh8^"R" } }
wmYmsIVY= {\drummode { <sn bd> 8^"L" tomml8^"R" <tomml bd hhp> 8^"R" tomh8^"L" <sn bd> 8^"L" tomh8^"L" <tomh bd hhp> 8^"L" tomml8^"R" } }
PIIqmtbv= {\drummode { <sn bd> 8^"L" tommh8^"R" <tomml bd hhp> 8^"R" sn8^"L" <sn bd> 8^"L" sn8^"L" <sn bd hhp> 8^"L" tommh8^"R" } }
xfOnhjHj= {\drummode { <tomh bd> 8^"L" tommh8^"R" <tommh bd hhp> 8^"R" tomh8^"L" <tomh bd> 8^"L" tomh8^"L" <tomh bd hhp> 8^"L" tommh8^"R" } }
PMYqyUVM= {\drummode { <tomml bd> 8^"R" tomml8^"R" <tomml bd hhp> 8^"R" tomml8^"R" <sn bd> 8^"L" tomml8^"R" <sn bd hhp> 8^"L" tomml8^"R" } }
sDfKRgPb= {\drummode { <tommh bd> 8^"R" tomml8^"R" <tomml bd hhp> 8^"R" tomml8^"R" <tomh bd> 8^"L" tomml8^"R" <sn bd hhp> 8^"L" tomml8^"R" } }
iRwcFQLr= {\drummode { <tommh bd> 8^"R" tommh8^"R" <tomml bd hhp> 8^"R" tommh8^"R" <tomh bd> 8^"L" tommh8^"R" <tomh bd hhp> 8^"L" tommh8^"R" } }
kKHhLMPF= {\drummode { <tomml bd> 8^"R" tomml8^"R" <tommh bd hhp> 8^"R" tomml8^"R" <sn bd> 8^"L" tomml8^"R" <tomh bd hhp> 8^"L" tomml8^"R" } }
AoBtvPdN= { \repeat unfold 1 { \AoBtvPdN } }
wmYmsIVY= { \repeat unfold 1 { \wmYmsIVY } }
PIIqmtbv= { \repeat unfold 1 { \PIIqmtbv } }
xfOnhjHj= { \repeat unfold 1 { \xfOnhjHj } \break }
PMYqyUVM= { \repeat unfold 1 { \PMYqyUVM } }
sDfKRgPb= { \repeat unfold 1 { \sDfKRgPb } }
iRwcFQLr= { \repeat unfold 1 { \iRwcFQLr } }
kKHhLMPF= { \repeat unfold 1 { \kKHhLMPF } \break }
drumnotes = {
\AoBtvPdN
\wmYmsIVY
\PIIqmtbv
\xfOnhjHj
\PMYqyUVM
\sDfKRgPb
\iRwcFQLr
\kKHhLMPF
}
\score {
\new DrumStaff
\with {
\consists "Parenthesis_engraver"
instrumentName = #"1"
\numericTimeSignature
\stemUp
\my-staff-count-mod
}
%% Hier werden die eigentlichen Noten eingefügt. Also die oben definierten Drumnotes.
<<
\time 4/4
\drumnotes
>>
% Notendruck
\layout {}
% MIDI Erzeugung
\midi {\tempo 4 = 120}
}
%% midis
\midiOut \drumnotes
Wie gewünscht werden dabei die Takte 1 bis 8 als MIDI generiert. Ist es auch möglich, zwei MIDI Dateien zu erzeugen? Also in dem Beispiel pro Zeile eine MIDI Datei Nr. 1 mit den Takten 1 bis 4 und Nr. 2 mit den Takten 5 bis 8?
-
Unter der Voraussetzung, daß Du immer komplette Takte vordefinierst sollte folgendes funktionieren.
\version "2.18.2"
#(define (split-list-in-n-sized-sublists nmbr lst)
(define (helper n l1 l2)
(if (> n (length l1))
(remove null? (reverse (cons l1 l2)))
(helper
n
(drop l1 n)
(cons (take l1 n) l2))))
(helper nmbr lst '()))
midiOut =
#(define-void-function (parser location number-of-elts m)(number? ly:music?)
(let* ((elts (ly:music-property m 'elements)))
; (display-scheme-music elts)
(if (null? elts)
;; do nothing if elts are empty
#f
(let (;; make a midi from every entry of elts
(scores
(map
(lambda (e)
#{
\score {
\new DrumStaff $(make-sequential-music e)
\midi {\tempo 4 = 120}
}
#})
(split-list-in-n-sized-sublists number-of-elts elts))))
;; return them, each as a new book
(for-each
(lambda (score name)
(let* ((my-new-book
(ly:make-book
$defaultpaper
$defaultheader
score)))
(ly:book-process
my-new-book
$defaultpaper
$defaultmidi
;; add increasing numbers to the name
(format #f "~a-test" name))))
scores
(iota (length elts) 1 1))))))
#(define counter 1)
my-staff-count-mod =
\with {
instrumentName = "1"
shortInstrumentName = ""
\override InstrumentName.after-line-breaking =
#(lambda (grob)
(ly:grob-set-property! grob 'text
(format #f "~5a" (number->string counter)))
(set! counter (1+ counter)))
%% Ausrichten und Positionieren der Handsatz Markierung
\override TextScript.padding = 4
%%\once \textLengthOn
%%\once \override TextScript.X-offset = #-0.4
}
%% Schlagzeugvorlage
%%#(set-default-paper-size "a4" 'landscape)
\header { tagline = ##f }
\layout {
indent = #0
line-width = #160
%%\set Score.currentBarNumber = #
}
\paper {
fonts = #
(make-pango-font-tree
"Calibri"
"Calibri"
"sans"
(/ (* staff-height pt) 2.5))
print-page-number = ##f
%% Definition von Rändern und Abständen
#(define left-margin (* 3.5 cm))
#(define top-margin (* 1.5 cm))
#(define bottom-margin (* 1.5 cm))
%% Abstände zwischen den Systemen & Verhindern eines weißen Randes am Seitenende
system-system-spacing = #'((padding . 0.4) (basic-distance . 12))
%%page-count = #10 (Seitenzahl kann erzwungen werden - optional)
systems-per-page = #2 %% (Systeme pro Seite können erzwungen werden - optional)
%%ragged-last-bottom = ##f
%%ragged-bottom = ##f
}
AoBtvPdN= {\drummode { <tomh bd> 8^"L" tommh8^"R" <tomml bd hhp> 8^"R" tomh8^"L" <tomh bd> 8^"L" tomh8^"L" <sn bd hhp> 8^"L" tommh8^"R" } }
wmYmsIVY= {\drummode { <sn bd> 8^"L" tomml8^"R" <tomml bd hhp> 8^"R" tomh8^"L" <sn bd> 8^"L" tomh8^"L" <tomh bd hhp> 8^"L" tomml8^"R" } }
PIIqmtbv= {\drummode { <sn bd> 8^"L" tommh8^"R" <tomml bd hhp> 8^"R" sn8^"L" <sn bd> 8^"L" sn8^"L" <sn bd hhp> 8^"L" tommh8^"R" } }
xfOnhjHj= {\drummode { <tomh bd> 8^"L" tommh8^"R" <tommh bd hhp> 8^"R" tomh8^"L" <tomh bd> 8^"L" tomh8^"L" <tomh bd hhp> 8^"L" tommh8^"R" } }
PMYqyUVM= {\drummode { <tomml bd> 8^"R" tomml8^"R" <tomml bd hhp> 8^"R" tomml8^"R" <sn bd> 8^"L" tomml8^"R" <sn bd hhp> 8^"L" tomml8^"R" } }
sDfKRgPb= {\drummode { <tommh bd> 8^"R" tomml8^"R" <tomml bd hhp> 8^"R" tomml8^"R" <tomh bd> 8^"L" tomml8^"R" <sn bd hhp> 8^"L" tomml8^"R" } }
iRwcFQLr= {\drummode { <tommh bd> 8^"R" tommh8^"R" <tomml bd hhp> 8^"R" tommh8^"R" <tomh bd> 8^"L" tommh8^"R" <tomh bd hhp> 8^"L" tommh8^"R" } }
kKHhLMPF= {\drummode { <tomml bd> 8^"R" tomml8^"R" <tommh bd hhp> 8^"R" tomml8^"R" <sn bd> 8^"L" tomml8^"R" <tomh bd hhp> 8^"L" tomml8^"R" } }
AoBtvPdN= { \repeat unfold 1 { \AoBtvPdN } }
wmYmsIVY= { \repeat unfold 1 { \wmYmsIVY } }
PIIqmtbv= { \repeat unfold 1 { \PIIqmtbv } }
xfOnhjHj= { \repeat unfold 1 { \xfOnhjHj } \break }
PMYqyUVM= { \repeat unfold 1 { \PMYqyUVM } }
sDfKRgPb= { \repeat unfold 1 { \sDfKRgPb } }
iRwcFQLr= { \repeat unfold 1 { \iRwcFQLr } }
kKHhLMPF= { \repeat unfold 1 { \kKHhLMPF } \break }
drumnotes = {
\AoBtvPdN
\wmYmsIVY
\PIIqmtbv
\xfOnhjHj
\PMYqyUVM
\sDfKRgPb
\iRwcFQLr
\kKHhLMPF
}
\score {
\new DrumStaff
\with {
\consists "Parenthesis_engraver"
instrumentName = #"1"
\numericTimeSignature
\stemUp
\my-staff-count-mod
}
%% Hier werden die eigentlichen Noten eingefügt. Also die oben definierten Drumnotes.
<<
\time 4/4
\drumnotes
>>
% Notendruck
\layout {}
% MIDI Erzeugung
\midi {\tempo 4 = 120}
}
%% midis
\midiOut #4 \drumnotes
HTH,
Harm
P.S.
Du nennst Deine Variablen:
AoBtvPdN
wmYmsIVY
PIIqmtbv
xfOnhjHj
PMYqyUVM
sDfKRgPb
iRwcFQLr
kKHhLMPF
... wirklich?
P.P.S.
Ein minimal-example ist das jetzt nicht gewesen
-
P.S.
Du nennst Deine Variablen:
AoBtvPdN
wmYmsIVY
PIIqmtbv
xfOnhjHj
PMYqyUVM
sDfKRgPb
iRwcFQLr
kKHhLMPF
... wirklich?
Sieht aus wie der Output von pwgen -s -0. Man könnte die Option -s weglassen, dann wären die wenigstens aussprechbar :D
-
Vielen Dank für diese Lösung. Das funktioniert sehr gut :)
Ja, ich nenne die Variablen so - genauer gesagt, meine Zufallsliste aus Excel...ist eben schon viel automatisiert bei mir. Für mich war das durchaus ein minimal Beispiel. Ich habe den Drumcode für die üblichen 20 bis 30 A4 Seiten in diesem Beispiel mal weggelassen ;)