Automatyczna Harmonizacja Melodii

Transkrypt

Automatyczna Harmonizacja Melodii
Bielska Wyższa Szkoła
im. Józefa Tyszkiewicza
w Bielsku-Białej
Praca dyplomowa
Filip Łakomik
Automatyczna harmonizacja melodii
Opiekun pracy: dr Maciej Smołka
Ocena pracy:
Numer albumu: 2077
Numer ewidencyjny pracy
Bielsko - Biała, 2008
Bielsko-Biała dn.31.01.2008
Imię i nazwisko:
Filip Łakomik
Nr albumu:
2077
Wydział:
Zarządzania i Informatyki
Kierunek:
Informatyka
OŚWIADCZENIE
Świadom odpowiedzialności prawnej oświadczam, że złożona praca inżynierska
pt.: „Automatyczna harmonizacja melodii” została napisana przeze mnie samodzielnie.
Równocześnie oświadczam, że praca ta nie narusza prawa autorskiego
w rozumieniu ustawy z dnia 4 lutego 1994 roku o prawie autorskim i prawach
pokrewnych (Dz.U.1994 nr 24 poz. 83) oraz dóbr osobistych chronionych prawem
cywilnym.
Ponadto praca nie zawiera informacji i danych uzyskanych w sposób nielegalny
i nie była wcześniej przedmiotem innych procedur urzędowych związanych
z uzyskaniem dyplomów lub tytułów zawodowych uczelni wyższej.
Podpis:
Spis treści
1 Informacje wstępne..................................................................5
1.1 Cele projektu...................................................................................5
1.2 Opis problemu harmonizacji melodii..............................................7
1.3 Istniejące rozwiązania.....................................................................9
2 Rozwiązanie problemu..........................................................11
2.1 Wybór narzędzi..............................................................................11
2.2 Ogólny schemat rozwiązania........................................................12
2.3 Wtyczka „Wizard”.........................................................................15
2.4 Wtyczka „Harmonizer”.................................................................19
2.5 Wtyczka „RuleChecker”...............................................................27
3 Podsumowanie.......................................................................37
3.1 Test wydajności.............................................................................37
3.2 Możliwości rozwoju......................................................................41
3.3 Wnioski.........................................................................................43
4 Bibliografia............................................................................45
3
4
1 Informacje wstępne
1.1 Cele projektu
Celem projektu jest stworzenia narzędzia:
•
przeznaczonego dla muzyków (szczególnie aranżerów i kompozytorów) pozwalającego w automatyczny sposób zharmonizować zadaną melodię napisaną
w dowolnej tonacji, a nawet atonalną;
•
umożliwiającego harmonizację według reguł określonych przez użytkownika,
pozwalając na uzyskanie efektów dostosowanych do jego upodobań i potrzeb;
•
generującego rozwiązania w których dopuszczalne są błędy, które użytkownik
będzie musiał poprawić ręcznie, jednak ilość koniecznych zmian musi być
na tyle mała żeby zaoszczędzić czas w stosunku do ręcznego harmonizowania
melodii.
Celem projektu nie jest:
•
Stworzenie narzędzia generującego rozwiązania bezbłędne w rozumieniu teorii
muzyki (jakiejkolwiek teorii muzyki).
Komentarz:
Chociaż projekt tworzony będzie w oparciu o wybrane reguły harmonii (głównie klasycznej) ma on pozostawiać użytkownikowi możliwość eksperymentowania z regułami.
Użytkownik ma mieć możliwość konfiguracji w jakim stopniu to, czy połączenie harmoniczne jest zgodne/niezgodne z daną regułą, ma wpływać na to, czy zostanie ono zastosowane w rozwiązaniu.
Istnieją w harmonii reguły bardzo szczegółowe np. dotyczące łączenia konkretnych
dwóch akordów ze sobą, które stanowią wyjątki od bardziej ogólnych reguł. Implementacja wszystkich istniejących reguł (o ile możliwe jest w ogóle ich zebranie) byłaby bardzo czasochłonna dla programisty, a ich konfiguracja dla użytkownika. Dlatego w ra5
mach projektu zakłada się implementację tylko reguł dotyczących łączenia akordów
„w ogóle”, a nie w szczególnych przypadkach jednocześnie pozostawiając użytkownikowi miejsce na definiowanie własnych reguł.
Celem reguł ogólnych (zaimplementowanych w programie) ma być zminimalizowanie
liczby błędów w rozwiązaniu generowanym przez program. Ewentualnych pojedynczych niepożądanych przez użytkownika błędów użytkownik będzie mógł uniknąć definiując własne reguły lub po prostu ręcznie zmodyfikować rozwiązanie.
6
1.2 Opis problemu harmonizacji melodii
Rozdział ten definiuje kilka pojęć z dziedziny problemu. Definicje te są podane
w sposób ogólny bez wchodzenia w szczegóły tak, żeby umożliwić osobie niezwiązanej
z dziedziną zrozumienie problemu harmonizacji melodii. Szczegółowe definicje oraz
związaną z nimi teorię można znaleźć w: [KSH184] oraz [KSH284].
“Harmonizacja – technika tworzenia współbrzmień akordowych
towarzyszących jakiejś melodii” (definicja z [JHSM77])
Żeby zrozumieć powyższą definicję należy zrozumieć czym jest melodia oraz współbrzmienie akordowe.
Melodia (jeden z elementów dzieła muzycznego) to ciąg następujących kolejno dźwięków różnej wysokości (częstotliwości). Melodia najczęściej łączy się z innym elementem dzieła muzycznego jakim jest rytm. Podczas gdy melodia określa jakiej wysokości
dźwięki mają być zagrane i w jakiej kolejności, rytm określa w jakim czasie te dźwięki
mają brzmieć.
Sama melodia i rytm nie tworzą jeszcze dzieła muzycznego. Z połączeniem wyłącznie
tych dwóch elementów mamy do czynienia bardzo rzadko. Nawet pojedynczy muzyk
grający solo np. na flecie, mimo iż nie jest w stanie wydać z tego instrumentu kilku
dźwięków jednocześnie wzbogaci wykonywaną melodię o inne elementy takie jak
np. dynamika (zróżnicowana głośność dźwięków), artykulacja (sposób wydobycia
dźwięku) itp. Więcej na temat elementów dzieła muzycznego można przeczytać
w [BDSEDM]. Przykładem połączenia wyłącznie melodii i rytmu może być
tzw. PC speaker (głośniczek systemowy) – najstarszy system dźwiękowy w komputerach PC, który umożliwiał wydawanie jednego dźwięku o określonej częstotliwości
w określonym czasie. Często można było go posłuchać w pierwszych grach w systemie
MS DOS.
Współbrzmienie akordowe to jednoczesne brzmienie co najmniej trzech dźwięków
o różnej wysokości oraz nazwie. Stosunki pomiędzy tymi dźwiękami określają zasady
akustyki, harmonii i psychologii muzyki. O zasadach budowy akordów oraz ich podstawach akustycznych przeczytać można w [KSH184].
7
Przykładem współbrzmienia akordowego może być np. naciśnięcie na fortepianie
co najmniej trzech klawiszy jednocześnie albo szarpnięcie kilku strun gitary naraz.
Harmonizacja melodii będzie więc polegała na dopisaniu do pojedynczych dźwięków
melodii dźwięków współbrzmiących. Realizuje się to poprzez odnalezienie akordu
zawierającego już dźwięk melodii i dopisanie pozostałych dźwięków tego akordu.
Zgodnie z powyższym:
•
przykładem utworu niezharmonizowanego będzie np. utwór śpiewany przez pojedynczą osobę, bez akompaniamentu;
•
przykładem utworu zharmonizowanego może być utwór chóralny w którym członkowie chóru podzieleni są na grupy według skali głosów: bas, tenor, alt i sopran
(od najniższego do najwyższego głosu) i każda grupa śpiewa inną melodię jednocześnie. Cztery osobne melodie tworzą współbrzmienia czterech różnych dźwięków,
czyli współbrzmienia harmoniczne następujące po sobie.
Przykład chóru ukazuje nieco inny sposób rozumienia harmonizacji: jako dopisania
do istniejącej melodii wykonywanej np. przez soprany kilku (w tym przypadku trzech)
dodatkowych melodii dla basów, tenorów i altów. Takie spojrzenie pozwala zauważyć
że podczas zastępowania kolejnych dźwięków współbrzmieniami należy brać pod uwagę nie tylko to, czy współbrzmienie zawiera dany dźwięk (sopranu), ale również
to czy jego pozostałe dźwięki (dźwięki pozostałych głosów) tworzą ładne melodie z poprzednimi dźwiękami tych głosów, czyli sprawdzać połączenia z poprzednimi współbrzmieniami. O zasadach łączenia współbrzmień akordowych można przeczytać
w [KSH184] oraz [KSH284].
8
1.3 Istniejące rozwiązania
Jedynym istniejącym rozwiązaniem problemu harmonizacji melodii, jakie udało
mi się odnaleźć jest wtyczka dostarczana z programem Sibelius 5 (rozbudowanym edytorem nut) o nazwie: „Add Simple Harmony” w grupie wtyczek: „Composing Tools”.
Umożliwia ona automatyczne dodanie akompaniamentu do zaznaczonej melodii w postaci prostych akordów. Więcej o programie Sibelius przeczytać można na [SHP08].
Wady rozwiązania:
•
brak możliwości konfiguracji – harmonizując daną melodię za pomocą tej wtyczki
nie mamy żadnego wpływu na wynik działania programu. Zawsze uzyskamy ten
sam wynik, co uniemożliwia nam poszukiwania rozwiązania, które najlepiej nam
odpowiada. Zadaną melodię zwykle można zharmonizować na wiele różnych sposobów zgodnie z regułami, a ta wtyczka tego nie umożliwia;
•
brak możliwości definiowania własnych reguł;
•
brak możliwości definicji własnych akordów;
•
powtarzające się wyniki, schematyczne działanie – jeżeli w harmonizowanej melodii występuje kilka razy ten sam motyw (fragment melodii) to za każdym razem
do jego harmonizacji zostaną użyte dokładnie te same współbrzmienia akordowe
do jego harmonizacji.
Zalety rozwiązania:
•
łatwa obsługa,
•
szybkie działanie.
Zalety wynikające ze zintegrowania wtyczki z rozbudowanym edytorem nut:
•
dobra reprezentacja graficzna zapisu nutowego;
•
możliwość szybkiej i łatwej modyfikacji rozwiązania za pomocą dostępnych w edytorze narzędzi;
•
możliwość odsłuchania utworu;
•
brak konieczności instalowania osobnego programu wspomagającego harmonizację.
9
10
2 Rozwiązanie problemu
2.1 Wybór narzędzi
Harmonizacja jest tylko jedną z wielu czynności jakie należy wykonać podczas
tworzenia czy aranżowania utworu muzycznego. Trudno wyobrazić sobie kompozytora,
który włącza inny program żeby napisać melodię, potem kolejny w celu jej harmonizacji, jeszcze inny żeby ją przetransponować itd. To tak jakby napisać osobny program
do sprawdzania pisowni w tekście, osobny do jego edycji, a jeszcze inny umożliwiający
jego wydrukowanie. Dlatego tak, jak w edytorach tekstu integruje się wiele funkcjonalności umożliwiających i ułatwiających przygotowanie dokumentu, tak również w przypadku edytorów nut najlepszym rozwiązaniem wydaje się być zintegrowanie dodatkowych funkcjonalności w jednym programie.
Na rynku istnieją dwa czołowe (komercyjne) edytory nut Sibelius oraz Finale [FM08].
Bardziej popularny jest Sibelius ze względu na łatwiejszą i bardziej intuicyjną obsługę.
Najistotniejszym kryterium wyboru w przypadku opracowywanego projektu jest możliwość prostej rozbudowy edytora o dodatkowe funkcjonalności. Sibelius posiada wbudowany edytor do pisania wtyczek. Do tworzenia wtyczek używa się języka ManuScript
specjalnie zaprojektowanego m.in. do automatyzacji technik kompozycji i aranżacji.
Opis języka znajduje się w [UTMSL05]. Wersja demonstracyjna Sibeliusa w wersji 5,
którą wybrałem do realizacji mojego projektu ograniczona jest jedynie brakiem możliwości pisania do plików, co w przypadku wykonania algorytmu harmonizacji nie jest
niezbędne.
11
2.2 Ogólny schemat rozwiązania
Chociaż ManuScript jest językiem obiektowym został on jednak stworzony
do manipulacji istniejącymi obiektami. Skutkiem tego podejścia jest brak możliwości
pisania własnych klas oraz tworzenia instancji istniejących klas. Istnieją jednak sposoby
radzenia sobie z powyższym ograniczeniem.
Wtyczka pisana w języku ManuScript sama przypomina klasę statyczną:
Okno edytora wtyczek Sibelius 5
Jak widać na powyższym rysunku przedstawiającym okno edytora wtyczek programu
Sibelius 5 Demo podobnie jak klasa, wtyczka składa się z danych (ang. data) oraz operujących na nich metod (ang. methods). Dodatkowo może zawierać i wyświetlać okna
dialogowe (ang. dialogs), które tworzy się za pomocą prostego edytora graficznego.
Podobnie jak w przypadku klas statycznych nie można tworzyć instancji wtyczek. Niemożliwe jest też we wtyczkach definiowanie pól prywatnych, agregacja oraz dziedziczenie.
Mimo wyżej wymienionych ograniczeń na poziomie koncepcyjnym wtyczki podobnie
jak obiekty (instancje klas) mogą być rozumiane jako byty o określonych odpowiedzialnościach i służyć do modularyzacji rozwiązania.
W problemie harmonizacji melodii można wydzielić dwa główne cele, które realizowane będą przez dwie wtyczki.
12
Konfiguracja algorytmu harmonizacji – wtyczka „Wizard”:
•
odpowiedzialna za komunikację z użytkownikiem - za pomocą okien dialogowych
odpyta użytkownika o parametry algorytmu harmonizacji;
•
sprawdza poprawności podawanych przez użytkownika danych;
•
uruchamia algorytm harmonizacji z określonymi parametrami.
Wykonanie algorytmu harmonizacji – wtyczka „Harmonizer”
•
zawiera implementację algorytmu harmonizacji melodii, którego parametry określane są przez wtyczkę „Wizard”.
Pseudokod algorytmu harmonizacji może wyglądać w następujący sposób:
Dla każdego dźwięku D w zaznaczonej melodii wykonuj:
begin
1. Wyszukaj akordy zawierające dźwięk D
2. Dla każdego akordu A2[i] z wyszukanych akordów oceń
połączenie z poprzednim akordem A1 na podstawie zasad ogólnych oraz zdefiniowanych przez użytkownika
3. Zastąp dźwięk D akordem, którego połączenie z akordem A1 zostało najwyżej ocenione
end.
Drugi krok tego algorytmu jest najbardziej skomplikowany. Powtarzana jest w nim
czynność od której sam algorytm harmonizacji jest niezależny:
oceń połączenie z poprzednim akordem A1 na podstawie
zasad ogólnych oraz zdefiniowanych przez użytkownika
Kod odpowiedzialny za tę czynność należy więc umieścić w osobnej wtyczce.
13
Ocena połączenia pomiędzy dwoma akordami – wtyczka „RuleChecker”:
•
zawiera reguły łączenia akordów;
•
ocenia jakość połączenia dwóch akordów w zależności od tego w jakim stopniu połączenie jest zgodne z regułami w niej zaimplementowanymi oraz zdefiniowanymi
przez użytkownika.
Poniższy diagram przedstawia schemat takiego rozwiązania:
Diagram przypomina diagram klas w języku UML, jednak należy rozumieć go nieco
inaczej. W sposób w jaki typowo przedstawiane są klasy przedstawiłem na nim wtyczki,
natomiast strzałka pomiędzy dwiema wtyczkami oznacza, że wtyczka wskazująca uruchamia wtyczkę wskazywaną.
W tym przypadku wtyczkę „Wizard” uruchamia użytkownik. „Wizard” odpyta go o parametry algorytmu, a następnie uruchomi wtyczkę „Harmonizer” z podanymi parametrami parametrami. „Harmonizer” wykona algorytm harmonizacji, a za każdym razem
kiedy będzie potrzebował ocenić połączenie dwóch akordów uruchomi wtyczkę
„RuleChecker”.
Zalety takiego podziału odpowiedzialności:
•
Oddzielenie wtyczki oceniającej połączenie akordów od algorytmu harmonizacji
umożliwia jej wykorzystanie do oceny połączeń akordów w innych algorytmach
harmonizacji.
•
Oddzielenie sposobu oceny połączenia pozwala też na jego podmianę bez większych zmian w algorytmie harmonizacji.
•
Oddzielenie wtyczki służącej do konfiguracji poza przejrzystością umożliwi też łatwe dostosowanie rozwiązania do systemu Mac OS, w którym nie działają okna dialogowe stworzone w wersji Sibeliusa pod system Windows, bo tylko ta wtyczka
używa okien dialogowych więc wystarczy jej podmiana na napisaną w systemie
Mac OS.
•
Możliwość niezależnego testowania wtyczek.
14
2.3 Wtyczka „Wizard”
Ponieważ program (Sibelius 5 Demo) nie jest dostępny w polskiej wersji językowej komunikaty wtyczki wyświetlane będą w języku angielskim.
Budowa wtyczki
Wtyczka składa się z sześciu okien dialogowych w których użytkownik wprowadza poszczególne parametry algorytmu harmonizacji:
1. okno powitalne (StartDlg);
2. okno
wyboru
ścieżki
do
pliku
zawierającego
bazę
akordów
(ChordsPathDlg);
3. okno wyboru interwału o jaki mają być przetransponowane akordy tak, by odpowiadały tonacji melodii (KeyDlg);
4. okno wyboru ścieżki do pliku zawierającego definicję reguł użytkownika
(RulesPathDlg);
5. Okno konfiguracji parametrów reguł sprawdzanych przez wtyczkę „RuleChecker” (RulesDlg);
6. okno informujące o ukończeniu konfiguracji i gotowości do uruchomienia algorytmu harmonizacji (FinishDlg);
Transponowanie to przenoszenie dźwięków z jednej tonacji do drugiej przez zmianę
ich wysokości o zadany interwał (miarę odległości między dźwiękami). Dzięki temu
można przygotować bazę akordów tylko dla jednej tonacji, a następnie w razie potrzeby
transponować ją do innych.
Wszystkie okna mają identyczne rozmiary, wyświetlane są pośrodku ekranu i zawierają
następujące elementy interfejsu graficznego:
•
przyciski nawigacyjne: „Back”(wszystkie oprócz pierwszego) i „Next” (wszystkie
oprócz ostatniego) oraz przycisk: „Cancel” oraz związane z nimi metody;
•
odpowiednie pola edycyjne służące do wpisania parametrów;
•
etykiety tekstowe z podpowiedziami.
15
Działanie wtyczki
Metoda Run()
Działanie kodu metody Run() wtyczki „Wizard” (uruchamianej po kliknięciu na nazwę wtyczki w menu głównym programu Sibelius) polega na sprawdzeniu czy została
zaznaczona melodia do harmonizacji. Jeśli tak, to wyświetlane są kolejne okna konfiguracyjne, jeżeli nie to użytkownik proszony jest o zaznaczenie melodii i ponowne uruchomienie wtyczki.
Wyświetlanie okien realizowane jest za pomocą następującego kodu:
ActDialog = "StartDlg";
while(ActDialog!="End")
{
Sibelius.ShowDialog(@ActDialog,Self);
}
Kod jest podobny do kodu popularnych języków programowania jak Java czy C++,
jednak jedna rzecz wymaga w nim wyjaśnienia. Znak „@” poprzedzający nazwę zmiennej powoduje odniesienie się nie do tej zmiennej ale do zmiennej, której nazwa jest jej
wartością. W tym przypadku wartość zmiennej ActDialog to ciąg znaków „StartDlg”
czyli zapis:
Sibelius.ShowDialog(@ActDialog,Self);
jest równoznaczny z zapisem:
Sibelius.ShowDialog(StartDlg,Self);
Zmienna ActDlg przechowuje informację o tym które okno ma zostać wyświetlone,
a okna są wyświetlane do momentu aż przyjmie ona wartość „End”.
16
Metody Next() i Back()
Kody metod związanych z przyciskami nawigacyjnymi okien są do siebie podobne,
a ich działanie polega na sprawdzeniu poprawności danych i ustaleniu które okno dialogowe ma być wyświetlone jako następne.
Np. kod metody ChordsPathDlgNext() związanej z przyciskiem: „Next” okna
ChordsPathDlg wygląda następująco:
if(Sibelius.FileExists(_ChordsPath))
{
ActDialog = "KeyDlg";
}
else
{
Sibelius.MessageBox("Wrong Path!");
}
Czyli jeśli plik o podanej ścieżce istnieje to po kliknięciu przycisku „Next” zostanie wyświetlone kolejne okno (KeyDlg), jeżeli nie program wyświetli ponownie okno
ChordsPathDlg. Metody związane z przyciskami „Back” i „Next” pozostałych okien
działają analogicznie.
Ponieważ język ManuScript nie posiada mechanizmów pozwalających na wyrażenie
przynależności metod do przycisków przyjęto konwencję nazywania metod tymi samymi nazwami co przycisków, poprzedzonymi nazwami okien dialogowych na których
przyciski się znajdują.
Metoda AnyDlgCancel()
Związana jest z przyciskami „Cancel” wszystkich okien dialogowych – jej wywołanie
przerywa działanie wtyczki: „Wizard”. Kod metody:
ActDialog = "End";
17
Metoda FinishDlgHarmonize()
Metoda ta kończy działanie wtyczki: „Wizard” i uruchamia metodę Run() wtyczki:
„Harmonizer” wraz z ustalonymi parametrami, kod metody:
ActDialog = "End";
Harmonizer.Run(_ChordsPath,
_KeyValue,
_RulesParameters,
_RulesPath);
18
2.4 Wtyczka „Harmonizer”
Wtyczka zbudowana jest z pięciu metod:
•
Run(ChP,kv, _RulesParameters, path) - zawiera algorytm harmonizacji. Parametrami metody są kolejno: ścieżka do pliku z bazą akordów, interwał o jaki mają być przetransponowane akordy, tablica z parametrami reguł oraz
ścieżka do pliku zawierającego reguły użytkownika;
•
_LoadChords(ChP) – wczytuje bazę akordów z pliku tekstowego, ścieżka
do pliku jest parametrem metody;
•
_FindPossibleChords(pitch, kv) – tworzy listę akordów, które teoretycznie mogą być zastosowane do harmonizacji danego dźwięku nie biorąc
pod uwagę reguł łączenia akordów (parametr pitch oznacza wysokość dźwięku, dla którego szukane są akordy, kv zawiera interwał o jaki akordy mają być
transponowane);
•
_FindName(ch) – odnajduje nazwę akordu w bazie, parametrem jest akord;
•
SetBestChord(x, ch) – jeżeli akord został wyżej oceniony niż akord
przechowywany w zmiennej globalnej _BestChord to jest wstawiany do tej
zmiennej. Parametry metody to ocena akordu (x) i akord (ch).
W języku ManuScript nie ma możliwości definiowania metod prywatnych i publicznych. Umownie dla zwiększenia czytelności kodu przyjęto następującą konwencję nazewnictwa metod – metoda, której nazwa rozpoczyna się od znaku podkreślenia oznacza metodę prywatną, a metoda której nazwa nie jest poprzedzona tym znakiem jest metodą publiczną. W tym przypadku metody: Run() oraz SetBestChord() to metody
publiczne, a pozostałe są metodami prywatnymi.
19
Działanie
Metoda Run(ChP,kv, _RulesParameters, path)
Odpowiada za wykonanie algorytmu harmonizacji i wprowadzenie zmian do zaznaczonej przez użytkownika melodii. Dodatkowo wyświetla okno z paskiem postępu informujące o stanie wykonywanego zadania.
Początkowymi krokami algorytmu są:
•
wczytanie bazy akordów z pliku o podanej ścieżce:
_LoadChords(ChP);
•
inicjalizacja generatora liczb pseudolosowych:
Sibelius.RandomSeedTime();
•
wyłączenie odrysowywania nut przy każdej zmianie (gdyż znacznie spowalnia
to działanie programu):
thisscore = Sibelius.ActiveScore;
thisscore.Redraw = false;
•
ustawienie wskaźnika na obiekt zaznaczenia – reprezentujący zaznaczoną przez
użytkownika melodię:
selection = thisscore.Selection;
•
obliczenie ilości nut w zaznaczonej melodii – żeby możliwe było określanie postępu harmonizacji na potrzeby okna postępu:
length=0;
for each NoteRest nr in selection
{
length = length+1;
}
20
stworzenie okna postępu:
•
Sibelius.CreateProgressDialog("Harmonizing melody
(please wait)",0,length);
Pseudokod samego algorytmu harmonizacji wygląda następująco:
Dla każdego z zaznaczonych taktów T wykonuj:
Begin
Dla każdego obiektu NR reprezentującego pojedynczy
dźwięk, lub współbrzmienie w takcie T wykonuj:
Begin
Jeżeli NR jest pojedynczym dźwiękiem:
begin
•
Znajdź możliwe do zastosowania akordy MA
•
Wybierz najbardziej odpowiedni akord A2 z MA
przez sprawdzenie połączeń MA[i] z poprzednio
zastosowanym akordem A1
•
Dopisz dźwięki akordu do NR i podpisz NR nazwą
akordu.
•
A1 := A2;
end;
Jeżeli NR jest akordem:
Begin
•
Określ nazwę NR korzystając z bazy danych.
•
A1 := NR;
end;
Aktualizuj okno postępu;
end;
End.
Posłużono się tutaj pseudokodem, ponieważ kod algorytmu w języku ManuScript jest
znacznie gorzej czytelny ze względu na konieczność reprezentacji akordów w postaci
tablic. Kod w języku ManuScript tej i innych metod w przypadku których posłużono
się pseudokodem dostępny jest w dokumentacji projektu.
21
Na koniec należy jeszcze włączyć z powrotem odrysowywanie nut, żeby zmiany dokonane w melodii się wyświetliły.
Metoda _LoadChords(ChP)
Używana jest w metodzie Run() w celu wczytania bazy akordów z pliku tekstowego.
Sam kod metody w języku ManuScript jest trywialny:
_Chords = Sibelius.ReadTextFile(ChP);
Metoda ReadTextFile() klasy Sibelius zwraca reprezentację tablicową pliku
w której kolejne rekordy odpowiadają kolejnym liniom pliku tekstowego. Należy jednak wyjaśnić budowę samego pliku przechowującego akordy.
Pierwsza linia pliku zawiera informację o ilości akordów zapamiętanych w pliku. Następna oznacza ilość dźwięków w pierwszym akordzie, kolejne linie oznaczają wysokości tych dźwięków (ustawione rosnąco) podane w postaci liczb całkowitych zgodnie
ze standardem MIDI. W tym standardzie np. dźwiękowi c¹ (czytaj „c razkreślne”) odpowiada liczba 60, a kolejnym co do wysokości dźwiękom odpowiadają kolejne liczby
całkowite.
Linia kolejna po linii z najwyższym dźwiękiem akordu zawiera nazwę tego akordu
w postaci ciągu znaków. W nazewnictwie akordów przyjęto następującą konwencję,
która ułatwia późniejsze definiowanie reguł:
•
1 znak nazwy to pierwsza litera nazwy funkcji akordu
•
2 znak to cyfra oznaczająca dodany składnik np. 7 oznacza dodaną septymę, przy
czym 0 oznacza brak dodanego składnika
•
3 znak to cyfra oznaczająca podstawę akordu np. 3 oznacza akord o podstawie tercji
•
4 znak to cyfra oznaczająca pozycję akordu np. 5 oznacza akord w pozycji kwinty
•
5 znak to cyfra oznaczająca stopień na którym zbudowany jest akord
•
6 znak oznacza układ akordu: S – układ skupiony, R – układ rozległy
•
kolejne znaki to numer akordu (jeśli istnieje inny akord o tej samej nazwie)
O pojęciach takich jak: funkcja, składnik, stopień oraz układ akordu można przeczytać
w [KSH184].
22
Kolejne linie zawierają informacje o kolejnych akordach – przykładowa baza zawierająca dwa akordy toniki (na prymie i w pozycji prymy w układzie skupionym i rozległym)
może wyglądać następująco:
2
4
48
52
55
60
T0111S
4
36
43
52
60
T0111R
Baza powinna zawierać tylko akordy, których najwyższe dźwięki (dźwięki melodii)
mieszczą się w oktawie razkreślnej – w razie potrzeby zostaną one automatycznie przetransponowane do innych oktaw.
23
Metoda _FindPossibleChords(pitch, kv)
Metoda wybiera ze wszystkich akordów (wczytanych do tablicy _Chords) te, które
mają w sopranie dźwięk, którego wysokość jest parametrem metody. Drugi parametr
mówi o jaki interwał akordy mają być transponowane.
Pierwszym krokiem metody jest określenie o ile dodatkowych oktaw mają być transponowane akordy i realizuje go następujący kod w języku ManuScript:
tkv = kv + 0;
while(pitch+tkv<60) {tkv = tkv+12;}
while(pitch+tkv>71) {tkv = tkv-12;}
Żeby powyższy kod był zrozumiały należy wyjaśnić następujące kwestie:
•
Nietypowy zapis „+ 0” wymusza skopiowanie do zmiennej tkv wartości zmiennej
kv - bez tego tkv mogłoby być interpretowane jako wskaźnik na kv.
•
Liczby 60 i 71 w pętlach while oznaczają zakres oktawy razkreślnej (wg. oznaczeń MIDI).
•
Liczba 12 dodawana lub odejmowana od zmiennej tkv to odległość oktawy wyrażona w półtonach np. dźwięk c¹ ma wartość MIDI = 60, dźwięk c w kolejnej oktawie (dwukreślnej) c² będzie miał wartość 60 + 12 = 72.
•
Zmienna pitch oznacza wysokość harmonizowanego dźwięku .
•
Zmienna kv to interwał o jaki mają być transponowane akordy do innej tonacji.
•
Zmienna tkv uwzględnia dodatkowo przesunięcie akordów o odpowiednią ilość
oktaw.
Po ustaleniu wartości tkv pozostaje stworzenie listy akordów zawierającej akordy,
które po przetransponowaniu o tkv będą miały w sopranie dźwięk o wysokości
pitch.
Pseudokod realizujący tą czynność jest następujący:
Dla każdego akordu A z bazy _Chords:
Jeśli wysokość najwyższego dźwięku w A
przetransponowana o tkv = pitch dodaj akord do listy
_PossibleChords
24
Metoda _FindName(ch, kv)
Używana jest w algorytmie jeśli użytkownik zaznaczy fragment melodii, której część
jest już zharmonizowana. Wtedy w celu prawidłowego połączenia istniejących akordów
ze wstawianymi przydatne jest ustalenie ich nazw.
Pseudokod metody jest następujący:
Ustal czy i o ile dodatkowych oktaw akord był transponowany
/* w sposób analogiczny do opisanego w przypadku metody
_FindPossibleChords() */
Dla każdego akordu z _Chords
Jeśli budowa akordu _Chords[i] jest taka sama jak
danego akordu zwróć nazwę akordu Chords[i]
Jeżeli nie znaleziono akordu o tej samej budowie zwróć ciąg
znaków ”unknown chord”.
Dla akordów o nazwie „unknown chord” reguły wymagające analizy nazwy
nie są sprawdzane.
Metoda SetBestChord(x, ch)
Używana jest przez wtyczkę „RuleChecker” i wywoływana za każdym razem, gdy
wtyczka ta oceni zadane połączenie akordów. Jeśli ocena połączenia (x) jest wyższa
niż ocena dotąd najwyżej ocenionego połączenia to akord (ch) i jego połączenia
z poprzednim akordem ustawiane są jako najlepsze, kod metody jest następujący:
if(x>_BestValue)
{
_BestValue = x;
_BestChord = ch;
}
25
26
2.5 Wtyczka „RuleChecker”
Wtyczka „RuleChecker” odpowiada za ocenę połączenia pomiędzy dwoma
akordami. Ocena jest wynikiem sprawdzenia zgodności połączenia z regułami zaimplementowanymi w tej wtyczce oraz zapisanymi w pliku przez użytkownika. Na ocenę
oprócz zgodności z daną regułą wpływa też waga nadana tej regule przez użytkownika.
Powód nadania regułom wag dobrze ilustruje następujący przykład z życia codziennego:
Weźmy pod uwagę kilka zasad, którymi kierujemy się w życiu codziennym:
1. Mężczyzna powinien ustępować pierwszeństwa kobiecie.
2. Osoby wchodzące powinny ustąpić pierwszeństwa osobom wychodzącym.
3. Należy ustąpić pierwszeństwa osobie jadącej samochodem z prawej strony.
Każda z zasad z osobna nie sprawia problemów, ale możliwe są sytuacje w których pojawią się sprzeczności np.:
–
Mężczyzna wychodzi z pomieszczenia w chwili gdy kobieta próbuje do niego
wejść.
–
Mężczyzna nadjeżdża z prawej strony.
Mężczyzna dżentelmen prawdopodobnie ustąpi pierwszeństwa kobiecie mimo
iż to on wychodzi z pomieszczenia, ale na drodze raczej uzna za ważniejsze przepisy
o ruchu drogowym.
Jego zachowanie można symulować nadając następujące wagi wymienionym wcześniej
zasadom:
Zasada 1 – waga: 2
Zasada 2 – waga: 1
Zasada 3 – waga: 3
27
O ocenie każdego z możliwych rozwiązań zadecyduje ich zgodność z zasadami oraz
wagi zasad np.:
Ustąpienie pierwszeństwa kobiecie podczas wychodzenia z pomieszczenia jest zgodne
z zasadą pierwszą i sprzeczne z zasadą drugą, a zasada 3 go nie dotyczy więc jego ocena będzie wynosić:
2 –1+0 =1
Wyjście z pomieszczenia przed kobietą jest sprzeczne z zasadą 1, ale zgodne z zasadą
drugą. Ocena więc wynosi:
-2 + 1 + 0 = -1
W ruchu drogowym dla przejechania przed kobietą ocena wynosi:
-2 + 0 + 3 = 1
Dla czekania aż kobieta przejedzie mimo że to mężczyzna ma pierwszeństwo:
2 + 0 – 3 = -1
Aby symulować zachowanie mężczyzny, który nie jest dżentelmenem można by pierwszej zasadzie ustawić wagę 0, a jeśli chciałoby się symulować zachowanie mężczyzny
przesadnie uprzejmego dla kobiet nadać jej najwyższą wagę.
Można też dodając inne reguły symulować zachowanie mężczyzny, który ustępuje
pierwszeństwa w zależności od tego na ile kobieta mu się podoba (dodając iloczyn oceny wyglądu i wagi tej reguły do całościowej oceny rozwiązania).
Podsumowując, nadawanie wag zasadom pozwala:
–
rozwiązać problem sprzecznych zasad;
–
tworzyć różne schematy postępowania przez ustawianie różnych wag regułom;
28
Podobnie jak w powyższym przykładzie w harmonii istnieją reguły, które w pewnych
sytuacjach są ze sobą sprzeczne. Stąd właśnie pomysł zastosowania wag w algorytmie
oceniającym połączenia akordów. Jednym z założeń projektu jest też możliwość dostosowania algorytmu do specyficznych potrzeb użytkownika, a konfiguracja wag jest jednym ze sposobów realizacji tego założenia.
Budowa wtyczki
Wtyczka składa się z następujących metod:
–
Run(ch1, ch2, RulesParameters, IsNewBar,path) realizującej algorytm oceny, której parametrami są kolejno: dwa akordy, których połączenie jest
oceniane, tablica z wagami kolejnych reguł, zmienna logiczna informująca o tym
czy połączenie występuje pomiędzy dwoma taktami oraz ścieżka do pliku zawierającego reguły użytkownika;
–
Zbiór metod oceniających połączenie według kolejnych reguł:
_Rule1(ch1, ch2, imp), _Rule2(ch1, ch2, imp) itd. Parametrami
wszystkich tych reguł są dwa akordy oraz waga reguły;
–
_CheckFileRules(ch1,ch2,path) – ocenia połączenie według reguł zapisanych w pliku przez użytkownika. Parametrami są dwa akordy oraz ścieżka
do pliku z regułami;
–
_IsDifferentFunction(ch1,ch2)
- pomocnicza metoda sprawdzająca
czy dwa akordy pełnią różne funkcje;
–
_CompareNames(n1,n2) – pomocnicza metoda sprawdzająca czy dwa wzory
nazw pasują do siebie.
29
Działanie wtyczki
Metoda Run(ch1, ch2, RulesParameters, IsNewBar,path):
Wtyczka najpierw inicjuje zmienne globalne: _Value reprezentującą łączną ocenę
akordu na zero oraz _IsNewBar mówiącą o tym czy akordy łączone są pomiędzy
dwoma taktami, czy znajdują się w jednym takcie zgodnie z podanym parametrem.
Kod:
_Value = 0;
_IsNewBar = IsNewBar;
Następnie wywołuje wszystkie funkcje sprawdzające reguły.
Kod:
rc = 8; //liczba zaimplementowanych reguł
i = 1;
while(i<rc)
{
x = RulesParameters[i]+0;
myRule = "_Rule" & i;
@myRule(ch1,ch2,x);
i=i+1;
}
Kolejnym krokiem jest wywołanie funkcji sprawdzającej reguły zapisane w pliku jeśli
ścieżka do pliku została podana.
Kod:
if(path!="none")
{
_CheckFileRules(ch1,ch2,path);
}
30
Na końcu wywoływana jest metoda wtyczki Harmonizer, która jeśli akord został najwyżej oceniony (z dotychczas ocenianych akordów) ustawia odpowiednie zmienne globalne we wtyczce Harmonizer.
Kod:
Harmonizer.SetBestChord(_Value, ch2);
Metody sprawdzające reguły łączenia akordów
Metoda _Rule1(ch1, ch2, imp) - „Reguła losowa”
Jest to reguła, która nie ma nic wspólnego z zasadami harmonii i służy tylko do tego,
żeby zróżnicować wyniki zwracane przez algorytm. Jej działanie polega na wylosowaniu liczby z przedziału od 0 do 100 i pomnożeniu przez nią wagi reguły oraz dodaniu
wyniku do łącznej oceny połączenia.
Kod:
result = (Sibelius.RandomNumber() % 100) * imp;
_Value = _Value + result;
Największy sens ma zastosowanie w tej regule małej wagi (w stosunku do innych
reguł). Wtedy spowoduje ona że jeśli kilka rozwiązań otrzyma identyczną ocenę to zamiast pierwszego napotkanego zostanie wylosowane jedno z najlepszych rozwiązań.
Nieco większe wagi spowodują, że lepsze rozwiązania będą miały większe szanse
na to by zostać zastosowane. Zbyt duże wagi spowodują uzyskanie losowych wyników.
Metoda _Rule2(ch1, ch2, imp) - „Reguła najkrótszej drogi”
Często pojawiającą się regułą w [KSH184] jest reguła mówiąca o tym, że dźwięki składowe pierwszego z akordów (oprócz dźwięku w basie) powinny dążyć najkrótszą drogą
na dźwięki drugiego akordu, czyli przesuwać się o jak najmniejsze interwały. Metoda
realizuje ten cel wyliczając sumę odległości o jaką przesuwają się dźwięki w trzech
pierwszych głosach (im dalsza droga tym większa suma) następnie mnoży ją przez
wagę reguły i odejmuje od łącznej oceny połączenia.
Ustalając wagę dla tej reguły należy wziąć pod uwagę to, że regułę najbliższej drogi należy traktować na zasadzie wskazówki, ponieważ akordy mogą zostać połączone dalszą
31
drogą w sposób uznawany za prawidłowy. Dlatego reguła ta powinna mieć mniejszą
wagę od reguł, których niestosowanie jest uznawane za błąd. Należy też pamiętać
o tym, że waga zostanie przemnożona przez liczbę całkowitą (wyliczoną sumę odległości) czyli zwiększy się kilka lub kilkunastokrotnie.
Metoda _Rule3(ch1, ch2, imp) - „Zachowaj wspólny dźwięk”
To inna z często pojawiających się w [KSH184] reguł. Mówi ona o tym, że jeśli akordy
posiadają wspólny dźwięk to należy go zachować w tym samym głosie. Zrealizować
można to poprzez zwiększenie całościowej oceny połączenia o wagę reguły jeśli został
w nim zachowany wspólny dźwięk w tym samym głosie.
Podobnie jak w przypadku poprzedniej z opisywanych reguł ustalając wagę tej reguły
należy pamiętać o tym że jej spełnienie nie jest konieczne do tego aby połączenie uznane było za prawidłowe, więc jej waga nie powinna być przesadnie wysoka.
Metoda _Rule4(ch1, ch2, imp) - „Równoległe prymy kwinty i oktawy”
Reguła (zaczerpnięta z [KSH184]) mówi o tym, że głosy nie mogą przesuwać się równoległymi prymami, kwintami oraz oktawami. Oznacza to, że jeśli w pierwszym z akordów występował któryś z tych interwałów pomiędzy dwoma głosami (pryma, kwinta
lub oktawa) to nie może on wystąpić między nimi w kolejnym akordzie.
Działanie tej metody polega na odnalezieniu wyżej wymienionych interwałów w pierwszym z akordów oraz sprawdzeniu czy w drugim z akordów występuje ten sam interwał
pomiędzy tymi głosami. Ilość równoległych niedozwolonych interwałów pomnożona
przez wagę reguły jest odejmowana od całościowej oceny połączenia.
Połączenia niezgodne z tą regułą uznawane są za błędne, o czym powinno się pamiętać
ustalając jej wagę tak, by była odpowiednio wysoka.
Metoda _Rule5(ch1, ch2, imp) - „Zmień funkcję jeśli sopran stoi, powtórz jeśli
skacze na inny dźwięk tej samej funkcji”
Ponieważ do jednego dźwięku można dopasować akordy będące różnymi funkcjami,
reguła (zaczerpnięta z [KSH184]) pomaga w decyzji o tym jaką funkcją powinien być
akord, który zostanie zastosowany. Całościowa ocena akordów spełniających regułę jest
zwiększana o jej wagę, natomiast ocena akordów niespełniających reguły jest
o nią zmniejszana.
32
Reguła często jest sprzeczna z regułą mówiącą o tym że nie należy powtarzać funkcji
przez kreskę taktową, co powinno być brane pod uwagę podczas dobierania wag do obu
reguł.
Metoda _Rule6(ch1, ch2, imp) - „Niedozwolone skoki o septymę oraz więcej
niż oktawę”
Reguła (zaczerpnięta z [KSH184]) mówi o tym, że w melodiach poszczególnych głosów nie mogą występować skoki o interwał septymy oraz interwały większe od oktawy.
Metoda zlicza takie skoki, a ich liczbę pomnożoną przez wagę reguły odejmuje od całościowej oceny połączenia.
Metoda _Rule7(ch1, ch2, imp) - „Nie powtarzaj funkcji przez kreskę taktową”
Reguła (zaczerpnięta z [KSH184]) mówi o tym, że należy podkreślić to, że rozpoczął
się nowy takt poprzez zmianę funkcji. Metoda sprawdza czy połączenie występuje pomiędzy dwoma taktami i jeśli tak, to całościowe oceny akordów będących powtórzeniami tej samej funkcji są obniżane o wagę reguły.
Reguła często jest sprzeczna z regułą mówiącą o tym, że należy powtórzyć funkcję jeśli
dźwięk w sopranie skacze na inny dźwięk tej samej funkcji, co powinno być brane pod
uwagę podczas dobierania wag do obu reguł.
Metoda _CheckFileRules(ch1,ch2,path)
Po zaimplementowaniu wyżej wymienionych reguł w celu sprawdzenia czy udało
się zminimalizować liczbę błędów (jako błąd rozumie się
tutaj rozwiązanie, które
nie odpowiada użytkownikowi) na podstawie [KSH184] opracowano przykładowe bazy
akordów („C major chords.sib” oraz „C minor chords.sib”) i w oparciu o te bazy poszukiwano najodpowiedniejszych parametrów metod sprawdzających reguły przez harmonizowanie różnych melodii z różnymi parametrami metod. Kiedy wyniki uznane zostały
za satysfakcjonujące przesłano rozwiązanie jednego z zadań (nr 46 z [KSH184])
do osób studiujących na kierunkach związanych z muzyką (czyli potencjalnych użytkowników tworzonego programu) do analizy. Pierwszą osobą do której wysłano zharmonizowany przykład był student kierunku „Jazz i Muzyka Estradowa”. Ponieważ muzykę rozrywkową cechuje dość luźne podejście do zasad harmonii wywodzących
33
się jeszcze z epoki klasycyzmu uznał on otrzymane rozwiązanie za prawidłowe. Zwrócił
jedynie uwagę na skok (o septymę), który udało się od razu wyeliminować poprzez
zwiększenie wagi metody wyszukującej niepoprawne skoki.
Drugą osobą do której wysłano program była studentka kierunku „Pedagogika Poprzez
Sztukę”, która wcześniej ukończyła też średnią szkołę muzyczną oraz studium organowe. Zwróciła ona uwagę, że w rozwiązaniu funkcja toniki często łączy się z funkcją dominanty septymowej w pozycji septymy, co powoduje częste powtarzanie funkcji dominanty. Jej zdaniem w tych sytuacjach lepszym rozwiązaniem było by zastosowanie
funkcji subdominanty w pozycji prymy, a dopiero potem ewentualnie dominanty.
Tej uwagi nie dało się zrealizować za pomocą modyfikacji wag istniejących reguł,
a dopisywanie nowej reguły dla tak szczególnego przypadku (prawdopodobnie nie jedynego) nie wydawało się dobrym rozwiązaniem. Lepszym rozwiązaniem wydaje
się stworzenie możliwości definiowania dodatkowych reguł w pliku tekstowym tak,
żeby użytkownik był w stanie samodzielnie je pisać.
Dzięki przyjęciu odpowiedniej konwencji nazewnictwa akordów możliwe okazuje
się definiowanie reguł na podstawie nazw akordów. Reguła może być reprezentowana
jako dwie nazwy akordów których dotyczy oraz ocena ich połączenia. Z tym, że dla
zmniejszenia liczby reguł w rozwiązaniu zastosowano wzorce nazw. Wzorce tworzyć
można przez zastępowanie wybranych znaków znakiem „X”, który nie będzie brany
pod uwagę podczas porównywania nazwy akordu z wzorcem. W ten sposób wzorzec:
D7X7XX
oznaczać będzie funkcję dominanty septymowej w pozycji septymy opartą na dowolnym składniku, w dowolnym układzie.
A reguła zapisana w następujący sposób:
TXXXXX
D7X7XX
-1000
34
spowoduje, że od całościowej oceny połączeń toniki w dowolnym układzie z dominantą septymową w pozycji septymy zostanie odjęty tysiąc. Czyli takie połączenia nie będą
występowały w rozwiązaniu.
Samo działanie metody _CheckFileRules() jest dość oczywiste i polega na odszukaniu w pliku wzorców nazw pasujących do nazw akordów, które są parametrami metody oraz dodaniu odpowiednich wartości do całościowej oceny połączenia. Nazwy
z wzorcami porównywane są za pomocą pomocniczej metody _CompareNames().
Po zaimplementowaniu wymienionych wyżej metod oraz zapisaniu w pliku reguły dotyczącej łączenia (a raczej nie łączenia) funkcji toniki z funkcją dominanty septymowej
w pozycji septymy ponownie zharmonizowano zadanie (nr 46 z [KSH184]) z użyciem
wcześniej używanych parametrów i posłano go do studentki mającej zastrzeżenia do poprzedniego rozwiązania. Tym razem stwierdziła, że sama by go rozwiązała w taki sam
sposób, co potwierdza skuteczność proponowanego rozwiązania.
Teoretycznie możliwe jest zapisanie w pliku reguł, które zostały wcześniej zaimplementowane, ale takie rozwiązanie wymagałoby zapisania osobnych reguł np. dla wszystkich
par akordów (z bazy akordów), w których połączeniu występują równoległe prymy,
kwinty lub oktawy. Takich reguł byłoby dużo, w dodatku ich ilość rosłaby wraz z powiększaniem się bazy akordów, dlatego lepszym rozwiązaniem wydaje się zastosowanie
dwóch mechanizmów sprawdzających reguły.
35
36
3 Podsumowanie
3.1 Test wydajności
Czas wykonania algorytmu harmonizacji zależy od następujących zmiennych
czynników czynników:
•
liczby dźwięków w danej melodii;
•
liczby akordów zapisanych w pliku tekstowym;
•
liczby reguł zapisanych w pliku tekstowym.
Poniższy wykres przedstawia zależność pomiędzy liczbą dźwięków w danej melodii,
a średnim czasem wykonania jej harmonizacji (średnia z 50 uruchomień algorytmu).
Melodie dla których wykonane były pomiary składają się z losowych dźwięków z oktawy razkreślnej i dwukreślnej. Harmonizacja wykonywana była w oparciu o przygotowaną na podstawie [KSH184] bazę akordów „C major chords.sib” zawierającą 98 akordów oraz przykładową bazę reguł „rules.sib” zawierającą 6 reguł.
40000
35000
30000
czas [ms]
25000
20000
15000
10000
5000
0
100
200
300
400
500
liczba dźwięków w m elodii
Z powyższego wykresu można wnioskować, że czas wykonania algorytmu rośnie
w przybliżeniu liniowo w stosunku do liczby dźwięków w melodii, a czas harmonizacji
37
jednego dźwięku wynosi około 70 milisekund. Zależność liniową potwierdza poniższy
wykres przedstawiający czas wykonania algorytmu dla wszystkich długości melodii
z zakresu od 1 do 200 dźwięków z użyciem tej samej bazy akordów i reguł co w poprzednich pomiarach.
18000
16000
14000
czas [ms]
12000
10000
8000
6000
4000
2000
0
0
50
100
150
200
250
liczba dźwięków w melodii
Poniższy wykres przedstawia średni czas harmonizacji jednego dźwięku melodii (5 prób
po 100 dźwięków) przy niewielkiej zmianie rozmiarów bazy akordów.
czas harmonizacji jednego dźwięku [ms]
80
70
60
50
40
30
20
10
0
82
86
90
liczba akordów w bazie
38
94
98
Test pokazał, że dopisanie jednego akordu do bazy akordów zwiększa czas harmonizacji
jednego dźwięku o około 0,75 milisekundy. W bazie akordów nie są spodziewane duże
zmiany jeśli chodzi o ilość akordów, a niewielkie zmiany nie mają dużego wpływu
na szybkość działania algorytmu.
Podobny pomiar wykonany przy zmianie wielkości bazy reguł pokazuje, że dodanie
jednej reguły do bazy reguł zwiększa czas harmonizacji dla jednego dźwięku o około
2,72 milisekundy.
Wszystkie testy przeprowadzone były na notebooku Toshiba Satellite A-135 z procesorem Intel Dual-Core T-2060 i 1,5 GB RAM.
Z testów wydajności programu wynika, że działa on wystarczająco szybko żeby jego
użytkowanie nie było uciążliwe dla użytkownika. Istnieją też rezerwy gwarantujące,
że rozbudowa baz akordów oraz reguł nie spowolni działania programu w stopniu
uciążliwym dla użytkownika.
39
40
3.2 Możliwości rozwoju
Zaproponowane rozwiązanie może być rozwijane przez samych użytkowników
(muzyków, aranżerów kompozytorów) poprzez tworzenie różnorodnych baz akordów
oraz reguł ich łączenia.
Narzędzie zaprojektowane było w taki sposób, żeby w razie potrzeby łatwo można było
wprowadzić odpowiednie zmiany w kodzie. Dlatego wydzielono te części kodu,
w których spodziewane są zmiany w przyszłości. Najbardziej prawdopodobnym miejscem, w którym należałoby spodziewać się zmian w przyszłości jest metoda Run()
wtyczki Harmonizer zawierająca algorytm harmonizacji.
Zaproponowany algorytm jest algorytmem liniowym, którego wynik opiera się na podjęciu szeregu suboptymalnych decyzji o tym, jakie współbrzmienie akordowe zastosować. Zaletą takiego rozwiązania jest szybkie działanie, jednak nie musi ono dawać optymalnego rozwiązania w sensie najwyższego stopnia zgodności sumy ocen wszystkich
połączeń z zadanymi regułami.
W celu uzyskania najwyższego stopnia zgodności z regułami należałoby ocenić wszystkie kombinacje możliwych do zastosowania współbrzmień. Taki algorytm charakteryzowałby się jednak bardzo dużym stopniem złożoności.
Innym możliwym rozwiązaniem jest zastosowanie algorytmu genetycznego, w którym
osobnikami mogłyby być rozwiązania tworzone za pomocą istniejącego algorytmu
z ustawioną dużą wagą dla reguły losowej, a funkcja oceny przystosowania działałaby w oparciu o wtyczkę „RuleChecker”. Biorąc jednak pod uwagę dość długi czas wykonywania się zaproponowanego przeze mnie algorytmu liniowego to rozwiązanie również na chwilę obecną wydaje się zbyt wolne.
Niezależnie od tego, które z wyżej wymienionych rozwiązań zostałoby zastosowane
w przyszłości to zmiany w projekcie będą dotyczyły tylko metody Run() wtyczki Harmonizer.
Dodatkowo poza modyfikacjami istniejącego rozwiązania dobrym pomysłem byłaby rozbudowa jego funkcjonalności o możliwość edycji bazy akordów w programie
Sibelius, a nie w pliku tekstowym. Taki sposób edycji byłby dużo bardziej wygodny dla
użytkownika, jednak ta funkcjonalność nie mogła zostać zrealizowana z powodu ograniczenia wersji demo jakim jest brak możliwości zapisywania plików.
41
42
3.3 Wnioski
Zaproponowane rozwiązanie pokazuje, że proces harmonizacji melodii może
być w dużym stopniu skutecznie zautomatyzowany. W projekcie udało się zrealizować
stawiane cele z tym zastrzeżeniem, że zastosowany liniowy algorytm harmonizacji jest
kompromisem pomiędzy wydajnością, a stopniem zgodności całego rozwiązania z zadanymi regułami. Rozwiązania generowane przez program są dobrze oceniane przez potencjalnych użytkowników.
Wnioski z doboru narzędzi
Istotne są też wnioski związane z doborem narzędzi, które sprawiały pewne nieoczekiwane problemy podczas realizacji projektu.
Język ManuScript oprócz problemów spowodowanych ograniczeniami związanymi
z brakiem możliwości definicji własnych typów i klas sprawia też problemy, których
rozwiązania próżno szukać w [UTMSL05] (jedynej dokumentacji języka). Przykładem
takiego problemu może być metoda:
Sibelius.ResetStopWatch(timer number);
Zgodnie z [UTMSL05] parametrem tej metody powinna być zmienna reprezentująca
czas, a metoda powinna ten czas wyzerować. Z tym, że ManuScript jako język dynamicznie typowany nie umożliwia deklaracji zmiennej takiego typu. Próba użycia zmiennej wcześniej nie zainicjowanej powoduje komunikat błędu mówiący, że nie odnaleziono parametru, próba zainicjowania parametru wartością „0” lub dowolnym ciągiem znaków powoduje komunikat błędu mówiący, że nie odnaleziono metody. Rozwiązaniem
okazuje się zainicjowanie parametru wartością „1”. Dojść do takiego rozwiązania można jedynie metodą prób i błędów, ponieważ to czy zastosuje się wartość całkowitą
0, czy 1 do zainicjowania parametru nie powinno mieć wpływu na to, czy metoda zostanie odnaleziona, czy nie. Tego rodzaju nieudokumentowane, nietypowe zachowania
znacznie utrudniają pracę nad projektem.
Problemem oprócz samego języka jest też edytor kodu wbudowany w program Sibelius.
Edytor ten w porównaniu z edytorami dedykowanymi do popularnych języków programowania jest bardzo ograniczony.
43
Wady edytora:
•
Nie posiada tak podstawowych funkcjonalności jak kolorowanie składni, podpowiedzi, czy obsługa popularnych skrótów klawiszowych (np. ctrl+a).
•
Kod każdej metody edytuje się w osobnym oknie, a okna te są oknami modalnymi
i nie można otworzyć kilku naraz.
•
Przypadkowe zamknięcie okna edycji metody powoduje utratę wszelkich zmian bez
typowego w tym przypadku pytania o potwierdzenie.
Wyżej wymienione ukryte wady języka ManuScript oraz wbudowanego w program
Sibelius edytora kodu znacznie wydłużają czas pracy nad projektem i w przypadku
większych projektów mogą być poważnymi argumentami za wyborem lub stworzeniem
innych narzędzi.
44
4 Bibliografia
[JHSM77] :
Jerzy Habela, „Słowniczek Muzyczny”, PWM 1977
[KSH184]:
Kazimierz Sikorski, „Harmonia cz. I”, PWM 1984
[KSH284]:
Kazimierz Sikorski, „Harmonia cz. II”, PWM 1984
[BDSEDM]:
Beata Drabik-Sowa, artykuł: „Elementy Dzieła Muzycznego”,
http://www.psmprzeworsk.republika.pl/pub_bds01_02.htm
data dostępu: 05.02.2008
[UTMSL05]:
Jonathan Finn, James Larcombe, Yasir Assam, Simon Whiteside, Mike
Copperwhite, Paul Walmsley and Graham,
„Using The ManuScript Language”, Westlake, Edition 4.1 2005,
http://mook.sibelius.com/download/software/win/ManuScriptLanguage.pdf
data dostępu: 05.02.2008
[SHP08]:
Sibelius home page
http://www.sibelius.com/
data dostępu: 05.02.2008
[FM08]
Finale music and composing software
http://www.finalemusic.com/
data dostępu: 05.02.2008
45