Moduł MIDI
Uniwersytet Gdański - Instytut Matematyki - Zakład Informatyki - Strona domowaCo to jest ?
MIDI to moduł, a właściwie zestaw modułów, służących do tworzenia plików typu .mid, czyli plików sterujących syntezatorem wbudowanym w kartę dźwiękową. W tym dokumencie skupię się tylko na zarysach tych modułów, szczególnie na funkcjach wykorzystywanych w programie przykładowym, który zamieszczam pod koniec dokumentu.
MIDI::Opus
Jest to moduł służący do operowania na utworach MIDI. Oto parametry, które można przekazać konstruktorowi :
- format
- Określa format pliku midi, zazwyczaj po prostu 0.
- ticks
- Prędkość utworu.
- tracks
- Lista ścieżek dźwiękowych, które opiszę za chwilę.
- from_file
- Wczytuje podany plik.
- from_handle
- Wczytuje dane z podanego uchwytu do pliku (strumienia).
- no_parse
- Pozwala zapobiegać parsowaniu wczytywanego pliku (gdy jest to niepotrzebne).
A oto wybrane metody :
- dump
- Zrzuca zawartość utworu do pliku tekstowego.
- write_to_file
- Zapisuje utwór do pliku .mid.
MIDI::Track
Moduł służący do tworzenia i modyfikowania ścieżek utworów. Ścieżki są składowymi utworu - korzysta z nich moduł opisany powyżej. Najważniejszym parametrem konstruktora jest events, który jest listą zdarzeń MIDI. Każdy event jest komunikatem, który może między innymi oznaczać wydobycie konkretnego dźwięku, ale nie tylko. Opisany poniżej moduł odpowiada za eventy.
MIDI::Event
Każdy event jest listą podobną do tej :
( 'note_on', 141, 4, 50, 64 )
Pierwszym parametrem jest nazwa komunikatu, drugim czas liczony od poprzedniego komunikatu. Pozostałe parametry są różne, zależnie od typu komunikatu. Pełną listę komunikatów można znaleźć w dokumentacji modułu, ja przytoczę te najważniejsze.
- ('note_on', dtime, channel, note, velocity)
- Rozpoczyna odtwarzanie dźwięku w czasie dtime od poprzedniego komunikatu, na kanale channel (0 - 15), o wysokości note (0 - 127) i o głośności velocity (0 - 127).
- ('note_off', dtime, channel, note, velocity)
- Kończy odtwarzanie dźwięku, rozpoczętego poprzednim komunikatem.
- ('patch_change', dtime, channel, patch)
- Zmienia barwę dźwięku na podaną parametrem patch (0 - 127).
Komunikatów jest o wiele więcej, m.in. 'key_after_touch', 'pitch_wheel_change' i inne.
Przykład
Posiadając podstawową wiedzę o opisanych modułach, można napisać prosty program, który zapisze plik midi ze znaną melodię :)
# Program generujacy melodie
# Autor : S.P.
use MIDI;
use warnings;
@NAZWY_NUT = ('C1', 'C#1', 'D1', 'D#1', 'E1', 'F1', 'F#1', 'G1', 'G#1', 'A1', 'B1', 'H1',
'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'B', 'H',
'c', 'c#', 'd', 'd#', 'e', 'f', 'f#', 'g', 'g#', 'a', 'b', 'h',
'c1', 'c#1', 'd1', 'd#1', 'e1', 'f1', 'f#1', 'g1', 'g#1', 'a1', 'b1', 'h1',
'c2', 'c#2', 'd2', 'd#2', 'e2', 'f2', 'f#2', 'g2', 'g#2', 'a2', 'b2', 'h2',
'c3');
$numer_pierwszej_nuty = 24;
%NUTY = ();
for($i = 0 ; $i < $#NAZWY_NUT ; $i++) {
$NUTY{$NAZWY_NUT[$i]} = $i + $numer_pierwszej_nuty;
}
my @events = (
['set_tempo', 0, 500_000],
);
@STAR_WARS = ('f1', 50, 'f1', 50, 'f1', 50, 'b1', 200, 'f2', 200, 'd#2', 30,
'd2', 30, 'c2', 30, 'b2', 200, 'f2', 60, 'd#2', 30, 'd2', 30,
'c2', 30, 'b2', 200, 'f2', 60, 'd#2', 30, 'd2', 30, 'd#2', 30,
'c2', 300, 'b1', 200, 'f2', 200,
'd#2', 30, 'd2', 30, 'c2', 30, 'b2', 200, 'f2', 60, 'd#2', 30,
'd2', 30, 'c2', 30, 'b2', 200, 'f2', 60, 'd#2', 30, 'd2', 30,
'd#2', 30, 'c2', 200, 'f1', 50, 'f1', 50, 'g1', 140, 'g1', 60,
'd#2', 50, 'd2', 50, 'c2', 50, 'b1', 50, 'b1', 30, 'c2', 30,
'd2', 30, 'c2', 70, 'g1', 30, 'a1', 100, 'f1', 40, 'f1', 40,
'g1', 130, 'g1', 60, 'd#2', 50, 'd2', 50, 'c2', 50, 'b1', 50,
'f2', 70, 'c2', 30, 'c2', 250, 'f1', 30, 'f1', 30, 'g1', 140,
'g1', 60, 'd#2', 50, 'd2', 50, 'c2', 50, 'b1', 50, 'b1', 30,
'c2', 30, 'd2', 30, 'c2', 70, 'g1', 30, 'a1', 100, 'f1', 50,
'f1', 60, 'b1', 60, 'g#1', 40, 'f#1', 60, 'f1', 40, 'd#1', 60,
'c#1', 40, 'c1', 60, 'b', 40, 'f1', 300);
graj(@STAR_WARS);
my $pianino_track = MIDI::Track->new({ 'events' => \@events });
my $opus = MIDI::Opus->new(
{ 'format' => 0, 'ticks' => 96, 'tracks' => [ $pianino_track ] } );
$opus->write_to_file( 'starwars.mid' );
sub graj {
@MELODIA = @_;
for($i = 0 ; $i < $#MELODIA ; $i = $i + 2) {
pianino($MELODIA[$i], 0, $MELODIA[$i + 1]);
}
}
sub pianino {
($wysokosc, $opoznienie, $dlugosc) = @_;
push @events, ['note_on', $opoznienie, 1, $NUTY{$wysokosc}, 127];
push @events, ['note_off', $dlugosc, 1, $NUTY{$wysokosc}, 127];
}
Dodatkowe informacje
Dokumentacja modułu znajduje się na stronie http://search.cpan.org/~sburke/MIDI-Perl-0.81/lib/MIDI.pm
Jeżeli mamy kłopot z odtworzeniem pliku midi na standardowym odtwarzaczu multimedialnym, możemy poszukać w Internecie odtwarzacza przeznaczonego wyłącznie do odczytu plików midi. Uwaga: nie każda karta dźwiękowa posiada syntezator, musimy wtedy kombinować z rozwiązaniami software'owymi.
Autor opracowania
S.P.