HFD-Driven Time Warping — User Guide

Measures frame-by-frame Higuchi Fractal Dimension (HFD), maps relative signal complexity to a continuous DurationTier, optionally pulls low-voicing regions toward unity stretch, and applies the same temporal map to every original channel.

Author: Shai Cohen Affiliation: Department of Music, Bar-Ilan University, Israel Version: 2.4 (2026) License: MIT License Repo: GitHub
Contents:

What this does

HFD-Driven Time Warping creates a non-uniform time-scale transformation whose local duration factor is derived from the relative Higuchi Fractal Dimension of successive analysis frames.

The current processing chain is:

  1. Build a mono, zero-based analysis copy of the selected Sound.
  2. Downsample and high-pass that analysis copy.
  3. Measure frame RMS and HFD.
  4. Exclude low-level frames from HFD normalization and force them to 1× stretch.
  5. Smooth active HFD values and normalize them with either percentile or min/max mapping.
  6. Apply one of four monotonic mapping curves.
  7. Optionally use the HNR-derived voicing track to pull low-voicing regions toward 1×.
  8. Smooth and slew-limit the resulting stretch command.
  9. Create a linearly interpolated Praat DurationTier.
  10. Apply that same tier independently to every original channel with Manipulation overlap-add resynthesis.
Analysis is mono; rendering is not. The mono fold is used only to derive one shared time-warp trajectory. Stereo and multichannel inputs retain their channel count in the rendered result.

What is Higuchi Fractal Dimension?

Higuchi Fractal Dimension is a time-series measure based on how the measured curve length changes when the signal is sampled at different integer step sizes k. The script estimates one HFD value for each analysis frame.

For k = 1 ... K_max: construct k offset sub-series estimate normalized curve length L(k) HFD = slope of ln[L(k)] versus ln(1/k)

The implementation clamps the resulting dimension to 1–2. Higher values are treated as greater local irregularity/complexity; lower values as smoother or more regular. The important control variable is primarily the relative HFD range inside the current file, not an absolute audio-category threshold.

HFD is an analysis descriptor, not a claim that the audio itself is a mathematical fractal over all scales.

Quick start

  1. Select exactly one Sound object.
  2. Run HFD-Driven_Time_Warping.praat.
  3. Choose Custom or Subtle / Moderate / Dramatic / Extreme / Glitch.
  4. Choose Speech or Music_Field_Recording for the analysis high-pass filter.
  5. Use Show_advanced_settings when you need direct control of analysis, mapping, voicing, pitch bounds or speed settings.
  6. Run the script. The result is named <source>_HFDwarp_<preset>.
Named presets are applied after the Advanced Settings dialog. They therefore overwrite most mapping and smoothing values entered there. Use Custom for unrestricted manual control. Pitch bounds, downsample factor and silence gate are not overwritten by the named presets.

Analysis pipeline

1. Mono fold and time domain

Multichannel input is converted to mono only for analysis. The analysis copy is shifted to a 0…T time domain, so non-zero Praat source times do not affect the control trajectory.

2. Downsampling

analysisRate = sourceSampleRate / Downsample_factor

The script stops if this rate is not above twice Maximum_pitch_Hz. The resampling uses precision 50.

3. Material-dependent high-pass

Material typeAnalysis filter
SpeechHigh-pass at 100 Hz
Music / Field RecordingHigh-pass at 30 Hz

This choice affects the analysis signal only. It does not filter the rendered output and does not otherwise change the preset parameters.

4. Frames

numFrames = floor((T - frameLength) / hopSize) + 1

At least three analysis frames are required. After downsampling, a frame must contain at least 20 samples and at least 3 × K_max samples.

5. Silence / inactive-frame gate

The script computes the global RMS of the filtered, downsampled analysis signal:

silenceThreshold = globalAnalysisRMS × 10^(Silence_gate_dB / 20)

Frames below this threshold are marked inactive. They are excluded from HFD normalization and map directly to before the later smoothing stage. The default gate is −50 dB relative to the analysis RMS.

6. Windowed HFD

Unless Skip_windowing is enabled, each frame uses a Hann window. The weighted frame mean is divided by the sum of the Hann weights before the HFD differences are computed. Silent or degenerate frames return HFD = 1 rather than an arbitrary mid-range value.

HFD → stretch mapping

HFD smoothing

Each frame's smoothed HFD is the moving average of the active frames in its smoothing neighborhood. A neighborhood with no active frames receives HFD = 1.

Robust normalization

Only active frames participate in the mapping range. With percentile mapping enabled, the script uses approximately the 5th and 95th percentiles of the active smoothed HFD values; otherwise it uses their minimum and maximum.

norm = clamp( (smoothedHFD - mappingLow) / (mappingHigh - mappingLow), 0, 1 )

If there are fewer than two active frames, or essentially no active HFD variation, the HFD mapping is disabled and the stretch command defaults toward 1×.

