Sonic Syntax — Global Optimization CSP Solver
"Caesura Logic" — Finds the globally optimal sequence of cuts using dynamic programming with hard and soft constraints.
What this does
This script implements global optimization for audio boundary detection — a dynamic programming approach to finding the optimal sequence of cuts (phrase boundaries) in speech or music audio. Unlike local or rule-based detectors, this solver evaluates all possible cut combinations under defined constraints to find the globally optimal path through candidate boundary points.
Key Features:
- Hard Constraints: Enforce absolute rules (minimum duration between cuts, silence detection)
- Soft Constraints: Weighted scoring for desirable properties (pitch slope, centering)
- Insertion Bonus: Controls cut density (higher = more cuts, lower = stricter quality)
- Dynamic Programming: Bellman-optimal pathfinding through candidate space
- Global Optimality: Guarantees best possible sequence under constraints
- TextGrid Output: Creates labeled phrase boundaries for analysis/annotation
- Variables: Candidate cut positions
- Hard Constraints: Must be satisfied (e.g., minimum spacing)
- Soft Constraints: Weighted preferences (e.g., falling pitch preferred)
- Objective: Maximize total score across all selected cuts
Quick start
- In Praat, select exactly one Sound object.
- Run script… →
Sonic_Syntax_Global_Optimizer.praat. - Set Hard Constraints:
Silence_threshold_relative_to_max_(dB): e.g., -25 dBMin_duration_between_cuts_(s): e.g., 0.5 seconds
- Set Soft Constraint Weights:
Weight_Pitch_Slope: Higher = prefer falling pitch at boundariesWeight_Centering: Higher = prefer cuts centered in silent intervals
- Adjust Insertion_bonus (50.0 default):
- Higher = more cuts allowed
- Lower = stricter quality control
- Set analysis parameters (pitch range, window size, etc.)
- Enable Create_TextGrid and Print_debug_log for output
- Click OK — algorithm runs, outputs optimal boundaries
Silence_threshold = -25 dB, Min_duration = 0.3s. For music, adjust pitch ceiling (e.g., 1000 Hz for instruments). Use Insertion_bonus to control density: 30-50 for normal speech, 70-100 for dense segmentation. Enable Print_debug_log to see candidate counts and final path score. The algorithm may take a few seconds for long files with many candidates.
Silence_threshold if needed (more negative = stricter). Min_duration_between_cuts is a HARD constraint — no two cuts will be closer than this. Dynamic programming complexity is O(n²) in number of candidates — very long files with many silences may be slower. Insertion_bonus dominates scoring — if set too high, the algorithm may select too many cuts; if too low, may select none.
Algorithm Theory
Dynamic Programming Formulation
🎯 Bellman Optimality Principle
Problem: Choose subset of candidate cuts maximizing total score while respecting minimum spacing.
State: dp_max_score[i] = best total score ending at cut i
Transition: dp_max_score[i] = max(dp_max_score[j] + local_score[i]) for all j where distance(i,j) ≥ min_duration
Initialization: dp_max_score[i] = local_score[i] if distance from start ≥ min_duration
Solution: Backtrack from best ending node using dp_prev_index[]
Mathematical Formulation
Candidate Generation
Path Reconstruction
Constraint System
Hard Constraints
⛔ Must Be Satisfied
Silence Threshold: Candidates must be within silent intervals (relative to max amplitude)
Minimum Duration Between Cuts: No two selected cuts can be closer than this value
Implementation: These constraints prune the search space during DP — invalid transitions are never considered.
Soft Constraints (Scoring)
⚖️ Weighted Preferences
Pitch Slope: Prefer boundaries where pitch is falling (negative slope)
Centering: Prefer cuts centered within silent intervals
Insertion Bonus: Constant added to every selected cut
Constraint Interaction
- Hard constraints define the feasible solution space
- Soft constraints score each candidate locally
- Insertion bonus biases toward more/less cuts
- DP algorithm finds the combination maximizing total score
Trade-offs: A candidate with excellent pitch slope but poor centering might still be selected if it allows other high-scoring cuts later (global optimality). The insertion bonus ensures the algorithm doesn't overly penalize simply having cuts.
Parameters
Hard Constraints
| Parameter | Type | Default | Description |
|---|---|---|---|
| Silence_threshold_relative_to_max_(dB) | real | -25 | Relative dB below max for silence detection (negative) |
| Min_duration_between_cuts_(s) | positive | 0.5 | Minimum time between any two cuts |
Soft Constraints (Weights)
| Parameter | Type | Default | Description |
|---|---|---|---|
| Weight_Pitch_Slope | positive | 2.0 | Importance of falling pitch at boundaries |
| Weight_Centering | positive | 1.0 | Importance of cut centered in silence |
Density Control
| Parameter | Type | Default | Description |
|---|---|---|---|
| Insertion_bonus | positive | 50.0 | Base score for selecting any cut (higher = more cuts) |
Analysis Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| Silent_interval_min_duration_(s) | positive | 0.05 | Minimum silence duration to consider |
| Pitch_analysis_window_(s) | positive | 0.05 | Window for pitch slope calculation |
| Pitch_floor_(Hz) | positive | 75 | Minimum pitch for analysis |
| Pitch_ceiling_(Hz) | positive | 500 | Maximum pitch for analysis |
Output Options
| Parameter | Type | Default | Description |
|---|---|---|---|
| Create_TextGrid | boolean | 1 | Create TextGrid with boundary tier |
| Print_debug_log | boolean | 1 | Print algorithm progress to info window |
| Output_tier_name | sentence | "Boundaries" | Name of TextGrid tier |
Processing Workflow
Visualization of DP Process
Candidates: c₁@1.0s, c₂@2.2s, c₃@3.1s, c₄@4.5s, c₅@5.0s
Min duration: 1.0s
DP Table:
dp_max_score[1] = 60 (first possible cut)
dp_max_score[2] = max(60+55, 70) = 115 (from c₁)
dp_max_score[3] = 75 (cannot come from c₂: 2.2→3.1 = 0.9s < 1.0s)
dp_max_score[4] = max(115+65, 75+65, 80) = 180 (from c₂)
dp_max_score[5] = max(180+50, 80+50) = 230 (from c₄)
Best path: c₁ → c₂ → c₄ → c₅ (score 230)
Not selected: c₃ (conflicts with spacing)
Applications
Speech Phrasing Analysis
Use case: Automatic detection of phrase boundaries in speech
Typical settings:
- Silence threshold: -25 to -30 dB
- Min duration: 0.3-0.5 s (natural phrase spacing)
- Pitch ceiling: 300 Hz (male) or 500 Hz (female)
- Insertion bonus: 40-60 (moderate density)
Musical Phrase Segmentation
Use case: Finding phrase boundaries in instrumental music
Adjustments:
- Pitch ceiling: 1000+ Hz for instruments
- Weight_Pitch_Slope: Higher (3.0-5.0) — pitch drops often mark phrase ends
- Min duration: 0.5-2.0 s depending on tempo
Audio Editing Automation
Use case: Automatic cut placement for editing dialogue or podcasts
Workflow:
- Run optimizer to get boundary times
- Export cut points to editing software
- Use for automatic silence removal or chapter markers
Linguistic Research
Use case: Studying prosodic phrasing across languages or speakers
Advantages:
- Consistent, algorithmically-defined boundaries
- Reproducible across datasets
- Parameter control for different speech styles
Practical Examples
🗣️ Conversational Speech
Goal: Natural phrase boundaries in dialogue
Settings:
- Silence threshold: -28 dB
- Min duration: 0.4 s
- Weight_Pitch_Slope: 2.5
- Insertion_bonus: 50
Result: Boundaries at natural breath points and prosodic breaks
🎵 Classical Music Phrases
Goal: Musical phrase segmentation
Settings:
- Silence threshold: -35 dB (stricter)
- Min duration: 1.2 s
- Weight_Pitch_Slope: 4.0
- Pitch ceiling: 800 Hz
Result: Boundaries at cadence points and breath marks
📚 Audio Book Chapter Markers
Goal: Detect natural pauses for chapter breaks
Settings:
- Silence threshold: -20 dB (lenient)
- Min duration: 1.5 s (long pauses only)
- Insertion_bonus: 30 (sparse selection)
Result: Key pause points suitable for chapter divisions
Troubleshooting Common Issues
Cause: Silence threshold too high (not negative enough) or audio has no silences
Solution: Lower threshold (e.g., -20 dB), check audio content
Cause: Insertion_bonus too high/low
Solution: Adjust insertion_bonus (20-80 typical range)
Cause: Min_duration_between_cuts too small
Solution: Increase to 0.3-1.0 s depending on application
Cause: Many silence candidates (long file with many pauses)
Solution: Algorithm is O(n²) — consider increasing silent_interval_min_duration to reduce candidates
Advanced Techniques
- Start with defaults for your audio type
- Run with Print_debug_log = yes
- Check candidate count (should be reasonable: 10-200 for 1 min audio)
- Adjust insertion_bonus to get desired cut count
- Fine-tune weights based on which boundaries seem wrong
- Use Create_TextGrid to visually verify boundaries
- Additional soft constraints: Add energy drop, spectral change, etc.
- Multiple feature weights: Expand scoring function with more terms
- Hierarchical processing: Run coarse-to-fine (first find major boundaries, then subdivide)
- Learning weights: Use machine learning to optimize weights for your corpus