struct

(**

Liste d'appareils testés

  1. Samson graphite 49
    Détection sous FreeBSD :
    ugen1.2: <SAMSON> at usbus1
    uaudio0: <SAMSON SAMSON Graphite 49, class 0/0, rev 1.10/0.01, addr 2> on usbus1
    uaudio0: No playback.
    uaudio0: No recording.
    uaudio0: MIDI sequencer.
    uaudio0: No HID volume keys found.
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".

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




(**

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 ;;


(**

Numéros de contrôleurs

*)



let bank_select = 0x00 ;;
let modulation = 0x01 ;;
let swell = 0x0B ;;
let sustain_pedal = 0x40 ;;


(**

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 ;;

(**

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