module Cherche_midi = struct (** {1 Descripton} Cette fonction sert à détecter quel périphérique MIDI envoie effectivement des données. Il faut actionner les commandes du clavier MIDI pour que des données soient effectivement perçues. {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.7} @version 0.7 @author Stéphane Grognet @since 2014 *) let cherche_midi = function (adresse:string) -> let ic = open_in_gen [Open_binary ; Open_rdonly] 0o400 adresse in ignore ( input_byte ic ) ; print_string adresse ; print_newline () ; close_in_noerr ic ; Sys.command "killall CHERCHE_MIDI" ;; cherche_midi Sys.argv.(1) ;; end ;; module Detect = struct (** {1 Descripton} La fonction [detect] sert à déterminer quel est le modèle de clavier MIDI qui envoie des données. Il faut manipuler suffisamment de boutons-poussoirs, boutons rotatifs et curseurs pour que le type de clavier soit déterminé soit par un numéro de contrôleur particulier au fabricant soit par éliminations successives. {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.7} @version 0.7 @author Stéphane Grognet @since 2014 *) type fabricant = | Inconnu | Alesis | Arturia | M_audio | Roland ;; let tout = [ Alesis ; Arturia ; M_audio ; Roland ] ;; let cmp = fun (x:fabricant) (y:fabricant) -> match x with | Inconnu -> begin match y with | Inconnu -> 0 | _ -> -1 end | Alesis -> begin match y with | Inconnu -> 1 | Alesis -> 0 | _ -> -1 end | Arturia -> begin match y with | Inconnu | Alesis -> 1 | Arturia -> 0 | _ -> -1 end | M_audio -> begin match y with | M_audio -> 0 | Roland -> -1 | _ -> 1 end | Roland -> begin match y with | Roland -> 0 | _ -> -1 end ;; let trad = function (x:fabricant) -> let chaine = match x with | Alesis -> "alesis" | Arturia -> "arturia" | M_audio -> "m_audio" | Roland -> "roland" | _ -> "" in print_string chaine ; print_newline () ;; let rec ajoute = fun (x:fabricant list) (y:fabricant list) -> match x with | [] -> y | z :: q -> begin if List.exists ( function w -> cmp w z = 0 ) y then ajoute q y else z :: ( ajoute q y ) end ;; let detect = function ic -> let continue = ref true and masque_entete = 0xF0 and mode = 0xB0 and instru = 0xC0 and c = ref 0 and entete = ref 0 and controleur = ref 0 and pas_fab = ref [ ] and fab = ref Inconnu in while !continue do c := input_byte ic ; entete := !c land masque_entete ; match !entete with | x when x land mode = mode -> begin controleur := input_byte ic ; begin fab := match !controleur with | 0x0E | 0x0F | 0x14 -> ( continue := false ; Alesis ) | 0x1E | 0x1F | 0x32 | 0x33 | 0x34 | 0x35 | 0x36 | 0x37 | 0x55 -> ( continue := false ; Arturia ) | 0x00 | 0x20 | 0x54 | 0x6E | 0x6F | 0x71 | 0xBF -> ( continue := false ; M_audio ) | 0x02 | 0x0B | 0x41 | 0x5E -> ( continue := false ; Roland ) | _ -> Inconnu ; end ; if !continue then begin begin pas_fab := match !controleur with | 0x07 | 0x47 | 0x48 | 0x49 | 0x4A | 0x4B | 0x4C | 0x4D | 0x5B | 0x5D -> ajoute [Alesis] !pas_fab | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C -> ajoute [M_audio] !pas_fab | 0x76 -> ajoute [Roland] !pas_fab | 0x05 | 0x0A | 0x4E | 0x5C | 0x5F -> ajoute [Alesis ; Arturia] !pas_fab | 0x50 | 0x51 | 0x52 | 0x53 -> ajoute [Alesis ; M_audio] !pas_fab | 0x4F -> ajoute [Alesis ; Roland] !pas_fab | 0x15 -> ajoute [Arturia ; M_audio] !pas_fab | 0x72 | 0x73 | 0x74 | 0x75 -> ajoute [Arturia ; Roland] !pas_fab | 0x10 | 0x11 | 0x12 | 0x13 | 0x1D | 0x77 -> ajoute [M_audio ; Roland] !pas_fab | _ -> !pas_fab end ; if List.length !pas_fab = 3 then begin let test = ref tout and x = ref Inconnu and poursuis = ref true in while !poursuis do x := List.hd !test ; test := List.tl !test ; if List.for_all ( function y -> cmp !x y <> 0 ) !pas_fab then poursuis := false ; done ; fab := !x ; continue := false ; end ; ignore ( input_byte ic ) ; end end | x when x land instru = instru -> begin ignore ( input_byte ic ) ; fab := M_audio ; continue := false ; end | _ -> () ; done ; trad !fab ;; detect stdin ;; end ;; module Gravure = struct (** {1 Description} L'unique fonction de ce module enregistre les messages MIDI. {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.8} @version 0.8 @author Stéphane Grognet @since 2014 *) let gravure = fun (adresse:string) -> let date = ref 0. and estampille = ref 0. and depart = Unix.gettimeofday () and oc = open_out adresse and c = ref 0 in try while true do c := input_byte stdin ; date := Unix.gettimeofday () ; estampille := !date -. depart ; output_string oc ( "*\n" ^ ( string_of_float !estampille ) ^ "\n" ) ; output_string oc ( ( string_of_int !c ) ^ "\n" ) ; output_byte stdout !c ; flush_all () ; done ; with _ -> close_out_noerr oc ;; gravure Sys.argv.(1) ;; end ;; module Data = struct (** {1 Exemples de jeux d'instruments historiques} Les orgues électromécaniques : à roues phoniques ou bien électroniques : soit à lampes soit à transistors discrets s'inspirent des orgues pneumatiques à tuyaux. Ceux-ci s'inspirent des instruments à vent ou à cordes frottées. Les instruments à vent cylindriques (trompette, clarinette, cor, trombone...) favorisent plus ou moins les harmoniques impaires et donnent un son clair ; les instruments à vent coniques (hautbois, basson, saxophone, cornet à bouquin, bugle et saxhorns...) favorisent les harmoniques paires et donnent un son relativement plus suave. Le cas des flûtes est différent. {2 TIRETTES des Hammond A100, B3, C3, RT3, XK*, XB* ; KeyB Solo, Duo, claviaNord C* en mode Hammond... Tirettes du clavier supérieur des Hammond M, M2, M3, M102... } + Bourdon 16' sous-fondamentale + Quint 16/3' = 5+1/3' troisième harmonique de la sous-fondamentale + Principal 8' fondamentale + Octave 4' deuxième harmonique [ percussion percussion sur deuxième ] + Nazard 8/3' = 2+2/3' troisième harmonique [ percussion sur troisième ] + Block flöte 2' quatrième harmonique + Tierce 8/5' = 1+3/5' cinquième harmonique + Larigot 4/3' = 1+1/3' sixième harmonique [ -> percussion sur clavier supérieur de série M ] + Sifflöte 1' huitième harmonique [ ne produit pas de son quand la percussion est active ] La septième harmonique (deux octaves et une septième mineure) a été omise parce que les rapports de fréquences étaient trop compliqués. Rien n'empêche de la rajouter... {2 TIRETTES du clavier inférieur des Hammond M, M2, M3, M102...} + 8' fondamentale + 4' deuxième harmonique + 8/3' = 2+2/3' troisième harmonique + 2' quatrième harmonique + 8/5' = 1+3/5' cinquième harmonique + 4/3' = 1+1/3' sixième harmonique + 1' huitième harmonique + II : 4/5' et 2/3' dixième et douzième harmoniques {2 TIRETTES du clavier des claviaNord C* en mode Vox...} + 16' fondamentale + 8' harmonique 2 + 4' harmonique 4 + 2' harmonique 8 + II harmoniques 3 et 5 + III harmoniques 6, 8 et 16 + IV harmoniques 12, 16, 20 et 32 + ~ signal filtré doux et sombre + vv signal non filtré brillant et intense {2 TIRETTES du clavier supérieur des Vox... } + 16' + 8' + 4' + II + III + ~ + vv {2 TIRETTES du clavier inférieur des Vox...} + 16' (absent chez Native Instruments mais il y a un potentiomètre de basse) + 8' + 4' + 2' + IV + ~ + vv {2 TIRETTES du clavier des claviaNord C* en mode Farfisa...} + Bass16 fondamentale + Strings16 fondamentale + Flute8 harmonique 2 + Oboe8 harmonique 2 + Trumpet8 harmonique 2 + Strings8 harmonique 2 + Flute4 harmonique 4 + Strings4 harmonique 4 + 2+2/3 harmonique 6 {2 INTERRUPTEURS du Farfisa compact chez Native Instruments en mode multitone booster off} + Bass16 fondamentale + Strings16 fondamentale + Flute8 harmonique 2 + Oboe8 harmonique 2 + Trumpet8 harmonique 2 + Strings8 harmonique 2 + Flute4 harmonique 4 + Piccolo4 harmonique 4 + Strings4 harmonique 4 {2 INTERRUPTEURS du Farfisa compact chez Native Instruments en mode multitone booster on} + 16 fondamentale + 8 harmonique 2 + 4 harmonique 4 + ALL booster toutes harmoniques non filtrées Il y a un potentiomètre de basse indépendant des modes. {2 Novachord Hammond} Le novachord Hammond comporte douze oscillateurs à tubes électroniques et des diviseurs de fréquence pour fabriquer les soixante-douze notes de la tessiture. Le timbre des notes est changé par filtrage : il s'agit plutôt de synthèse soustractive à partir d'oscillateurs riches en harmoniques. {1 Exemples de réglages d'instruments historiques} {2 RÉGLAGES PRINCIPAUX des orgues Hammond} + vibrato 1, 2, 3 : différentes profondeurs sur la ligne à retard, + chorus 1, 2, 3 (chorus = vibrato mélangé avec le son droit), + percussion decay: slow, fast ; level: normal, soft ; sur deuxième ou troisième harmonique. {2 RÉGLAGES PRINCIPAUX des novachords Hammond} + chant ou bien percussion avec six formes d'enveloppes, + vibrato petit ou normal, + équilibrage de timbre (filtre passe-bas dépendant du clavier), + trois résonateurs avec trois niveaux chacun (filtres passe-bande). {2 RÉGLAGES PRINCIPAUX des enceintes Leslie} + fast (tremolo), + slow (chorale), + brake. {1 Quelques données physiques} Le moteur des générateurs de Hammond tourne à 20 Hz quand le secteur est à 60 Hz et les roues comportent 2, 4, 8, 16, 32, 64, 128, 192 voire 256 dents. Le balayeur de vibrato -{e vibrato scanner}- (par couplage capacitif vers différents points d'une ligne à retard) tourne à 412 tours par minute, soit environ 6,87 Hz. Sur la page {{:http://www.dikiri.org/HammondWiki/LeslieRotationSpeed}http://www.dikiri.org/HammondWiki/LeslieRotationSpeed} il est indiqué comme vitesses en tours par minute pour les rotors des enceintes Leslie : - aigu : 400 et 48, grave 342 et 40, - aigu : 409 et 48, grave 396 et 48, - fast : 5,7 à 6,8 Hz, slow : 0,8 Hz. Sur la page {{:http://electronicmusic.wikia.com/wiki/Leslie}http://electronicmusic.wikia.com/wiki/Leslie} il est indiqué comme vitesses en tours par minute pour les rotors des enceintes Leslie : - fast : 250, slow : 30 à 50. Sur la page {{:http://clonewheel.pbworks.com/w/page/8507660/Leslie}http://clonewheel.pbworks.com/w/page/8507660/Leslie} il est indiqué comme vitesses en hertz pour les rotors des enceintes Leslie : - fast : 7, slow : 0,5. Il semble que l'inertie du rotor de grave demande une dizaine de secondes pour le passage entre vitesse lente et vitesse rapide. La fréquence de coupure d'une enceinte Leslie est 800 Hz. {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 1.0} @version 1.0 @author Stéphane Grognet @since 2014 *) (** {1 Commande d'oisiveté} *) let sommeil = ( 0 = Sys.command "TEST=`time -p sleep 0.5 2>&1 | head -n 1 | sed 's/real //'` NOMBRE=`echo \"2 * $TEST < 1\" | bc` exit $NOMBRE" ) ;; let passe_temps = function () -> if sommeil then ignore ( Sys.command "sleep 0.001" ) else ignore ( tan 2. ) ;; (** {1 Données générales} *) let adresse_rotation = "/tmp/orgueIREM/ROTATION" ;; let adresse_etat_clavier = "/tmp/orgueIREM/etatClavier" ;; let adresse_etat_orgue = "/tmp/orgueIREM/etatOrgue" ;; let adresse_etat_jeux = "/tmp/orgueIREM/etatJeux" ;; let adresse_etat_reglages = "/tmp/orgueIREM/etatReglages" ;; let adresse_archive_jeux = "../orgueIREMrc/etatJeux" ;; let adresse_archive_reglages = "../orgueIREMrc/etatReglages" ;; let adresse_rotation_bf = "../orgueIREMrc/rotation_bf" ;; let adresse_entete = "../orgueIREMrc/entete" ;; let frequence_d_echantillonnage = 44100 ;; (** 44100 = ( 2 * 3 * 5 * 7 ) ^ 2 *) (** let taille_d_echantillon = 441 ;; let taille_d_echantillon = 882 ;; let taille_d_echantillon = 1536 ;; let taille_d_echantillon = 1764 ;; let taille_d_echantillon = 4410 ;; *) let taille_d_echantillon = 882 ;; let pred_taille_d_echantillon = pred taille_d_echantillon ;; let taille_d_echantillon_reelle = float taille_d_echantillon ;; let pred_taille_d_echantillon_reelle = float pred_taille_d_echantillon ;; let duree_d_echantillon = taille_d_echantillon_reelle /. (float frequence_d_echantillonnage ) ;; (** Constantes de dosage entre deux quantités pour un paramètre variant de 0 à 127 avec une perception logarithmique. *) let pas = 0.989228013193975464 ;; (** 0.5 ^ ( 1/64 ) *) let pas2 = 0.97857206208770009 ;; (** 0.5 ^ ( 1/32 ) *) let pas4 = 0.9576032806985737 ;; (** 0.5 ^ ( 1/16 ) *) let pas8 = 0.917004043204671215 ;; (** 0.5 ^ ( 1/8 ) *) let pas16 = 0.840896415253714613 ;; (** 0.5 ^ ( 1/4 ) *) let pas32 = 0.707106781186547573 ;; (** 0.5 ^ ( 1/2 ) *) let pas64 = 0.5 ;; let antipas = 0.0107719868060245361 ;; (** 1 - pas *) let antipas2 = 0.0214279379122999103 ;; (** 1 - pas2 *) let antipas4 = 0.0423967193014263 ;; (** 1 - pas4 *) let antipas8 = 0.0829959567953287847 ;; (** 1 - pas8 *) let antipas16 = 0.159103584746285387 ;; (** 1 - pas16 *) let antipas32 = 0.292893218813452427 ;; (** 1 - pas32 *) let antipas64 = 0.5 ;; (** 1 - pas64 *) let coefficient_gain = 0.947463525655375394 ;; (** coefficient_gain ^ 64 correspond à 10 ^ (-1.5) c'est-à-dire -30 dBV. *) let coefficient_tirettes = sqrt coefficient_gain ;; let coeff_excursion_vibrato = ( float frequence_d_echantillonnage ) *. 0.00898842822301309206 ;; (** 300 microsecondes ou 22.05 points d'échantillonnage de retard pour la valeur MIDI 64 *) let coefficient_coupure = 0.861328125 ;; (** 44100. /. ( 800. *. 64. ) *) (** Dans la norme {e general midi}, le la du diapason (440 à 442 hz) porte le numéro 69, et le do en-dessous (do médian) le numéro 60. *) let excursion_pitch = 1.00364273704211771 ;; (** 2.01 ^ (1/(64*3)). La fréquence du la du diapason est excursion ^ ( parametres.(molette_pitch) - 64 ) * f0 où f0 est la fréquence du la du diapason (=~= 441hz). Ceci donne une excursion maximale de 2 tons du diapason (pitch bend). *) let coefficient_diapason = 1.00090944287864625 ;; (** 2.01 ^ (1/(64*12)). La fréquence du la du diapason avec molette de pitch au repos est coefficient_diapason ^ ( parametres.(bouton_diapason) - 64 ) * 441 hz. Ceci donne une excursion maximale d'un demi-ton. *) (** L'octave correspond à une multiplication de la fréquence par une valeur proche de 2. Les coefficients multiplicateurs de la fréquence pour monter ou descendre d'un demi-ton en découlent. *) let un_douzieme = 0.0833333333333333333 ;; (** Avec 0.35 l'amplitude est limitée ; elle devrait rester entre -1 et 1 si aucun effet n'est rajouté. *) let rose_zero = 0.35 ;; let modulo_vibrato = 3 ;; let modulo_vibrato_mono = 7 ;; let angle_mini = 0.049473900056532176 ;; (** 2 * pi / 127.0 *) let pi_sur_quatre = atan 1. ;; let pi_sur_deux = 2. *. pi_sur_quatre ;; let pi = 4. *. pi_sur_quatre ;; let facteur_pulsation = 2. *. pi /. ( float frequence_d_echantillonnage ) ;; let facteur_triangle = 2. /. pi ;; let cos_vc = cos ( facteur_pulsation *. 412. /. 60. ) ;; let sin_vc = sin ( facteur_pulsation *. 412. /. 60. ) ;; let nombre_de_parametres_clavier = 45 ;; let nombre_de_parametres_orgue = 2 + nombre_de_parametres_clavier ;; let nombre_de_curseurs = 9 ;; let succ_nombre_de_curseurs = succ nombre_de_curseurs ;; let coefficient_octave = 0.00015625 ;; (** COEFFICIENT_OCTAVE = 1/6400. L'octave correspond à une multiplication de la fréquence par 2 + COEFFICIENT_OCTAVE * parametres.(bouton_octave). Ceci donne 2 pour 0 ; 2.01 pour 64 et 2.01984375 pour 127. *) let coeff_delai = ( float taille_d_echantillon ) /. 127.0 ;; (** {1 Numéros des paramètres de commande} *) let molette_pitch = 0 ;; (** molette modulation ou curseur 0 *) let tirette0 = 1 ;; (** curseur 1 *) let tirette1 = 2 ;; (** curseur 2 *) let tirette2 = 3 ;; (** curseur 3 *) let tirette3 = 4 ;; (** curseur 4 *) let tirette4 = 5 ;; (** curseur 5 *) let tirette5 = 6 ;; (** curseur 6 *) let tirette6 = 7 ;; (** curseur 7 *) let tirette7 = 8 ;; (** curseur 8 *) let tirette8 = 9 ;; (** bouton 1 *) let bouton_swell = 10 ;; (** bouton 8 *) let bouton_saturation = 11 ;; (** bouton 2 *) let bouton_inflexion = 12 ;; (** bouton 3 *) let bouton_dephasage_inflexion = 13 ;; (** bouton 4 *) let bouton_dephasage_creneaux = 14 ;; (** bouton 5 *) let bouton_niveau_inflexion = 15 ;; (** bouton 6 *) let bouton_niveau_triangle = 16 ;; (** bouton 7 *) let bouton_niveau_creneaux = 17 ;; (** bouton 2 *) let bouton_longueur_clic = 18 ;; (** bouton 3 *) let bouton_diff_enveloppe_percu = 19 ;; (** bouton 4 *) let bouton_diff_niveau_percu = 20 ;; (** bouton 5 *) let bouton_niveau_clic = 21 ;; (** bouton 6 *) let bouton_enveloppe_percu = 22 ;; (** bouton 7 *) let bouton_niveau_percu = 23 ;; (** bouton 2 *) let bouton_diff_excursion_vibrato = 24 ;; (** bouton 3 *) let bouton_diff_basse_frequence = 25 ;; (** bouton 4 *) let bouton_diff_dephasage_rotation = 26 ;; (** bouton 5 *) let bouton_excursion_vibrato = 27 ;; (** bouton 6 *) let bouton_basse_frequence = 28 ;; (** bouton 7 *) let bouton_dephasage_rotation = 29 ;; (** bouton 2 *) let bouton_diapason = 30 ;; (** bouton 3 *) let bouton_octave = 31 ;; (** bouton 4 *) let bouton_rose = 32 ;; (** bouton 5 *) let bouton_coupure = 33 ;; (** bouton 6 *) let bouton_timbre = 34 ;; (** bouton 7 *) let bouton_equilibre = 35 ;; (** bouton 2 *) let bouton_delai_reverb = 36 ;; (** bouton 3 *) let bouton_pli_haut = 37 ;; (** bouton 4 *) let bouton_diff_tremolo = 38 ;; (** bouton 5 *) let bouton_niveau_reverb = 39 ;; (** bouton 6 *) let bouton_pli_bas = 40 ;; (** bouton 7 *) let bouton_tremolo = 41 ;; (** boucle ; modulo modulo_vibrato *) let poussoir_vibrato_chorus = 42 ;; (** boucle ; modulo modulo_vibrato_mono *) let poussoir_vibrato_mono_chorus = 43 ;; (** pads 1, 2, 3 ou poussoirs 5, 6, 7 ; annulation par Pad4 ( valeur modulo 4 ) *) let demi_lune = 44 ;; (** nombre de notes simultanées *) let polyphonie = 45 ;; (** une touche a récemment été enfoncée *) let detache = 46 ;; (** {1 Valeurs des tirettes en demi-tons d'écart par rapport à la fondamentale} *) let tirettes = [| -12 ; 7 ; 0 ; 12 ; 19 ; 24 ; 28 ; 31 ; 36 |] ;; (** {1 Fabrication des fréquences, décroissances d'amplitudes et rotations} *) let pulsation = fun (diapason:float) (octave:float) (parametre_rose:float) (destination:string) -> let oc = open_out destination and excursion = parametre_rose -. 64. and sof = string_of_float and demi_ton = octave ** un_douzieme in let anti_demi_ton = 1. /. demi_ton and frequences = Array.make 128 0. in let coefficient_rose = anti_demi_ton ** ( 0.5 +. 0.0025 *. excursion ) and k = ref 69 and rose = ref ( rose_zero *. demi_ton ** ( 0.16 *. excursion ) ) in frequences.(!k) <- diapason ; for i = 70 to 127 do frequences.(i) <- frequences.(!k) *. demi_ton ; k := i ; done ; k := 69 ; for i = 68 downto 0 do frequences.(i) <- frequences.(!k) *. anti_demi_ton ; k := i ; done ; for i = 0 to 127 do let pouls = facteur_pulsation *. frequences.(i) in let c0 = cos ( pouls *. taille_d_echantillon_reelle ) and s0 = sin ( pouls *. taille_d_echantillon_reelle ) and c = cos ( pouls ) and s = sin ( pouls ) in rose := !rose *. coefficient_rose ; output_string oc ( ( sof c0 ) ^ "\n" ^ ( sof s0 ) ^ "\n" ^ ( sof c ) ^ "\n" ^ ( sof s ) ^ "\n" ^ ( sof !rose ) ^ "\n" ^ ( sof pouls ) ^ "\n" ) ; done ; close_out_noerr oc ;; let generation_bf = function (destination:string) -> let oc = open_out destination and k = ref 127 and sof = string_of_float and anti_demi_ton = 0.5 ** un_douzieme and frequences = Array.make 128 0. in frequences.(!k) <- 1e3 ; for i = 126 downto 0 do frequences.(i) <- frequences.(!k) *. anti_demi_ton ; k := i ; done ; for i = 0 to 127 do let pouls = facteur_pulsation *. frequences.(i) in let c = cos ( pouls ) and s = sin ( pouls ) in output_string oc ( ( sof c ) ^ "\n" ^ ( sof s ) ^ "\n" ) ; done ; close_out_noerr oc ;; (** {1 Préréglages} *) let excursion_vibrato_stereo = 70 ;; let diff_excursion_vibrato_stereo = 20 ;; let dephasage_rotation_vibrato_stereo = 16 ;; let diff_dephasage_rotation_vibrato_stereo = 0 ;; let tremolo_vibrato_stereo = 100 ;; let diff_tremolo_vibrato_stereo = 8 ;; let basse_frequence_grave_vibrato_stereo_lent = 52. ;; let basse_frequence_aigue_vibrato_stereo_lent = 52. ;; let basse_frequence_grave_vibrato_stereo_rapide = 86. ;; let basse_frequence_aigue_vibrato_stereo_rapide = 89. ;; let valeurs_clic = [| 80 ; 100 ; 100 ; 48 ; 127 ; 32 |] ;; let valeurs_percu = [| 127 ; 0 ; 64 ; 48 ; 127 ; 64 ; 56 ; 40 ; 127 ; 127 ; 48 ; 32 |] ;; let valeurs_reverb = [| 108 ; 32 ; 102 ; 127 ; 115 ; 127 |] ;; let valeurs_forme = [| 64 ; 64 ; 32 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 127 ; 0 ; 0 ; 0 ; 0 ; 0 ; 0 ; 32 ; 16 ; 64 ; 64 ; 32 ; 64 ; 0 ; 0 ; 64 ; 32 ; 32 ; 0 ; 10 ; 16 ; 64 ; 96 ; 64 ; 84 ; 16 ; 16 |] ;; end ;; module Perroquet = struct (** {1 Description} L'unique fonction de ce module rejoue des messages MIDI enregistrés. {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.8} @version 0.8 @author Stéphane Grognet @since 2014 *) let perroquet = fun () -> let date = ref 0. and estampille = ref 0. and ligne = ref "" and echeance = ref 0. and depart = Unix.gettimeofday () and condition = ref true in while true do ligne := read_line () ; if !ligne.[0] = '*' then begin ligne := read_line () ; estampille := float_of_string !ligne ; echeance := depart +. !estampille ; date := Unix.gettimeofday () ; condition := !echeance > !date ; while !condition do Data.passe_temps () ; date := Unix.gettimeofday () ; condition := !echeance > !date ; done ; end else output_byte stdout ( int_of_string !ligne ) ; done ;; try perroquet () with _ -> () ;; end ;; module Init = struct (** {1 Initialisation de l'orgue} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.7} @version 0.7 @author Stéphane Grognet @since 2014 *) let init = function () -> Data.pulsation 441. 2. 64. Data.adresse_rotation ; Data.generation_bf Data.adresse_rotation_bf ;; init () ;; end ;; module InitJeux = struct (** {1 Effaçage de la mémoire des jeux de tirettes} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.3} @version 0.3 @author Stéphane Grognet @since 2014 *) let init_jeux = function () -> let oc = open_out Data.adresse_archive_jeux in for i = 0 to 59 do for j = 1 to 9 do output_char oc '\x7F' ; done ; done ; for j = 1 to 9 do output_char oc '\x00' ; done ; for i = 61 to 127 do for j = 1 to 9 do output_char oc '\x7F' ; done ; done ; close_out_noerr oc ;; init_jeux () ;; end ;; module InitReglages = struct (** {1 Effaçage de la mémoire des réglages} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.6} @version 0.6 @author Stéphane Grognet @since 2014 *) let init_reglages = function () -> let oc = open_out Data.adresse_archive_reglages and vide = '\x00' and milieu = '\x40' and plein = '\x7F' in for i = 0 to 127 do output_char oc plein ; output_char oc vide ; output_char oc milieu ; for j = 3 to 8 do output_char oc vide ; done ; for j = 9 to 10 do output_char oc milieu ; done ; for j = 11 to 19 do output_char oc vide ; done ; output_char oc milieu ; output_char oc vide ; for j = 22 to 25 do output_char oc milieu ; done ; for j = 26 to 27 do output_char oc plein ; done ; for j = 28 to 34 do output_char oc vide ; done ; done ; close_out_noerr oc ;; init_reglages () ;; end ;; module Clavier = struct (** {1 Descripton} Le foncteur Clavier.Make permet d'interpréter les signaux MIDI de contrôleurs provenant de divers fabricants. Cette interprétation des signaux MIDI ne tient compte ni des canaux MIDI ni de la valeur de la vélocité. Le résultat est un vecteur de 171 caractères dont les cent-vingt-huit premiers donnent l'état de chaque note/touche de clavier : 0 pour haut, 127 pour bas. Le suivant donne la valeur d'excursion de diapason (pitch bend). Les neuf caractères suivants donnent la position des tirettes (127 au fond, 0 vers l'interprète) ; la première tirette est la molette de modulation quand seulement huit curseurs sont disponibles. Les huit autres sont les curseurs dans l'ordre. Les caractères suivants donnent les valeurs des boutons rotatifs (de 0 à 127) suivant les modes (2+5*6 puisque swell et saturation sont toujours présents). Le caractère qui reste indique l'activité du bouton-poussoir boucle (bouton de transport de style magnétophone). {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.8} @version 0.8 @author Stéphane Grognet @since 2014, 2015 *) (** {1 Constantes locales} *) type select = | Vide | Rappel | Rappel_boutons | Sauvegarde | Sauvegarde_boutons | Forme | Percussion | Vibrato | Filtrage | Reverb | Special | Rembobine | Avance_rapide | Arret | Lecture ;; let vide = 0 ;; let plein = 127 ;; let milieu = 64 ;; let haut = 0 ;; let bas = 127 ;; (** {1 Fonctions utilitaires} *) let pourcent_cpu = fun () -> let x = Sys.command "exit `ps -ro %cpu | head -n 2 | tail -n 1 | cut -d. -f 1`" in ( string_of_int x ) ^ "% " ;; let detricote = fun (sigma:int) (delta:int) -> let s = 2 * sigma in ( ( s + delta ) / 2 , ( s - delta ) / 2 ) ;; let aux = fun (adresse:string) (decalage:int) (c:int) -> let oc = open_out_gen [Open_binary ; Open_wronly] 0o644 adresse in seek_out oc decalage ; output_byte oc c ; flush_all () ; close_out_noerr oc ;; let rappel_boutons = fun (decalage:int ref) (pred_facteur_decalage:int) (facteur_decalage:int) (reglages:int array) (note:int) -> let ict = open_in_gen [Open_binary ; Open_rdonly] 0o400 Data.adresse_etat_reglages in decalage := facteur_decalage * note ; seek_in ict !decalage ; for i = 0 to pred_facteur_decalage do reglages.(i) <- input_byte ict ; done ; close_in_noerr ict ; let oc = open_out_gen [Open_binary ; Open_wronly] 0o644 Data.adresse_etat_clavier in seek_out oc ( 128 + Data.succ_nombre_de_curseurs ) ; for i = 0 to pred_facteur_decalage do output_byte oc reglages.(i) ; done ; flush_all () ; close_out_noerr oc ; prerr_int note ; prerr_newline () ; prerr_endline ( ( pourcent_cpu () ) ^ "mode vide" ) ;; let sauvegarde_boutons = fun (decalage:int ref) (pred_facteur_decalage:int) (facteur_decalage:int) (reglages:int array) (note:int) -> let oc = open_out_gen [Open_binary ; Open_wronly] 0o644 Data.adresse_etat_reglages in decalage := facteur_decalage * note ; seek_out oc !decalage ; for i = 0 to pred_facteur_decalage do output_byte oc reglages.(i) ; done ; flush_all () ; close_out_noerr oc ; prerr_int note ; prerr_newline () ; prerr_endline ( ( pourcent_cpu () ) ^ "mode vide" ) ;; let demande_rappel_boutons = function (selection:select ref) -> selection := Rappel_boutons ; prerr_endline ( ( pourcent_cpu () ) ^ "rappel de reglages" ) ;; let demande_sauvegarde_boutons = function (selection:select ref) -> selection := Sauvegarde_boutons ; prerr_endline ( ( pourcent_cpu () ) ^ "enregistrement de reglages" ) ;; let vc = fun (poussoir_mono:int ref) (reglages:int array) -> poussoir_mono := ( succ !poussoir_mono ) mod Data.modulo_vibrato_mono ; reglages.( Data.poussoir_vibrato_mono_chorus - Data.succ_nombre_de_curseurs ) <- !poussoir_mono ; aux Data.adresse_etat_clavier ( 128 + Data.poussoir_vibrato_mono_chorus ) !poussoir_mono ; let chaine = match !poussoir_mono with | 0 -> "son mono droit" | 1 -> "vibrato mono 1" | 2 -> "chorus mono 1" | 3 -> "vibrato mono 2" | 4 -> "chorus mono 2" | 5 -> "vibrato mono 3" | _ -> "chorus mono 3" in prerr_endline ( ( pourcent_cpu () ) ^ chaine ) ;; let pouss_mono = fun (poussoir_mono:int ref) (reglages:int array) (indice:int) -> if !poussoir_mono <> 0 then begin let chaine = ref "" in poussoir_mono := if !poussoir_mono mod 2 = 0 then ( chaine := "chorus" ; 2 * indice ) else ( chaine := "vibrato" ; pred ( 2 * indice ) ) ; reglages.(33) <- !poussoir_mono ; aux Data.adresse_etat_clavier ( 128 + Data.poussoir_vibrato_mono_chorus ) !poussoir_mono ; prerr_endline ( ( pourcent_cpu () ) ^ !chaine ^ " mono " ^ ( string_of_int indice ) ) end ;; let frein = fun (selection:select ref) (poussoir:int ref) (demi_lune:int ref) (reglages:int array) -> selection := Vibrato ; if !poussoir = 0 then poussoir := 1 ; demi_lune := 2 ; reglages.(32) <- !poussoir ; reglages.(34) <- !demi_lune ; aux Data.adresse_etat_clavier ( 128 + Data.poussoir_vibrato_chorus ) !poussoir ; aux Data.adresse_etat_clavier ( 128 + Data.demi_lune ) !demi_lune ; prerr_endline ( ( pourcent_cpu () ) ^ "vibrato frein" ) ;; let lent = fun (selection:select ref) (poussoir:int ref) (demi_lune:int ref) (reglages:int array) -> selection := Vibrato ; if !poussoir = 0 then poussoir := 1 ; demi_lune := 1 ; reglages.(32) <- !poussoir ; reglages.(34) <- !demi_lune ; aux Data.adresse_etat_clavier ( 128 + Data.poussoir_vibrato_chorus ) !poussoir ; aux Data.adresse_etat_clavier ( 128 + Data.demi_lune ) !demi_lune ; reglages.(Data.bouton_excursion_vibrato - Data.succ_nombre_de_curseurs) <- Data.excursion_vibrato_stereo ; reglages.(Data.bouton_diff_excursion_vibrato - Data.succ_nombre_de_curseurs) <- Data.diff_excursion_vibrato_stereo ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_excursion_vibrato ) Data.excursion_vibrato_stereo ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_excursion_vibrato ) Data.diff_excursion_vibrato_stereo ; reglages.(Data.bouton_dephasage_rotation - Data.succ_nombre_de_curseurs) <- Data.dephasage_rotation_vibrato_stereo ; reglages.(Data.bouton_diff_dephasage_rotation - Data.succ_nombre_de_curseurs) <- Data.diff_dephasage_rotation_vibrato_stereo ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_dephasage_rotation ) Data.dephasage_rotation_vibrato_stereo ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_dephasage_rotation ) Data.diff_dephasage_rotation_vibrato_stereo ; reglages.(Data.bouton_tremolo - Data.succ_nombre_de_curseurs) <- Data.tremolo_vibrato_stereo ; reglages.(Data.bouton_diff_tremolo - Data.succ_nombre_de_curseurs) <- Data.diff_tremolo_vibrato_stereo ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_tremolo ) Data.tremolo_vibrato_stereo ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_tremolo ) Data.diff_tremolo_vibrato_stereo ; prerr_endline ( ( pourcent_cpu () ) ^ "vibrato lent" ) ;; let rapide = fun (selection:select ref) (poussoir:int ref) (demi_lune:int ref) (reglages:int array) -> selection := Vibrato ; if !poussoir = 0 then poussoir := 1 ; demi_lune := 3 ; reglages.(32) <- !poussoir ; reglages.(34) <- !demi_lune ; aux Data.adresse_etat_clavier ( 128 + Data.poussoir_vibrato_chorus ) !poussoir ; aux Data.adresse_etat_clavier ( 128 + Data.demi_lune ) !demi_lune ; reglages.(Data.bouton_excursion_vibrato - Data.succ_nombre_de_curseurs) <- Data.excursion_vibrato_stereo ; reglages.(Data.bouton_diff_excursion_vibrato - Data.succ_nombre_de_curseurs) <- Data.diff_excursion_vibrato_stereo ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_excursion_vibrato ) Data.excursion_vibrato_stereo ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_excursion_vibrato ) Data.diff_excursion_vibrato_stereo ; reglages.(Data.bouton_dephasage_rotation - Data.succ_nombre_de_curseurs) <- Data.dephasage_rotation_vibrato_stereo ; reglages.(Data.bouton_diff_dephasage_rotation - Data.succ_nombre_de_curseurs) <- Data.diff_dephasage_rotation_vibrato_stereo ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_dephasage_rotation ) Data.dephasage_rotation_vibrato_stereo ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_dephasage_rotation ) Data.diff_dephasage_rotation_vibrato_stereo ; reglages.(Data.bouton_tremolo - Data.succ_nombre_de_curseurs) <- Data.tremolo_vibrato_stereo ; reglages.(Data.bouton_diff_tremolo - Data.succ_nombre_de_curseurs) <- Data.diff_tremolo_vibrato_stereo ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_tremolo ) Data.tremolo_vibrato_stereo ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_tremolo ) Data.diff_tremolo_vibrato_stereo ; prerr_endline ( ( pourcent_cpu () ) ^ "vibrato rapide" ) ;; let mono = fun (selection:select ref) (poussoir:int ref) (demi_lune:int ref) (reglages:int array) -> selection := Vibrato ; poussoir := 0 ; demi_lune := 0 ; reglages.(32) <- !poussoir ; reglages.(34) <- !demi_lune ; aux Data.adresse_etat_clavier ( 128 + Data.poussoir_vibrato_chorus ) !poussoir ; aux Data.adresse_etat_clavier ( 128 + Data.demi_lune ) !demi_lune ; prerr_endline ( ( pourcent_cpu () ) ^ "son droit" ) ;; let clic = fun (poussoir_clic:int ref) (reglages:int array) (valeurs_clic:int array) -> poussoir_clic := ( succ !poussoir_clic ) mod ( succ ( Array.length valeurs_clic / 2 ) ) ; match !poussoir_clic with | 0 -> begin reglages.(Data.bouton_niveau_clic - Data.succ_nombre_de_curseurs) <- 0 ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_clic ) 0 ; prerr_endline ( ( pourcent_cpu () ) ^ "arret du clic" ) ; end | x when x > 0 -> begin let i = ref ( 2 * ( pred x ) ) in reglages.(Data.bouton_niveau_clic - Data.succ_nombre_de_curseurs) <- valeurs_clic.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_clic ) valeurs_clic.(!i) ; incr i ; reglages.(Data.bouton_longueur_clic - Data.succ_nombre_de_curseurs) <- valeurs_clic.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_longueur_clic ) valeurs_clic.(!i) ; prerr_endline ( ( pourcent_cpu () ) ^ "clic " ^ ( string_of_int x ) ) ; end | _ -> () ;; let percu = fun (poussoir_percu:int ref) (reglages:int array) (valeurs_percu:int array) -> poussoir_percu := ( succ !poussoir_percu ) mod ( succ ( Array.length valeurs_percu / 4 ) ) ; match !poussoir_percu with | 0 -> begin reglages.(Data.bouton_niveau_percu - Data.succ_nombre_de_curseurs) <- 0 ; reglages.(Data.bouton_diff_niveau_percu - Data.succ_nombre_de_curseurs) <- 64 ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_percu ) 0 ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_niveau_percu ) 64 ; prerr_endline ( ( pourcent_cpu () ) ^ "arret de la percussion" ) ; end | x when x > 0 -> begin let i = ref ( 4 * ( pred x ) ) in reglages.(Data.bouton_niveau_percu - Data.succ_nombre_de_curseurs) <- valeurs_percu.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_percu ) valeurs_percu.(!i) ; incr i ; reglages.(Data.bouton_diff_niveau_percu - Data.succ_nombre_de_curseurs) <- valeurs_percu.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_niveau_percu ) valeurs_percu.(!i) ; incr i ; reglages.(Data.bouton_enveloppe_percu - Data.succ_nombre_de_curseurs) <- valeurs_percu.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_enveloppe_percu ) valeurs_percu.(!i) ; incr i ; reglages.(Data.bouton_diff_enveloppe_percu - Data.succ_nombre_de_curseurs) <- valeurs_percu.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_enveloppe_percu ) valeurs_percu.(!i) ; prerr_endline ( ( pourcent_cpu () ) ^ "percussion " ^ ( string_of_int x ) ) ; end | _ -> () ;; let reverb = fun (poussoir_reverb:int ref) (reglages:int array) (valeurs_reverb:int array) -> poussoir_reverb := ( succ !poussoir_reverb ) mod ( succ ( Array.length valeurs_reverb / 2 ) ) ; match !poussoir_reverb with | 0 -> begin reglages.(Data.bouton_niveau_reverb - Data.succ_nombre_de_curseurs) <- 0 ; reglages.(Data.bouton_delai_reverb - Data.succ_nombre_de_curseurs) <- 127 ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_reverb ) 0 ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_delai_reverb ) 127 ; prerr_endline ( ( pourcent_cpu () ) ^ "arret de la reverberation" ) ; end | x when x > 0 -> begin let i = ref ( 2 * ( pred x ) ) in reglages.(Data.bouton_niveau_reverb - Data.succ_nombre_de_curseurs) <- valeurs_reverb.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_reverb ) valeurs_reverb.(!i) ; incr i ; reglages.(Data.bouton_delai_reverb - Data.succ_nombre_de_curseurs) <- valeurs_reverb.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_delai_reverb ) valeurs_reverb.(!i) ; prerr_endline ( ( pourcent_cpu () ) ^ "reverberation " ^ ( string_of_int x ) ) ; end | _ -> () ;; let forme = fun (poussoir_forme:int ref) (reglages:int array) (valeurs_forme:int array) -> poussoir_forme := ( succ !poussoir_forme ) mod ( succ ( Array.length valeurs_forme / 6 ) ) ; match !poussoir_forme with | 0 -> begin reglages.(Data.bouton_niveau_inflexion - Data.succ_nombre_de_curseurs) <- 0 ; reglages.(Data.bouton_niveau_triangle - Data.succ_nombre_de_curseurs) <- 0 ; reglages.(Data.bouton_niveau_creneaux - Data.succ_nombre_de_curseurs) <- 0 ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_inflexion ) 0 ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_triangle ) 0 ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_creneaux ) 0 ; prerr_endline ( ( pourcent_cpu () ) ^ "forme sinus" ) ; end | x when x > 0 -> begin let i = ref ( 6 * ( pred x ) ) in reglages.(Data.bouton_niveau_inflexion - Data.succ_nombre_de_curseurs) <- valeurs_forme.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_inflexion ) valeurs_forme.(!i) ; incr i ; reglages.(Data.bouton_inflexion - Data.succ_nombre_de_curseurs) <- valeurs_forme.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_inflexion ) valeurs_forme.(!i) ; incr i ; reglages.(Data.bouton_dephasage_inflexion - Data.succ_nombre_de_curseurs) <- valeurs_forme.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_dephasage_inflexion ) valeurs_forme.(!i) ; incr i ; reglages.(Data.bouton_niveau_triangle - Data.succ_nombre_de_curseurs) <- valeurs_forme.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_triangle ) valeurs_forme.(!i) ; incr i ; reglages.(Data.bouton_niveau_creneaux - Data.succ_nombre_de_curseurs) <- valeurs_forme.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_creneaux ) valeurs_forme.(!i) ; incr i ; reglages.(Data.bouton_dephasage_creneaux - Data.succ_nombre_de_curseurs) <- valeurs_forme.(!i) ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_dephasage_creneaux ) valeurs_forme.(!i) ; prerr_endline ( ( pourcent_cpu () ) ^ "forme " ^ ( string_of_int x ) ) ; end | _ -> () ;; (** {1 Foncteur d'absorption des données des fabricants} *) module type Type_clavier = sig val nom_clavier : string ;; (** Prend la valeur [true] si la pédale sustain donne 0 à l'enfoncement et 127 au relâchement ; [false] dans le cas inverse. *) val tenue : bool ;; val alter_swell : int ;; val alter_modulation : int ;; val curseur_0 : int ;; val curseur_1 : int ;; val curseur_2 : int ;; val curseur_3 : int ;; val curseur_4 : int ;; val curseur_5 : int ;; val curseur_6 : int ;; val curseur_7 : int ;; val curseur_8 : int ;; val curseur_9 : int ;; val bouton_1 : int ;; val bouton_2 : int ;; val bouton_3 : int ;; val bouton_4 : int ;; val bouton_5 : int ;; val bouton_6 : int ;; val bouton_7 : int ;; val bouton_8 : int ;; val bouton_8bis : int ;; val bouton_p1 : int ;; val bouton_p2 : int ;; val bouton_p3 : int ;; val bouton_p4 : int ;; val bouton_p5 : int ;; val bouton_p6 : int ;; val bouton_p7 : int ;; val bouton_p8 : int ;; val bouton_p9 : int ;; val bouton_p10 : int ;; val poussoir_boucle : int ;; val poussoir_rembobine : int ;; val poussoir_avance_rapide : int ;; val poussoir_arret : int ;; val poussoir_lecture : int ;; val poussoir_enregistrement : int ;; val poussoir_debut : int ;; val poussoir_fin : int ;; val poussoir_1 : int ;; val poussoir_2 : int ;; val poussoir_3 : int ;; val poussoir_4 : int ;; val poussoir_5 : int ;; val poussoir_6 : int ;; val poussoir_7 : int ;; val poussoir_8 : int ;; val poussoir_9 : int ;; val poussoir_10 : int ;; val poussoir_11 : int ;; val poussoir_12 : int ;; val pad_5 : int ;; val pad_6 : int ;; val pad_7 : int ;; val pad_8 : int ;; val vers_instru : int ;; val pad1 : int ;; val pad2 : int ;; val pad3 : int ;; val pad4 : int ;; val pad5 : int ;; val pad6 : int ;; val pad7 : int ;; val pad8 : int ;; end ;; module Make ( C:Type_clavier ) = struct let masque_entete = 0xF0 ;; let numero_de_canal = 0x0F ;; (** Note off event *) let touche_relachee = 0x80 ;; (** Note on event *) let touche_appuyee = 0x90 ;; (** Polyphonic key pressure/aftertouch *) let poly_press = 0xA0 ;; (** Controle change *) let mode = 0xB0 ;; (** Program change *) let instru = 0xC0 ;; (** Channel pressure/aftertouch *) let can_press = 0xD0 ;; (** Pitch bend change. La molette de pitch est centrée sur la valeur 64. *) let pitch = 0xE0 ;; let pitch_mot_vide = 0x00 (** System messages *) let sys = 0xF0 ;; (** {1 Numéros de modes} *) let modulation = 0x01 ;; let swell = 0x0B ;; (** Prend la valeur 0 à l'enfoncement et 127 au relâchement pour le réglage habituel : court-circuit au repos, pour une source M-audio ou Alesis. Pour une source Roland, c'est l'inverse. Les valeurs sont échangées pour le réglage inverse de la pédale. *) let sustain_pedal = 0x40 ;; (** {1 Scrutation de l'entrée MIDI} *) let scrute = fun ic -> let oc = open_out Data.adresse_etat_clavier and tirettes = Array.make 9 0 and facteur_decalage = Data.nombre_de_parametres_clavier - Data.succ_nombre_de_curseurs and pred_facteur_decalage = Data.nombre_de_parametres_clavier - Data.succ_nombre_de_curseurs - 1 and poussoir = ref 0 and poussoir_mono = ref 0 and poussoir_clic = ref 0 and valeurs_clic = Data.valeurs_clic and poussoir_percu = ref 0 and valeurs_percu = Data.valeurs_percu and poussoir_reverb = ref 0 and valeurs_reverb = Data.valeurs_reverb and poussoir_forme = ref 0 and valeurs_forme = Data.valeurs_forme and demi_lune = ref 0 and c = ref 0 and entete = ref 0 and canal = ref 0 and note = ref 0 and controleur = ref 0 and decalage = ref 0 and selection = ref Vide in let reglages = Array.make facteur_decalage 0 in for i = 0 to 127 do output_byte oc haut ; done ; (** pitch *) output_byte oc milieu ; (** tirettes : modulation et curseurs *) for i = 0 to 8 do output_byte oc plein ; done ; (** bouton rotatifs swell et saturation *) for i = 0 to 1 do output_byte oc vide ; done ; (** bouton rotatif inflexion *) output_byte oc milieu ; (** boutons rotatifs *) for i = 3 to 8 do output_byte oc vide ; done ; (** bouton rotatifs différence grave-aigu pour enveloppe et niveau de percussion *) for i = 9 to 10 do output_byte oc milieu ; done ; (** boutons rotatifs *) for i = 11 to 15 do output_byte oc vide ; done ; (** bouton rotatif différence de déphasage grave-aigu pour la rotation *) output_byte oc milieu ; (** boutons rotatifs *) for i = 17 to 19 do output_byte oc vide ; done ; (** bouton rotatif diapason *) output_byte oc milieu ; (** bouton rotatif octave *) output_byte oc vide ; (** bouton rotatif rose *) output_byte oc milieu ; (** boutons rotatifs *) for i = 23 to 24 do output_byte oc vide ; done ; (** bouton rotatif équilibre *) output_byte oc milieu ; (** boutons rotatifs *) for i = 26 to 31 do output_byte oc vide ; done ; (** poussoirs boucles *) for i = 32 to 33 do output_byte oc vide ; done ; (** demi-lune *) output_byte oc vide ; close_out_noerr oc ; begin try while true do c := input_byte ic ; entete := !c land masque_entete ; canal := !c land numero_de_canal ; match !entete with | x when x = touche_appuyee -> begin note := input_byte ic ; (** vélocité *) c := input_byte ic ; if !c > 0 then begin if !canal = 9 then begin match !note with | z when z = C.pad1 -> begin if !selection = Special then begin pouss_mono poussoir_mono reglages 1 ; selection := Special ; end else if !selection = Lecture then clic poussoir_clic reglages valeurs_clic else lent selection poussoir demi_lune reglages end | z when z = C.pad2 -> begin if !selection = Special then begin pouss_mono poussoir_mono reglages 2 ; selection := Special ; end else if !selection = Lecture then percu poussoir_percu reglages valeurs_percu else frein selection poussoir demi_lune reglages end | z when z = C.pad3 -> begin if !selection = Special then begin pouss_mono poussoir_mono reglages 3 ; selection := Special ; end else if !selection = Lecture then reverb poussoir_reverb reglages valeurs_reverb else rapide selection poussoir demi_lune reglages end | z when z = C.pad4 -> begin if !selection = Special then begin vc poussoir_mono reglages ; selection := Special ; end else if !selection = Lecture then forme poussoir_forme reglages valeurs_forme else mono selection poussoir demi_lune reglages end | z when z = C.pad5 -> clic poussoir_clic reglages valeurs_clic | z when z = C.pad6 -> percu poussoir_percu reglages valeurs_percu | z when z = C.pad7 -> reverb poussoir_reverb reglages valeurs_reverb | z when z = C.pad8 -> forme poussoir_forme reglages valeurs_forme | _ -> () ; end else match !selection with | Rappel -> begin selection := Vide ; let ict = open_in_gen [Open_binary ; Open_rdonly] 0o400 Data.adresse_etat_jeux in decalage := 9 * !note ; seek_in ict !decalage ; for i = 0 to 8 do tirettes.(i) <- input_byte ict ; done ; close_in_noerr ict ; let oc = open_out_gen [Open_binary ; Open_wronly] 0o644 Data.adresse_etat_clavier in seek_out oc 129 ; for i = 0 to 8 do output_byte oc tirettes.(i) ; done ; flush_all () ; close_out_noerr oc ; prerr_int !note ; prerr_newline () ; prerr_endline ( ( pourcent_cpu () ) ^ "mode vide" ) ; end | Rappel_boutons -> ( selection := Vide ; rappel_boutons decalage pred_facteur_decalage facteur_decalage reglages !note ) | Sauvegarde -> begin selection := Vide ; let oc = open_out_gen [Open_binary ; Open_wronly] 0o644 Data.adresse_etat_jeux in decalage := 9 * !note ; seek_out oc !decalage ; for i = 0 to 8 do output_byte oc tirettes.(i) ; done ; flush_all () ; close_out_noerr oc ; prerr_int !note ; prerr_newline () ; prerr_endline ( ( pourcent_cpu () ) ^ "mode vide" ) ; end | Sauvegarde_boutons -> ( selection := Vide ; sauvegarde_boutons decalage pred_facteur_decalage facteur_decalage reglages !note ) | _ -> aux Data.adresse_etat_clavier !note bas ; end (** vélocité nulle *) else if !canal <> 9 then aux Data.adresse_etat_clavier !note haut ; end | x when x = touche_relachee -> begin note := input_byte ic ; (** vélocité *) c := input_byte ic ; if !canal <> 9 then aux Data.adresse_etat_clavier !note haut ; end | x when x = pitch -> begin (** valeur nulle *) c := input_byte ic ; c := input_byte ic ; aux Data.adresse_etat_clavier 128 !c ; end | x when x = mode -> begin controleur := input_byte ic ; (** valeur *) c := input_byte ic ; match !controleur with (** all notes off *) | y when ( 123 <= y ) && ( y <= 127 ) -> begin let oc = open_out_gen [Open_binary ; Open_wronly] 0o644 Data.adresse_etat_clavier and chaine = String.make 128 ( char_of_int haut ) in output oc chaine 0 128 ; flush_all () ; close_out_noerr oc ; end (** boutons curseurs *) | y when y = C.curseur_1 -> begin tirettes.(0) <- !c ; aux Data.adresse_etat_clavier 129 !c ; end | y when y = C.curseur_2 -> begin tirettes.(1) <- !c ; aux Data.adresse_etat_clavier 130 !c ; end | y when y = C.curseur_3 -> begin tirettes.(2) <- !c ; aux Data.adresse_etat_clavier 131 !c ; end | y when y = C.curseur_4 -> begin tirettes.(3) <- !c ; aux Data.adresse_etat_clavier 132 !c ; end | y when y = C.curseur_5 -> begin tirettes.(4) <- !c ; aux Data.adresse_etat_clavier 133 !c ; end | y when y = C.curseur_6 -> begin tirettes.(5) <- !c ; aux Data.adresse_etat_clavier 134 !c ; end | y when y = C.curseur_7 -> begin tirettes.(6) <- !c ; aux Data.adresse_etat_clavier 135 !c ; end | y when y = C.curseur_8 -> begin tirettes.(7) <- !c ; aux Data.adresse_etat_clavier 136 !c ; end | y when y = C.curseur_9 -> begin tirettes.(8) <- !c ; aux Data.adresse_etat_clavier 137 !c ; end (** swell *) | y when y = C.bouton_1 || y = swell || y = C.alter_swell || y = C.alter_modulation -> begin reglages.(0) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_swell ) !c end (** saturation *) | y when y = C.bouton_8 || y = C.bouton_p10 -> begin reglages.(1) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_saturation ) !c end (** boutons rotatifs *) | y when y = C.bouton_2 || y = C.bouton_p1 -> begin match !selection with | Forme -> ( reglages.(2) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_inflexion ) !c ) | Percussion -> ( reglages.(8) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_longueur_clic ) !c ) | Vibrato -> ( reglages.(14) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_excursion_vibrato ) !c ) | Filtrage -> ( reglages.(20) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diapason ) !c ) | Reverb -> ( reglages.(26) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_delai_reverb ) !c ) | _ -> () ; end | y when y = C.bouton_3 || y = C.bouton_p2 -> begin match !selection with | Forme -> ( reglages.(3) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_dephasage_inflexion ) !c ) | Percussion -> ( reglages.(9) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_enveloppe_percu ) !c ) | Vibrato -> ( reglages.(15) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_basse_frequence ) !c ) | Filtrage -> ( reglages.(21) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_octave ) !c ) | Reverb -> ( reglages.(27) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_pli_haut ) !c ) | _ -> () ; end | y when y = C.bouton_4 || y = C.bouton_p3 -> begin match !selection with | Forme -> ( reglages.(4) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_dephasage_creneaux ) !c ) | Percussion -> ( reglages.(10) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_niveau_percu ) !c ) | Vibrato -> ( reglages.(16) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_dephasage_rotation ) !c ) | Filtrage -> ( reglages.(22) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_rose ) !c ) | Reverb -> ( reglages.(28) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_tremolo ) !c ) | _ -> () ; end | y when y = C.bouton_5 || y = C.bouton_p6 -> begin match !selection with | Forme -> ( reglages.(5) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_inflexion ) !c ) | Percussion -> ( reglages.(11) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_clic ) !c ) | Vibrato -> ( reglages.(17) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_excursion_vibrato ) !c ) | Filtrage -> ( reglages.(23) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_coupure ) !c ) | Reverb -> ( reglages.(29) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_reverb ) !c ) | _ -> () ; end | y when y = C.bouton_6 || y = C.bouton_p7 -> begin match !selection with | Forme -> ( reglages.(6) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_triangle ) !c ) | Percussion -> ( reglages.(12) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_enveloppe_percu ) !c ) | Vibrato -> ( reglages.(18) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_basse_frequence ) !c ) | Filtrage -> ( reglages.(24) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_timbre ) !c ) | Reverb -> ( reglages.(30) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_pli_bas ) !c ) | _ -> () ; end | y when y = C.bouton_7 || y = C.bouton_p8 -> begin match !selection with | Forme -> ( reglages.(7) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_creneaux ) !c ) | Percussion -> ( reglages.(13) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_percu ) !c ) | Vibrato -> ( reglages.(19) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_dephasage_rotation ) !c ) | Filtrage -> ( reglages.(25) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_equilibre ) !c ) | Reverb -> ( reglages.(31) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_tremolo ) !c ) | _ -> () ; end | y when y = C.bouton_8bis || y = C.curseur_0 -> begin if !selection = Special then begin let position = ( min 125 !c ) / 18 in if !poussoir_mono <> position then begin poussoir_mono := ( 6 + position ) mod 7 ; vc poussoir_mono reglages ; end ; end else begin let position = !c / 32 in if !demi_lune <> position then match position with | 0 -> mono selection poussoir demi_lune reglages | 1 -> lent selection poussoir demi_lune reglages | 2 -> frein selection poussoir demi_lune reglages | _ -> rapide selection poussoir demi_lune reglages end end (** Les claviers Arturia offrent plus de boutons. *) | y when y = C.bouton_p4 -> begin match !selection with | Percussion -> ( reglages.(26) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_delai_reverb ) !c ) | Vibrato -> ( reglages.(28) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diff_tremolo ) !c ) | Forme -> ( reglages.(20) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_diapason ) !c ) | Filtrage -> ( reglages.(27) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_pli_haut ) !c ) | _ -> () ; end | y when y = C.bouton_p5 -> begin match !selection with | Vibrato -> ( reglages.(25) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_equilibre ) !c ) | Percussion -> ( reglages.(23) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_coupure ) !c ) | Forme -> ( reglages.(22) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_rose ) !c ) | _ -> () ; end | y when y = C.bouton_p9 -> begin match !selection with | Percussion -> ( reglages.(29) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_niveau_reverb ) !c ) | Vibrato -> ( reglages.(31) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_tremolo ) !c ) | Forme -> ( reglages.(24) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_timbre ) !c ) | Filtrage -> ( reglages.(30) <- !c ; aux Data.adresse_etat_clavier ( 128 + Data.bouton_pli_bas ) !c ) | _ -> () ; end (** Les claviers Arturia offrent des coussinets percussifs (pads) qui envoient des trains de messages de contrôleurs. Un unique mot par manipulation du coussinet contient la valeur 0. *) | y when y = C.pad_5 && !c = 0 -> clic poussoir_clic reglages valeurs_clic | y when y = C.pad_6 && !c = 0 -> percu poussoir_percu reglages valeurs_percu | y when y = C.pad_7 && !c = 0 -> reverb poussoir_reverb reglages valeurs_reverb | y when y = C.pad_8 && !c = 0 -> forme poussoir_forme reglages valeurs_forme (** boutons-poussoirs de transport *) | y when y = C.poussoir_boucle -> begin if !c > 0 then begin if !selection = Rembobine then begin prerr_endline "L'orgue est arrete." ; ignore ( Sys.command ( "killall ORGUE & killall " ^ C.nom_clavier ) ) ; end else if !selection = Special then begin selection := Reverb ; prerr_endline ( ( pourcent_cpu () ) ^ "mode reverberation" ) ; end else if !selection = Lecture then vc poussoir_mono reglages else begin selection := Vibrato ; demi_lune := 0 ; poussoir := ( succ !poussoir ) mod Data.modulo_vibrato ; reglages.(32) <- !poussoir ; reglages.(34) <- !demi_lune ; aux Data.adresse_etat_clavier ( 128 + Data.poussoir_vibrato_chorus ) !poussoir ; aux Data.adresse_etat_clavier ( 128 + Data.demi_lune ) !demi_lune ; let chaine = match !poussoir with | 0 -> "son droit" | 1 -> "vibrato" | _ -> "chorus" in prerr_endline ( ( pourcent_cpu () ) ^ chaine ) ; end ; end ; end | y when y = C.poussoir_rembobine -> begin if !c > 0 then begin if !selection = Avance_rapide then begin selection := Rembobine ; prerr_endline "Arret de l'orgue : taper sur BOUCLE." ; end else if !selection = Special then begin selection := Rappel_boutons ; prerr_endline ( ( pourcent_cpu () ) ^ "rappel de reglages" ) ; end else begin selection := Rappel ; prerr_endline ( ( pourcent_cpu () ) ^ "rappel de jeux" ) ; end end end | y when y = C.poussoir_avance_rapide -> begin if !c > 0 then begin if !selection = Arret then begin selection := Avance_rapide ; prerr_endline "Arret de l'orgue : taper sur REMBOBINAGE." ; end else if !selection = Special then begin selection := Sauvegarde_boutons ; prerr_endline ( ( pourcent_cpu () ) ^ "enregistrement de reglages" ) ; end else begin selection := Sauvegarde ; prerr_endline ( ( pourcent_cpu () ) ^ "enregistrement de jeux" ) ; end end end | y when y = C.poussoir_debut -> if !c > 0 then demande_rappel_boutons selection ; | y when y = C.poussoir_fin -> if !c > 0 then demande_sauvegarde_boutons selection ; | y when y = C.poussoir_arret -> begin if !c > 0 then begin if !selection = Lecture then begin selection := Arret ; prerr_endline "Arret de l'orgue : taper sur AVANCE RAPIDE." ; end else if !selection = Special then begin selection := Filtrage ; prerr_endline ( ( pourcent_cpu () ) ^ "mode filtrage-equilibrage" ) ; end else begin selection := Forme ; prerr_endline ( ( pourcent_cpu () ) ^ "mode forme" ) ; end end end | y when y = C.poussoir_lecture -> begin if !c > 0 then begin if !selection = Special then begin selection := Lecture ; prerr_endline ( ( pourcent_cpu () ) ^ "Mode lecture.\n Arret de l'orgue : taper sur ARRET.\n Vibrato/chorus mono 1, 2 ou 3 : taper sur BOUCLE.\n Clic : Pad1 ou bouton-poussoir 1 ; percussion : Pad2 ou bouton-poussoir 2 ; reverberation : Pad3 ou bouton-poussoir 3 ; forme : Pad4 ou bouton-poussoir 4." ) ; end else begin selection := Percussion ; prerr_endline ( ( pourcent_cpu () ) ^ "mode percussion" ) ; end end end | y when y = C.poussoir_enregistrement -> if !c > 0 then begin if !selection = Special then begin selection := Vide ; prerr_endline ( ( pourcent_cpu () ) ^ "mode vide" ) ; end else begin selection := Special ; prerr_endline ( ( pourcent_cpu () ) ^ "mode special" ) ; end end (** boutons-poussoirs numérotés *) | y when y = C.poussoir_4 -> begin if !c > 0 then begin if !selection = Special then begin mono selection poussoir demi_lune reglages ; selection := Special ; end else if !selection = Lecture then forme poussoir_forme reglages valeurs_forme else vc poussoir_mono reglages end end | y when y = C.poussoir_1 -> begin if !c > 0 then begin if !selection = Special then begin lent selection poussoir demi_lune reglages ; selection := Special ; end else if !selection = Lecture then clic poussoir_clic reglages valeurs_clic else pouss_mono poussoir_mono reglages 1 end end | y when y = C.poussoir_2 -> begin if !c > 0 then begin if !selection = Special then begin frein selection poussoir demi_lune reglages ; selection := Special ; end else if !selection = Lecture then percu poussoir_percu reglages valeurs_percu else pouss_mono poussoir_mono reglages 2 end end | y when y = C.poussoir_3 -> begin if !c > 0 then begin if !selection = Special then begin rapide selection poussoir demi_lune reglages ; selection := Special ; end else if !selection = Lecture then reverb poussoir_reverb reglages valeurs_reverb else pouss_mono poussoir_mono reglages 3 end end | y when y = C.poussoir_5 -> begin if !c > 0 then clic poussoir_clic reglages valeurs_clic end | y when y = C.poussoir_6 -> begin if !c > 0 then percu poussoir_percu reglages valeurs_percu end | y when y = C.poussoir_7 -> begin if !c > 0 then reverb poussoir_reverb reglages valeurs_reverb end | y when y = C.poussoir_8 -> begin if !c > 0 then forme poussoir_forme reglages valeurs_forme end | _ -> () end | x when x = instru -> begin c := input_byte ic ; match !c with | 0 -> begin if !selection = Special then begin lent selection poussoir demi_lune reglages ; selection := Special ; end else if !selection = Lecture then clic poussoir_clic reglages valeurs_clic else pouss_mono poussoir_mono reglages 1 end | 1 -> begin if !selection = Special then begin frein selection poussoir demi_lune reglages ; selection := Special ; end else if !selection = Lecture then percu poussoir_percu reglages valeurs_percu else pouss_mono poussoir_mono reglages 2 end | 2 -> begin if !selection = Special then begin rapide selection poussoir demi_lune reglages ; selection := Special ; end else if !selection = Lecture then reverb poussoir_reverb reglages valeurs_reverb else pouss_mono poussoir_mono reglages 3 end | 3 -> begin if !selection = Special then begin mono selection poussoir demi_lune reglages ; selection := Special ; end else if !selection = Lecture then forme poussoir_forme reglages valeurs_forme else vc poussoir_mono reglages end | 4 -> clic poussoir_clic reglages valeurs_clic | 5 -> percu poussoir_percu reglages valeurs_percu | 6 -> reverb poussoir_reverb reglages valeurs_reverb | 7 -> demande_rappel_boutons selection | 8 -> demande_sauvegarde_boutons selection | _ -> () ; end | _ -> () done with End_of_file -> close_in_noerr ic ; end ; Sys.remove Data.adresse_etat_clavier ;; end ;; end ;; module Alesis = struct (** {1 Liste de claviers testés} + Alesis QX49 {v Détection sous FreeBSD : ugen0.2: at usbus0 uaudio0: on usbus0 uaudio0: No playback. uaudio0: No recording. uaudio0: MIDI sequencer. uaudio0: No HID volume keys found. v} Pour assigner le canal MIDI numéro 9 aux coussinets percussifs (pads), procéder comme suit : - appuyer sur [ADVANCED] - appuyer sur [CHAN ASSIGN] - appuyer sur [P1] - appuyer sur [1] - appuyer sur [0] - appuyer sur [ENTER] - appuyer sur [CHAN ASSIGN] - appuyer sur [P2] - appuyer sur [1] - appuyer sur [0] - appuyer sur [ENTER] - appuyer sur [CHAN ASSIGN] - appuyer sur [P3] - appuyer sur [1] - appuyer sur [0] - appuyer sur [ENTER] - appuyer sur [CHAN ASSIGN] - appuyer sur [P4] - appuyer sur [1] - appuyer sur [0] - appuyer sur [ENTER] - appuyer sur [ADVANCED] {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.8} @version 0.8 @author Stéphane Grognet @since 2014 *) let nom_clavier = "CLAVIERs" ;; let tenue = true ;; let curseur1 = 0x16 ;; let curseur2 = 0x17 ;; let curseur3 = 0x18 ;; let curseur4 = 0x19 ;; let curseur5 = 0x1A ;; let curseur6 = 0x1B ;; let curseur7 = 0x1C ;; let curseur8 = 0x1D ;; (** molette de modulation puisqu'il n'y a que huit curseurs *) let curseur_1 = 0x01 ;; let curseur_2 = curseur1 ;; let curseur_3 = curseur2 ;; let curseur_4 = curseur3 ;; let curseur_5 = curseur4 ;; let curseur_6 = curseur5 ;; let curseur_7 = curseur6 ;; let curseur_8 = curseur7 ;; let curseur_9 = curseur8 ;; let bouton_1 = 0x0E ;; let bouton_2 = 0x0F ;; let bouton_3 = 0x10 ;; let bouton_4 = 0x11 ;; let bouton_5 = 0x12 ;; let bouton_6 = 0x13 ;; let bouton_7 = 0x14 ;; let bouton_8 = 0x15 ;; let alter_swell = bouton_1 ;; (** Les valeurs des boutons-poussoirs prennent les valeurs 127 à l'enfoncement et 0 au relâchement. *) let poussoir_boucle = 0x77 ;; let poussoir_rembobine = 0x76 ;; let poussoir_avance_rapide = 0x75 ;; let poussoir_arret = 0x72 ;; let poussoir_lecture = 0x73 ;; let poussoir_enregistrement = 0x74 ;; (** Valeurs absentes *) let curseur_0 = 0xFF ;; let poussoir_debut = 0xFF ;; let poussoir_fin = 0xFF ;; let bouton_8bis = 0xFF ;; let bouton_p1 = 0xFF ;; let bouton_p2 = 0xFF ;; let bouton_p3 = 0xFF ;; let bouton_p4 = 0xFF ;; let bouton_p5 = 0xFF ;; let bouton_p6 = 0xFF ;; let bouton_p7 = 0xFF ;; let bouton_p8 = 0xFF ;; let bouton_p9 = 0xFF ;; let bouton_p10 = 0xFF ;; let alter_modulation = 0xFF ;; let poussoir_1 = 0xFF ;; let poussoir_2 = 0xFF ;; let poussoir_3 = 0xFF ;; let poussoir_4 = 0xFF ;; let poussoir_5 = 0xFF ;; let poussoir_6 = 0xFF ;; let poussoir_7 = 0xFF ;; let poussoir_8 = 0xFF ;; let poussoir_9 = 0xFF ;; let poussoir_10 = 0xFF ;; let poussoir_11 = 0xFF ;; let poussoir_12 = 0xFF ;; let vers_instru = 0xFF ;; let pad_5 = 0xFF ;; let pad_6 = 0xFF ;; let pad_7 = 0xFF ;; let pad_8 = 0xFF ;; (** Coussinets percussifs. Par défaut ce sont des notes envoyées sur le canal MIDI 0x00. *) let pad1 = 0x30 ;; let pad2 = 0x31 ;; let pad3 = 0x32 ;; let pad4 = 0x33 ;; (** Valeurs absentes *) let pad5 = 0xFF ;; let pad6 = 0xFF ;; let pad7 = 0xFF ;; let pad8 = 0xFF ;; end ;; module Arturia = struct (** {1 Liste de claviers testés} + Arturia keylab61 {v Détection sous FreeBSD : ugen0.2: at usbus0 uaudio0: on usbus0 uaudio0: No playback. uaudio0: No recording. uaudio0: MIDI sequencer. uaudio0: No HID volume keys found. v} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.8} @version 0.8 @author Stéphane Grognet @since 2014 *) let nom_clavier = "CLAVIERa" ;; let tenue = true ;; let curseur_1 = 0x49 ;; let curseur_2 = 0x4B ;; let curseur_3 = 0x4F ;; let curseur_4 = 0x48 ;; let curseur_5 = 0x50 ;; let curseur_6 = 0x51 ;; let curseur_7 = 0x52 ;; let curseur_8 = 0x53 ;; let curseur_9 = 0x55 ;; let bouton1 = 0x4A ;; let bouton2 = 0x47 ;; let bouton3 = 0x4C ;; let bouton4 = 0x4D ;; let bouton5 = 0x5D ;; let bouton6 = 0x12 ;; let bouton7 = 0x13 ;; let bouton8 = 0x10 ;; let bouton9 = 0x11 ;; let boutonA = 0x5B ;; let bouton_p1 = bouton1 ;; let bouton_p2 = bouton2 ;; let bouton_p3 = bouton3 ;; let bouton_p4 = bouton4 ;; let bouton_p5 = bouton5 ;; let bouton_p6 = bouton6 ;; let bouton_p7 = bouton7 ;; let bouton_p8 = bouton8 ;; let bouton_p9 = bouton9 ;; let bouton_p10 = boutonA ;; let alter_swell = 0x07 ;; let alter_modulation = 0x01 ;; (** Les valeurs des boutons-poussoirs prennent les valeurs 127 à l'enfoncement et 0 au relâchement. *) let poussoir_boucle = 0x37 ;; let poussoir_rembobine = 0x35 ;; let poussoir_avance_rapide = 0x34 ;; let poussoir_arret = 0x33 ;; let poussoir_lecture = 0x36 ;; let poussoir_enregistrement = 0x32 ;; (** Boutons-poussoirs spécifiques *) let sound = 0x76 ;; let multi = 0x77 ;; let bank_1 = 0x2f ;; let bank_2 = 0x2e ;; let prog_chng = 0x16 ;; let recall = 0x17 ;; let store = 0x18 ;; let global = 0x19 ;; let curve = 0X1A ;; let mode = 0x1B ;; let midi_ch = 0x1C ;; let cc = 0x1D ;; let min_lsb = 0x1E ;; let max_msb = 0x1F ;; let poussoir_debut = sound ;; let poussoir_fin = multi ;; (** Pads considérés comme des contrôleurs. Le problème est qu'ils envoient des trains de messages interminables. Il faut isoler le mot qui contient la valeur 0. Apparemment, il y en a exactement un par manipulation du bouton (au relâchement ?). *) let pad_5 = 0x28 ;; let pad_6 = 0x29 ;; let pad_7 = 0x2a ;; let pad_8 = 0x2b ;; let pad_9 = 0x38 ;; let pad_10 = 0x39 ;; let pad_11 = 0x3a ;; let pad_12 = 0x3b ;; let pad_13 = 0x3c ;; let pad_14 = 0x3d ;; let pad_15 = 0x3e ;; let pad_16 = 0x3f ;; (** Poussoirs numérotés *) let poussoir_1 = prog_chng ;; let poussoir_2 = recall ;; let poussoir_3 = store ;; let poussoir_4 = global ;; let poussoir_5 = curve ;; let poussoir_6 = mode ;; let poussoir_7 = midi_ch ;; let poussoir_8 = cc ;; let poussoir_9 = min_lsb ;; let poussoir_10 = max_msb ;; let poussoir_11 = bank_1 ;; let poussoir_12 = bank_2 ;; (** Valeurs absentes *) let curseur_0 = 0xFF ;; let bouton_8bis = 0xFF ;; let bouton_1 = 0xFF ;; let bouton_2 = 0xFF ;; let bouton_3 = 0xFF ;; let bouton_4 = 0xFF ;; let bouton_5 = 0xFF ;; let bouton_6 = 0xFF ;; let bouton_7 = 0xFF ;; let bouton_8 = 0xFF ;; let vers_instru = 0xFF ;; (** Coussinets percussifs. Par défaut ce sont des notes envoyées sur le canal MIDI 0x09. *) let pad1 = 0x7c ;; let pad2 = 0x7d ;; let pad3 = 0x7e ;; let pad4 = 0x7f ;; (** Valeurs absentes *) let pad5 = 0xFF ;; let pad6 = 0xFF ;; let pad7 = 0xFF ;; let pad8 = 0xFF ;; end ;; module M_audio = struct (** {1 Liste de claviers testés} + M-audio Oxygen 49 {v Détection sous FreeBSD : ugen0.2: at usbus0 uaudio0: on usbus0 uaudio0: No playback. uaudio0: No recording. uaudio0: MIDI sequencer. uaudio0: No HID volume keys found. v} + M-audio Axiom 61 {v Détection sous FreeBSD : ugen0.2: at usbus0 uaudio0: on usbus0 uaudio0: No playback. uaudio0: No recording. uaudio0: MIDI sequencer. uaudio0: No HID volume keys found. v} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.8} @version 0.8 @author Stéphane Grognet @since 2014 *) let nom_clavier = "CLAVIERm" ;; let tenue = true ;; let curseur_1 = 0x4A ;; let curseur_2 = 0x47 ;; let curseur_3 = 0x5B ;; let curseur_4 = 0x5D ;; let curseur_5 = 0x49 ;; let curseur_6 = 0x48 ;; let curseur_7 = 0x05 ;; let curseur_8 = 0x54 ;; let curseur_9 = 0x07 ;; let bouton_1 = 0x4B ;; let bouton_2 = 0x4C ;; let bouton_3 = 0x5C ;; let bouton_4 = 0x5F ;; let bouton_5 = 0x0A ;; let bouton_6 = 0x4D ;; let bouton_7 = 0x4E ;; let bouton_8 = 0x4F ;; let alter_swell = 0x01 ;; let alter_modulation = 0x01 ;; (** Les boutons-poussoirs sont branchés sur le dernier canal MIDI par défaut (mode 0xBF). Les valeurs des boutons-poussoirs prennent les valeurs 127 à l'enfoncement et 0 au relâchement. *) let poussoir_boucle = 0x71 ;; let poussoir_rembobine = 0x72 ;; let poussoir_avance_rapide = 0x73 ;; let poussoir_arret = 0x74 ;; let poussoir_lecture = 0x75 ;; let poussoir_enregistrement = 0x76 ;; (** Oxygen 49 : les boutons TRACK [<] et [>] donnent des contrôleurs sur le dernier canal midi avec la valeur 127 à l'enfoncement et 0 eu relâchement. *) let track_moins = 0x6E ;; let track_plus = 0x6F ;; let poussoir_debut = track_moins ;; let poussoir_fin = track_plus ;; (** Contrôleur particulier : voir plus bas. *) let vers_instru = 0x20 ;; (** Valeurs absentes *) let curseur_0 = 0xFF ;; let bouton_8bis = 0xFF ;; let bouton_p1 = 0xFF ;; let bouton_p2 = 0xFF ;; let bouton_p3 = 0xFF ;; let bouton_p4 = 0xFF ;; let bouton_p5 = 0xFF ;; let bouton_p6 = 0xFF ;; let bouton_p7 = 0xFF ;; let bouton_p8 = 0xFF ;; let bouton_p9 = 0xFF ;; let bouton_p10 = 0xFF ;; let poussoir_1 = 0xFF ;; let poussoir_2 = 0xFF ;; let poussoir_3 = 0xFF ;; let poussoir_4 = 0xFF ;; let poussoir_5 = 0xFF ;; let poussoir_6 = 0xFF ;; let poussoir_7 = 0xFF ;; let poussoir_8 = 0xFF ;; let poussoir_9 = 0xFF ;; let poussoir_10 = 0xFF ;; let poussoir_11 = 0xFF ;; let poussoir_12 = 0xFF ;; let pad_5 = 0xFF ;; let pad_6 = 0xFF ;; let pad_7 = 0xFF ;; let pad_8 = 0xFF ;; (** Poussoirs particuliers. Les neuf boutons poussoirs situés sous les curseurs envoient les signaux MIDI suivants : b0 00 00 b0 20 00 c0 0X avec X = 0 à 8. Ces signaux sont envoyés seulement à l'enfoncement et rien n'est envoyé au relâchement.*) let instru_0 = 0x00 ;; let instru_1 = 0x01 ;; let instru_2 = 0x02 ;; let instru_3 = 0x03 ;; let instru_4 = 0x04 ;; let instru_5 = 0x05 ;; let instru_6 = 0x06 ;; let instru_7 = 0x07 ;; let instru_8 = 0x08 ;; (** Coussinets percussifs. Par défaut ce sont des notes envoyées sur le canal MIDI 0x09. *) let pad1 = 0x24 ;; let pad2 = 0x26 ;; let pad3 = 0x2a ;; let pad4 = 0x2e ;; let pad5 = 0x32 ;; let pad6 = 0x2d ;; let pad7 = 0x33 ;; let pad8 = 0x31 ;; end ;; module Omega = struct (** {1 Aucun clavier testé} Ceci modélise un clavier générique. {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.9} @version 0.9 @author Stéphane Grognet @since 2014 *) let nom_clavier = "CLAVIERo" ;; let tenue = true ;; (** {1 Liste des masques d'évènements réservés} 0x80 0x90 0xA0 0xB0 0xC0 0xD0 0xE0 0xF0 {1 Liste des numéros de contrôleurs réservés} 0x01 0x0B 0x40 all notes off : 0xFB 0xFC 0xFD 0xFE 0xFF *) (** {1 Contrôleurs} *) let bouton_1 = 0x10 ;; let bouton_2 = 0x11 ;; let bouton_3 = 0x12 ;; let bouton_4 = 0x13 ;; let bouton_5 = 0x14 ;; let bouton_6 = 0x15 ;; let bouton_7 = 0x16 ;; let bouton_8 = 0x17 ;; let bouton_8bis = 0x18 ;; let alter_swell = 0x19 ;; let alter_modulation = 0x1A ;; let bouton_p1 = 0x20 ;; let bouton_p2 = 0x21 ;; let bouton_p3 = 0x22 ;; let bouton_p4 = 0x23 ;; let bouton_p5 = 0x24 ;; let bouton_p6 = 0x25 ;; let bouton_p7 = 0x26 ;; let bouton_p8 = 0x27 ;; let bouton_p9 = 0x28 ;; let bouton_p10 = 0x29 ;; let curseur_0 = 0x30 ;; let curseur_1 = 0x31 ;; let curseur_2 = 0x32 ;; let curseur_3 = 0x33 ;; let curseur_4 = 0x34 ;; let curseur_5 = 0x35 ;; let curseur_6 = 0x36 ;; let curseur_7 = 0x37 ;; let curseur_8 = 0x38 ;; let curseur_9 = 0x39 ;; let poussoir_boucle = 0x50 ;; let poussoir_rembobine = 0x51 ;; let poussoir_avance_rapide = 0x52 ;; let poussoir_arret = 0x53 ;; let poussoir_lecture = 0x54 ;; let poussoir_enregistrement = 0x55 ;; let poussoir_debut = 0x56 ;; let poussoir_fin = 0x57 ;; let poussoir_1 = 0x60 ;; let poussoir_2 = 0x61 ;; let poussoir_3 = 0x62 ;; let poussoir_4 = 0x63 ;; let poussoir_5 = 0x64 ;; let poussoir_6 = 0x65 ;; let poussoir_7 = 0x66 ;; let poussoir_8 = 0x67 ;; let poussoir_9 = 0x68 ;; let poussoir_10 = 0x69 ;; let poussoir_11 = 0x6A ;; let poussoir_12 = 0x6B ;; let pad_1 = 0x70 ;; let pad_2 = 0x71 ;; let pad_3 = 0x72 ;; let pad_4 = 0x73 ;; let pad_5 = 0x74 ;; let pad_6 = 0x75 ;; let pad_7 = 0x76 ;; let pad_8 = 0x77 ;; let pad_9 = 0x78 ;; let pad_10 = 0x79 ;; let pad_11 = 0x7A ;; let pad_12 = 0x7B ;; let pad_13 = 0x7C ;; let pad_14 = 0x7D ;; let pad_15 = 0x7E ;; let pad_16 = 0x7F ;; let vers_instru = 0x80 ;; (** {1 Notes} *) let pad1 = 0x70 ;; let pad2 = 0x71 ;; let pad3 = 0x72 ;; let pad4 = 0x73 ;; let pad5 = 0x74 ;; let pad6 = 0x75 ;; let pad7 = 0x76 ;; let pad8 = 0x77 ;; end ;; module Roland = struct (** {1 Liste de claviers testés} + Roland A-800PRO {v Détection sous FreeBSD : ugen1.2: at usbus1 uaudio0: on usbus1 uaudio0: No playback. uaudio0: No recording. uaudio0: MIDI sequencer. uaudio0: No HID volume keys found. v} Dans "USB settings" il faut sélectionner "advanced driver mode" "OFF" (mode d'emploi page 65). À ce moment là les messages midi sont envoyés comme suit : les notes sur "/dev/umidi0.1", les boutons de réglage sur "/dev/umidi0.2". Dans "Keyboard/pad" il faut sélectionner "kbd port set" "port 1+2" (ou bien "port 2" : mode d'emploi page 61). À ce moment-là tout sort sur "/dev/umidi0.2". Dans "System settings" il faut sélectionner "OMNI" "ON" (mode d'emploi page 42) de façon que le canal MIDI soit celui choisi par l'encodeur rotatif (par défaut : le premier). On peut aussi tout récupérer à ce moment-là sur "/dev/umidi0.1". Il est alors impossible d'envoyer avec les coussinets percussifs (pads) une note sur un autre canal MIDI que celui des touches. L'utilisation des contrôleurs est incompatible avec celle des pads. {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.8} @version 0.8 @author Stéphane Grognet @since 2014 *) let nom_clavier = "CLAVIERr" ;; let tenue = false ;; let curseur_1 = 0x49 ;; let curseur_2 = 0x4B ;; let curseur_3 = 0x48 ;; let curseur_4 = 0x5B ;; let curseur_5 = 0x5C ;; let curseur_6 = 0x5D ;; let curseur_7 = 0x5E ;; let curseur_8 = 0x5F ;; let curseur_9 = 0x07 ;; let bouton1 = 0x4A ;; let bouton2 = 0x47 ;; let bouton3 = 0x41 ;; let bouton4 = 0x02 ;; let bouton5 = 0x05 ;; let bouton6 = 0x4C ;; let bouton7 = 0x4D ;; let bouton8 = 0x4E ;; let bouton9 = 0x0A ;; let bouton_1 = bouton1 ;; let bouton_2 = bouton2 ;; let bouton_3 = bouton3 ;; let bouton_4 = bouton4 ;; let bouton_5 = bouton5 ;; let bouton_6 = bouton6 ;; let bouton_7 = bouton7 ;; let bouton_8 = bouton8 ;; let bouton_8bis = bouton9 ;; let alter_swell = 0x0B ;; let alter_modulation = 0x01 ;; (** Les valeurs des boutons-poussoirs prennent les valeurs 127 à l'enfoncement et 0 au relâchement. *) let poussoir_debut = 0x15 ;; let poussoir_rembobine = 0x16 ;; let poussoir_avance_rapide = 0x17 ;; let poussoir_fin = 0x18 let poussoir_arret = 0x19 ;; let poussoir_lecture = 0x1A ;; let poussoir_pause = 0x1B ;; let poussoir_enregistrement = 0x1C ;; let poussoir_boucle = poussoir_pause ;; (** Boutons-poussoirs spécifiques. Les messages sont envoyés à l'enfoncement seulement. La valeur est alternativement 127 et 0. *) let poussoir_1 = 0x50 ;; let poussoir_2 = 0x51 ;; let poussoir_3 = 0x52 ;; let poussoir_4 = 0x53 ;; (** Valeurs absentes *) let curseur_0 = 0xFF ;; let bouton_p1 = 0xFF ;; let bouton_p2 = 0xFF ;; let bouton_p3 = 0xFF ;; let bouton_p4 = 0xFF ;; let bouton_p5 = 0xFF ;; let bouton_p6 = 0xFF ;; let bouton_p7 = 0xFF ;; let bouton_p8 = 0xFF ;; let bouton_p9 = 0xFF ;; let bouton_p10 = 0xFF ;; let poussoir_5 = 0xFF ;; let poussoir_6 = 0xFF ;; let poussoir_7 = 0xFF ;; let poussoir_8 = 0xFF ;; let poussoir_9 = 0xFF ;; let poussoir_10 = 0xFF ;; let poussoir_11 = 0xFF ;; let poussoir_12 = 0xFF ;; let vers_instru = 0xFF ;; let pad_5 = 0xFF ;; let pad_6 = 0xFF ;; let pad_7 = 0xFF ;; let pad_8 = 0xFF ;; (** Coussinets percussifs. Ce sont des notes envoyées sur le canal MIDI 0x00. *) let pad1 = 0x24 ;; let pad2 = 0x26 ;; let pad3 = 0x2a ;; let pad4 = 0x2e ;; let pad5 = 0x2b ;; let pad6 = 0x2d ;; let pad7 = 0x33 ;; let pad8 = 0x31 ;; end ;; module Filtre_evolution = struct (** {1 Liste d'appareils testés} + Evolution electronics MK-249C2 {v Détection sous FreeBSD : ugen1.2: at usbus1 uaudio0: on usbus1 uaudio0: No playback. uaudio0: No recording. uaudio0: MIDI sequencer. uaudio0: No HID volume keys found. v} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 1.1} @version 1.1 @author Stéphane Grognet @since 2014, 2015 *) (** {1 Données universelles} *) let masque_entete = 0xF0 ;; let numero_de_canal = 0x0F ;; (** Note off event *) let touche_relachee = 0x80 ;; (** Note on event *) let touche_appuyee = 0x90 ;; (** Controle change *) let mode = 0xB0 ;; (** Program change *) let instru = 0xC0 ;; (** Pitch bend change. La molette de pitch est centrée sur la valeur 64. *) let pitch = 0xE0 ;; (** System messages *) let sys = 0xF0 ;; (** {1 Numéros de contrôleurs} *) let bank_select = 0x00 ;; let modulation = 0x01 ;; let swell = 0x0B ;; let sustain_pedal = 0x40 ;; (** {1 Données locales} *) let message_vide = 0xFE ;; let canal_vide = 0x0E ;; let bouton1 = 0x0A ;;(*pan*) let bouton2 = 0x0B ;;(*expression*) let bouton3 = 0x0C ;;(*effect1*) let bouton4 = 0x0D ;;(*effect2*) let bouton5 = 0x5B ;;(*reverb*) let bouton6 = 0x5D ;;(*chorus*) let bouton7 = 0x5E ;;(*delay*) let bouton8 = 0x46 ;;(*phaser*) let bouton9 = 0x49 ;;(*attack*) let bouton10 = 0x48 ;;(*release*) let bouton11 = 0x4A ;;(*cut off*) let bouton12 = 0x47 ;;(*resonance*) let master_volume = 0x07 ;; (** Poussoirs particuliers. Les neuf boutons poussoirs situés sous les curseurs envoient les signaux MIDI suivants : b0 00 00 b0 20 00 c0 0X avec X = 0 à 9. Ces signaux sont envoyés seulement à l'enfoncement et rien n'est envoyé au relâchement.*) let instru_0 = 0x00 ;; let instru_1 = 0x01 ;; let instru_2 = 0x02 ;; let instru_3 = 0x03 ;; let instru_4 = 0x04 ;; let instru_5 = 0x05 ;; let instru_6 = 0x3F ;; let instru_7 = 0x07 ;; let instru_8 = 0x58 ;; let instru_9 = 0x31 ;; (** {1 Traduction} *) let scrute = fun ic oc -> let c = ref 0 and entete = ref 0 and canal = ref 0 and note = ref 0 and controleur = ref 0 and valeur = ref 0 in try while true do c := input_byte ic ; entete := !c land masque_entete ; canal := !c land numero_de_canal ; match !entete with | x when x = sys && !canal = canal_vide -> flush_all () | x when x = pitch || x = touche_relachee || x = touche_appuyee -> begin note := input_byte ic ; valeur := input_byte ic ; output_byte oc !c ; output_byte oc !note ; output_byte oc !valeur ; flush_all () ; end | x when x land mode = mode -> begin controleur := input_byte ic ; valeur := input_byte ic ; match !controleur with (** all notes off *) | y when ( 123 <= y ) && ( y <= 127 ) -> begin output_byte oc !c ; output_byte oc !controleur ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton1 -> begin output_byte oc !c ; output_byte oc Omega.bouton_p1 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton2 -> begin output_byte oc !c ; output_byte oc Omega.bouton_p2 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton3 -> begin output_byte oc !c ; output_byte oc Omega.bouton_p3 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton4 -> begin output_byte oc !c ; output_byte oc Omega.bouton_p4 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton5 -> begin output_byte oc !c ; output_byte oc Omega.bouton_p5 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton6 -> begin output_byte oc !c ; output_byte oc Omega.bouton_p6 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton7 -> begin output_byte oc !c ; output_byte oc Omega.bouton_p7 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton8 -> begin output_byte oc !c ; output_byte oc Omega.bouton_p8 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton9 -> begin output_byte oc !c ; output_byte oc Omega.bouton_p9 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton10 -> begin output_byte oc !c ; output_byte oc Omega.bouton_p10 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton11 -> begin output_byte oc !c ; output_byte oc Omega.bouton_8bis ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton12 -> begin output_byte oc !c ; output_byte oc Omega.alter_swell ; output_byte oc !valeur ; flush_all () ; end | y when y = master_volume -> begin output_byte oc !c ; output_byte oc Omega.curseur_0 ; output_byte oc !valeur ; flush_all () ; end | y when y = bank_select -> begin ignore ( input_byte ic ) ; ignore ( input_byte ic ) ; ignore ( input_byte ic ) ; ignore ( input_byte ic ) ; valeur := input_byte ic ; begin match !valeur with | z when z = instru_0 -> controleur := Omega.poussoir_boucle | z when z = instru_1 -> controleur := Omega.poussoir_rembobine | z when z = instru_2 -> controleur := Omega.poussoir_avance_rapide | z when z = instru_3 -> controleur := Omega.poussoir_arret | z when z = instru_4 -> controleur := Omega.poussoir_lecture | z when z = instru_5 -> controleur := Omega.poussoir_enregistrement | z when z = instru_6 -> controleur := Omega.poussoir_1 | z when z = instru_7 -> controleur := Omega.poussoir_2 | z when z = instru_8 -> controleur := Omega.poussoir_3 | z when z = instru_9 -> controleur := Omega.poussoir_4 | _ -> controleur := 0xFF end ; output_byte oc mode ; output_byte oc !controleur ; output_byte oc 0x7F ; flush_all () ; end | y when y = modulation -> begin output_byte oc !c ; output_byte oc swell ; output_byte oc !valeur ; flush_all () ; end | y when y = sustain_pedal -> begin output_byte oc !c ; output_byte oc sustain_pedal ; output_byte oc !valeur ; flush_all () ; end | _ -> flush_all () end | _ -> flush_all () done with _ -> begin close_in_noerr ic ; close_out_noerr oc ; end ;; scrute stdin stdout ;; end ;; module Filtre_eagletone = struct (** {1 Liste d'appareils testés} + Eagletone Engineering tinycontrol {v Détection sous FreeBSD : ugen1.2: at usbus1 uaudio0: on usbus1 uaudio0: No playback. uaudio0: No recording. uaudio0: MIDI sequencer. uaudio0: No HID volume keys found. v} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 1.1} @version 1.1 @author Stéphane Grognet @since 2014, 2015 *) (** {1 Données universelles} *) let masque_entete = 0xF0 ;; let numero_de_canal = 0x0F ;; (** Note off event *) let touche_relachee = 0x80 ;; (** Note on event *) let touche_appuyee = 0x90 ;; (** Controle change *) let mode = 0xB0 ;; (** Program change *) let instru = 0xC0 ;; (** Pitch bend change. La molette de pitch est centrée sur la valeur 64. *) let pitch = 0xE0 ;; (** System messages *) let sys = 0xF0 ;; (** {1 Numéros de contrôleurs} *) let bank_select = 0x00 ;; let modulation = 0x01 ;; let swell = 0x0B ;; let sustain_pedal = 0x40 ;; (** {1 Données locales} *) let curseur_1 = 0x03 ;; let curseur_2 = 0x04 ;; let curseur_3 = 0x05 ;; let curseur_4 = 0x06 ;; let curseur_5 = 0x07 ;; let curseur_6 = 0x08 ;; let curseur_7 = 0x09 ;; let curseur_8 = 0x0A ;; let curseur_9 = 0x0B ;; let bouton_1 = 0x0E ;; let bouton_2 = 0x0F ;; let bouton_3 = 0x10 ;; let bouton_4 = 0x11 ;; let bouton_5 = 0x12 ;; let bouton_6 = 0x13 ;; let bouton_7 = 0x14 ;; let bouton_8 = 0x15 ;; let bouton_8bis = 0x16 ;; let poussoir_boucle = 0x31 ;; let poussoir_rembobine = 0x2F ;; let poussoir_avance_rapide = 0x30 ;; let poussoir_arret = 0x2E ;; let poussoir_lecture = 0x2D ;; let poussoir_enregistrement = 0x2C ;; let poussoir_1 = 0x17 ;; let poussoir_2 = 0x18 ;; let poussoir_3 = 0x19 ;; let poussoir_4 = 0x1A ;; let poussoir_5 = 0x1B ;; let poussoir_6 = 0x1C ;; let poussoir_7 = 0x1D ;; let poussoir_8 = 0x1E ;; let poussoir_9 = 0x1F ;; (** Les poussoirs autour de l'encodeur rotatif sont appelés a et b. Ceux sous le curseur de volumesont appelés c et d. à l'enfocement, ils envoient des messages avec valeur 127 puis 0. *) let poussoir_a = 0x43 ;; let poussoir_b = 0x40 ;; let poussoir_c = 0x01 ;; let poussoir_d = 0x02 ;; (** L'encodeur rotatif envoie des messages "program change" (C0 xy). *) (** Le curseur panoramique A-B envoie des messages F0 7F 7F 04 01 00 xy F7 avec xy variable. *) (** Le poussoir BANK envoie des messages F0 42 40 00 01 04 00 5F 4F xy F7 avec xy qui cycle de 00 à 03. *) (** {1 Traduction} *) let scrute = fun ic oc -> let c = ref 0 and entete = ref 0 and canal = ref 0 and note = ref 0 and controleur = ref 0 and valeur = ref 0 in try while true do c := input_byte ic ; entete := !c land masque_entete ; canal := !c land numero_de_canal ; match !entete with | x when x = sys -> note := input_byte ic ; if !note = 0x7F then begin for i = 1 to 4 do ignore ( input_byte ic ) ; done ; valeur := input_byte ic ; ignore ( input_byte ic ) ; output_byte oc mode ; output_byte oc swell ; output_byte oc !valeur ; flush_all () ; end else if !note = 0x42 then begin for i = 1 to 7 do ignore ( input_byte ic ) ; done ; valeur := input_byte ic ; ignore ( input_byte ic ) ; begin note := match !valeur with | 0 -> Omega.pad1 | 1 -> Omega.pad2 | 2 -> Omega.pad3 | _ -> Omega.pad4 end ; let z = touche_appuyee + 9 in output_byte oc z ; output_byte oc !note ; output_byte oc 0x7F ; output_byte oc z ; output_byte oc !note ; output_byte oc 0x00 ; flush_all () ; end | x when x = instru -> begin valeur := input_byte ic ; output_byte oc mode ; output_byte oc Omega.bouton_8bis ; output_byte oc !valeur ; flush_all () ; end | x when x = pitch || x = touche_relachee || x = touche_appuyee -> begin note := input_byte ic ; valeur := input_byte ic ; output_byte oc !c ; output_byte oc !note ; output_byte oc !valeur ; flush_all () ; end | x when x land mode = mode -> begin controleur := input_byte ic ; valeur := input_byte ic ; match !controleur with (** all notes off *) | y when ( 123 <= y ) && ( y <= 127 ) -> begin output_byte oc !c ; output_byte oc !controleur ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton_1 -> begin output_byte oc !c ; output_byte oc Omega.bouton_1 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton_2 -> begin output_byte oc !c ; output_byte oc Omega.bouton_2 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton_3 -> begin output_byte oc !c ; output_byte oc Omega.bouton_3 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton_4 -> begin output_byte oc !c ; output_byte oc Omega.bouton_4 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton_5 -> begin output_byte oc !c ; output_byte oc Omega.bouton_5 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton_6 -> begin output_byte oc !c ; output_byte oc Omega.bouton_6 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton_7 -> begin output_byte oc !c ; output_byte oc Omega.bouton_7 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton_8 -> begin output_byte oc !c ; output_byte oc Omega.bouton_8 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton_8bis -> begin output_byte oc !c ; output_byte oc Omega.bouton_8bis ; output_byte oc !valeur ; flush_all () ; end | y when y = curseur_1 -> begin output_byte oc !c ; output_byte oc Omega.curseur_1 ; output_byte oc !valeur ; flush_all () ; end | y when y = curseur_2 -> begin output_byte oc !c ; output_byte oc Omega.curseur_2 ; output_byte oc !valeur ; flush_all () ; end | y when y = curseur_3 -> begin output_byte oc !c ; output_byte oc Omega.curseur_3 ; output_byte oc !valeur ; flush_all () ; end | y when y = curseur_4 -> begin output_byte oc !c ; output_byte oc Omega.curseur_4 ; output_byte oc !valeur ; flush_all () ; end | y when y = curseur_5 -> begin output_byte oc !c ; output_byte oc Omega.curseur_5 ; output_byte oc !valeur ; flush_all () ; end | y when y = curseur_6 -> begin output_byte oc !c ; output_byte oc Omega.curseur_6 ; output_byte oc !valeur ; flush_all () ; end | y when y = curseur_7 -> begin output_byte oc !c ; output_byte oc Omega.curseur_7 ; output_byte oc !valeur ; flush_all () ; end | y when y = curseur_8 -> begin output_byte oc !c ; output_byte oc Omega.curseur_8 ; output_byte oc !valeur ; flush_all () ; end | y when y = curseur_9 -> begin output_byte oc !c ; output_byte oc Omega.curseur_9 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_boucle -> begin output_byte oc !c ; output_byte oc Omega.poussoir_boucle ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_rembobine -> begin output_byte oc !c ; output_byte oc Omega.poussoir_rembobine ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_avance_rapide -> begin output_byte oc !c ; output_byte oc Omega.poussoir_avance_rapide ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_arret -> begin output_byte oc !c ; output_byte oc Omega.poussoir_arret ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_lecture -> begin output_byte oc !c ; output_byte oc Omega.poussoir_lecture ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_enregistrement -> begin output_byte oc !c ; output_byte oc Omega.poussoir_enregistrement ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_1 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_1 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_2 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_2 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_3 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_3 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_4 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_4 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_5 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_5 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_6 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_6 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_7 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_7 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_8 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_8 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_9 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_9 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_a -> begin output_byte oc ( touche_appuyee + 9 ) ; output_byte oc Omega.pad1 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_b -> begin output_byte oc ( touche_appuyee + 9 ) ; output_byte oc Omega.pad2 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_c -> begin output_byte oc ( touche_appuyee + 9 ) ; output_byte oc Omega.pad3 ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_d -> begin output_byte oc ( touche_appuyee + 9 ) ; output_byte oc Omega.pad4 ; output_byte oc !valeur ; flush_all () ; end | y when y = modulation -> begin output_byte oc !c ; output_byte oc swell ; output_byte oc !valeur ; flush_all () ; end | y when y = sustain_pedal -> begin output_byte oc !c ; output_byte oc sustain_pedal ; output_byte oc !valeur ; flush_all () ; end | _ -> flush_all () end | _ -> flush_all () done with _ -> begin close_in_noerr ic ; close_out_noerr oc ; end ;; scrute stdin stdout ;; end ;; module Filtre_akai_mpk = struct (** {1 Liste d'appareils testés} + Akai MPK mini {v Détection sous FreeBSD : ugen1.2: at usbus1 uaudio0: on usbus1 uaudio0: No playback. uaudio0: No recording. uaudio0: MIDI sequencer. uaudio0: No HID volume keys found. v} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 1.1} @version 1.1 @author Stéphane Grognet @since 2014, 2015 *) (** Il faut mettre ARPEGIATOR sur OFF. Pour que les boutons rotatifs envoient des messages, il faut sélectionner un programme différent de PROG1. {v Maintenir le poussoir PROGRAM enfoncé et appuyer sur une touche PROG2 ou PROG3 ou PROG4. v} Pour que les pads n'envoient pas de notes mais des messages "control change", il faut appuyer sur la touche CC. Les pads 9 à 16 correspondent aux pads 1 à 8 dans "PAD BANK 2". C'est eux qu'il faut activer. DISPOSITION des pads 1 à 8 simulant les boutons de transport : () << >> [] |< >| > O *) (** {1 Données universelles} *) let masque_entete = 0xF0 ;; let numero_de_canal = 0x0F ;; (** Note off event *) let touche_relachee = 0x80 ;; (** Note on event *) let touche_appuyee = 0x90 ;; (** Controle change *) let mode = 0xB0 ;; (** Program change *) let instru = 0xC0 ;; (** Pitch bend change. La molette de pitch est centrée sur la valeur 64. *) let pitch = 0xE0 ;; (** System messages *) let sys = 0xF0 ;; (** {1 Numéros de contrôleurs} *) let bank_select = 0x00 ;; let modulation = 0x01 ;; let swell = 0x0B ;; let sustain_pedal = 0x40 ;; (** {1 Données locales} *) let message_vide = 0xFE ;; let canal_vide = 0x0E ;; let bouton1 = 0x01 ;; let bouton2 = 0x02 ;; let bouton3 = 0x03 ;; let bouton4 = 0x04 ;; let bouton5 = 0x05 ;; let bouton6 = 0x06 ;; let bouton7 = 0x07 ;; let bouton8 = 0x08 ;; (** Il y a un conflit entre les boutons rotatifs et la première banque de coussinets. *) let pad_1 = 0x01 ;; let pad_2 = 0x02 ;; let pad_3 = 0x03 ;; let pad_4 = 0x04 ;; let pad_5 = 0x05 ;; let pad_6 = 0x06 ;; let pad_7 = 0x08 ;; let pad_8 = 0x09 ;; let pad_9 = 0x0A ;; let pad_10 = 0x0B ;; let pad_11 = 0x0C ;; let pad_12 = 0x0D ;; let pad_13 = 0x0E ;; let pad_14 = 0x0F ;; let pad_15 = 0x10 ;; let pad_16 = 0x11 ;; (** {1 Traduction} *) let scrute = fun ic oc -> let c = ref 0 and entete = ref 0 and canal = ref 0 and note = ref 0 and controleur = ref 0 and valeur = ref 0 in try while true do c := input_byte ic ; entete := !c land masque_entete ; canal := !c land numero_de_canal ; match !entete with | x when x = pitch || x = touche_relachee || x = touche_appuyee -> begin note := input_byte ic ; valeur := input_byte ic ; output_byte oc !c ; output_byte oc !note ; output_byte oc !valeur ; flush_all () ; end | x when x land mode = mode -> begin controleur := input_byte ic ; valeur := input_byte ic ; match !controleur with | y when y = bouton1 -> begin output_byte oc !c ; output_byte oc Omega.bouton_1 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton2 -> begin output_byte oc !c ; output_byte oc Omega.bouton_2 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton3 -> begin output_byte oc !c ; output_byte oc Omega.bouton_3 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton4 -> begin output_byte oc !c ; output_byte oc Omega.bouton_4 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton5 -> begin output_byte oc !c ; output_byte oc Omega.bouton_5 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton6 -> begin output_byte oc !c ; output_byte oc Omega.bouton_6 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton7 -> begin output_byte oc !c ; output_byte oc Omega.bouton_7 ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton8 -> begin output_byte oc !c ; output_byte oc Omega.bouton_8 ; output_byte oc !valeur ; flush_all () ; end | y when y = pad_13 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_boucle ; output_byte oc !valeur ; flush_all () ; end | y when y = pad_14 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_rembobine ; output_byte oc !valeur ; flush_all () ; end | y when y = pad_15 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_avance_rapide ; output_byte oc !valeur ; flush_all () ; end | y when y = pad_16 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_arret ; output_byte oc !valeur ; flush_all () ; end | y when y = pad_9 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_debut ; output_byte oc !valeur ; flush_all () ; end | y when y = pad_10 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_fin ; output_byte oc !valeur ; flush_all () ; end | y when y = pad_11 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_lecture ; output_byte oc !valeur ; flush_all () ; end | y when y = pad_12 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_enregistrement ; output_byte oc !valeur ; flush_all () ; end | _ -> flush_all () end | _ -> flush_all () done with _ -> begin close_in_noerr ic ; close_out_noerr oc ; end ;; scrute stdin stdout ;; end ;; module Filtre_samson = struct (** {1 Liste d'appareils testés} + Samson graphite 49 {v Détection sous FreeBSD : ugen1.2: at usbus1 uaudio0: on usbus1 uaudio0: No playback. uaudio0: No recording. uaudio0: MIDI sequencer. uaudio0: No HID volume keys found. v} La conception et la qualité fabrication du clavier Samson graphite 49 ne paraissent pas à la hauteur des autres fabricants. À cause du commportement bizarre du train de messages "PANIC" (obtenu par appui simultané des touches REMBOBINE et AVANCE RAPIDE), un message de rappel de jeu est envoyé, ainsi qu'un recentrage du "pitch bend". {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 1.1} @version 1.1 @author Stéphane Grognet @since 2015 *) (** {1 Données universelles} *) let masque_entete = 0xF0 ;; let numero_de_canal = 0x0F ;; (** Note off event *) let touche_relachee = 0x80 ;; (** Note on event *) let touche_appuyee = 0x90 ;; (** Controle change *) let mode = 0xB0 ;; (** Program change *) let instru = 0xC0 ;; (** Pitch bend change. La molette de pitch est centrée sur la valeur 64. *) let pitch = 0xE0 ;; (** System messages *) let sys = 0xF0 ;; (** {1 Numéros de contrôleurs} *) let bank_select = 0x00 ;; let modulation = 0x01 ;; let swell = 0x0B ;; let sustain_pedal = 0x40 ;; (** {1 Données locales} *) (** Les curseurs 1 à 8 et les boutons rotatifs envoient des messages de contrôleurs sur les ports MIDI successifs, de 0x0 à 0x7 pour la banque 1 et de 0x8 à 0xF pour la banque 2. Le comportement obtenu est indépendant du choix de la banque. *) let curseur_generique = 0x07 ;; let bouton_generique = 0x0A ;; (** Le curseur 9 envoie des messages "f0 7f 7f 04 01 xy f7" où "xy" est la valeur entre 0 et 127, quelle que soit la banque sélectionnée. *) (** Tous les boutons-poussoirs fonctionnent par défaut en mode "Toggle", c'est à dire qu'ils envoient alternativement la valeur 0 et la valeur 127. Il n'y a pas de poussoir boucle. Sur notre exemplaire d'occasion, les poussoirs 1 à 8 ne fonctionnent pas. Le poussoir 16 est utilisé comme poussoir boucle. *) let poussoir_rembobine = 0x74 ;; let poussoir_avance_rapide = 0x75 ;; let poussoir_arret = 0x76 ;; let poussoir_lecture = 0x77 ;; let poussoir_enregistrement = 0x72 ;; let poussoir_9 = 0x18 ;; let poussoir_10 = 0x19 ;; let poussoir_11 = 0x1A ;; let poussoir_12 = 0x1B ;; let poussoir_13 = 0x1C ;; let poussoir_14 = 0x1D ;; let poussoir_15 = 0x1E ;; let poussoir_16 = 0x1F ;; (** Les coussinets percussif (pads) respectivement 1 à 4 envoient sur le canal 0x9 les notes 0x24 à 0x27 dans la banque A et 0x28 à 0x2B dans la banque B. *) let pad_1 = 0x24 ;; let pad_2 = 0x25 ;; let pad_3 = 0x26 ;; let pad_4 = 0x27 ;; let pad_5 = 0x28 ;; let pad_6 = 0x29 ;; let pad_7 = 0x2A ;; let pad_8 = 0x2B ;; let decalage_de_pad = Omega.pad_1 - pad_1 ;; (** {1 Traduction} *) let scrute = fun ic oc -> let c = ref 0 and entete = ref 0 and canal = ref 0 and note = ref 0 and controleur = ref 0 and valeur = ref 0 in try while true do c := input_byte ic ; entete := !c land masque_entete ; canal := !c land numero_de_canal ; match !entete with | x when x = sys -> note := input_byte ic ; if !note = 0x7F then begin for i = 1 to 3 do ignore ( input_byte ic ) ; done ; valeur := input_byte ic ; ignore ( input_byte ic ) ; output_byte oc mode ; output_byte oc Omega.curseur_9 ; output_byte oc !valeur ; flush_all () ; end else if !note = 0x7E then begin for i = 1 to 15 do ignore ( input_byte ic ) ; done ; output_byte oc ( mode + !canal ) ; output_byte oc 123 ; output_byte oc 0x00 ; flush_all () ; end | x when x = pitch || x = touche_relachee || x = touche_appuyee -> begin if !canal <> 9 then begin note := input_byte ic ; valeur := input_byte ic ; output_byte oc !c ; output_byte oc !note ; output_byte oc !valeur ; flush_all () ; end else begin note := input_byte ic ; valeur := input_byte ic ; output_byte oc !c ; output_byte oc ( decalage_de_pad + !note ) ; output_byte oc !valeur ; flush_all () ; end end | x when x land mode = mode -> begin controleur := input_byte ic ; valeur := input_byte ic ; match !controleur with (** all notes off *) | y when ( 123 <= y ) && ( y <= 127 ) -> begin output_byte oc !c ; output_byte oc !controleur ; output_byte oc !valeur ; flush_all () ; end | y when y = curseur_generique -> begin output_byte oc !entete ; canal := !canal mod 8 ; output_byte oc ( Omega.curseur_1 + !canal ) ; output_byte oc !valeur ; flush_all () ; end | y when y = bouton_generique -> begin output_byte oc !entete ; canal := !canal mod 8 ; output_byte oc ( Omega.bouton_1 + !canal ) ; output_byte oc !valeur ; flush_all () ; end | y when y = poussoir_rembobine -> begin output_byte oc !c ; output_byte oc Omega.poussoir_rembobine ; output_byte oc 0x7F ; flush_all () ; end | y when y = poussoir_avance_rapide -> begin output_byte oc !c ; output_byte oc Omega.poussoir_avance_rapide ; output_byte oc 0x7F ; flush_all () ; end | y when y = poussoir_arret -> begin output_byte oc !c ; output_byte oc Omega.poussoir_arret ; output_byte oc 0x7F ; flush_all () ; end | y when y = poussoir_lecture -> begin output_byte oc !c ; output_byte oc Omega.poussoir_lecture ; output_byte oc 0x7F ; flush_all () ; end | y when y = poussoir_enregistrement -> begin output_byte oc !c ; output_byte oc Omega.poussoir_enregistrement ; output_byte oc 0x7F ; flush_all () ; end | y when y = poussoir_9 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_1 ; output_byte oc 0x7F ; flush_all () ; end | y when y = poussoir_10 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_2 ; output_byte oc 0x7F ; flush_all () ; end | y when y = poussoir_11 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_3 ; output_byte oc 0x7F ; flush_all () ; end | y when y = poussoir_12 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_4 ; output_byte oc 0x7F ; flush_all () ; end | y when y = poussoir_13 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_5 ; output_byte oc 0x7F ; flush_all () ; end | y when y = poussoir_14 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_6 ; output_byte oc 0x7F ; flush_all () ; end | y when y = poussoir_15 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_7 ; output_byte oc 0x7F ; flush_all () ; end | y when y = poussoir_16 -> begin output_byte oc !c ; output_byte oc Omega.poussoir_boucle ; output_byte oc 0x7F ; flush_all () ; end | y when y = modulation -> begin output_byte oc !c ; output_byte oc swell ; output_byte oc !valeur ; flush_all () ; end | y when y = sustain_pedal -> begin output_byte oc !c ; output_byte oc sustain_pedal ; output_byte oc !valeur ; flush_all () ; end | _ -> flush_all () end | _ -> flush_all () done with _ -> begin close_in_noerr ic ; close_out_noerr oc ; end ;; scrute stdin stdout ;; end ;; module Filtre_tty = struct (** {1 Aucun appareil testé} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 1.1} @version 1.1 @author Stéphane Grognet @since 2014, 2015 *) (** {1 Données universelles} *) let masque_entete = 0xF0 ;; let numero_de_canal = 0x0F ;; (** Note off event *) let touche_relachee = 0x80 ;; (** Note on event *) let touche_appuyee = 0x90 ;; (** Controle change *) let mode = 0xB0 ;; (** Program change *) let instru = 0xC0 ;; (** Pitch bend change. La molette de pitch est centrée sur la valeur 64. *) let pitch = 0xE0 ;; (** System messages *) let sys = 0xF0 ;; (** {1 Numéros de controleurs} *) let bank_select = 0x00 ;; let modulation = 0x01 ;; let swell = 0x0B ;; let sustain_pedal = 0x40 ;; (** {1 Données locales} *) let notepad = touche_appuyee + 9 ;; (** {1 Traduction} *) let scrute = fun ic oc -> let c = ref ' ' in try while true do c := input_char ic ; match !c with | 'a' -> begin output_byte oc mode ; output_byte oc 123 ; output_byte oc 0 ; flush_all () ; end | 'z' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_boucle ; output_byte oc 127 ; flush_all () ; end | 'e' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_debut ; output_byte oc 127 ; flush_all () ; end | 'r' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_rembobine ; output_byte oc 127 ; flush_all () ; end | 't' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_avance_rapide ; output_byte oc 127 ; flush_all () ; end | 'y' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_fin ; output_byte oc 127 ; flush_all () ; end | 'u' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_arret ; output_byte oc 127 ; flush_all () ; end | 'i' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_lecture ; output_byte oc 127 ; flush_all () ; end | 'o' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_enregistrement ; output_byte oc 127 ; flush_all () ; end | '&' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_1 ; output_byte oc 127 ; flush_all () ; end | 'é' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_2 ; output_byte oc 127 ; flush_all () ; end | '"' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_3 ; output_byte oc 127 ; flush_all () ; end | '\'' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_4 ; output_byte oc 127 ; flush_all () ; end | '(' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_5 ; output_byte oc 127 ; flush_all () ; end | '-' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_6 ; output_byte oc 127 ; flush_all () ; end | 'è' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_7 ; output_byte oc 127 ; flush_all () ; end | '_' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_8 ; output_byte oc 127 ; flush_all () ; end | 'ç' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_9 ; output_byte oc 127 ; flush_all () ; end | 'à' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_10 ; output_byte oc 127 ; flush_all () ; end | ')' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_11 ; output_byte oc 127 ; flush_all () ; end | '=' -> begin output_byte oc mode ; output_byte oc Omega.poussoir_12 ; output_byte oc 127 ; flush_all () ; end | '1' -> begin output_byte oc notepad ; output_byte oc Omega.pad1 ; output_byte oc 127 ; flush_all () ; end | '2' -> begin output_byte oc notepad ; output_byte oc Omega.pad2 ; output_byte oc 127 ; flush_all () ; end | '3' -> begin output_byte oc notepad ; output_byte oc Omega.pad3 ; output_byte oc 127 ; flush_all () ; end | '4' -> begin output_byte oc notepad ; output_byte oc Omega.pad4 ; output_byte oc 127 ; flush_all () ; end | '5' -> begin output_byte oc notepad ; output_byte oc Omega.pad5 ; output_byte oc 127 ; flush_all () ; end | '6' -> begin output_byte oc notepad ; output_byte oc Omega.pad6 ; output_byte oc 127 ; flush_all () ; end | '7' -> begin output_byte oc notepad ; output_byte oc Omega.pad7 ; output_byte oc 127 ; flush_all () ; end | '8' -> begin output_byte oc notepad ; output_byte oc Omega.pad8 ; output_byte oc 127 ; flush_all () ; end | '<' -> begin output_byte oc touche_appuyee ; output_byte oc 60 ; output_byte oc 127 ; flush_all () ; end | '>' -> begin output_byte oc touche_relachee ; output_byte oc 60 ; output_byte oc 0 ; flush_all () ; end | 'q' -> begin output_byte oc touche_appuyee ; output_byte oc 61 ; output_byte oc 127 ; flush_all () ; end | 'Q' -> begin output_byte oc touche_relachee ; output_byte oc 61 ; output_byte oc 0 ; flush_all () ; end | 'w' -> begin output_byte oc touche_appuyee ; output_byte oc 62 ; output_byte oc 127 ; flush_all () ; end | 'W' -> begin output_byte oc touche_relachee ; output_byte oc 62 ; output_byte oc 0 ; flush_all () ; end | 's' -> begin output_byte oc touche_appuyee ; output_byte oc 63 ; output_byte oc 127 ; flush_all () ; end | 'S' -> begin output_byte oc touche_relachee ; output_byte oc 63 ; output_byte oc 0 ; flush_all () ; end | 'x' -> begin output_byte oc touche_appuyee ; output_byte oc 64 ; output_byte oc 127 ; flush_all () ; end | 'X' -> begin output_byte oc touche_relachee ; output_byte oc 64 ; output_byte oc 0 ; flush_all () ; end | 'c' -> begin output_byte oc touche_appuyee ; output_byte oc 65 ; output_byte oc 127 ; flush_all () ; end | 'C' -> begin output_byte oc touche_relachee ; output_byte oc 65 ; output_byte oc 0 ; flush_all () ; end | 'f' -> begin output_byte oc touche_appuyee ; output_byte oc 66 ; output_byte oc 127 ; flush_all () ; end | 'F' -> begin output_byte oc touche_relachee ; output_byte oc 66 ; output_byte oc 0 ; flush_all () ; end | 'v' -> begin output_byte oc touche_appuyee ; output_byte oc 67 ; output_byte oc 127 ; flush_all () ; end | 'V' -> begin output_byte oc touche_relachee ; output_byte oc 67 ; output_byte oc 0 ; flush_all () ; end | 'g' -> begin output_byte oc touche_appuyee ; output_byte oc 68 ; output_byte oc 127 ; flush_all () ; end | 'G' -> begin output_byte oc touche_relachee ; output_byte oc 68 ; output_byte oc 0 ; flush_all () ; end | 'b' -> begin output_byte oc touche_appuyee ; output_byte oc 69 ; output_byte oc 127 ; flush_all () ; end | 'B' -> begin output_byte oc touche_relachee ; output_byte oc 69 ; output_byte oc 0 ; flush_all () ; end | 'h' -> begin output_byte oc touche_appuyee ; output_byte oc 70 ; output_byte oc 127 ; flush_all () ; end | 'H' -> begin output_byte oc touche_relachee ; output_byte oc 70 ; output_byte oc 0 ; flush_all () ; end | 'n' -> begin output_byte oc touche_appuyee ; output_byte oc 71 ; output_byte oc 127 ; flush_all () ; end | 'N' -> begin output_byte oc touche_relachee ; output_byte oc 71 ; output_byte oc 0 ; flush_all () ; end | ',' -> begin output_byte oc touche_appuyee ; output_byte oc 72 ; output_byte oc 127 ; flush_all () ; end | '?' -> begin output_byte oc touche_relachee ; output_byte oc 72 ; output_byte oc 0 ; flush_all () ; end | 'k' -> begin output_byte oc touche_appuyee ; output_byte oc 73 ; output_byte oc 127 ; flush_all () ; end | 'K' -> begin output_byte oc touche_relachee ; output_byte oc 73 ; output_byte oc 0 ; flush_all () ; end | ';' -> begin output_byte oc touche_appuyee ; output_byte oc 74 ; output_byte oc 127 ; flush_all () ; end | '.' -> begin output_byte oc touche_relachee ; output_byte oc 74 ; output_byte oc 0 ; flush_all () ; end | 'l' -> begin output_byte oc touche_appuyee ; output_byte oc 75 ; output_byte oc 127 ; flush_all () ; end | 'L' -> begin output_byte oc touche_relachee ; output_byte oc 75 ; output_byte oc 0 ; flush_all () ; end | ':' -> begin output_byte oc touche_appuyee ; output_byte oc 76 ; output_byte oc 127 ; flush_all () ; end | '/' -> begin output_byte oc touche_relachee ; output_byte oc 76 ; output_byte oc 0 ; flush_all () ; end | '!' -> begin output_byte oc touche_appuyee ; output_byte oc 77 ; output_byte oc 127 ; flush_all () ; end | '§' -> begin output_byte oc touche_relachee ; output_byte oc 77 ; output_byte oc 0 ; flush_all () ; end | _ -> flush_all () done with _ -> begin close_in_noerr ic ; close_out_noerr oc ; end ;; scrute stdin stdout ;; end ;; module ClavierA = struct (** {1 Utilisation d'une source MIDI de type Arturia} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.3} @version 0.3 @author Stéphane Grognet @since 2014 *) module C = Clavier.Make (Arturia) ;; C.scrute (stdin) ;; end ;; module ClavierM = struct (** {1 Utilisation d'une source MIDI de type M-audio} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.3} @version 0.3 @author Stéphane Grognet @since 2014 *) module C = Clavier.Make (M_audio) ;; C.scrute (stdin) ;; end ;; module ClavierO = struct (** {1 Utilisation d'une source MIDI de type générique} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.9} @version 0.9 @author Stéphane Grognet @since 2014 *) module C = Clavier.Make (Omega) ;; C.scrute (stdin) ;; end ;; module ClavierR = struct (** {1 Utilisation d'une source MIDI de type Roland} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.3} @version 0.3 @author Stéphane Grognet @since 2014 *) module C = Clavier.Make (Roland) ;; C.scrute (stdin) ;; end ;; module ClavierS = struct (** {1 Utilisation d'une source MIDI de type Alesis} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.3} @version 0.3 @author Stéphane Grognet @since 2014 *) module C = Clavier.Make (Alesis) ;; C.scrute (stdin) ;; end ;; module Etat = struct (** {1 Description} La fonction {v etat v} effectue certains calculs suivant les données provenant du clavier. {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.7} @version 0.7 @author Stéphane Grognet @since 2014 *) (** 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 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 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 (notes:int array) (polyphonie:int ref) (sons:float array) (parametres:float array) -> for i = 0 to 127 do sons.(i) <- 0. ; done ; let accu = ref 0 and ic = open_in_gen [Open_binary ; Open_rdonly] 0o400 Data.adresse_etat_clavier in for i = 0 to 127 do let c = input_byte ic in if c > 0 then begin notes.(i) <- 127 ; incr accu ; end else notes.(i) <- 0 ; done ; if ( !accu > 0 ) && ( !polyphonie = 0 ) then parametres.(Data.detache) <- 1. else parametres.(Data.detache) <- 0. ; for i = 0 to pred Data.nombre_de_parametres_clavier do parametres.(i) <- float ( input_byte ic ) ; done ; close_in_noerr ic ; polyphonie := !accu ; parametres.(Data.polyphonie) <- float !accu ; (** On part du principe que la commande 0 est le pitch, que les commandes 1 à 9 sont les tirettes, que les commandes 10 à 41 sont des boutons rotatifs, que les commandes 42 à 44 sont des boutons-poussoirs. 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 ; (** boutons rotatifs *) parametres.(Data.bouton_swell) <- gain_reel parametres.(Data.bouton_swell) ; 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) ; (** 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) ) ) in for i = 0 to 127 do if notes.(i) > 0 then begin let j = ref 0 in for k = 1 to 9 do let index = plusplus bord_bas bord_haut i Data.tirettes.(!j) in sons.(index) <- sons.(index) +. parametres.(k) ; j := k ; done ; end ; done ;; end ;; module Test_etat = struct (** {1 Test du module Etat} {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.3} @version 0.3 @author Stéphane Grognet @since 2014 *) let test_etat = function () -> let notes = Array.make 128 0 and sons = Array.make 128 0. and polyphonie = ref 0 and parametres = Array.make Data.nombre_de_parametres_orgue 0. in Etat.etat notes polyphonie sons parametres ; let oc = open_out Data.adresse_etat_orgue in for i = 0 to 127 do output_string oc ( ( string_of_float sons.(i) ) ^ "\n" ) ; done ; for i = 0 to pred Data.nombre_de_parametres_orgue do output_string oc ( ( string_of_float parametres.(i) ) ^ "\n" ) ; done ; close_out_noerr oc ;; test_etat () ;; end ;; module Manivelle = struct (** {1 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é. {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 1.0} @version 1.0 @author Stéphane Grognet @since 2014 *) (** {v signe nombre v} *) let signe = function (x:float) -> match x with | y when y > 0. -> 1. | y when y < 0. -> -1. | _ -> 0. ;; (** {v tronque nombre v} *) let tronque = function (x:float) -> min 1.0 ( max ( -1.0 ) x ) ;; (** {v carre nombre v} *) let carre = function (x:float) -> x *. x ;; (** {v carre_signe nombre v} *) let carre_signe = function (x:float) -> x *. ( abs_float x ) ;; (** {v deforme exposant nombre v} *) 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. ;; (** {v inflexion parametre nombre v} *) let inflexion = fun (p:float) (x:float) -> let a = 2 + ( int_of_float ( 0.03125 *. p ) ) in deforme a x ;; (** {v detricote_centre somme difference v} *) 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 ) ) ;; (** {v detricote somme difference v} *) 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 ) ) ;; (** {v percussion detache enveloppe niveau echantillon v} *) 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 ;; (** {v sauvegarde echantillon adresse v} *) 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 ;; (** {v reverb delai niveau precedent_stockage_echantillon stockage_echantillon precedent_echantillon echantillon v} *) 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. *) (** {v vibrato_mono poussoir_vc cosinu sinus phase_vc phase_finale_vc precedent_echantillon echantillon v} La fréquence de balayage est fixée à 412 cycles par minute (voir {{:../doc/Doc.Data.html} 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 ;; (** {v 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 v} 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 de l'orgue (voir {{:../doc/Doc.Data.html} 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}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 ) ;; (** {v filtre coupure precedent_echantillon echantillon v} *) 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 ) ; ;; (** {v 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 polyphonie canal_de_sortie v} *) let manivelle = fun (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) (polyphonie:int ref) (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 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 128 0. and parametres = Array.make Data.nombre_de_parametres_orgue 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 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 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 notes polyphonie sons 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 zz = parametres.(Data.polyphonie) 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 ( epg , epa ) = detricote_centre parametres.(Data.bouton_enveloppe_percu) parametres.(Data.bouton_diff_enveloppe_percu) and ( npg , npa ) = detricote_centre parametres.(Data.bouton_niveau_percu) parametres.(Data.bouton_diff_niveau_percu) 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) and compression = if zz > 1.0 then 1.0 /. ( sqrt zz ) else 1.0 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 amplitude = compression *. sons.(i) *. rose.(i) in 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. 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 *. ( 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 *. ( 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 parametres.(Data.detache) > 0.5 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 (** ********** *) (** Percussion *) (** ********** *) percussion parametres.(Data.detache) ( Etat.gain_reel epg ) ( Etat.gain_reel npg ) grave ; percussion parametres.(Data.detache) ( Etat.gain_reel epa ) ( Etat.gain_reel npa ) aigu ; (** *************************** *) (** 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 (swell), 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 := parametres.(Data.bouton_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 ;; module Orgue = struct (** {1 Description} L'unique fonction de ce module est la boucle infinie qui fabrique le son de l'orgue. {C Copyright Stéphane Grognet } {C IREM des Pays de la Loire - Université de Nantes } {C Laboratoire de mathématiques Jean Leray UMR 6629 CNRS } {C version 0.6} @version 0.6 @author Stéphane Grognet @since 2014 *) let orgue = function () -> let date = ref 0. and compte = ref 0 and polyphonie = ref 0 and echeance = ref 0. and x = ref 0. and y = ref 0. and cos_bf = Array.make 128 0. and sin_bf = Array.make 128 0. and phase_bf_grave = Array.make 2 0. and phase_finale_bf_grave = Array.make 2 0. and phase_bf_1_grave = Array.make 2 0. and phase_finale_bf_1_grave = Array.make 2 0. and phase_bf_aigu = Array.make 2 0. and phase_finale_bf_aigu = Array.make 2 0. and phase_bf_1_aigu = Array.make 2 0. and phase_finale_bf_1_aigu = Array.make 2 0. and phase_vc = Array.make 2 0. and phase_finale_vc = Array.make 2 0. and phase_generateurs = Array.make_matrix 128 3 0. and precedent_signal = Array.make Data.taille_d_echantillon 0. and penultieme_echantillon = Array.make Data.taille_d_echantillon 0. and precedent_echantillon = Array.make Data.taille_d_echantillon 0. and tampon = Buffer.create ( 4 * Data.taille_d_echantillon ) in date := Unix.gettimeofday () ; echeance := !date ; phase_bf_grave.(0) <- 1. ; phase_bf_1_grave.(0) <- 1. ; phase_bf_aigu.(0) <- 1. ; phase_bf_1_aigu.(0) <- 1. ; phase_vc.(0) <- 1. ; phase_finale_bf_grave.(0) <- 1. ; phase_finale_bf_1_grave.(0) <- 1. ; phase_finale_bf_aigu.(0) <- 1. ; phase_finale_bf_1_aigu.(0) <- 1. ; phase_finale_vc.(0) <- 1. ; for i = 0 to 127 do x := Random.float ( float i ) ; y := cos !x ; let ligne_de_phases = phase_generateurs.(i) in ligne_de_phases.(0) <- !y ; ligne_de_phases.(1) <- sin !x ; ligne_de_phases.(2) <- asin !y ; done ; let ic = open_in_gen [Open_binary ; Open_rdonly] 0o400 Data.adresse_rotation_bf in for i = 0 to 127 do cos_bf.(i) <- float_of_string ( input_line ic ) ; sin_bf.(i) <- float_of_string ( input_line ic ) ; done ; close_in_noerr ic ; while true do date := Unix.gettimeofday () ; if !date > !echeance then begin Manivelle.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 precedent_signal penultieme_echantillon precedent_echantillon polyphonie tampon stdout ; echeance := !echeance +. Data.duree_d_echantillon ; (** Rattrapage en cas de panique *) if !date > !echeance then begin echeance := !date ; prerr_string "Saturation du calcul " ; prerr_int !compte ; prerr_newline () ; incr compte ; end ; end else (** Pour faire passer le temps *) Data.passe_temps () ; done ;; orgue () ;; end ;;