Crossfade Concatenator — User Guide

Build a new mono or stereo Sound from whole files or extracted chunks, using explicit overlap-add crossfades, optional random ordering, and global or segment-based dynamics.

Author: Shai Cohen Affiliation: Department of Music, Bar-Ilan University, Israel Version: 1.4 (2026) License: MIT License Output: concat_crossfade_<PresetName>
Contents:

What this does

Advanced Concatenate with Crossfade v1.4 creates a new sequence from one or more selected Sound objects. Each source can contribute its whole duration or one or more fixed/random excerpts. The resulting chunks can remain in extraction order, be uniformly shuffled without replacement, or be sampled with replacement. Adjacent chunks are joined by a manual overlap-add crossfade using one of five selectable curves.

The processor supports mono and stereo material. Mixed sample rates are resampled to the sampling frequency of the first selected Sound. Mixed mono/stereo inputs are converted to the channel count of the first extracted chunk. Material with more than two channels is rejected.

Important implementation detail: the crossfade is not Praat's built-in Concatenate with overlap. The script applies one fade-out and one fade-in, then explicitly sums the two time-aligned buffers. This avoids a second hidden overlap window and makes the selected crossfade curve the only crossfade law applied.

Quick start

  1. Select at least one Sound object in Praat.
  2. Run Concatenate_with_crossfade_v1.4.praat.
  3. Choose a preset, or leave Custom and set chunking, order, crossfade, overlap, and dynamics manually.
  4. Enable Draw_visualization if you want the result waveform, segment map, dynamics envelope, file legend, and summary.
  5. Click OK. The final Sound is named concat_crossfade_<PresetName>.
Default Custom settings: whole-file chunks, one chunk per file, randomized order without repeats, linear crossfade, 25% overlap of the incoming chunk, no dynamics, peak scaling to 0.95, visualization on, playback on.

Parameters

Chunk extraction and order

ParameterDefaultImplemented behavior
PresetCustomSelects one of six factory configurations or leaves the form values unchanged.
Chunk_modeWhole fileWhole file, fixed-duration excerpt, or random-duration excerpt.
Fixed_chunk_duration_s2.0 sRequested fixed excerpt length; capped at the source duration.
Min_chunk_duration_s0.5 sLower bound for random excerpt duration.
Max_chunk_duration_s3.0 sUpper bound for random excerpt duration. If min > max, the script swaps them and reports the adjustment.
Chunks_per_file1Number of chunks extracted from every selected source. Whole-file mode therefore duplicates the whole file if this is greater than 1.
Randomize_orderOnOff = extraction order. On = random ordering.
Allow_repeatsOffOnly matters when randomization is on. Off uses a Fisher–Yates permutation; on samples each output position independently with replacement.

Crossfade and overlap

ParameterDefaultImplemented behavior
Crossfade_typeLinearLinear, equal-power, S-curve, normalized exponential, or logarithmic.
Overlap_modePercentagePercentage of incoming chunk, fixed duration, or random duration.
Overlap_percentage25%Requested overlap as a percentage of the incoming chunk.
Fixed_overlap_s0.5 sRequested fixed overlap.
Min_overlap_s0.1 sLower bound for random overlap.
Max_overlap_s1.0 sUpper bound for random overlap. Inverted min/max values are automatically swapped.

Dynamics and output

ParameterDefaultImplemented behavior
Dynamics_modeNoneFlat, crescendo, diminuendo, swell, inverse swell, wave, random per segment, or terraced.
Wave_cycles2Number of sine-modulation cycles across the complete output in Wave mode.
Dynamics_depth_percent80%Defines minAmp = 1 - depth. Values are clamped to 0–100%.
Scale_peak0.95For non-silent output, Praat Scale peak sets the final absolute peak to this value. Values above 1 are clamped to 1.
Draw_visualizationOnDraws the five-panel Picture report.
Play_resultOnPlays the final Sound after processing.

Factory presets

PresetChunking / orderCrossfade / overlapDynamics
Simple CrossfadeWhole file ×1; sequential; no repeatsLinear; 25% of incoming chunkNone
Smooth CollageRandom 1–4 s ×2/file; shuffled; no repeatsEqual-power; 30%None
Rhythmic ChopFixed 0.5 s ×3/file; shuffled; no repeatsLinear; fixed 0.05 sNone
Cinematic SwellWhole file ×1; sequential; no repeatsS-curve; 20%Swell; 90% depth
Chaos MixRandom 0.3–2.5 s ×3/file; random with repeatsS-curve; random 0.05–0.8 sRandom per segment; 60% depth
Granular CloudRandom 0.05–0.3 s ×10/file; random with repeatsEqual-power; 50%Wave; 3 cycles; 50% depth
Presets overwrite only the parameters explicitly assigned by the script. The final peak target, visualization, and playback remain at the current form values unless the user changes them.

Chunk extraction, compatibility, and playback order

Extraction

