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 tirettes_enveloppes = Array.make 9 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 enveloppes sons parametres ;
   for k = 0 to 8 do
    tirettes_enveloppes.(k) <- parametres.( 10 + k )
   done ;

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

(** 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

(** 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. *)


         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 ;
          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 := 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. ;
           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. *)


             for i = 0 to Data.pred_taille_d_echantillon do
              x_1 := ( 1. +. !facteur_saturation ) *. correction *. echantillon.(i) ;
              xx_1 := tanh !x_1 ;
              x := gauche *. !xx_1 *. ( 1. -. abs_float !xx_1 ) ;
              echantillon.(i) <- !x ;
              y_1 := ( 1. +. !facteur_saturation ) *. correction *. 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