29 #include "../system/log.h"
30 #include "../math/mathtools.h"
63 if (not piano)
return;
94 if (K<=0 or B<=0 or B>K)
return;
96 LogI(
"Compute overpull interaction matrix");
100 for (
auto &row :
R) row.resize(K);
101 for (
auto &row : R) row.assign(K,0);
103 double DL=0,DR=0,SL=0,SR=0,SB=0,SN=0,shift=0;
126 LogW(
"Undefined piano type encountered");
131 double G =-(pow(2,-0.08333333333333333)*
132 (-(SL*pow(2,0.08333333333333333 + B/12.)) +
133 K*SL*pow(2,0.08333333333333333 + B/12.) - B*SR*pow(2,K/12.))*
135 double H =((SL*pow(2,1 + B/12.) - SR*pow(2,0.9166666666666666 + K/12.))*
136 pow(1 + B - K,-1))/2.;
137 auto stringlength = [G,H] (
int k) {
return (G+H*k)*pow(2,-k/12.0); };
140 std::vector<double> arc(K,0);
141 const double d = 13.6;
143 for (
int k=B+1; k<K; ++k) arc[k] = arc[k-1] +
144 sqrt(d*d + pow(stringlength(k)-stringlength(k-1),2));
145 double L = arc[K-1]+DR;
148 auto def = [L,arc] (
int j,
int k)
153 return b/L*x*(L*L-x*x-b*b) ;
157 auto deflection = [def] (
int j,
int k)
159 if (j<=k)
return def(j,k);
160 else return def(k,j);
164 auto epsilon = [deflection,B,shift] (
int j,
int k)
166 if (j<B and k<B)
return deflection(j+B+shift,k+B+shift);
167 else if (j<B and k>=B)
return deflection(j+B+shift,k);
168 else if (j>=B and k<B)
return deflection(j,k+B+shift);
169 else return deflection(j,k);
173 auto response = [B,SB,SN,stringlength,epsilon] (
int j,
int k)
176 if (k<8) unison=1;
else if (k<B) unison=2;
177 double stringlen = (j<B ? SB+SN : stringlength(j)+SN);
178 return unison * epsilon(j,k) / stringlen;
184 for (
int j=0; j<K; ++j)
for (
int k=0; k<K; ++k) sum += (R[j][k] = response(j,k));
186 for (
int j=0; j<K; ++j)
for (
int k=0; k<K; ++k)
187 R[j][k] *= p * averagePull / sum;
191 const double sigma = 20;
192 const double amplitude = averagePull * (1-p);
193 double avstring = B/SB;
194 for (
int k=B; k<K; k++) avstring += 1.0/stringlength(k);
196 double prefactor = amplitude / sqrt(2*3.141) / sigma / avstring / 0.7;
197 for (
int j=0; j<B; ++j)
for (
int k=0; k<B; ++k) R[j][k] += prefactor*exp(-0.5*(j-k)*(j-k)/sigma/sigma)/SB;
198 for (
int j=B; j<K; ++j)
for (
int k=B; k<K; ++k) R[j][k] += prefactor*exp(-0.5*(j-k)*(j-k)/sigma/sigma)/stringlength(j);
248 if (not piano)
return 0;
249 int K = piano->getKeyboard().getNumberOfKeys();
250 int B = piano->getKeyboard().getNumberOfBassKeys();
251 double cpratio = piano->getConcertPitch() / 440.0;
252 if (K<=0 or B<=0 or keynumber<0 or keynumber>=K)
return 0;
260 std::vector<double> weightedRedMarkers (K,0);
261 const int maxGapsize = 7;
265 for (
int k=0; k<K; ++k)
267 double computed = piano->getKey(k).getComputedFrequency();
268 double tuned = piano->getKey(k).getTunedFrequency();
269 if (computed>20 and computed<20000 and tuned>20 and tuned<20000 and cpratio>0)
272 weightedRedMarkers[k] = chi*(gapsize+1);
273 lastkey = k; lastchi = chi;
277 if (gapsize > maxGapsize)
return 0;
278 if (k==K-1 and gapsize>0)
279 weightedRedMarkers[lastkey] += lastchi*gapsize;
283 double overpull = 0, totaldeviation = 0;
284 for (
int k=0; k<K; k++)
if (weightedRedMarkers[k])
286 totaldeviation += weightedRedMarkers[k];
287 overpull -= weightedRedMarkers[k] *
R[keynumber][k];
292 if (fabs(totaldeviation/K)>5)
return overpull;
void init(const Piano *piano)
Initialize.
int mNumberOfKeys
Total number of keys.
double mConcertPitch
Concert pitch (A4)
The piano is a upgright piano.
OverpullEstimator()
Constructor, resetting the member variables.
piano::PianoType mPianoType
Piano type (upright/grand)
double getOverpull(int keynumber, const Piano *piano)
Compute the required overpull on the basis of the interaction matrix.
void computeInteractionMatrix(double averagePull=0.22)
Compute the interaction matrix between the string.
std::vector< std::vector< float > > R
Response matrix.
The piano is a grand piano.
int mNumberOfBassKeys
Keys on the bass bridge.