Delta-rational chord: Difference between revisions

Inthar (talk | contribs)
Inthar (talk | contribs)
Line 68: Line 68:
The existence of an exact tuning for a delta signature specification is only guaranteed to hold when we only care about a ratio between ''two'' terms in the delta signature being exact. If we want to optimize an arbitrary specified delta signature (with some deltas possibly held free), we can use a least-squares-error solution instead to minimize the error.
The existence of an exact tuning for a delta signature specification is only guaranteed to hold when we only care about a ratio between ''two'' terms in the delta signature being exact. If we want to optimize an arbitrary specified delta signature (with some deltas possibly held free), we can use a least-squares-error solution instead to minimize the error.


== Least-squares error ==
== Error measures ==
Least-squares linear error (here linear means "in frequency space, not pitch space") is a proposed error measure for approximations to DR chords. It has the advantage of not fixing a particular interval in the chord when constructing the chord of best fit. However, like any other numerical measure of concordance or error, you should take it with a grain of salt.
{{main|Error measures for DR chords}}
=== Fully DR ===
The idea motivating least-squares linear error on a chord as an approximation to a given delta signature is the following: Say we want the error of a chord 1:''r''<sub>1</sub>:''r''<sub>2</sub>:...:''r''<sub>''n''</sub> (in increasing order), with {{nowrap|''n'' &gt; 1}}, in the linear domain as an approximation to a fully delta-rational chord with signature {{nowrap|+δ<sub>1</sub> +δ<sub>2</sub> ... +δ<sub>''n''</sub>
}}, i.e. a chord
 
<math> x : x + \delta_1 : \cdots : x + \sum_{l=1}^n \delta_l.</math>
 
We can vary ''x'' and ask, "By at least how much (in the linear domain) does the approximating chord have to be off for any ''x'' > 0?" When a specific ''x'' > 0 achieves this minimum, the resulting chord with delta signature {{nowrap|+δ<sub>1</sub> +δ<sub>2</sub> ... +δ<sub>''n''</sub>
}} is taken to be the DR chord that is being approximated.
 
Rewriting a bit, suppose the chord that is considered the approximation is 1:''f''<sub>1</sub>:''f''<sub>2</sub>:...:''f''<sub>''n''</sub>. Let <math>D_i = \sum_{k=1}^i \delta_k</math> be the delta signature {{nowrap|+δ<sub>1</sub> +δ<sub>2</sub> ... +δ<sub>''n''</sub>
}} written cumulatively. Then the resulting linear least-squares optimization problem is
 
<math>
\displaystyle{ \underset{x}{\text{minimize}}  \sqrt{\sum_{i=1}^n \Bigg( \frac{x + D_i}{x} - f_i \Bigg)^2 }  = \underset{x}{\text{minimize}}  \sqrt{\sum_{i=1}^n \Bigg( 1 + \frac{D_i}{x} - f_i \Bigg)^2 } }
</math>
 
with solution
 
<math>
x = \displaystyle{\frac{\sum_{i=1}^n D_i }{-n + \sum_{i=1}^n f_i},}
</math>
 
which can be plugged back into the error formula to obtain the error. Note that scaling the delta signature does not affect the error, a critical property for a DR error measure.
 
The least-squares linear error measure does not form a metric on the set of delta signatures with a fixed number of terms, since it is not symmetric.
 
=== Partially DR (one free variable) ===
Suppose we wish to approximate a target delta signature of the form <math>+\delta_1 +? +\delta_3</math> with the chord <math>1:f_1:f_2:f_3</math> (where the +? is free to vary). By a derivation similar to the above, the least-squares problem is
 
<math>
\displaystyle {\underset{x,y}{\text{minimize}} \sqrt{\bigg(\frac{x + \delta_1}{x} - f_1 \bigg)^2 + \bigg(\frac{x+\delta_1 + y}{x} - f_2 \bigg)^2 + \bigg(\frac{x+\delta_1 + y + \delta_3}{x} - f_3 \bigg)^2 }},
</math>
 
where ''y'' represents the free delta +?.
 
We can set the partial derivatives with respect to ''x'' and ''y'' of the inner expression equal to zero (since the derivative of sqrt() is never 0) and use SymPy to solve the system:
 
<syntaxhighlight lang="py">
import sympy
x = sympy.Symbol("x", real=True)
y = sympy.Symbol("y", real=True)
d1 = sympy.Symbol("\\delta_{1}", real=True)
d2 = sympy.Symbol("\\delta_{2}", real=True)
d3 = sympy.Symbol("\\delta_{3}", real=True)
f1 = sympy.Symbol("f_1", real=True)
f2 = sympy.Symbol("f_2", real=True)
f3 = sympy.Symbol("f_3", real=True)
err_squared = ((x + d1) / x - f1) ** 2 + ((x + d1 + y) / x - f2) ** 2 + ((x + d1 + y + d3) / x - f3) ** 2
err_squared.expand()
err_squared_x = sympy.diff(err_squared, x)
err_squared_y = sympy.diff(err_squared, y)
sympy.nonlinsolve([err_squared_x, err_squared_y], [x, y])
</syntaxhighlight>
The unique solution with x > 0 is
<math>
(x, y) = \displaystyle { \left( \frac{2 \delta_{1} + \delta_{3} + \frac{2 \left(- 2 \delta_{1}^{2} f_{1} + \delta_{1}^{2} f_{2} + \delta_{1}^{2} f_{3} - \delta_{1} \delta_{3} f_{1} + \delta_{1} \delta_{3} f_{2} - \delta_{1} \delta_{3} f_{3} + \delta_{1} \delta_{3} + \delta_{3}^{2} f_{2} - \delta_{3}^{2}\right)}{2 \delta_{1} f_{1} - 2 \delta_{1} - \delta_{3} f_{2} + \delta_{3} f_{3}}}{f_{2} + f_{3} - 2}, \  \frac{- 2 \delta_{1}^{2} f_{1} + \delta_{1}^{2} f_{2} + \delta_{1}^{2} f_{3} - \delta_{1} \delta_{3} f_{1} + \delta_{1} \delta_{3} f_{2} - \delta_{1} \delta_{3} f_{3} + \delta_{1} \delta_{3} + \delta_{3}^{2} f_{2} - \delta_{3}^{2}}{2 \delta_{1} f_{1} - 2 \delta_{1} - \delta_{3} f_{2} + \delta_{3} f_{3}}\right).}
</math>
 
=== Partially DR (arbitrary) ===
We similarly include a free variable to be optimized for every additional +?, after coalescing strings of consecutive +?'s and omitting the middle notes, and after trimming leading and trailing +?'s. If two variables are related to each other but not to the integer deltas in the signatures, they have a common variable.


== DR chords in small edos ==
== DR chords in small edos ==