struct

(**

Description

Chaque échantillon est fabriqué en fonction des informations retournées par Etat.etat.

La construction du vecteur rose devrait éviter toute saturation pour une note quelconque avec toutes les harmoniques au maximum si aucun effet n'est appliqué.

Copyright Stéphane Grognet
IREM des Pays de la Loire - Université de Nantes
Laboratoire de mathématiques Jean Leray UMR 6629 CNRS
version 1.0
@version 1.0 @author Stéphane Grognet @since 2014, 2015 *)



(**
signe nombre
*)

let signe = function (x:float) ->
 match x with
 | y when y > 0. -> 1.
 | y when y < 0. -> -1.
 | _ -> 0. ;;


(**
tronque nombre
*)

let tronque = function (x:float) ->
 min 1.0 ( max ( -1.0 ) x ) ;;


(**
carre nombre
*)

let carre = function (x:float) ->
 x *. x ;;


(**
carre_signe nombre
*)

let carre_signe = function (x:float) ->
 x *. ( abs_float x ) ;;


(**
deforme exposant nombre
*)

let deforme = fun (exposant:int) (x:float) ->
 match x with
 | pos when pos > 0. -> Etat.int_pow exposant ( abs_float x )
 | neg when neg < 0. -> ~-. ( Etat.int_pow exposant ( abs_float x ) )
 | _ -> 0. ;;


(**
inflexion parametre nombre
*)

let inflexion = fun (p:float) (x:float) ->
 let a = 2 + ( int_of_float ( 0.03125 *. p ) ) in
  deforme a x ;;


(**
detricote_centre somme difference
*)

let detricote_centre = fun (sigma:float) (delta:float) ->
 let x = 32. -. 0.5 *. delta in
  let xx = float ( int_of_float ( sigma +. x ) )
  and yy = float ( int_of_float ( sigma -. x ) ) in
   ( max 0. ( min 127. xx ) , max 0. ( min 127. yy ) ) ;;


(**
detricote somme difference
*)

let detricote = fun (sigma:float) (delta:float) ->
 let s = 2. *. sigma in
  let xx = float ( ( int_of_float ( s -. delta ) ) / 2 )
  and yy = float ( ( int_of_float ( s +. delta ) ) / 2 ) in
   ( max 0. ( min 127. xx ) , max 0. ( min 127. yy ) ) ;;


(**
percussion detache enveloppe niveau echantillon
*)

let percussion = fun (detache:float) (enveloppe_percu:float) (niveau_percu:float) (echantillon:float array) ->
 if ( detache > 0.5 ) && ( niveau_percu > 0. ) then
  begin
   let d = 0.008 *. enveloppe_percu
   and ddd = ref 0. in
    for j = 0 to Data.pred_taille_d_echantillon do
     ddd := tanh ( d *. ( float j ) ) ;
     ddd := 30. *. !ddd *. ( 1. -. !ddd ) ;
     echantillon.(j) <- echantillon.(j) *. ( 1. +. !ddd *. niveau_percu ) ;
    done ;
  end ;;


(**
sauvegarde echantillon adresse
*)

let sauvegarde = fun (echantillon:float array) (adresse:string) ->
 let oc = open_out adresse in
  for j = 0 to Data.pred_taille_d_echantillon do
   output_string oc  ( ( string_of_float echantillon.(j) ) ^ "\n" ) ;
  done ;
  close_out_noerr oc  ;;


(**
reverb delai niveau precedent_stockage_echantillon stockage_echantillon precedent_echantillon echantillon
*)

let reverb = fun (delai:float) (niveau:float) (precedent_stockage_echantillon:float array) (stockage_echantillon:float array) (precedent_echantillon:float array) (echantillon:float array) ->

(** Avec un coefficient rr trop élevé une oscillation interviendrait. *)


 let rr = 0.7 *. niveau
 and decalage = ref 0
 and anti_decalage = ref 0 in
  decalage := int_of_float delai ;
  anti_decalage := min Data.pred_taille_d_echantillon ( max 0 ( Data.taille_d_echantillon - !decalage ) ) ;
  for j = 0 to pred !decalage do
   echantillon.(j) <- echantillon.(j) +. rr *. precedent_echantillon.( !anti_decalage + j ) ;
   stockage_echantillon.(j) <- echantillon.(j) ;
   precedent_stockage_echantillon.(j) <- precedent_echantillon.(j) ;
  done ;
  for j = !decalage to Data.pred_taille_d_echantillon do
   echantillon.(j) <- echantillon.(j) +. rr *. echantillon.( j - !decalage ) ;
   stockage_echantillon.(j) <- echantillon.(j) ;
   precedent_stockage_echantillon.(j) <- precedent_echantillon.(j) ;
  done ;;


(** Les vibratos sont obtenus en balayant la ligne à retard constituée de la juxtaposition de l'échantillon précédent et de l'échantillon en cours.

On notera dans les fonctions vibrato_mono et vibrato que l'interpolation angulaire de l'amplitude du signal entre deux indices successifs rappelle la conception du scanner de vibrato Hammond par couplage capacitif et atténue les effets de la discrétisation. *)




