Tworzę audio i efekty w mojej grze w locie z bardzo podstawową syntezą dźwięku. Zasadniczo, mam kilka metod, które mogą odtwarzać dźwięk z częstotliwością & czas trwania amplitudy.Jak utworzyć prostą, ale dobrze zorganizowaną klasę zapisu nutowego (punkt muzyczny) w języku Java?
W przypadku krótkich fraz i melodii, chciałbym wymyślić podstawową notację, aby móc z łatwością przepisać lub dodać nowe melodie do kodu (w końcu może mógłbym odczytać z plików, ale to chyba przesada).
Nie jestem pewien, jak to zaimplementować.
Zacząłem od stworzenia enum EqualTemperamentTuning, który zawiera wszystkie 88 podstawowych nut fortepianu z polem MIDI # i polem częstotliwości. To przynajmniej oznacza, że mogę zajmować się nazwami nut, a nie częstotliwościami.
public enum EqualTemperamentTuning {
A_0 (1, 27.5),
A_SHARP_0 (2, 29.1352),
...
C_8 (88, 4186.01);
private int num;
private double frequency;
EqualTemperamentTuning(int num, double frequency){
this.num = num;
this.frequency = frequency;
}
public double getFrequency(){
return frequency;
}
public double getNum(){
return num;
}
}
Potem zaczął tworzyć więcej przedmiotów, najpierw notatkę, która posiada EqualTemperamentTuning, amplitudę i długość:
public class Note {
/** Note frequency */
private double frequency;
/** Note Amplitude */
private double amplitude;
/** Note length */
private int length;
public Note(EqualTemperamentTuning tuning, double amplitude, int length){
this.frequency = tuning.getFrequency();
this.amplitude = amplitude;
this.length = length;
}
public double getFrequency(){
return frequency;
}
public double getAmplitude(){
return amplitude;
}
public int getLength(){
return length;
}
}
Wreszcie zdefiniowania melodii chcę grać, stworzyłem klasę NotePhrase :
public class NotePhrase {
/** The arrayList of notes*/
private Note[] notes;
public NotePhrase(Note[] notes){
this.notes = notes;
}
public double getFrequency(int counter){
// for each note in the array
for (int i = 0; i< notes.length; i++){
// for each unit of length per note
for (int j=0; j<notes[i].getLength(); j++){
counter--;
// return the frequency at this point
if (counter <= 0) return notes[i].getFrequency();
}
}
return -1;
}
}
Wtedy w mojej klasie dźwięku generującego mam pętlę (przy kasie), który generuje próbki z generatora fal. Za każdym razem, gdy potrzebuję nowej próbki do odegrania, ustawia częstotliwość fali zgodnie z powyższą metodą NotePhrase.getFrequency (int counter). To powinno (jeszcze nie przetestowałem!) Po prostu odtwarzaj melodię NotePhraz zgodnie z częstotliwością i amplitudą (do dodania).
Problem polega na tym, że nie wydaje się bardzo elegancki, a dokładniej bardzo trudno jest "napisać" melodię w jakikolwiek czytelny sposób. Muszę zakodować całą masę nowych obiektów Note, a następnie skonstruować obiekt NotePhrase z ich szeregiem ... Nie jest dla mnie oczywiste, jak mocno zakodowałem kilka melodii, a następnie łatwo przełączałem się między nimi później.
Naprawdę chciałbym stworzyć wyliczenie Melodii lub coś w tym rodzaju, gdzie mogę z łatwością zakodować ludzką czytelną konfigurację dla każdej melodii, a kiedy chcę z nich skorzystać, wystarczy podać typ wyliczeniowy do odtwarzacz audio ...
najlepszym mam to:
private static enum Melody {
NOKIA_RINGTONE (new Note(EqualTemperamentTuning.E_5, 0.5, 1), new Note(EqualTemperamentTuning.D_5, 0.5, 1))
;
private Note[] notes = new Note[2];
Melody (Note note1, Note note2){
this.notes[0] = note1;
this.notes[1] = note2;
}
}
który ja następnie załadować do obiektu NotePhrase przy starcie. Nie jest to zbyt dobre, ponieważ muszę stworzyć nowy konstruktor melodii z różną ilością nut. Jeśli zrobię to na odwrót i skonstruuję enum z szeregiem nut, to po prostu "piszę" melodię gdzie indziej i na dwie części, co wydaje się jeszcze bardziej zagmatwane ...
Więc utknąłem jak właściwie to ustrukturyzować? tj. jakie klasy tworzyć i jakie informacje powinny posiadać ... Chcę uzyskać to "prawo", ponieważ, chciałbym rozszerzyć notację w przyszłości, aby uwzględnić efekty (echo itp.) i już znalazłem z moim bardzo niewielkie doświadczenie, że odpowiednie klasy, struktura i relacje (nawet nazwy) mogą sprawić, że moje programy będą bardzo łatwe lub trudne do zrozumienia.
Przepraszam za esej, to może nie być bardzo dobrze sformułowane (ahem) pytanie, ale jako początkujący użytkownik języka Java & początkujący, wszelkie wskazówki byłyby bardzo mile widziane!
EDIT * *
Dzięki za odpowiedzi & sugestie, bardzo pomocne. Myślenie o odpowiedziach podanych w tym przypadku skłoniło mnie do ponownego przemyślenia mojej ogólnej implementacji audio, która jest teraz dość chwiejna. Nie jestem pewien, kogo mam oznaczyć jako poprawny, ponieważ zamierzam wziąć wszystkie rekomendacje na pokładzie i spróbować od tego miejsca.
"Nie jest to zbyt dobre, ponieważ muszę stworzyć nowy konstruktor melodii z różną ilością nut." Możesz użyć varargs tutaj – Zavior
Thx, varargs jest dokładnie to, czego potrzebuję tam. – kiman
Może to pomóc w utworzeniu klas Voice and Measure, więc twoja klasa Melody nie próbuje zrobić więcej niż jedną rzecz. –