Fixed and random chunks are taken from a uniformly random valid offset inside the source Sound. The code uses each Sound object's actual start and end times, so sources with non-zero time origins are handled correctly. A requested chunk longer than its source is shortened to the full available duration.

Sample rate and channels

The sampling frequency of the first selected Sound is the target. Any extracted chunk with a different rate is resampled to that rate with Praat's Resample: sr, 50.

Only mono and stereo chunks are accepted. The channel count of the first extracted chunk becomes the target channel format: stereo chunks are converted to mono when the target is mono; mono chunks are duplicated into stereo when the target is stereo.

Order

  • Sequential: identity order 1, 2, …, N.
  • Random, no repeats: an in-place Fisher–Yates shuffle; every extracted chunk appears exactly once.
  • Random with repeats: every output slot independently draws an integer from 1…N. A chunk may appear several times and another may not appear at all.
The script does not expose a random-seed control, so random excerpts, ordering, overlaps, and Random dynamics are not designed to be repeatable from the form alone.

Crossfade curves and overlap rules

For normalized overlap position u from 0 to 1, the outgoing and incoming chunks are multiplied by complementary curves, then summed by manual overlap-add.

TypeIncoming gainOutgoing gainProperty
Linearu1-uAmplitude weights sum to 1.
Equal-powersqrt(u)sqrt(1-u)Squared gains sum to 1; intended to reduce the center power dip for uncorrelated material.
S-curve0.5 - 0.5 cos(pi u)0.5 + 0.5 cos(pi u)Smooth complementary cosine curve.
Exponential(1-exp(-4u))/(1-exp(-4))(exp(-4u)-exp(-4))/(1-exp(-4))Fast-start curve normalized exactly to 0/1 endpoints in v1.4.
Logarithmicln(1+9u)/ln(10)1 - incomingAlternative fast-start complementary curve.

Actual overlap duration

The selected overlap mode first produces a requested overlap. The script then caps it to 90% of both neighboring chunks:

capacity = min(0.9 × incomingDuration, 0.9 × outgoingDuration)
overlap = min(requestedOverlap, capacity)
minimum = min(0.01 s, capacity)
overlap = max(overlap, minimum)

Therefore a join never consumes an entire neighboring chunk. When both chunks permit it, the overlap is at least 10 ms; for extremely short chunks, the available 90% capacity takes precedence.

Dynamics modes

Let d = Dynamics_depth_percent / 100 and minAmp = 1-d. A depth of 0% gives unity gain; 100% allows the chosen envelope to reach zero where its shape reaches its minimum.

ModeImplemented envelope
NoneUnity gain.
CrescendoLinear rise from minAmp at the beginning to 1 at the end.
DiminuendoLinear fall from 1 to minAmp.
SwellTriangular macro-envelope: minAmp → 1 → minAmp.
Inverse swell1 → minAmp → 1.
WaveSine modulation across the full result; starts at minAmp and completes Wave_cycles cycles.
Random per segmentEach playback position receives an independent gain uniformly drawn from [minAmp, 1].
TerracedUp to five equally spaced levels from minAmp to 1, repeated cyclically across segment positions. With only one total chunk, its gain is 1.
Where dynamics are applied matters. Crescendo, diminuendo, swell, inverse swell, and wave are applied once to the complete concatenated result. Random and Terraced gains are baked into each playback-position chunk before crossfading, so the overlap naturally blends the two neighboring segment gains through the selected crossfade law.

Processing pipeline

  1. Store the selected Sound object IDs and use the first Sound's sampling frequency as the target.
  2. Apply the selected preset, then sanitize inverted chunk/overlap ranges, dynamics depth, and peak target.
  3. Extract Chunks_per_file chunks from each source.
  4. Resample mismatched chunks to the first Sound's sampling frequency.
  5. Reject channel counts other than 1 or 2, then convert all chunks to the first extracted chunk's mono/stereo format.
  6. Build sequential, shuffled, or with-replacement playback order.
  7. For Random/Terraced dynamics, assign the per-position gains before rendering.
  8. Starting from the first playback chunk, calculate each overlap, apply exactly one fade-out/fade-in pair, and sum the buffers with manual overlap-add.
  9. Apply any continuous whole-output dynamics envelope.
  10. If the result is non-silent, scale its absolute peak to Scale_peak; if completely silent, skip peak scaling.
  11. Rename to concat_crossfade_<PresetName>, compute output RMS, optionally draw, clean temporary chunks/control objects, and optionally play.
Peak scaling is normalization, not a ceiling-only limiter. For any non-silent result, Scale peak changes the level so the absolute peak equals the requested target. It can attenuate a hot render or amplify a quiet one.

Visualization

When Draw_visualization is enabled, v1.4 draws a vertically stacked 8-inch report:

In Random/Terraced mode, Panel C now represents the actual crossfade-blended control coefficients. With Equal-power crossfades, the displayed combined amplitude coefficient can legitimately exceed 1 inside an overlap because sqrt(u) + sqrt(1-u) > 1 away from the endpoints; the power relation, not the amplitude sum, is constant.

Limits and edge cases