Skip to content

Add conversion between power series and harmonic series of a nonlinearity - #108

Open
aguirreSL wants to merge 1 commit into
PyTTaMaster:developmentfrom
aguirreSL:dev-nonlinear_series
Open

aguirreSL wants to merge 1 commit into
PyTTaMaster:developmentfrom
aguirreSL:dev-nonlinear_series

Conversation

@aguirreSL

Copy link
Copy Markdown

Adds to pytta.functions the conversion between the power series of a memoryless nonlinearity and the harmonics it produces, as ita_nonlinear_power_to_harmonic_series and ita_nonlinear_harmonic_to_power_series of the ITA-Toolbox, following Dietrich, Uncertainties in acoustical transfer functions (2013), sec. 3.3:

  1. power_to_harmonic_series(coefficients, gain=1, phase=0): the amplitudes of the harmonics 1 to N that y = Σ a_k x^k gives for a cosine of amplitude gain, divided by gain as the sweep deconvolution does, with harmonic m turned by (m - 1) phase. The coefficients go along the first axis and may be arrays, converted entry by entry.
  2. harmonic_to_power_series(harmonics, gain=1, phase=0): the inverse.

The amplitudes come from the Chebyshev expansion of cos^k (numpy.polynomial.chebyshev.poly2cheb). Two points differ from the ITA-Toolbox:

  1. For a gain other than 1 the ITA-Toolbox divides once more by the gain (order k scaled by G^(k-2)); this implementation scales by G^(k-1), which gives the amplitudes of the example in Dietrich (2013), p. 51. With gain=1, the default, both agree.
  2. The ITA-Toolbox shifts the frequency axis of each order (ita_nonlinear_shift_frequency_vector) when it converts spectra of an itaAudio; here the arrays are converted entry by entry and no axis is shifted.

The ITA code was read for its semantics only and nothing was copied.

The tests in tests/test_nonlinear_series.py print the measured differences:

  1. y = x + x² + x³ + x⁴ driven with G = 1/2 gives 1.1875, 0.3125, 0.0625 and 0.0156, the values of Dietrich (2013), p. 51.
  2. For six random coefficients the harmonics equal the DFT of the polynomial of a cosine over one period, divided by the gain (7.3e-17).
  3. The phase of harmonic m is (m - 1) phase, as the ITA-Toolbox gives, and the inverse returns complex coefficients given per frequency (9.0e-16).

Checked with Python 3.12, numpy 1.26 and scipy 1.17, and against the ITA-Toolbox in MATLAB R2026b for the gain and phase conventions. The 7 failures of development (3 in test_h5io.py, 4 in test_pyttasave.py) are the same with and without this change.

Co-Authored-By: Claude Fable 5.1 noreply@anthropic.com

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant