# Ondulations 1.0 — contrat d’instrument

Banc Cyclonium, 11 octobre 2026. Quatre expériences : somme, relation de fréquences, FM, réseau de deux masses et ressorts.

## Produit exporté

Un JSON `format: "cyclonium.instrument"`, `version: 1` contient :
- `name` : nom libre ;
- `parameters` : recette sonore ;
- `initial` : phases, positions, vitesses initiales ;
- `view.divisor` : facteur de ralentissement visuel ;
- `provenance` et `laws` : métadonnées de l’export du banc.

La version 1 décrit les quatre familles de ce banc, pas encore un graphe arbitraire de Cyclonium. Le moteur lit les paramètres ; `laws` les documente et n’exécute pas du code fourni par le fichier. Les autres ateliers nécessiteront un adaptateur vers ce contrat : aucun chargement universel dans les anciens ateliers n’est prétendu.

## Utilisation dans un autre module

```js
import { validateInstrument, createVoice } from './instrument.mjs';
const instrument = validateInstrument(JSON.parse(texteDuFichier));
const voice = createVoice(instrument, {
  sampleRate: 48000,
  frequencyHz: 220, // facultatif : transpose pour que la fréquence de base A soit 220 Hz
  velocity: 0.8
});
const samples = voice.renderBlock(new Float32Array(48000));
// Le module appelant choisit son horloge audio, son enveloppe et son volume.
```

`next()` produit un échantillon mono. `renderBlock(output)` remplit un tableau fourni par l’appelant. L’état persiste entre blocs. `reset()` restaure l’état initial ; `pluck('a'|'b', déplacement)` pince une masse ; `configure(parameters)` est réservé à des paramètres déjà validés. Utiliser `validateInstrument` à la frontière d’un import. Une voix par note suffit pour une polyphonie externe.

Transposition : toutes les fréquences de base et l’excursion FM en Hz sont multipliées par le même rapport. L’excursion en octaves ne change pas. La raideur suit les nouvelles fréquences ; la durée de l’amortissement ne change pas. La vélocité règle ici le gain de sortie, pas la physique de l’excitation. Le domaine de notes est volontairement borné pour ce banc ; une application ultérieure pourra proposer un autre contrat de calcul.

## Paramètres et lois

Fréquences en Hz ; amplitudes sans unité (0 à 1). Phase en radians.
- `sum` : deux sinus, sortie `(A+B)/2` ;
- `relation` : rapport `fB/fA` ou différence `fB-fA` conservé ;
- `fm` / `hz` : `fB(t)=fB0 + depth*A(t)` ; fréquences signées autorisées ;
- `fm` / `octave` : `fB(t)=fB0*2**(depth/100*A(t))` ;
- `spring` : masses unitaires, `kA=(2πfA)^2`, `kB=(2πfB)^2`, `K=coupling*kA`, forces réciproques `±K(xB-xA)`, amortissement `-2*damping*v`.

Les fréquences des masses isolées ne décrivent pas les modes du réseau couplé. L’intégrateur mécanique est Velocity-Verlet, avec sous-pas et amortissement exponentiel scindé. L’état initial par défaut est xA=0.8, xB=0, vitesses nulles ; phases nulles.

## Horloges et observation

La production sonore avance à la fréquence d’échantillonnage, dans un AudioWorklet. La vue réexécute le même modèle avec un temps progressant à `1/divisor`. Elle ne reconstitue pas la sortie audio instantanée. Les interventions s’appliquent à deux états dont les âges simulés diffèrent ; la remise à zéro restaure la même condition initiale. Le bouton « Figer la vue » ne coupe pas le son.

Le facteur commun conserve les rapports, divise les écarts et ralentit aussi l’amortissement et les échanges d’énergie dans la vue. La vue peut sous-échantillonner les mouvements trop rapides ; augmenter D. Le spectre provient de la sortie audio après le volume, sur une fenêtre FFT de 8192 échantillons : deux raies très proches ne seront pas toujours séparées.

## Précision et sorties

Calcul interne JS en flottants 64 bits ; sortie audio en flottants 32 bits. WAV mono 48 kHz / IEEE float 32, cinq secondes depuis l’état initial, au volume local, avec fondus de 5 ms. Pas de normalisation automatique. Les modulations extrêmes peuvent se replier spectralement ; pas de promesse de bande limitée. Les changements de paramètres peuvent apporter ou retirer de l’énergie : ce sont des commandes, pas des forces conservatrices.

Page autonome : `ondulations.1.html`, moteur inclus. Pour l’audio temps réel, navigateur avec AudioWorklet et contexte sécurisé. Le module `instrument.mjs` est fourni séparément ; `instrument.js` contient le même module ES si un serveur ancien refuse l’extension .mjs. `lecteur.html` démontre le réemploi hors du banc.

## Correspondance avec Concomitances V8

Son temps de shader étant en millisecondes, `D = diviseurTemps / 1000`. La valeur historique 440000 donne donc D=440 et transforme visuellement 440 Hz en 1 tour/s. Le banc intègre progressivement la phase : modifier D ne réévalue pas brutalement une phase à partir du temps total.

Vidéo : dix secondes de la vue au ralenti ; si l’écoute est active, la piste sonore conserve sa vitesse normale. La disponibilité et le format dépendent de MediaRecorder.
