Estoy creando audio y efectos en mi juego sobre la marcha con síntesis de sonido muy básica. Básicamente, tengo algunos métodos que pueden reproducir un sonido dada una frecuencia & amplitud & duración.¿Cómo crear una clase de notación musical simple pero bien estructurada (puntuación musical) en java?
Para frases cortas y melodías, me gustaría encontrar una notación básica para que pueda reescribir fácilmente o agregar nuevas melodías en el código (al final tal vez podría leer de los archivos, pero eso probablemente sea exagerado))
No estoy seguro de cómo implementar esto sin embargo.
Comencé creando un ecualizador de temperatura igual de enum que contiene las 88 notas básicas de piano con un campo MIDI # y un campo de frecuencia. Esto al menos significa que puedo tratar nombres de notas y no frecuencias.
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;
}
}
Entonces empecé a crear más objetos, primero una nota que contiene un EqualTemperamentTuning, una amplitud y una longitud:
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;
}
}
último para definir la melodía Quiero jugar, he creado una clase 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;
}
}
Luego, en mi clase de generación de audio I tienen un bucle (con el contador) que genera muestras de un generador de ondas. Cada vez que necesito una nueva muestra para reproducir, establece la frecuencia de la onda de acuerdo con el método NotePhrase.getFrequency (int counter) anterior. Esto debería (¡aún no lo he probado!) Solo toque la melodía de NotePhrase de acuerdo con la frecuencia y amplitud (para ser agregado).
El problema es que no parece muy elegante y más específicamente es muy difícil "escribir" una melodía de forma legible. Tengo que codificar un montón de nuevos objetos Note y luego construir un objeto NotePhrase con una matriz de ellos ... No es obvio para mí cómo codificaría un montón de estas melodías y luego cambiaría fácilmente entre ellas más tarde.
Realmente me gustaría crear una enumeración de Melodías o algo así, donde puedo codificar fácilmente una configuración humana legible para cada melodía diferente, y luego cuando quiero usarlas, simplemente paso el tipo de enumeración al reproductor de audio ...
El mejor que tengo es:
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;
}
}
Qué me permitiría cargar en un objeto NotePhrase en tiempo de ejecución. Esto no es muy bueno porque tengo que crear un nuevo constructor para melodías con diferentes cantidades de notas. Si lo hago al revés y construyo la enumeración con una serie de notas, entonces simplemente estoy "escribiendo" la melodía en otro lugar y en dos partes, lo que parece aún más confuso ...
Así que estoy atascado en cuanto a cómo estructurar esto correctamente? es decir, qué clases crear y qué información deben contener ... Quiero obtener este "correcto" porque, me gustaría expandir la notación en el futuro para incluir efectos (eco, etc.) y ya he encontrado con mi muy poca experiencia, que las clases, estructura y relaciones correctas (incluso nombres) pueden hacer que mis programas sean muy fáciles o difíciles de entender.
Disculpas por el ensayo, esta podría no ser una pregunta muy bien formulada (ejem), pero como un principiante OOP java &, cualquier sugerencia sería muy bienvenida.
EDITAR * *
Gracias por las respuestas & sugerencias, muy útil. Pensar en las respuestas dadas en este caso me llevó a replantear mi implementación general de audio, que ahora es bastante inestable. Sin embargo, no estoy seguro de a quién debería marcar como correcto, ya que realmente voy a tomar todas las recomendaciones a bordo y tratar de ir desde allí.
"Esto no es muy bueno porque tengo que crear un nuevo constructor para melodías con diferentes cantidades de notas". Puede usar varargs aquí – Zavior
Thx, varargs es exactamente lo que necesito allí. – kiman
Puede ser útil crear clases de voz y medición, por lo que su clase Melody no intenta hacer más de una cosa. –