Corrigé Projet Musique
1. Introduction
1.0.1. Fréquence d’une touche de piano
| coeff | valeurs <= 0 | valeurs >= 89 | autres |
| 1 | 2 | 2 | 5 |
def freq_touche(n) : if 0 < n and n < 89 : return 2 ** ( ( n - 49 ) / 12 ) * 440 return 0
2. Mélodie MIDI depuis une liste
2.1. Outils numériques
2.1.1. Valeur absolue
| coeff | valeurs < 0 | valeurs > 0 | en 0 |
| 1 | 4 | 4 | 1 |
def vabs(x) : if x < 0 : return -x return x
2.1.2. Approximation de pi
| coeff | en 0 | rang correct | calcul correct | structure correcte |
| 2 | 1 | 2 | 4 | 3 |
def approx_pi(n) : somme = 1 for i in range(1,n+1) : somme += (-3.0) ** (-i) / (2.0 * i + 1.0) return 12.0 ** 0.5 * somme
2.1.3. Modulo deux pi
| coeff | valeur < -pi | valeur entre -pi et pi | valeur > pi |
| 2 | 3 | 3 | 3 |
On note que dans la correction si dessous, \(\pi\) est envoyé sur \(-\pi\), ce qui
ne répond pas à la consigne. Cela n’a toutefois que très peu de sens de parler
de ce qui se passe exactement en \(\pi\), ce nombre n’étant pas représentable dans
la mémoire d’un ordinateur. Ce n’est donc pas important de traiter le cas où x
= pi qui n’est de toute façon pas réellement le cas \(x = \pi\) \ldots.
def modulo_2pi(x) : x_modulo = abs(x) while x_modulo > pi : x_modulo = x_modulo - 2 * pi if x < 0 : x_modulo = -x_modulo return x_modulo
2.1.4. Approximation du sinus
| coeff | au rang 0 | rang correct | calcul correct | grandes valeurs | structure correcte |
| 2 | 1 | 2 | 4 | 2 | 1 |
def approx_sin(x,n) : x_modulo = modulo_2pi(x) u = x_modulo somme = u for i in range(1, n+1) : u = - u * x_modulo * x_modulo / ( 2 * i * (2 * i + 1) ) somme += u return somme
2.2. Échantillonnage
2.2.1. Discrétisation d’un intervalle
| coeff | commence par a | contient n valeurs | intervalles réguliers |
| 3 | 1 | 4 | 4 |
def discretisation(a,b,n) : ecart = (b-a) / (n-1) dis = [a] for i in range(1,n-1) : dis.append(a + i * ecart) dis.append(b) return dis
2.2.2. Échantillonnage d’une note
| coeff | nombre de valeurs | discretisation correcte | echantillonnage correct |
| 3 | 2 | 2 | 4 |
def echantillonnage_note(frequence,duree,freq_ech,amplitude) : t = discretisation(0,duree,int(freq_ech*duree)) e = [] for x in t : e.append(amplitude * approx_sin(2 * pi * frequence * x, 100)) return e
2.2.3. Échantillonnage d’une partition
| coeff | parcours partition | appel | concaténation |
| 3 | 3 | 2 | 4 |
def echantillonnage_partition(partition, freq_ech, amplitude) : e = [] for (note,duree) in partition : freq = freq_touche(note) e += echantillonnage_note(freq,duree/8,freq_ech,amplitude) return e
2.2.4. Échantillonnage d’un accord
| coeff | parcours accord | calcul | résultat |
| 3 | 3 | 2 | 4 |
def echantillonnage_accord(frequences,duree,freq_ech,amplitude) : pi = approx_pi(40) t = discretisation(0,duree,int(freq_ech*duree)) e = [] for x in t : valeur = 0 for f in frequences : valeur = valeur + amplitude * approx_sin(2 * pi * f * x, 100) e.append(valeur) return e
2.2.5. Échantillonnage d’une partition d’accord
| coeff | parcours partition | calcul fréquences | résultat |
| 3 | 3 | 3 | 3 |
def echantillonnage_partition_accords(partition, freq_ech, amplitude) : e = [] for (accord,duree) in partition : freqs_accord = [] for note in accord : freqs_accord.append(freq_touche(note)) e += echantillonnage_accord(freqs_accord,duree/8,freq_ech,amplitude) return e
3. Mélodie MIDI depuis une partition écrite
3.0.1. Touche correspondant à une note dans l’octave
| coeff | touche valide | touche invalide |
| 2 | 6 | 3 |
def touche_octave(s) : notes = "CcDdEFfGgAaB" for i in range(len(notes)) : if notes[i] == s : return i return -1
3.0.2. Touche correspondant à une note sur le piano
| coeff | touche valide | touche invalide |
| 2 | 6 | 3 |
def touche_piano(s,n) : t = touche_octave(s) if t != - 1 : t = t - 8 + n * 12 return t
3.0.3. Lecture d’une partition
| coeff | parcours | création de la liste de couple | Partition vide |
| 3 | 4 | 4 | 1 |
def partition(s) : notes = [] for i in range(0,len(s),3) : notes.append((touche_piano(s[i],int(s[i+1])), int(s[i+2]))) return notes
3.0.4. Conversion fichier vers WAV
| coeff | ouverture de fichier | lecture | appels | écriture |
| 2 | 3 | 2 | 2 | 2 |
def generer_partition(fichier, wave, freq_ech, amplitude) : ofichier = open(fichier,'r') s = ofichier.read() p = partition(s) e = echantillonnage_partition(p,freq_ech,amplitude) wavfile.write(wave, rate=freq_ech, data=np.array(e).astype(np.int16) )