Four mapping curves

CurveMapping of normalized HFD xEffect
LinearxDirect mapping.
High-complexity emphasisPushes low/mid values downward while preserving the high end.
Low-complexity liftsqrt(x)Raises lower/middle values toward the upper end.
Quantized steps0.125 / 0.375 / 0.625 / 0.875Four discrete normalized levels.
stretch = Min_stretch_factor + mappedNorm × (Max_stretch_factor - Min_stretch_factor)
All four curves are monotonic. Because the script requires Min_stretch_factor ≤ Max_stretch_factor, higher normalized HFD always maps to an equal or larger base stretch factor. The current script does not provide an inverted “high complexity → shorter” mapping.

Voicing gate — exact current behavior

When enabled, the script converts Praat Harmonicity (HNR) to a 0–1 voicing value:

v = clamp((HNR + 5) / 20, 0, 1)

The voicing track is then smoothed. Its effect on the HFD-derived stretch s is:

voicedCandidate = 1 + v × (s - 1) rawStretch = (1 - Voicing_influence) × s + Voicing_influence × voicedCandidate

This means:

The current implementation therefore protects low-HNR / unvoiced regions from extreme time warping. It does not implement the older documentation's claim that voiced regions are the ones pulled toward unity.

Presets

PresetFrame / hopKHFD smoothStretch rangeCurveVoicingFinal smoothSlew / sHann
Subtle60 / 60 ms470.85–1.15×On, 0.80; smooth 553Yes
Moderate50 / 50 ms550.70–1.50×LinearOn, 0.70; smooth 444Yes
Dramatic50 / 50 ms540.50–2.00×sqrt(x)On, 0.60; smooth 336No
Extreme40 / 40 ms530.40–2.50×sqrt(x)On, 0.50; smooth 228No
Glitch30 / 30 ms420.40–2.50×4 stepsOff120No

Subtle through Extreme use percentile mapping. Glitch uses min/max mapping.

Named presets do not overwrite Material_type, Minimum/Maximum_pitch_Hz, Downsample_factor, Silence_gate_dB, Draw_visualization, or Play_result.

Advanced settings

ParameterCustom defaultMeaning
Frame_length_s0.05HFD analysis frame length.
Hop_size_s0.05Spacing between analysis frames.
K_max5Largest integer scale in the Higuchi estimate; must be at least 3.
Silence_gate_dB relative RMS−50Inactive-frame threshold relative to global filtered analysis RMS; must be ≤ 0.
Smoothing_window_size5Moving average of active HFD values.
Min / Max stretch factor0.5 / 2.0Positive mapping endpoints; min must not exceed max.
Use_percentile_mappingOnUse active-frame 5th/95th-percentile range instead of min/max.
Mapping_curveLinearLinear, x², sqrt(x), or four steps.
Use_voicing_gateOnEnable HNR-based low-voicing pull toward 1×.
Voicing_influence0.7Blend strength, 0–1.
Voicing_smooth_window3Moving-average width for the HNR-derived voicing track.
Final_stretch_smooth3Moving-average width after mapping/gating.
Max_stretch_change_per_sec5.0Forward slew limit; 0 permits no frame-to-frame change after the first frame.
Minimum / Maximum pitch Hz75 / 600Used by Harmonicity and Manipulation pitch analysis.
Downsample_factor6Analysis-only sample-rate reduction; must leave rate > 2 × pitch ceiling.
Skip_windowingOffSkip the Hann window in HFD analysis.

Final smoothing and slew limit

maxChangePerFrame = Max_stretch_change_per_sec × Hop_size_s

After the final moving average, the script scans forward and limits each frame's difference from the already-limited previous frame to this amount.

DurationTier & resynthesis

The final command values are written into a zero-based DurationTier at time 0, every frame centre, and the source end. Praat linearly interpolates between these points.

DurationTier point = (sourceTime, relativeDurationFactor) factor > 1 → local expansion factor < 1 → local contraction factor = 1 → unchanged local duration

The script asks the tier for its predicted target duration before rendering. Conceptually, the target duration is the area under the relative-duration curve.

For every input channel:

  1. Extract that channel and shift it to start at 0.
  2. Create a Manipulation with 10 ms time step and the selected pitch bounds.
  3. Replace its DurationTier with the shared HFD tier.
  4. Use Get resynthesis (overlap-add).

The independently warped channels are then combined back in channel order. This produces one common temporal deformation while preserving the multichannel layout.

Visualization

The v2.4 Picture view follows the processing chain rather than presenting a generic analysis dashboard:

The source and result waveforms use the same amplitude range, so their displayed level difference is meaningful.

Output behavior

Peak safety

After resynthesis the script measures the Sinc70 absolute peak. It attenuates only when that peak exceeds 0.95:

if peak > 0.95: output *= 0.95 / peak

This is an attenuate-only safety ceiling. Quiet output is not normalized upward.