struct

(**

Description

La sortie donne d'abord les 128 valeurs d'amplitude pour chaque note de l'instrument, puis les 128 fréquences fondamentales du générateur, puis les paramètres de réglage.

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


(** Les deux fonctions qui suivent servent à replier le clavier quand les harmoniques sortent de l'ambitus MIDI. *)


let plus = fun (x:int) (y:int) ->
 let z = ref ( x + y ) in
  while !z > 127 do
   z := !z - 12 ;
  done ;
  while !z < 0 do
   z := !z + 12 ;
  done ;
  !z ;;

let plusplus = fun (bord_bas:int) (bord_haut:int) (x:int) (y:int) ->
 let z = ref ( x + y ) in
  while !z > bord_haut do
   z := !z - 12 ;
  done ;
  while !z < bord_bas do
   z := !z + 12 ;
  done ;
  !z ;;


let moins = fun (x:int) (y:int) ->
 let z = ref ( x - y ) in
  while !z > 127 do
   z := !z - 12 ;
  done ;
  while !z < 0 do
   z := !z + 12 ;
  done ;
  !z ;;

let rec terme_geometrique = fun (accu:float) (n:int) (x:float) ->
 match n with
 | 0 -> accu
 | 1 -> accu *. x
 | 2 -> accu *. x *. x
 | negatif when negatif < 0 -> terme_geometrique accu ( - n ) ( 1. /. x )
 | pair when pair land 1 = 0 -> terme_geometrique accu ( n / 2 ) ( x *. x )
 | _ -> terme_geometrique ( accu *. x ) ( n / 2 ) ( x *. x ) ;;

let int_pow = fun (n:int) (x:float) ->
 terme_geometrique 1. n x ;;

let gain = function (x:int) ->
 if x = 0 then
  0.
 else
  int_pow ( 127 - x ) Data.coefficient_gain ;;

let gain_reel = function (x:float) ->
 gain ( int_of_float x ) ;;

let gain_rapide = function (x:int) ->
 if x = 0 then
  0.
 else
  int_pow ( 127 - x ) Data.coefficient_rapide ;;

let gain_rapide_reel = function (x:float) ->
 gain_rapide ( int_of_float x ) ;;

let antigain = function (x:int) ->
 if x = 127 then
  0.
 else
  int_pow x Data.coefficient_tirettes ;;

let antigain_reel = function (x:float) ->
 antigain ( int_of_float x ) ;;

let antigain_rapide = function (x:int) ->
 if x = 127 then
  0.
 else
  int_pow x Data.coefficient_gain ;;

let antigain_rapide_reel = function (x:float) ->
 antigain_rapide ( int_of_float x ) ;;

let antigain_lent = function (x:int) ->
 if x = 127 then
  0.
 else
  int_pow x Data.coefficient_lent ;;

let antigain_lent_reel = function (x:float) ->
 antigain_lent ( int_of_float x ) ;;

let gain_median = 1. /. ( gain 64 ) ;;

let angle = function (x:float) ->
 Data.angle_mini *. x ;;

let rec repartition = function (x:int) ->
 match x with
 | negatif when x <= 0 -> [| 1. ; 0. |]
 | 64 -> Array.make 2 Data.pas32
 | petit when petit < 64 ->
  begin
   let y = ref 1. in
    if x land 1 > 0 then
     y := !y *. Data.pas ;
    if x land 2 > 0 then
     y := !y *. Data.pas2 ;
    if x land 4 > 0 then
     y := !y *. Data.pas4 ;
    if x land 8 > 0 then
     y := !y *. Data.pas8 ;
    if x land 16 > 0 then
     y := !y *. Data.pas16 ;
    if x land 32 > 0 then
     y := !y *. Data.pas32 ;
    let z = 1. -. !y in
     let w = 1. /. ( sqrt ( max !y z ) ) in
      [| w *. !y ; w *. z |] ;
  end
 | grand when grand >= 127 -> [| 0. ; 1. |]
 | _ -> 
    (** 65 <= x <= 126 *)

  begin
   let a = repartition ( 127 - x ) in
    [| a.(1) ; a.(0) |] ;
  end ;;

let trirepartition = function (x:int) ->
 match x with
 | petit when petit < 64 ->
  begin
   let a = repartition ( 2 * x ) in
    [| a.(0) ; a.(1) ; 0. |] ;
  end
 | grand when grand > 64 ->
  begin
   let a = repartition ( 2 * ( x - 64 ) ) in
    [| 0. ; a.(0) ; a.(1) |] ;
  end
 | _ -> [| 0. ; 1. ; 0. |] ;; 
            (** x = 64 *)



let etat = fun (forme:float array) (notes:int array) (ages:int array array) (sons:float array array) (enveloppes:float array array) (parametres:float array) ->
 for i = 0 to 127 do
  let ligne = sons.(i) in
   for j = 0 to 8 do
    ligne.(j) <- 0. ;
   done ;
 done ;
 let tirettes = Array.make 9 0.
 and ic = open_in_gen [Open_binary ; Open_rdonly] 0o400 Data.adresse_etat_clavier in
  for i = 0 to 127 do
   notes.(i) <- input_byte ic ;
  done ;
  for i = 0 to pred Data.nombre_de_parametres_clavier do
   parametres.(i) <- float ( input_byte ic ) ;
  done ;
  close_in_noerr ic ;
(** On part du principe que la commande 0 est le pitch, que les commandes 1 à 9 sont les tirettes, que les commandes 10 à 29 sont des boutons rotatifs, que la commande 30 est un bouton-poussoir. Sur le pitch bend, la valeur centrale de repos est à 64. Sur les tirettes, la valeur maximale est à 0, la minimale à 127. Sur les boutons rotatifs la valeur maximale est à 127 et la minimale à 0. Le bouton du diapason a une valeur par défaut de 64 au démarrage. *)

  let k = ( int_of_float parametres.(Data.molette_pitch) ) - 64 in
   let pitch = int_pow k Data.excursion_pitch in
    parametres.(Data.molette_pitch) <- pitch ;
    parametres.(Data.bouton_diapason) <- 441. *. Data.coefficient_diapason ** ( parametres.(Data.bouton_diapason) -. 64. ) ;
    parametres.(Data.bouton_octave) <- 2. +. Data.coefficient_octave *. parametres.(Data.bouton_octave) ;
    let diapason = parametres.(Data.bouton_diapason) *. pitch in
     Data.pulsation diapason parametres.(Data.bouton_octave) parametres.(Data.bouton_rose) Data.adresse_rotation ;

(** tirettes *)


    for i = 1 to 9 do
     parametres.(i) <- antigain_reel parametres.(i) ;
    done ;
    for i = 10 to 18 do
     parametres.(i) <- antigain_reel ( min 126. parametres.(i) ) ;
     tirettes.( i - 10 ) <- parametres.(i) ;
    done ;

(** boutons rotatifs *)


    parametres.(Data.bouton_saturation) <- gain_reel parametres.(Data.bouton_saturation) ;
    parametres.(Data.bouton_dephasage_inflexion) <- angle parametres.(Data.bouton_dephasage_inflexion) ;
    parametres.(Data.bouton_dephasage_creneaux) <- angle parametres.(Data.bouton_dephasage_creneaux) ;
    parametres.(Data.bouton_longueur_clic) <- ( gain_reel parametres.(Data.bouton_longueur_clic) ) *. Data.pred_taille_d_echantillon_reelle ;
    parametres.(Data.bouton_niveau_clic) <- gain_reel parametres.(Data.bouton_niveau_clic) ;
    parametres.(Data.bouton_coupure) <- float ( ( 127 - ( int_of_float parametres.(Data.bouton_coupure) ) ) / 3 ) ;
    parametres.(Data.bouton_delai_reverb) <- parametres.(Data.bouton_delai_reverb) *. Data.coeff_delai ;
    parametres.(Data.bouton_niveau_reverb) <- gain_reel parametres.(Data.bouton_niveau_reverb) ;
    parametres.(Data.bouton_traine) <- Data.coeff_traine *. ( gain_rapide_reel ( max 1. parametres.(Data.bouton_traine) ) ) ;
    parametres.(Data.bouton_nervosite) <- 1e6 *. ( gain_rapide_reel ( max 1. parametres.(Data.bouton_nervosite) ) ) ;
    parametres.(Data.bouton_remanence) <- gain_reel parametres.(Data.bouton_remanence) ;
    parametres.(Data.bouton_pente_remanence) <- antigain_lent_reel parametres.(Data.bouton_pente_remanence) ;

(** notes *)


    let bord_bas = max 0 ( min 63 ( int_of_float parametres.(Data.bouton_pli_bas) ) )
    and bord_haut = max 64 ( min 127 ( int_of_float parametres.(Data.bouton_pli_haut) ) )
    and nervosite = parametres.(Data.bouton_nervosite)
    and remanence = parametres.(Data.bouton_remanence)
    and pente_remanence = parametres.(Data.bouton_pente_remanence)
    and traine = parametres.(Data.bouton_traine) in
     let decalage = Data.max_de_forme *. ( 1. -. 1. /. nervosite )
     and a = ref 0
     and alpha = Data.inv_16129 *. ( 127. -. parametres.(Data.bouton_swell) )
     and beta = Data.inv_127 *. parametres.(Data.bouton_swell) in
      for i = 0 to 127 do
       let velocite = notes.(i) in
        if velocite > 0 then
         begin
          let n = alpha *. float velocite +. beta
          and rappuie = ( velocite >= 128 ) in
           if rappuie then
            begin
             let valeur = 255 - notes.(i) in
              Clavier.aux Data.adresse_etat_clavier i valeur ;
              notes.(i) <- valeur ;
            end ;
           for k = 0 to 8 do
            let index = plusplus bord_bas bord_haut i Data.tirettes.(k) in
             if rappuie then
              a := 0
             else
              a := ages.(index).(k) ;
             sons.(index).(k) <- sons.(index).(k) +. parametres.( 1 + k ) *. n ;
             enveloppes.(index).(k) <- enveloppes.(index).(k) +. Data.enveloppe forme decalage nervosite ( remanence *. int_pow !a pente_remanence ) ( traine *. tirettes.(k) *. float !a ) ;
             ages.(index).(k) <- succ !a ;
           done ;
         end
        else
         begin
          for k = 0 to 8 do
           let index = plusplus bord_bas bord_haut i Data.tirettes.(k) in
            ages.(index).(k) <- 0 ;
          done ;
         end
      done ;;


end