(**
vibrato_mono poussoir_vc cosinu sinus phase_vc phase_finale_vc precedent_echantillon echantillon
La fréquence de balayage est fixée à 412 cycles par minute (voir data.ml). La profondeur de balayage est faible et ne peut prendre que trois valeurs. *)

let vibrato_mono = fun (poussoir_vc:float) (cosinus:float) (sinus:float) (phase_vc:float array) (phase_finale_vc:float array) (precedent_echantillon:float array) (echantillon:float array) ->
 let facteur_s = ref 1.
 and facteur_v = ref 0.
 and difference = ref 0
 and alpha = ref 1.
 and beta = ref 0.
 and int_poussoir = int_of_float ( poussoir_vc )
 and sortie = Array.make Data.taille_d_echantillon 0. in
  for i = 0 to Data.pred_taille_d_echantillon do
   sortie.(i) <- echantillon.(i) ;
  done ;
  if poussoir_vc > 0. then
   begin
    let selecteur = int_poussoir mod 2
    and expression = 2e-5 *. ( float Data.frequence_d_echantillonnage ) *. ( Etat.int_pow ( ( succ int_poussoir ) / 2 ) 3. ) in
     if selecteur <> 0 then
      begin
       facteur_s := 0. ;
       facteur_v := 1. ;
      end
     else
      begin
       facteur_s := 0.5 +. 0.08 *. ( sqrt poussoir_vc ) ;
       facteur_v := !facteur_s ;
      end ;
     let x = ref phase_vc.(0)
     and y = ref phase_vc.(1)
     and xx = ref 0.
     and yy = ref 0.
     and indice = ref 0
     and pred_indice = ref 0
     and excursion = ref 0.
     and deviation = ref 0.
     and vibrato_i = Array.make Data.taille_d_echantillon 0.
     and vibrato_ii = Array.make Data.taille_d_echantillon 0. in
      for i = 0 to Data.pred_taille_d_echantillon do
       xx := cosinus *. !x -. sinus *. !y ;
       yy := sinus *. !x +. cosinus *. !y ;
       xx := tronque !xx ;
       yy := tronque !yy ;
       x := !xx ;
       y := !yy ;
       excursion := 0.759934207678533147 *. !xx -. 0.65 *. !yy ;
       deviation := max 0. ( min 2. ( 1. -. !excursion ) ) ;
       deviation := expression *. !deviation ;
       difference := int_of_float !deviation ;
       indice := i - !difference ;
       pred_indice := pred !indice ;
       alpha := !deviation -. float !difference ;
       beta := 1. -. !alpha ;
       vibrato_i.(i) <- if !indice < 0 then precedent_echantillon.( Data.taille_d_echantillon + !indice ) else echantillon.(!indice) ;
       vibrato_ii.(i) <- if !pred_indice < 0 then precedent_echantillon.( Data.taille_d_echantillon + !pred_indice ) else echantillon.(!pred_indice) ;
       vibrato_i.(i) <- !alpha *. vibrato_ii.(i) +. !beta *. vibrato_i.(i) ;
      done ;
      phase_finale_vc.(0) <- tronque ( cosinus *. !x -. sinus *. !y ) ;
      phase_finale_vc.(1) <- tronque ( sinus *. !x +. cosinus *. !y ) ;
      for i = 0 to Data.pred_taille_d_echantillon do
       sortie.(i) <- !facteur_s *. sortie.(i) +. !facteur_v *. vibrato_i.(i) ;
      done ;
   end ;
  sortie ;;


