Fuzzy Time Re-Composer — Rule-Based Temporal Recomposition
Segments a Sound, derives seven relative acoustic descriptors, maps them to fuzzy memberships, combines six weighted rules into a continuous time-warp factor plus a discrete gesture, reorders the segments, and renders a new multichannel timeline with adaptive crossfades.
What this does
Fuzzy Time Re-Composer treats temporal organization as a compositional variable. It does not apply one uniform stretch or one fixed granular process to the whole file. Instead, every detected segment receives its own acoustic description, fuzzy-rule activations, continuous warp factor, and winning gesture.
- Segment the analysis signal using adaptive onsets, a fixed grid, or accumulated pitch periods.
- Measure seven descriptors and normalize each descriptor across this file's segments.
- Map the normalized descriptors to fuzzy memberships.
- Evaluate six rule activations.
- Defuzzify all rule activations into one continuous time-warp factor, while the strongest rule supplies the discrete gesture label.
- Reorder the segment vector.
- Render preserve/dilate/compress material, shuffled micro-grains, forward+retrograde pairs, or ostinato repetitions into a new timeline.
What is fuzzy logic?
Ordinary binary classification asks whether a condition is true or false. Fuzzy logic allows graded membership between 0 and 1. In this script, a segment can simultaneously have strong transient membership, moderate entropy membership, weak sustain membership, and so on. Several rules can therefore be active at once.
The important distinction is:
- Continuous result: all active rules contribute to the time-warp factor.
- Discrete result: the strongest rule determines the gesture category shown in the visualization and, for some categories, an additional structural operation.
Quick start
- Select exactly one Sound object. The input must be at least 0.25 s long.
- Run
Fuzzy_Time_Recomposer.praat. - Choose Manual or one of the five presets.
- Choose the segmentation mode and set the target Segment_length_ms.
- Set Pitch_floor and Pitch_ceiling for pitch-period segmentation, pitch/motion analysis, and PSOLA warping.
- Adjust Fuzzy_sensitivity, Fragmentation, Dilation, and Mirroring.
- Choose a reorder mode and optional macro trajectory.
- Use a fixed Random_seed for repeatable results. Set it to 0 for an unpredictable run; the concrete seed is printed so that run can still be reproduced later.
- Run the script. The output is named
<source>_fuzzytime.
Segmentation
Adaptive onsets
The analysis Intensity contour is sampled every 5 ms. The script measures the positive frame-to-frame intensity derivative and computes:
A boundary is accepted at a local positive-derivative peak only when it is sufficiently separated from the previous accepted onset and stays away from the file edges. Fuzzy_sensitivity does not alter this onset threshold.
Fixed grid
Boundaries are placed at the requested Segment_length_ms interval, with a final segment covering the remaining material.
Pitch periods
Praat creates a periodic PointProcess between Pitch_floor and Pitch_ceiling. Pitch-period intervals are accumulated until they reach approximately the requested segment length, then a boundary is created. This is therefore period-aligned segmentation at the requested timescale, not one segment per pitch period.
Zero-crossing snapping
Adaptive-onset and fixed-grid interior boundaries are moved to the nearest channel-1 zero crossing only when the moved boundary remains safely between both neighboring boundaries. Pitch-period boundaries are not re-snapped.
Seven descriptors & fuzzy memberships
| Membership | Raw descriptor | Implemented measurement |
|---|---|---|
| Transient | Attack strength | Early intensity peak minus intensity near the segment onset. |
| Sustain | Harmonicity | Mean HNR from Praat Harmonicity (cc). |
| Motion | Pitch motion | F0 standard deviation in semitones. |
| HF | High-frequency ratio | Energy from 2000 Hz to Nyquist divided by total spectral energy. |
| Entropy | Coarse spectral entropy | Normalized Shannon entropy over up to seven broad frequency bands. |
| Low | Low-frequency ratio | Energy from 0–500 Hz divided by total spectral energy. |
| Rise | Energy slope | Late-segment mean intensity minus early-segment mean intensity. |
Self-calibration
Each raw descriptor is min–max normalized across the segments of the current file:
If a descriptor is effectively constant across the file, all segments receive the neutral value 0.5. These values are relative positions within the descriptor range, not percentile ranks; for example, 0.9 does not mean “top 10% of segments.”
Membership ramp
Fuzzy_sensitivity is clamped to 0–1. Higher values narrow the ramp around 0.5 and make low/high evidence separate more sharply.
Rule base & continuous warp
The three user biases are not probabilities and do not need to sum to 1. They scale rule activations together with the macro trajectory.
Trajectory-dependent bias weights
Six rule activations
Log-domain defuzzification
Each rule contributes a target time factor:
- Dilate →
Max_dilation - Compress →
Max_compression - Granulate →
max(Max_compression, 0.7) - Preserve, Retrograde, Ostinato → 1×
The result is finally clamped to the requested Max_compression ... Max_dilation range. The discrete gesture is the activation argmax. The visualization also compares the winner with the runner-up; a lead below 25% is shown as a ring rather than a filled marker.
What the six gestures actually render
| Gesture | Additional structural action |
|---|---|
| Preserve | No additional structural action; render one segment after applying the continuously defuzzified warp. |
| Dilate | Same one-segment render path. The Dilate rule strongly pulls the continuous warp toward Max_dilation. |
| Compress | Same one-segment render path. The Compress rule pulls the continuous warp toward Max_compression. |
| Granulate | Warp first, then split into micro-grains and Fisher–Yates shuffle their order. Micro-grain length also contracts as the macro trajectory becomes more chaotic. |
| Retrograde | Warp first, then emit two items: the forward segment followed by a reversed copy. The joint fade allowance is 1.6× the segment's normal fuzzy fade. |
| Ostinato | Warp first, then repeat the segment 2–4 times according to Sustain membership. |
Reordering & macro trajectory
| Mode | Exact behavior |
|---|---|
| Sequential | Keep source segment order. |
| Fuzzy nearest-profile chain | Start at source segment 1, then greedily choose the nearest unused segment in the seven-dimensional fuzzy-membership space. |
| Shuffle | Fisher–Yates permutation. |
| Retrograde order | Reverse the segment order. Segment audio itself is not reversed unless its discrete gesture is Retrograde. |
| Interleave (odd then even) | Order = 1,3,5,… followed by 2,4,6,… . It does not alternate odd/even one by one. |
Trajectory
Trajectory is evaluated over each segment's output slot after reordering:
- None: chaos = 0.5 everywhere.
- Order to chaos: chaos rises from 0 to 1 across the output order.
- Chaos to order: chaos falls from 1 to 0.
The trajectory does not add random swaps by itself. It progressively changes the rule biases — most notably increasing the fragmentation weighting while reducing the dilation weighting as chaos rises.
Five presets
| Preset | Segment | Frag. | Dilation | Mirror | Warp range | Reorder | Trajectory | Micro grain |
|---|---|---|---|---|---|---|---|---|
| Micro-shuffle | 90 ms | 0.90 | 0.15 | 0.10 | 0.45–1.6× | Sequential | None | 16 ms |
| Frozen resonance | 200 ms | 0.10 | 0.95 | 0.10 | 0.60–8.0× | Sequential | None | 30 ms |
| Directional mirroring | 160 ms | 0.20 | 0.35 | 0.95 | 0.50–2.5× | Sequential | None | 24 ms |
| Poly-temporal interleave | 110 ms | 0.55 | 0.45 | 0.20 | 0.35–3.0× | Odd then even | None | 20 ms |
| Entropy injection | 130 ms | 0.60 | 0.40 | 0.25 | 0.30–3.5× | Nearest-profile | Order → chaos | 18 ms |
Time warping, rendering & crossfades
PSOLA time warping
Warping uses Praat Lengthen (overlap-add). A single pass is kept between 0.25× and 3×; larger requested factors are reached by chaining passes. Before rendering, the script computes the number of passes required by the requested warp range and rejects settings requiring more than eight passes.
Segments shorter than:
are left unwarped and reported. This is a duration transformation; it is not a pitch-transposition stage.
Multichannel rendering
Each original channel is rendered independently with the same segment order, fuzzy decisions, PSOLA seeds, and micro-grain permutations. The channels are then recombined in their original order. This preserves inter-channel relationships while avoiding the mono-only limitation of Praat's PSOLA command.
Adaptive crossfades
At each joint the actual overlap is limited by the fade requests of both adjacent items and by 45% of each grain duration, then sample-aligned. The active law is a raised-cosine equal-gain fade. The timeline is assembled by writing the windowed grains into pre-allocated buffers at sample-aligned offsets; Praat Concatenate is not used.
Visualization
When Draw_analysis is enabled, the Picture window shows the complete inference-to-render chain:
- Source / segmentation: an unnormalized display copy following the same channel decision as analysis. Source and Output share one amplitude scale. Up to 60 segments use explicit boundary lines; denser segmentations use alternating bands.
- Fuzzy memberships: seven grayscale rows. White = 0, dark = 1. The time axis is aligned with Source.
- Gesture legend: gesture color has one meaning throughout the decision and remapping panels. Filled marker = clear winner; ring = close call.
- Fuzzy decision map: x = source segment span; y =
log2(warp); color = winning gesture; stems are drawn before markers so they cannot overwrite them. - Temporal remapping: source interval → output interval for each rendered item. The dotted reference is the identity mapping; downward runs indicate reversed material. Very large maps are display-thinned only.
- Output: neutral dark-gray waveform on the same amplitude scale as Source.
- Summary: segments, grains, seed, duration, warp range, channel count, peaks, gesture census, and close-call count.
Output behavior & limits
| Item | Behavior |
|---|---|
| Input minimum | 0.25 s. |
| Segment cap | 400 segments. |
| Grain cap | 6000 rendered items. If reached, additional items are dropped and reported. |
| Output duration guard | Projected output above 900 s stops before assembly. |
| Channel count | Preserved. |
| Output time domain | Starts at 0 s because the timeline is newly composed. |
| Object name | <source>_fuzzytime. |
Safety peak
Safety_peak is clamped to 0–1. A value of 0 disables it. Otherwise the completed result is attenuated only when its Sinc70 peak exceeds the requested ceiling:
There is no upward normalization. Quiet output remains quiet.