On va tout d'abord importer les données mesurées pour en déduire les $\rho_i$.
In [1]:
data = """79,05 102,40 115,40 126,10 217,50 240,70
82,4 101,5 114,1 123,1 215,8 239
81,90 104,80 113,20 121,50 214,20 237,50"""
In [2]:
data = data.replace(',', '.')
In [3]:
lines = data.split('\n')
In [4]:
values = [line.split('\t') for line in lines]
In [5]:
values
Out[5]:
In [6]:
import numpy as np
In [7]:
import pandas as pd
In [8]:
s = pd.DataFrame(values)
In [9]:
s
Out[9]:
In [10]:
s.values.astype(np.float)
Out[10]:
In [11]:
df = pd.DataFrame(s.values.astype(np.float), columns=range(6))
In [12]:
df
Out[12]:
Il nous faut construire le vecteur des $\Delta T _ i$ à partir des mesures de fréquences. On construit d'abord le vecteur des $F_i$
In [13]:
df ** 2
Out[13]:
In [14]:
(df ** 2).ix[0][0]
Out[14]:
note importante : j'utilise ici des $mu_i$ qui sont lus sur une pochette de cordes. Je n'ai aucune garantie que cela soient bien les vrais $mu_i$ nécessaires aux cordes qui sont sur ma guitare !
In [46]:
freqs = np.array([82.4, 110., 146.8, 196., 246.9, 329.6]) # frequencies of the guitar strings, from low E to high E, in Hz
calibration_tensions = np.array([9.59, 11.61, 11.22, 8.43, 8.09, 8.9]) * 9.81 # calibration tensions found on package (in kg) converted to N
mu = calibration_tensions / (4 * 0.648**2 * freqs**2)
mu
Out[46]:
In [47]:
psi = 4 * 0.648**2 * mu
In [48]:
psi
Out[48]:
In [49]:
T = (df ** 2).values * psi
T
Out[49]:
attention les tensions sont bien en Newton, pas en kg comme dans la feuille Numbers.
On peut maintenant construire une première matrice de 5 lignes fois 6 colonnes.
In [50]:
T_end = T[1, :]
T_start = T[0, :]
mat = np.zeros((5, 6))
dT = T_end - T_start
dT
Out[50]:
In [51]:
mat
Out[51]:
On s'attend à ce qu'il n'y ait qu'une valeur qui a augmenté, ici c'est la première.
In [52]:
np.nonzero(dT > 0)
Out[52]:
In [53]:
tuned_string = np.nonzero(dT > 0)[0]
assert tuned_string.size == 1
tuned_string = tuned_string[0]
In [54]:
tuned_string
Out[54]:
In [55]:
cnt = 0
for string in range(6):
if string == tuned_string:
continue
else:
for other_string in range(6):
if other_string == tuned_string:
mat[cnt, other_string] = 0
elif other_string == string:
mat[cnt, other_string] = dT[tuned_string] + dT[string]
else:
mat[cnt, other_string] = dT[string]
cnt += 1
In [56]:
mat[0]
Out[56]:
In [57]:
mat[1]
Out[57]:
In [58]:
mat
Out[58]:
On peut écrire une fonction avec le code précédent :
In [134]:
def make_matrix(T_end, T_start):
""" builds the matrix that describes the effect of the individual rho_i on the
overall tuning change
M * [rho_i] = [dT]
"""
mat = np.zeros((5, 6))
dT = T_end - T_start
upstrings = np.nonzero(dT > 0)[0]
downstrings = np.nonzero(dT < 0)[0]
if (upstrings.size == 5) and (downstrings.size == 1):
tuned_string = downstrings[0]
elif (upstrings.size == 1) and (downstrings.size == 5):
tuned_string = upstrings[0]
else:
raise Exception('problem: no changed string was detected!')
cnt = 0
for string in range(6):
if string == tuned_string:
continue
else:
for other_string in range(6):
if other_string == tuned_string:
mat[cnt, other_string] = 0
elif other_string == string:
mat[cnt, other_string] = dT[tuned_string] + dT[string]
else:
mat[cnt, other_string] = dT[string]
cnt += 1
rhs = -dT[[_ for _ in range(6) if _ != tuned_string]]
return mat, rhs
In [135]:
make_matrix(T_end, T_start)
Out[135]:
On vérifie que le RHS est correct :
In [136]:
dT
Out[136]:
On peut maintenant construire les deux matrices :
In [137]:
mat1, rhs1 = make_matrix(T[1, :], T[0, :])
mat2, rhs2 = make_matrix(T[2, :], T[1, :])
In [138]:
mat2
Out[138]:
In [139]:
rhs2
Out[139]:
On peut les concaténer :
In [140]:
total_mat = np.vstack((mat1, mat2))
total_rhs = np.vstack((rhs1[:, np.newaxis],
rhs2[:, np.newaxis]))
In [141]:
total_mat
Out[141]:
In [142]:
total_rhs
Out[142]:
On peut maintenant inverser le système :
In [143]:
total_mat.shape
Out[143]:
In [144]:
total_rhs.shape
Out[144]:
In [145]:
rho, err, rank, eigs = np.linalg.lstsq(total_mat, total_rhs)
In [146]:
err
Out[146]:
In [147]:
rho
Out[147]:
In [148]:
err
Out[148]:
On a la solution !
cependant on note que les raideurs ne sont pas exactement dans l'ordre croissant !! Problème ou pas ?
On peut maintenant voir si ces coefs permettent de bien prédire la variation de tension observée. On peut tout simplement repartir des matrices mat1 et mat2 et vérifier que l'on tombe bien sur ce qu'on veut.
In [149]:
np.dot(mat1, rho)
Out[149]:
In [150]:
rhs1
Out[150]:
Mouai...
In [151]:
np.dot(mat2, rho)
Out[151]:
In [152]:
rhs2
Out[152]:
Ceci est peut être dû à l'erreur à l'issue de la régression linéaire... on va quand même essayer d'implémenter la méthode d'inversion pour l'accordage.
ou au mauvais $\mu_i$, qui ont été choisis... au hasard ?
Il faut ici encore construire la matrice responsable de l'accordage.
In [153]:
tuning_mat = np.zeros((6, 6))
for other_string in range(6):
for tuning_string in range(6):
if tuning_string == other_string:
tuning_mat[other_string, tuning_string] = 1.
else:
tuning_mat[other_string, tuning_string] = \
psi[tuning_string] / psi[other_string] * \
(- rho[other_string] / (1 + np.sum([rho[i] for i in range(6) if i != tuning_string])))
In [154]:
tuning_mat
Out[154]:
In [155]:
np.dot(tuning_mat, np.array([1, 0, 0, 0, 0, 0]))
Out[155]:
On vérifie que ces termes sont les bons.
In [156]:
psi[0] / psi[1] * (- rho[1] / (1 + np.sum([rho[k] for k in range(6) if k != 0])))
Out[156]:
On écrit la fonction pour calculer la matrice :
In [157]:
def compute_tuning_matrix(psi, rho):
tuning_mat = np.zeros((6, 6))
for other_string in range(6):
for tuning_string in range(6):
if tuning_string == other_string:
tuning_mat[other_string, tuning_string] = 1.
else:
tuning_mat[other_string, tuning_string] = \
psi[tuning_string] / psi[other_string] * \
(- rho[other_string] / (1 + np.sum([rho[i] for i in range(6) if i != tuning_string])))
return tuning_mat
In [158]:
compute_tuning_matrix(psi, rho)
Out[158]:
On peut maintenant inverser la matrice en calculant l'accordage cible.
In [159]:
freqs
Out[159]:
Le $\Delta f$ à appliquer peut se calculer en faisant la différence à obtenir :
In [160]:
target_freqs = freqs.copy()
In [161]:
current_freqs = df.values[2, :]
L'écart que l'on cherche à obtenir est donc :
In [162]:
target_freqs - current_freqs
Out[162]:
On doit le mettre au carré :
In [163]:
target_dF = (target_freqs - current_freqs) ** 2
In [164]:
Delta_F = np.linalg.solve(tuning_mat, target_dF)
Delta_F
Out[164]:
On doit prendre la racine de ce grand F pour trouver les fréquences à appliquer :
In [165]:
np.sqrt(Delta_F)
Out[165]:
In [166]:
np.sqrt(np.dot(tuning_mat, Delta_F))
Out[166]:
In [167]:
current_freqs
Out[167]:
In [168]:
current_freqs + np.sqrt(np.dot(tuning_mat, Delta_F))
Out[168]:
Cela devrait marcher. Voyons voir quels deltas de fréquence il faut imposer.
In [169]:
np.sqrt(Delta_F)
Out[169]:
Testons !
In [170]:
current_freqs + np.sqrt(Delta_F)
Out[170]:
Conclusion : ça n'a pas marché et le pont n'a pas arrêté de monter. Je pense que cela vient d'autre chose : la tension du set de cordes n'était pas adaptée !!!
Je change donc de set de cordes et je recommence.
J'ai mis des nouvelles cordes dont les propriétés sont les suivantes :
On en déduit les $\mu_i$ :
In [171]:
freqs = np.array([82.4, 110., 146.8, 196., 246.9, 329.6]) # frequencies of the guitar strings, from low E to high E, in Hz
calibration_tensions = np.array([7.94, 8.84, 8.34, 6.67, 4.99, 5.94]) * 9.81 # calibration tensions found on package (in kg) converted to N
mu = calibration_tensions / (4 * 0.648**2 * freqs**2)
In [172]:
mu
Out[172]:
J'ai remesuré la longueur des cordes et j'ai trouvé 65 cm. Je décide de garder la longueur standard de 0.648 m.
On en déduit les Psi_i :
In [173]:
psi = 4 * 0.648**2 * mu
In [174]:
psi
Out[174]:
On peut maintenant remesurer les différentes fréquences sur la guitare :
In [175]:
lines = """83,55 94,70 193,7 138,8 203 190
89,2 93,3 192,55 135,2 200,55 186,9
87,8 99,2 191,25 130,9 197,85 183,7""".replace(',', '.').split('\n')
In [176]:
history = np.array([line.split('\t') for line in lines], dtype=np.float)
history
Out[176]:
In [177]:
T = (history ** 2) * psi
In [178]:
mat1, rhs1 = make_matrix(T[1, :], T[0, :])
mat2, rhs2 = make_matrix(T[2, :], T[1, :])
total_mat = np.vstack((mat1, mat2))
total_rhs = np.vstack((rhs1[:, np.newaxis],
rhs2[:, np.newaxis]))
In [179]:
rho, err, rank, eigs = np.linalg.lstsq(total_mat, total_rhs)
In [180]:
rho
Out[180]:
In [181]:
err
Out[181]:
Cette fois-ci on constate que les rho_i sont dans l'ordre !
In [182]:
np.dot(mat1, rho)
Out[182]:
In [183]:
rhs1
Out[183]:
In [184]:
np.dot(mat2, rho)
Out[184]:
In [185]:
rhs2
Out[185]:
In [186]:
np.dot(total_mat, rho)
Out[186]:
In [187]:
total_rhs
Out[187]:
Bizarre la vérification...
In [188]:
tuning_mat = compute_tuning_matrix(psi, rho)
In [189]:
tuning_mat
Out[189]:
In [190]:
target_freqs = freqs.copy()
In [191]:
current_freqs = history[2, :]
In [192]:
target_freqs - current_freqs
Out[192]:
In [193]:
target_dF = (target_freqs - current_freqs) ** 2
In [194]:
Delta_F = np.linalg.solve(tuning_mat, target_dF)
Delta_F
Out[194]:
In [195]:
np.sqrt(Delta_F)
Out[195]:
In [196]:
for _ in np.sqrt(Delta_F):
print("{:.2f}".format(_))
Un des problèmes des parties précédentes provient du fait que l'accordage modifie au fur et à mesure les tensions des cordes et que lorsqu'on veut accorder la deuxième corde, on se pose la question de sa tension cible, qui a déjà changé par rapport aux conditions initiales.
Il y a deux possibilités :
Idéalement, c'est à dire si le modèle est correct et que les paramètres ont été bien estimés, les deux méthodes se rejoignent.
Dans cette partie, nous allons confronter dans un premier temps les variations mesurées à l'issue d'un désaccordage avec les variations prédites. Dans un deuxième temps, nous conclurons sur la méthode à utiliser parmi les deux possibilités évoquées ci-dessus.
Plan de cette partie :
Propriétés de la guitare connues à l'avance :
In [197]:
freqs = np.array([82.4, 110., 146.8, 196., 246.9, 329.6]) # frequencies of the guitar strings, from low E to high E, in Hz
calibration_tensions = np.array([7.94, 8.84, 8.34, 6.67, 4.99, 5.94]) * 9.81 # calibration tensions found on package (in kg) converted to N
mu = calibration_tensions / (4 * 0.648**2 * freqs**2)
psi = 4 * 0.648**2 * mu
Afin de faire les prochaines mesures, on écrit la partie restante de l'application avec PyQt.
On désaccorde successivement le mi grave et le la pour obtenir les relevés suivants (à 0.1 Hz) :
In [198]:
history = np.array([[84.6,111.4,148.8,193.8,244.3,328.7],
[82.1,111.6,149.0,194.1,244.5,329.0],
[81.8,114.6,148.8,193.7,244.2,328.7]])
history
Out[198]:
In [199]:
T = (history ** 2) * psi
T
Out[199]:
On peut regarder la somme des tensions (et la remettre en kg pour avoir une petite idée) :
In [200]:
T.sum(axis=1) / 9.81
Out[200]:
On constate qu'on reste proche, mais qu'on ne conserve pas exactement les tensions. Je me demande ce que prédit le modèle à ce sujet.
In [258]:
mat1, rhs1 = make_matrix(T[1, :], T[0, :])
mat2, rhs2 = make_matrix(T[2, :], T[1, :])
total_mat = np.vstack((mat1, mat2))
total_rhs = np.vstack((rhs1[:, np.newaxis],
rhs2[:, np.newaxis]))
rho, err, rank, eigs = np.linalg.lstsq(total_mat, total_rhs)
In [203]:
rho
Out[203]:
In [204]:
err
Out[204]:
In [205]:
np.dot(total_mat, rho)
Out[205]:
In [206]:
total_rhs
Out[206]:
Cette fois-ci, la prédiction n'est pas si mauvaise...
On peut maintenant calculer la matrice d'accord (dans le cadre du modèle linéaire).
In [207]:
tuning_mat = compute_tuning_matrix(psi, rho)
In [208]:
tuning_mat
Out[208]:
Et maintenant, on peut prédire les changements à partir d'un état vers un autre :
In [ ]:
def predict_changes(initial_T, final_T, tuning_mat):
"""predicts changes in tuning (frequency) from a vector of tensions"""
print("initial tunings: {:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}".format(*[x for x in np.sqrt(initial_T))]))
print("final tunings: {:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}".format(*[x for x in np.sqrt(final_T))]))
print("predicted tunings")
attention au calcul des target_dF
, c'est :
$$
\delta F = f_{target}^2 - f_{current}^2
$$
In [218]:
target_freqs = freqs.copy()
current_freqs = history[2, :]
target_dF = target_freqs**2 - current_freqs**2
Delta_F = np.linalg.solve(tuning_mat, target_dF)
Delta_F
Out[218]:
In [219]:
np.sqrt(current_freqs**2 + np.dot(tuning_mat, Delta_F))
Out[219]:
In [216]:
target_freqs
Out[216]:
On peut maintenant écrire la séquence attendue :
In [227]:
print("initial: {:.1f}, {:.1f}, {:.1f}, {:.1f}, {:.1f}, {:.1f}".format(*[x for x in current_freqs]))
for step in range(6):
new_F = np.sqrt(current_freqs**2 + np.dot(tuning_mat, Delta_F * (np.arange(6) <= step)))
print(" step {}: {:.1f}, {:.1f}, {:.1f}, {:.1f}, {:.1f}, {:.1f}".format(step, *[x for x in new_F]))
On peut écrire une fonction qui facilite le calcul :
In [228]:
def tuning_step(tuning_mat, initial_freqs, Delta_F, step_number):
"""predicts observed tuning as a function of tuning step
convention: step 0 means nothing has changed"""
step = step_number - 1
if step == -1:
return initial_freqs
return np.sqrt(initial_freqs**2 + np.dot(tuning_mat, Delta_F * (np.arange(6) <= step)))
In [237]:
print_strings = lambda v: print("{:.1f}, {:.1f}, {:.1f}, {:.1f}, {:.1f}, {:.1f}".format(*v))
In [233]:
%matplotlib inline
import matplotlib.pyplot as plt
In [229]:
initial_freqs = current_freqs.copy()
Les fréquences cibles des cordes sont :
In [246]:
for target, string in zip([tuning_step(tuning_mat, initial_freqs, Delta_F, i)[i-1] for i in range(1, 7)],
["low E", "A", "D", "G", "B", "high E"]):
print("string: {}, target frequency: {:.1f}".format(string, target))
In [240]:
measured_freqs = [82.0,114.5,148.5,193.5,244.0,328.7]
expected_freqs = tuning_step(tuning_mat, initial_freqs, Delta_F, 1)
print_strings(measured_freqs)
print_strings(expected_freqs)
plt.plot(measured_freqs, 'o')
plt.plot(expected_freqs, 'o')
Out[240]:
In [247]:
measured_freqs = [82.3,110.0,148.8,194.1,244.5,329.2]
expected_freqs = tuning_step(tuning_mat, initial_freqs, Delta_F, 2)
print_strings(measured_freqs)
print_strings(expected_freqs)
plt.plot(measured_freqs, 'o')
plt.plot(expected_freqs, 'o')
Out[247]:
In [248]:
measured_freqs = [82.4,110.2,146.9,194.4,244.7,329.5]
expected_freqs = tuning_step(tuning_mat, initial_freqs, Delta_F, 3)
print_strings(measured_freqs)
print_strings(expected_freqs)
plt.plot(measured_freqs, 'o')
plt.plot(expected_freqs, 'o')
Out[248]:
In [250]:
measured_freqs = [82.4,110.2,147.0,196.1,244.6,329.2]
expected_freqs = tuning_step(tuning_mat, initial_freqs, Delta_F, 4)
print_strings(measured_freqs)
print_strings(expected_freqs)
plt.plot(measured_freqs, 'o')
plt.plot(expected_freqs, 'o')
Out[250]:
In [251]:
measured_freqs = [82.4,110.2,146.9,196.3,246.8,329.2]
expected_freqs = tuning_step(tuning_mat, initial_freqs, Delta_F, 5)
print_strings(measured_freqs)
print_strings(expected_freqs)
plt.plot(measured_freqs, 'o')
plt.plot(expected_freqs, 'o')
Out[251]:
In [253]:
measured_freqs = [82.4,110.1,146.9,196.3,246.7,329.6]
expected_freqs = tuning_step(tuning_mat, initial_freqs, Delta_F, 6)
print_strings(measured_freqs)
print_strings(expected_freqs)
plt.plot(measured_freqs, 'o')
plt.plot(expected_freqs, 'o')
Out[253]:
J'ai envie de penser que cela suffit.
à faire demain :
Effet du serrage des boulons en tête de guitare sur l'accordage :
Conclusion : petit effet, on va négliger ça.
J'utilise le protocole d'accordage suivant (attention différent de celui de l'étape précédente où j'avais descendu le mi et monté le la) :
Au préalable, je met toutes les vis dans leurs positions neutres sur le vibrato pour le fine tuning.
In [254]:
freqs = np.array([82.4, 110., 146.8, 196., 246.9, 329.6]) # frequencies of the guitar strings, from low E to high E, in Hz
calibration_tensions = np.array([7.94, 8.84, 8.34, 6.67, 4.99, 5.94]) * 9.81 # calibration tensions found on package (in kg) converted to N
mu = calibration_tensions / (4 * 0.648**2 * freqs**2)
psi = 4 * 0.648**2 * mu
In [255]:
history = np.array([[83.7,112.7,151.3,204.2,251.2,333.4],
[84.9,112.3,150.9,203.3,250.5,332.8],
[85.0,109.4,151.1,203.9,250.9,333.0]])
history
Out[255]:
In [256]:
T = (history ** 2) * psi
In [257]:
T.sum(axis=1) / 9.81
Out[257]:
In [259]:
mat1, rhs1 = make_matrix(T[1, :], T[0, :])
mat2, rhs2 = make_matrix(T[2, :], T[1, :])
total_mat = np.vstack((mat1, mat2))
total_rhs = np.vstack((rhs1[:, np.newaxis],
rhs2[:, np.newaxis]))
rho, err, rank, eigs = np.linalg.lstsq(total_mat, total_rhs)
In [260]:
rho
Out[260]:
In [261]:
err
Out[261]:
In [262]:
np.dot(total_mat, rho)
Out[262]:
In [263]:
total_rhs
Out[263]:
On peut remarquer que l'inversion ne donne pas des valeurs satisfaisantes car les signes du produit matrice vecteur ne respectent pas celles observées (que des moins ou que des plus). On peut imaginer faire plus de mesures pour voir ce que ça donne : je vais rajouter un désaccordage.
In [264]:
history = np.vstack((history,
np.array([82.3,109.5,151.3,204.0,251.1,333.3])))
In [265]:
history
Out[265]:
In [268]:
T = (history ** 2) * psi
In [269]:
mat3, rhs3 = make_matrix(T[3, :], T[2, :])
In [270]:
total_mat = np.vstack((mat1, mat2, mat3))
total_rhs = np.vstack((rhs1[:, np.newaxis],
rhs2[:, np.newaxis],
rhs3[:, np.newaxis]))
rho, err, rank, eigs = np.linalg.lstsq(total_mat, total_rhs)
In [271]:
rho
Out[271]:
In [272]:
err
Out[272]:
In [273]:
np.dot(total_mat, rho)
Out[273]:
In [274]:
total_rhs
Out[274]:
On laisse tomber et on recommence la procédure de calibration, avec un précision supérieure :
In [275]:
history = np.array([[81.08,110.53,151.17,203.89,251.09,333.24],
[82.9,110.47,151.04,203.57,250.96,333.19],
[82.87,112.37,150.96,203.42,250.69,333.02]])
history
Out[275]:
In [276]:
T = (history ** 2) * psi
In [277]:
T.sum(axis=1) / 9.81
Out[277]:
In [278]:
mat1, rhs1 = make_matrix(T[1, :], T[0, :])
mat2, rhs2 = make_matrix(T[2, :], T[1, :])
total_mat = np.vstack((mat1, mat2))
total_rhs = np.vstack((rhs1[:, np.newaxis],
rhs2[:, np.newaxis]))
rho, err, rank, eigs = np.linalg.lstsq(total_mat, total_rhs)
In [279]:
rho
Out[279]:
In [280]:
err
Out[280]:
In [281]:
np.dot(total_mat, rho)
Out[281]:
In [282]:
total_rhs
Out[282]:
Tout est de même signe, c'est pas si mal. Et l'erreur est faible.
In [286]:
tuning_mat = compute_tuning_matrix(psi, rho)
In [287]:
target_freqs = freqs.copy()
current_freqs = history[2, :]
target_dF = target_freqs**2 - current_freqs**2
Delta_F = np.linalg.solve(tuning_mat, target_dF)
Delta_F
Out[287]:
In [288]:
initial_freqs = current_freqs.copy()
initial_freqs
Out[288]:
In [294]:
for target, string in zip([tuning_step(tuning_mat, initial_freqs, Delta_F, i)[i-1] for i in range(1, 7)],
["low E", "A", "D", "G", "B", "high E"]):
print("string: {}, target frequency: {:.1f}".format(string, target))
Mi grave :
In [290]:
measured_freqs = [82.18,112.37,150.94,203.43,250.67,333.08]
expected_freqs = tuning_step(tuning_mat, initial_freqs, Delta_F, 1)
print_strings(measured_freqs)
print_strings(expected_freqs)
La :
In [291]:
measured_freqs = [82.44,109.75,150.91,203.92,251.13,333.26]
expected_freqs = tuning_step(tuning_mat, initial_freqs, Delta_F, 2)
print_strings(measured_freqs)
print_strings(expected_freqs)
Re :
In [292]:
measured_freqs = [82.66,110.12,146.65,204.46,251.57,333.51]
expected_freqs = tuning_step(tuning_mat, initial_freqs, Delta_F, 3)
print_strings(measured_freqs)
print_strings(expected_freqs)
Sol :
In [296]:
measured_freqs = [82.86,110.39,146.96,195.81,251.94,333.99]
expected_freqs = tuning_step(tuning_mat, initial_freqs, Delta_F, 4)
print_strings(measured_freqs)
print_strings(expected_freqs)
Si :
In [298]:
measured_freqs = [82.97,110.52,147.1,196.29,246.53,334.24]
expected_freqs = tuning_step(tuning_mat, initial_freqs, Delta_F, 5)
print_strings(measured_freqs)
print_strings(expected_freqs)
Mi :
In [300]:
measured_freqs = [83.2,110.75,147.17,196.55,246.67,329.84]
expected_freqs = tuning_step(tuning_mat, initial_freqs, Delta_F, 6)
print_strings(measured_freqs)
print_strings(expected_freqs)
Même si l'accord n'est pas parfait, on a atteint le but. Je reserre les boulons du manche et remesure :
On peut maintenant utiliser les vis de tuning fines pour arriver à un accordage parfait.
to do pour la suite