Un algoritmo musicale

Sentivo il bisogno di cambiare le segnalazioni acustiche dei progetti. I soliti beep a 1000, 1500 Hz, mi avevano un po stufato.

L’idea era di avere un algoritmo il piu piccolo possibile che producesse frequenze corrispondenti alle 7 note musicali. Alla fine ho trovato questo

f = (440-41.5) * exp(0.203*n/2.05)

le ottave vengono riprodotte in maniera precisa, gli intervalli con semitono sono ovviamente leggermente stonati. pero’ grosso modo per ogni n si ottiene una frequenza di una nota.

Me lo sono inventato, non ha nessuna pretesa, e sicuramente ce ne saranno altri di gran lunga migliori. Non lo so. Pero se puo’ interessare lo condivido.

ciao

Se l’espressione ti da la frequenza, che differenza c’è nel mettere direttamente la frequenza.

… che posso produrre una scala con un semplice ciclo for…
Oppure posso generare una breve melodia casuale, sempre al posto di un beep.

Ovviamente in rete l’algoritmo per ricavare la scala cromatica (a 12 note) è ben conosciuto
f = 440 + exp(n/12)

Secondo me un array di int è un metodo più efficiente (e preciso), soprattutto con mcu poco potenti come l’atmega328 dell’Uno

Scusa ma non ho capito bene perché di quei valori “correttivi” se la scala temperata è data dalla formula che hai postato (che parte da 440 come frequenza base, ossia il La4). Suppongo che tu non abbia usato quella per via dei cast automatici e quindi della perdita di decimali nei calcoli intermedi.

In ogni caso come ha scritto cotestatnt per evitare di calcolare elevazioni a potenza su piccole MCU si fa prima a tenere in memoria un array delle 12 frequenze (float) di una ottava di base (diciamo la 4), ed ottenere tutte le altre tramite raddoppio.
Penso ad una cosa di questo tipo:

// Frequenze dell'ottava di base (C4-B4)
float ottava[12] = {261.6, 277.2, 293.7, ... };
...
float freq(int ottava, int nota) {
  float f = ottava[nota];
  if (ottava > 4) 
    f = f*2*(ottava-4);
  return f;
}

Volevo trovare un algoritmo da solo, senza conoscere quelli esistenti. Solo dopo averlo trovato mi sono andato a leggere la vulgata.

A differenza di quello classico, che fornisce la scala cromatica (12 note), il mio algoritmo fornisce una scala diatonica (7 note).
Il motivo di quei correttivi e coefficienti sta nel fatto che ho trovato l’algoritmo per via prevalentemente empirica.

Per quanto riguarda il metodo che consigliate, è un ottimo e preciso metodo, ma meno economico in termini di codice.

Grazie.

… dimenticavo, i decimali sono praticamente ininfluenti, nessun orecchio umano può distinguere una differenza di mezzo hz

Puoi anche fare un array di int con le 11 radici dodicesime di 2 moltiplicate per 1000 (da 1059 a 1888) e poi moltiplicare 55Hz per l’ottava e per la posizione nella scala cromatica diviso 100:

tone (55.0/100*ottava*f_note[nota]);

Ok, ma a parte eventualmente il piacere della scoperta, perché “reinventare l’acqua calda”? Tra l’altro l’aspetto matematico della musica puoi vederlo applicato in questo video, introduttivo ma ben fatto, e che ti permette di comprendere meglio:
Perché le note musicali sono 7?

Comunque la “economicità” di un algoritmo non si basa sul numero di righe ma dalla complessità dei calcolo, e calcolare “f = (440-41.5) * exp(0.203n/2.05)" non è affatto più “economico” di fare "f = f2*(ottava-4)” in quanto l’elevazione a potenza su float è abbastanza “complessa”. Se poi l’array delle 12 frequenze “base” lo trasformi in int (quindi anche “f”), è ancora più efficiente in quanto elimini tutti i float.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.