Skip to content

[FEATURE] add pitch detection, Wiener-Hopf factorization and normalized 2-D cross-correlation - #118

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

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

Conversation

@aguirreSL

Copy link
Copy Markdown

Adds to pytta.functions three analysis functions that the ITA-Toolbox has in its kernel (ita_pitch_detection, ita_wiener_hopf_factorization and ita_normxcorr2):

  1. pitch_detection(signal, fmin, fmax, blockSize=None, overlap=0, overtones=5, maxPitches=1, minDistance=10, minConfidence=0.1, fftDegree=16): the pitch of every block by the cepstrum biased harmonic product spectrum of ita_pitch_detection. The magnitude spectrum of the Hann windowed block is multiplied by itself decimated by 2 to overtones + 1 (Noll 1969) and by the real cepstrum at the quefrency of each bin. Several pitches can be taken one after the other, each with a confidence from the share of energy around it. It returns the pitches, the confidences and the start time of each block.
  2. wiener_hopf(signal, invert=False): the factorization of each channel into a causal and an anticausal part whose spectra multiply to the spectrum of the signal, by splitting the complex cepstrum.
  3. normxcorr2(template, image): the normalized two-dimensional cross-correlation with the full output of MATLAB's normxcorr2, computed with local sums (Lewis, "Fast normalized cross-correlation", 1995).

Differences from the ITA-Toolbox, kept on purpose:

  1. pitch_detection decimates the spectrum by taking every a-th bin, as the harmonic product spectrum is defined, where the ITA-Toolbox resamples it with a filter. It also weights by the real cepstrum, where the ITA-Toolbox uses the complex one. The pitch is the frequency of the peak bin; the ITA-Toolbox returns the bin before it.
  2. wiener_hopf leaves out the last step of the ITA-Toolbox, which replaces the phase of each factor by that of a windowed copy. That step is heuristic and breaks the product of the two factors, which here is exact.

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

The tests in tests/test_dsp_analysis.py print the measured values:

  1. A tone of six harmonics of 220 Hz gives 220.04 Hz with confidence 1, also when the fundamental is missing, within one bin of 2^16 points.
  2. Blocks of 0.25 s follow a change from 220 to 330 Hz.
  3. The product of a minimum phase and an anticausal maximum phase filter is factorized back into both, up to a gain (6.0e-9 and 5.4e-9), and the spectra of the factors multiply to the original (1.4e-8).
  4. normxcorr2 has the full output shape, is 1 exactly where a patch of random data was taken as template, and equals the definition at another lag.

Checked with Python 3.12, numpy 1.26 and scipy 1.17. 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