(**
vibrato poussoir_vc tremolo expression basse_frequence dephasage cos_rot sin_rot phase_bf phase_finale_bf phase_bf_1 phase_finale_bf_1 precedent_echantillon echantillon
L'oscillateur très basse fréquence est obtenu par battement entre oscillateurs de deux notes BF successives. Les générateurs pour les basses fréquences ont des fréquences environ 13 fois inférieures par rapport aux générateurs de notes du pianel (voir data.ml). Le battement multiplie la fréquence des générateurs BF par environ 0.06, c'est-à-dire la divise par environ 15 (une rotation précise à très basse fréquence est inaccessible sans cet artifice : on descend jusqu'à 40 milliHertz). La rotation stéréophonique est obtenue en combinant un retard déphasé pour le vibrato de la voie droite. Une variation d'enveloppe (trémolo) est possible, en phase avec l'amplitude de balayage. *)

let vibrato = fun (poussoir_vc:float) (tremolo:float) (expression:float) (basse_frequence:float) (dephasage:float) (cos_rot:float array) (sin_rot:float array) (phase_bf:float array) (phase_finale_bf:float array) (phase_bf_1:float array) (phase_finale_bf_1:float array) (precedent_echantillon:float array) (echantillon:float array) ->
 let facteur_s = ref 0.
 and facteur_v = ref 0.
 and ampleur = ref 0.
 and facteur_t = 0.0078125 *. tremolo
 and cos_a = cos dephasage
 and sin_a = sin dephasage
 and cos_diff = ref 0.
 and sin_diff = ref 0.
 and c = ref 0.
 and s = ref 0.
 and c_1 = ref 0.
 and s_1 = ref 0.
 and x = ref 1.
 and y = ref 0.
 and x_1 = ref 0.
 and y_1 = ref 0.
 and xx = ref 0.
 and yy = ref 0.
 and xx_1 = ref 0.
 and yy_1 = ref 0.
 and indice = ref 0
 and pred_indice = ref 0
 and excursion = ref 0.
 and deviation = ref 0.
 and difference = ref 0
 and alpha = ref 1.
 and beta = ref 0.
 and signal_gauche = Array.make Data.taille_d_echantillon 0.
 and signal_droit = Array.make Data.taille_d_echantillon 0.
 and vibrato_i = Array.make Data.taille_d_echantillon 0.
 and vibrato_ii = Array.make Data.taille_d_echantillon 0.
 and vibrato_q = Array.make Data.taille_d_echantillon 0.
 and vibrato_qq = Array.make Data.taille_d_echantillon 0. in
  for i = 0 to Data.pred_taille_d_echantillon do
   signal_gauche.(i) <- echantillon.(i) ;
  done ;
  if ( expression > 0. ) && ( poussoir_vc > 0. ) then
   begin
    let bf = max 1 ( min 127 ( int_of_float basse_frequence ) )
    and partie_fixe = 1. +. facteur_t in
     if poussoir_vc < 1.5 then
      begin
       facteur_s := 0. ;
       facteur_v := 1. ;
      end
     else
      begin
       facteur_s := 0.707106781186547573 ;
       facteur_v := !facteur_s ;
      end ;
     let jj = pred bf in
      c := cos_rot.(jj) ;
      s := sin_rot.(jj) ;
      c_1 := cos_rot.(bf) ;
      s_1 := sin_rot.(bf) ;
      x := phase_bf.(0) ;
      y := phase_bf.(1) ;
      x_1 := phase_bf_1.(0) ;
      y_1 := phase_bf_1.(1) ;
      for i = 0 to Data.pred_taille_d_echantillon do
       xx := !c *. !x -. !s *. !y ;
       yy := !s *. !x +. !c *. !y ;
       xx_1 := !c_1 *. !x_1 -. !s_1 *. !y_1 ;
       yy_1 := !s_1 *. !x_1 +. !c_1 *. !y_1 ;
       x := !xx ;
       y := !yy ;
       x_1 := !xx_1 ;
       y_1 := !yy_1 ;

(** Pour juguler les erreurs d'arrondi, procéder a posteriori à un battement de fréquences moyennes permet d'accéder avec une précision suffisante aux très basses fréquences.

Dans le cadre analogique, ce procédé a été utilisé au vingtième siècle dans les générateurs de fréquences Adret.

http://www.adret-electronique.fr *)



       cos_diff := tronque ( !xx_1 *. !xx +. !yy_1 *. !yy ) ;
       sin_diff := tronque ( !yy_1 *. !xx -. !xx_1 *. !yy ) ;
       excursion := 0.759934207678533147 *. !cos_diff -. 0.65 *. !sin_diff ;
       deviation := max 0. ( min 2. ( 1. -. !excursion ) ) ;
       ampleur := partie_fixe -. facteur_t *. !deviation ;
       deviation := expression *. !deviation ;
       difference := int_of_float !deviation ;
       indice := i - !difference ;
       pred_indice := pred !indice ;
       alpha := !deviation -. float !difference ;
       beta := 1. -. !alpha ;
       vibrato_i.(i) <- if !indice < 0 then !ampleur *. precedent_echantillon.( Data.taille_d_echantillon + !indice ) else !ampleur *. echantillon.(!indice) ;
       vibrato_ii.(i) <- if !pred_indice < 0 then !ampleur *. precedent_echantillon.( Data.taille_d_echantillon + !pred_indice ) else !ampleur *. echantillon.(!pred_indice) ;
       vibrato_i.(i) <- !alpha *. vibrato_ii.(i) +. !beta *. vibrato_i.(i) ;
       excursion := cos_a *. !excursion -. sin_a *. ( 0.65 *. !cos_diff +. 0.759934207678533147 *. !sin_diff ) ;
       deviation := max 0. ( min 2. ( 1. -. !excursion ) ) ;
       ampleur := partie_fixe -. facteur_t *. !deviation ;
       deviation := expression *. !deviation ;
       difference := int_of_float !deviation ;
       indice := i - !difference ;
       pred_indice := pred !indice ;
       alpha := !deviation -. float !difference ;
       beta := 1. -. !alpha ;
       vibrato_q.(i) <- if !indice < 0 then !ampleur *. precedent_echantillon.( Data.taille_d_echantillon + !indice ) else !ampleur *. echantillon.(!indice) ;
       vibrato_qq.(i) <- if !pred_indice < 0 then !ampleur *. precedent_echantillon.( Data.taille_d_echantillon + !pred_indice ) else !ampleur *. echantillon.(!pred_indice) ;
       vibrato_q.(i) <- !alpha *. vibrato_qq.(i) +. !beta *. vibrato_q.(i) ;
      done ;
      phase_finale_bf.(0) <- tronque ( !c *. !x -. !s *. !y ) ;
      phase_finale_bf.(1) <- tronque ( !s *. !x +. !c *. !y ) ;
      phase_finale_bf_1.(0) <- tronque ( !c_1 *. !x_1 -. !s_1 *. !y_1 ) ;
      phase_finale_bf_1.(1) <- tronque ( !s_1 *. !x_1 +. !c_1 *. !y_1 ) ;
      for i = 0 to Data.pred_taille_d_echantillon do
       let valeur = signal_gauche.(i) in
        signal_gauche.(i) <- !facteur_s *. valeur +. !facteur_v *. vibrato_i.(i) ;
        signal_droit.(i) <- !facteur_s *. valeur +. !facteur_v *. vibrato_q.(i) ;
      done ;
   end
  else
   begin
    for i = 0 to Data.pred_taille_d_echantillon do
     signal_droit.(i) <- signal_gauche.(i) ;
    done ;
   end ;
  ( signal_gauche , signal_droit ) ;;


(**
filtre coupure precedent_echantillon echantillon
*)

let filtre = fun (coupure:float) (precedent_echantillon:float array) (echantillon:float array) ->
 let grave = Array.make Data.taille_d_echantillon 0.
 and aigu = Array.make Data.taille_d_echantillon 0.
 and decalage = ref 0 in
  for i = 0 to Data.pred_taille_d_echantillon do
   grave.(i) <- echantillon.(i) ;
  done ;
  if coupure > 0.5 then
   begin
    let k = int_of_float coupure
    and kkk = coupure +. 1. in
     let kk = succ k
     and bb = 1. /. kkk in
      for i = Data.pred_taille_d_echantillon downto k do
       decalage := i - kk ;
       for j = 1 to k do
        grave.(i) <- grave.(i) +. echantillon.( !decalage + j ) ;
       done ;
       grave.(i) <- grave.(i) *. bb ;
       aigu.(i) <- echantillon.(i) -. grave.(i) ;
      done ;
      for i = pred k downto 0 do
       let limite = k - i in
        decalage := Data.taille_d_echantillon + i - kk ;
        for j = 0 to limite do
         grave.(i) <- grave.(i) +. precedent_echantillon.( !decalage + j ) ;
        done ;
        for j = 0 to pred i do
         grave.(i) <- grave.(i) +. echantillon.(j) ;
        done ;
        grave.(i) <- grave.(i) *. bb ;
        aigu.(i) <- echantillon.(i) -. grave.(i) ;
      done ;
   end ;
   ( grave , aigu ) ; ;;


(**
manivelle cos_bf sin_bf phase_bf_grave phase_finale_bf_grave phase_bf_1_grave phase_finale_bf_1_grave phase_bf_aigu phase_finale_bf_aigu phase_bf_1_aigu phase_finale_bf_1_aigu phase_vc phase_finale_vc phase_generateurs penultieme_echantillon precedent_signal precedent_echantillon ages canal_de_sortie
*)

let manivelle = fun (forme:float array) (cos_bf:float array) (sin_bf:float array) (phase_bf_grave:float array) (phase_finale_bf_grave:float array) (phase_bf_1_grave:float array) (phase_finale_bf_1_grave:float array) (phase_bf_aigu:float array) (phase_finale_bf_aigu:float array) (phase_bf_1_aigu:float array) (phase_finale_bf_1_aigu:float array) (phase_vc:float array) (phase_finale_vc:float array) (phase_generateurs:float array array) (penultieme_echantillon:float array) (precedent_signal:float array) (precedent_echantillon:float array) (ages:int array array) (anciennes_amplitudes:float array array) (tampon:Buffer.t) oc ->
 let octet = 256
 and coi = function n -> char_of_int ( max 0 ( min 255 ( if n < 0 then 256 + n else n ) ) )
 and itde = 1. /. Data.taille_d_echantillon_reelle
 and pente = ref 0.
 and accu = ref 0.
 and tmp = Array.make 9 0.
 and phase_triangle = ref 0.
 and w = ref 0.
 and x = ref 0.
 and y = ref 0.
 and x_1 = ref 0.
 and y_1 = ref 0.
 and ww = ref 0.
 and xx = ref 0.
 and yy = ref 0.
 and xx_1 = ref 0.
 and yy_1 = ref 0.
 and c = ref 0.
 and s = ref 0.
 and cos_a = ref 0.
 and sin_a = ref 0.
 and cos_b = ref 0.
 and sin_b = ref 0.
 and facteur_swell = ref 0.
 and facteur_saturation = ref 0.
 and notes = Array.make 128 0
 and sons = Array.make_matrix 128 9 0.
 and enveloppes = Array.make_matrix 128 9 0.
 and parametres = Array.make Data.nombre_de_parametres_clavier 0.
 and pentes = Array.make 128 0.
 and cos_fin = Array.make 128 0.
 and sin_fin = Array.make 128 0.
 and cos_rot = Array.make 128 0.
 and sin_rot = Array.make 128 0.
 and rose = Array.make 128 0.
 and phase = Array.make_matrix 128 2 0.
 and phase_finale = Array.make_matrix 128 3 0.
 and amplitude = Array.make Data.taille_d_echantillon 0.
 and signal_cos = Array.make Data.taille_d_echantillon 0.
 and signal_sin = Array.make Data.taille_d_echantillon 0.
 and signal_creneau = Array.make Data.taille_d_echantillon 0.
 and echantillon = Array.make Data.taille_d_echantillon 0.
 and echantillon_q = Array.make Data.taille_d_echantillon 0.
 and stockage_signal = Array.make Data.taille_d_echantillon 0.
 and precedent_stockage_echantillon = Array.make Data.taille_d_echantillon 0.
 and stockage_echantillon = Array.make Data.taille_d_echantillon 0. in
  let attaque = fun (x:int) (y:int) ->
   begin
    let indice = ref 0
    and test = ref false in
     while !indice < 128 do
      let a = Array.map ( function z -> ( x <= z ) && ( z <= y ) ) ages.(!indice) in
       if ( Array.fold_left ( || ) false a ) then
        begin
         test := true ;
         indice := 128 ;
        end
       else
        incr indice ;
     done ;
     !test
   end
  and ic1 = open_in_gen [Open_binary ; Open_rdonly] 0o400 Data.adresse_rotation in
   for i = 0 to  127 do
    cos_fin.(i) <- float_of_string ( input_line ic1 ) ;
    sin_fin.(i) <- float_of_string ( input_line ic1 ) ;
    cos_rot.(i) <- float_of_string ( input_line ic1 ) ;
    sin_rot.(i) <- float_of_string ( input_line ic1 ) ;
    rose.(i) <- float_of_string ( input_line ic1 ) ;
    pentes.(i) <- float_of_string ( input_line ic1 ) ;
   done ;
   close_in_noerr ic1 ;
   Etat.etat forme notes ages sons enveloppes parametres ;

(** ********************************************** *)

(** Oscillateurs et mise en forme (sinus/créneaux) *)

(** ********************************************** *)


   let z = parametres.(Data.bouton_dephasage_creneaux)
   and z_z = parametres.(Data.bouton_dephasage_inflexion)
   and ri = Etat.repartition ( int_of_float parametres.(Data.bouton_niveau_inflexion) )
   and rc = Etat.repartition ( int_of_float parametres.(Data.bouton_niveau_creneaux) )
   and rt = Etat.repartition ( int_of_float parametres.(Data.bouton_niveau_triangle) )
   and ( eva , evg ) = detricote parametres.(Data.bouton_excursion_vibrato) parametres.(Data.bouton_diff_excursion_vibrato)
   and ( bfg , bfa ) = if parametres.(Data.demi_lune) < 0.5 then
     detricote parametres.(Data.bouton_basse_frequence) parametres.(Data.bouton_diff_basse_frequence)
    else
     begin
      let but_aigu =
       begin
        match parametres.(Data.demi_lune) with
        | un when 0.5 < un && un < 1.5 -> Data.basse_frequence_aigue_vibrato_stereo_lent
        | trois when 2.5 < trois -> Data.basse_frequence_aigue_vibrato_stereo_rapide
        | _ -> 0.
       end
      and but_grave =
       begin
        match parametres.(Data.demi_lune) with
        | un when 0.5 < un && un < 1.5 -> Data.basse_frequence_grave_vibrato_stereo_lent
        | trois when 2.5 < trois -> Data.basse_frequence_grave_vibrato_stereo_rapide
        | _ -> 0.
       end
      and ( grave , aigu ) = detricote parametres.(Data.bouton_basse_frequence) parametres.(Data.bouton_diff_basse_frequence)
      and condition_grave = Random.int 6 < 5 in

(** La condition pseudo-aléatoire de phase ralentit l'établissement de la vitesse de rotation des graves. *)


       let resultat_grave = if condition_grave then
         grave
        else if grave < but_grave then
         grave +. 1.
        else if grave > but_grave then
         grave -. 1.
        else
         but_grave
       and resultat_aigu = if aigu < but_aigu -. 1. then
         aigu +. 2.
        else if aigu > but_aigu +. 1. && aigu > grave +. 1. then
         aigu -. 2.
        else if aigu > but_aigu then
         aigu -. 1.
        else if aigu < but_aigu then
         aigu +. 1.
        else
         but_aigu in
        parametres.(Data.bouton_basse_frequence) <- float ( int_of_float ( resultat_grave +. resultat_aigu +. 1. ) / 2 ) ;
        parametres.(Data.bouton_diff_basse_frequence) <- max 0. ( resultat_aigu -. resultat_grave ) ;
        Clavier.aux Data.adresse_etat_clavier ( 128 + Data.bouton_basse_frequence ) ( int_of_float parametres.(Data.bouton_basse_frequence) ) ;
        Clavier.aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_basse_frequence ) ( int_of_float parametres.(Data.bouton_diff_basse_frequence) ) ;
        ( resultat_grave , resultat_aigu )
     end
   and ( drg , dra ) = detricote parametres.(Data.bouton_dephasage_rotation) parametres.(Data.bouton_diff_dephasage_rotation)
   and ( tg , ta ) = detricote parametres.(Data.bouton_tremolo) parametres.(Data.bouton_diff_tremolo)
   and coupure = parametres.(Data.bouton_coupure ) *. Data.coefficient_coupure
   and timbre = Etat.repartition ( int_of_float parametres.(Data.bouton_timbre) ) in
    let facteur_sinus = ri.(0)
    and facteur_inflexion = ri.(1)
    and facteur_lisse = rt.(0)
    and facteur_triangle = rt.(1)
    and facteur_continu = rc.(0)
    and facteur_creneau = 0.5 *. rc.(1)
    and facteur_grave = timbre.(0)
    and facteur_aigu = timbre.(1) in
     sin_a := sin z ;
     cos_a := cos z ;
     sin_b := sin z_z ;
     cos_b := cos z_z ;
     let coefficient_lisse = facteur_continu *. facteur_lisse in
      let coeff_s = facteur_sinus *. coefficient_lisse
      and coeff_i = facteur_inflexion *. coefficient_lisse
      and coeff_t = facteur_continu *. facteur_triangle in
       let existe_inflexion = coeff_i > 0.
       and existe_triangle = coeff_t > 0.
       and inflex = inflexion parametres.(Data.bouton_inflexion)
       and existe_creneau = facteur_creneau > 0. in
        for i = 0 to 127 do

(** Les amplitudes sont calculées en fonction de la fréquence et des enveloppes. Quand l'une des notes est à son début, les amplitudes ne varient pas au cours d'un échantillon pour préserver la nervosité du détaché. Le reste du temps, les amplitudes sont interpolées avec les valeurs de la fin de l'échantillon précédent afin de minimiser les ronflements. *)


         let ligne_de_phases = phase_generateurs.(i)
         and c0 = cos_fin.(i)
         and s0 = sin_fin.(i)
         and son = sons.(i)
         and enveloppe = enveloppes.(i)
         and ancienne_amplitude = anciennes_amplitudes.(i)
         and ros = rose.(i) in
          for k = 0 to 8 do
           tmp.(k) <- son.(k) *. enveloppe.(k) ;
          done ;
          if attaque 1 Data.duree_d_attaque then
           begin
            accu := tmp.(0) ;
            for k = 1 to 8 do
             accu := !accu +. tmp.(k) ;
            done ;
            accu := ros *. !accu ;
            for j = 0 to Data.pred_taille_d_echantillon do
             amplitude.(j) <- !accu ;
            done ;
           end
          else
           begin
            let coeff = ros *. itde in
             for j = 0 to Data.pred_taille_d_echantillon do
              let jj = float ( succ j )
              and jjj = float ( Data.pred_taille_d_echantillon - j ) in
               accu := jj *. tmp.(0) +. jjj *. ancienne_amplitude.(0) ;
               for k = 1 to 8 do
                accu := !accu +. jj *. tmp.(k) +. jjj *. ancienne_amplitude.(k) ;
               done ;
               accu := !accu *. coeff ;
               amplitude.(j) <- !accu ;
             done ;
           end ;
          for k = 0 to 8 do
           ancienne_amplitude.(k) <- tmp.(k) ;
          done ;

(** Le signal sinusoïdal est la partie réelle d'un arc paramétré à valeurs dans le plan complexe. La discrétisation consiste à itérer une petite rotation. *)


          x := ligne_de_phases.(0) ;
          y := ligne_de_phases.(1) ;
          phase_triangle := ligne_de_phases.(2) ;
          pente := pentes.(i) ;
          phase.(i).(0) <- !x ;
          phase.(i).(1) <- !y ;
          xx := c0 *. !x -. s0 *. !y ;
          yy := s0 *. !x +. c0 *. !y ;
          phase_finale.(i).(0) <- tronque !xx ;
          phase_finale.(i).(1) <- tronque !yy ;
          if amplitude.(0) > 0. then
           begin
            c := cos_rot.(i) ;
            s := sin_rot.(i) ;
            let zzz = ref ( signe ( !cos_a *. !y -. !sin_a *. !x ) +. signe ( !cos_a *. !x +. !sin_a *. !y ) )
            and zz_zz = ref ( inflex ( !cos_b *. !x +. !sin_b *. !y ) ) in
             signal_creneau.(0) <- !zzz ;
             echantillon.(0) <- echantillon.(0) +. amplitude.(0) *. ( coeff_s *. !x +. coeff_i *. !zz_zz +. coeff_t *. !phase_triangle +. facteur_creneau *. !zzz ) ;
             for j = 1 to Data.pred_taille_d_echantillon do
              xx := !c *. !x -. !s *. !y ;
              yy := !s *. !x +. !c *. !y ;
              x := !xx ;
              y := !yy ;
              signal_cos.(j) <- !x ;
              signal_sin.(j) <- !y ;
              if existe_creneau then
               begin
                zzz := signe ( !cos_a *. !y -. !sin_a *. !x ) +. signe ( !cos_a *. !x +. !sin_a *. !y ) ;
                signal_creneau.(j) <- !zzz ;
               end ;
             done ;

(** Pour juguler les erreurs d'arrondi, on part de la fin et l'on effectue les rotations dans l'autre sens. En interpolant, on doit obtenir des sinusoïdes qui se recollent un peu plus harmonieusement d'un échantillon à l'autre. *)


             x := phase_finale.(i).(0) ;
             y := phase_finale.(i).(1) ;
             s := ~-. !s ;
             for j = Data.pred_taille_d_echantillon downto 0 do
              xx := !c *. !x -. !s *. !y ;
              yy := !s *. !x +. !c *. !y ;
              x := !xx ;
              y := !yy ;
              let jj = float j
              and j_j = float ( Data.taille_d_echantillon - j ) in
               x := itde *. ( j_j *. signal_cos.(j) +. jj *. !x ) ;
               y := itde *. ( j_j *. signal_sin.(j) +. jj *. !y ) ;
               signal_cos.(j) <- tronque !x ;
               signal_sin.(j) <- tronque !y ;
             done ; 

(** Il ne reste plus qu'à mélanger les signaux.

Si le signal triangle se désynchronise par rapport au signal sinusoïdal, il se resynchronise en moins d'une période grâce à la troncature. *)



             w := !phase_triangle ;
             for j = 1 to Data.pred_taille_d_echantillon do
              x := signal_cos.(j) ;
              y := signal_sin.(j) ;
              if existe_triangle then
               begin
                ww := !w -. !pente *. ( signe !y ) ;
                w := tronque !ww ;
               end ;
              if existe_inflexion then
               zz_zz := inflex ( !cos_b *. !x +. !sin_b *. !y ) ;
              echantillon.(j) <- echantillon.(j) +. amplitude.(j) *. ( coeff_s *. !x +. coeff_i *. !zz_zz +. coeff_t *. !w +. facteur_creneau *. signal_creneau.(j) ) ;
             done ;
             if existe_triangle then
              begin
               ww := !w -. !pente *. ( signe phase_finale.(i).(1) ) ;
               w := tronque !ww ;
               phase_finale.(i).(2) <- !w ;
              end ;
           end ;
        done ;

(** **** *)

(** Clic *)

(** **** *)


        if attaque 2 2 then
         begin
          let d = parametres.(Data.bouton_niveau_clic)
          and dd = parametres.(Data.bouton_longueur_clic) in
           if d > 0. && dd > 0. then
            for j = 0 to pred ( int_of_float dd ) do
             echantillon.(j) <- d *. signe echantillon.(j) ;
            done ;
         end ;

(** ******************** *)

(** Vibrato monophonique *)

(** ******************** *)


        for i = 0 to Data.pred_taille_d_echantillon do
         stockage_signal.(i) <- echantillon.(i) ;
        done ;
        let nouveau_signal = vibrato_mono parametres.(Data.poussoir_vibrato_mono_chorus) Data.cos_vc Data.sin_vc phase_vc phase_finale_vc precedent_signal echantillon in
         for i = 0 to Data.pred_taille_d_echantillon do
          echantillon.(i) <- nouveau_signal.(i) ;
         done ;
        for i = 0 to Data.pred_taille_d_echantillon do
         precedent_signal.(i) <- stockage_signal.(i) ;
        done ;


(** ************* *)

(** Réverbération *)

(** ************* *)


        reverb parametres.(Data.bouton_delai_reverb) parametres.(Data.bouton_niveau_reverb) precedent_stockage_echantillon stockage_echantillon precedent_echantillon echantillon ;

(** ******** *)

(** Filtrage *)

(** ******** *)


        let ( grave , aigu ) = filtre coupure precedent_echantillon echantillon
        and ( precedent_echantillon_grave , precedent_echantillon_aigu ) = filtre coupure penultieme_echantillon precedent_echantillon in


(** *************************** *)

(** Vibrato, chorus et rotation *)

(** *************************** *)


         let dephasage_grave = Etat.angle drg
         and dephasage_aigu = Etat.angle dra
         and excursion_grave = ref ( Etat.gain_reel evg )
         and excursion_aigue = ref ( Etat.gain_reel eva ) in
          excursion_grave := !excursion_grave *. Data.coeff_excursion_vibrato ;
          excursion_aigue := !excursion_aigue *. Data.coeff_excursion_vibrato ;
          let ( signal_grave_gauche , signal_grave_droit ) = vibrato parametres.(Data.poussoir_vibrato_chorus) tg !excursion_grave bfg dephasage_grave cos_bf sin_bf phase_bf_grave phase_finale_bf_grave phase_bf_1_grave phase_finale_bf_1_grave precedent_echantillon_grave grave
          and ( signal_aigu_gauche , signal_aigu_droit ) = vibrato parametres.(Data.poussoir_vibrato_chorus) ta !excursion_aigue bfa dephasage_aigu cos_bf sin_bf phase_bf_aigu phase_finale_bf_aigu phase_bf_1_aigu phase_finale_bf_1_aigu precedent_echantillon_aigu aigu in

(** ****** *)

(** timbre *)

(** ****** *)


           for i = 0 to Data.pred_taille_d_echantillon do
            echantillon.(i) <- facteur_grave *. signal_grave_gauche.(i) +. facteur_aigu *. signal_aigu_gauche.(i) ;
            echantillon_q.(i) <- facteur_grave *. signal_grave_droit.(i) +. facteur_aigu *. signal_aigu_droit.(i) ;
           done ;

(** ************************************************ *)

(** Amplification saturation, filtrage et expédition *)

(** ************************************************ *)


           facteur_saturation := 1. +. 100. *. parametres.(Data.bouton_saturation) ;

(** En multipliant par 2 ^ 15 on prépare le formatage.

L'amplitude du signal est corrigée grossièrement en fonction du pli bas pour exploiter au mieux la discrétisation des niveaux. *)



           facteur_swell := 32768. *. 4. /. !facteur_saturation ;
           let equilibre = Etat.repartition ( int_of_float parametres.(Data.bouton_equilibre) )
           and correction = Data.rose_zero /. rose.( int_of_float ( 0.3 *. ( min 64. parametres.(Data.bouton_pli_bas) ) ) ) in
            let gauche = !facteur_swell *. equilibre.(0)
            and droite = !facteur_swell *. equilibre.(1) in

(** L'écrêtage d'un amplificateur à tubes est doux, ce qui est modélisé par la fonction tangente hyperbolique. De plus, quand le niveau est très élevé, la sortie de l'amplificateur diminue parce qu'une grille de commande à un potentiel élévé fait perdre une partie du faisceau d'électrons par rebond (pas avec des pentodes). Le comportement impair de la fonction -choisi par facilité- suppose un amplificateur symétrique ou de type push-pull. *)


             facteur_saturation := !facteur_saturation *. correction ;
             for i = 0 to Data.pred_taille_d_echantillon do
              x_1 := !facteur_saturation *. echantillon.(i) ;
              xx_1 := tanh !x_1 ;
              x := gauche *. !xx_1 *. ( 1. -. abs_float !xx_1 ) ;
              echantillon.(i) <- !x ;
              y_1 := !facteur_saturation *. echantillon_q.(i) ;
              yy_1 := tanh !y_1 ;
              y := droite *. !yy_1 *. ( 1. -. abs_float !yy_1 ) ;
              echantillon_q.(i) <- !y ;
             done ;

(** Les données sont quantifiées dans un format convenant aux cares son des ordinateurs portables ordinaires. *)


             Buffer.clear tampon ;
             for i = 0 to Data.pred_taille_d_echantillon do
              penultieme_echantillon.(i) <- precedent_stockage_echantillon.(i) ;
              precedent_echantillon.(i) <- stockage_echantillon.(i) ;
              x := echantillon.(i) ;
              y := echantillon_q.(i) ;
              let k_x = int_of_float !x
              and k_y = int_of_float !y
              and s_x = !x < 0.
              and s_y = !y < 0. in
               let h_x = k_x / octet
               and h_y = k_y / octet in
                let i_x = if s_x then pred h_x else h_x
                and i_y = if s_y then pred h_y else h_y in
                 let j_x = k_x - h_x * octet
                 and j_y = k_y - h_y * octet in
                  Buffer.add_char tampon ( coi ( if s_x then pred j_x else j_x ) ) ;
                  Buffer.add_char tampon ( coi i_x ) ;
                  Buffer.add_char tampon ( coi ( if s_y then pred j_y else j_y ) ) ;
                  Buffer.add_char tampon ( coi i_y ) ;
             done ;
             Buffer.output_buffer oc tampon ;

(** ******************************************** *)

(** Ici il faut rafraîchir les nouvelles phases. *)

(** ******************************************** *)


             phase_bf_grave.(0) <- phase_finale_bf_grave.(0) ;
             phase_bf_grave.(1) <- phase_finale_bf_grave.(1) ;
             phase_bf_1_grave.(0) <- phase_finale_bf_1_grave.(0) ;
             phase_bf_1_grave.(1) <- phase_finale_bf_1_grave.(1) ;
             phase_bf_aigu.(0) <- phase_finale_bf_aigu.(0) ;
             phase_bf_aigu.(1) <- phase_finale_bf_aigu.(1) ;
             phase_bf_1_aigu.(0) <- phase_finale_bf_1_aigu.(0) ;
             phase_bf_1_aigu.(1) <- phase_finale_bf_1_aigu.(1) ;
             phase_vc.(0) <- phase_finale_vc.(0) ;
             phase_vc.(1) <- phase_finale_vc.(1) ;
             for i = 0 to 127 do
              let pfi = phase_finale.(i)
              and ligne_de_phases = phase_generateurs.(i) in
               ligne_de_phases.(0) <- pfi.(0) ;
               ligne_de_phases.(1) <- pfi.(1) ;
               ligne_de_phases.(2) <- pfi.(2) ;
             done ;;





end