Séquenceur MIDI avec Ada

Séquenceur MIDI avec Ada - Ada - Programmation

Marsh Posté le 13-08-2009 à 11:47:20    

Bonjour,
 
Sous le conseil je pense avisé de el muchacho, je viens vous demander conseil pour le réalisation d'un séquenceur MIDI avec Ada.
 
Voilà, j'y connais rien en temps réel.
Je peux vous poster ce que j'ai fait depuis 7 heure ce matin...
 

Code :
  1. with Portmidi, Porttime;
  2. use Portmidi, Porttime;
  3. with System;
  4. use System;
  5. with Musician;
  6. use Musician;
  7.  
  8. package body Harmonia is
  9.  
  10.  
  11.   type T_Orchester is array (Positive range <> ) of T_Musician;
  12.  
  13.  
  14.   task body Conductor is
  15.      End_Of_Task : Boolean := False;
  16.      Entract : Boolean := False;
  17.  
  18.      Orchester : T_Orchester(1..1);
  19.  
  20.      Pt_Error : PtError;
  21.      Pm_Error : PmError;
  22.      Resolution : Integer := 1;
  23.      PtCallback,
  24.      UserData : System.Address := Null_Address;
  25.   begin
  26.  
  27.      Pt_Error := Pt_Start(Resolution, PtCallback, UserData);
  28.      Pm_Error := Pm_Initialize;
  29.  
  30.      Orchester(1).Initialize(6);
  31.      while not End_Of_Task loop
  32.         accept Start do
  33.            for I in Orchester'Range loop
  34.               Orchester(I).start;
  35.            end loop;
  36.            Entract := False;
  37.         end Start;
  38.         loop
  39.            select
  40.               accept Stop do
  41.                  for I in Orchester'Range loop
  42.                     Orchester(I).stop;
  43.                  end loop;
  44.                  Entract := True;
  45.               end Stop;
  46.            or
  47.               accept Halt do
  48.                  for I in Orchester'Range loop
  49.                     Orchester(I).Halt;
  50.                  end loop;
  51.                  Entract := True;
  52.                  End_Of_Task := True;
  53.               end Halt;
  54.            or
  55.               delay 0.0;
  56.         null;
  57.  
  58.  
  59.            end select;
  60.            exit when Entract;
  61.         end loop;
  62.      end loop;
  63.  
  64.      Pm_Error := Pm_Terminate;
  65.  
  66.   end Conductor;
  67.  
  68.  
  69. end Harmonia;


 
Et  

Code :
  1. with Text_Io;
  2. with System;
  3. with System.Address_To_Access_Conversions;
  4. with Interfaces.C;
  5. with Portmidi, Porttime;
  6. use Text_Io;
  7. use System;
  8. use Interfaces.C;
  9. use Portmidi, Porttime;
  10.  
  11.  
  12.  
  13. package body Musician is
  14.  
  15.   subtype SubString is Char_array(1..64);
  16.   package String_Address_Conversion is new System.Address_To_Access_Conversions(substring);
  17.   use String_Address_conversion;
  18.  
  19.  
  20.  
  21.   task body T_Musician is
  22.      End_Of_Task : Boolean := False;
  23.      Entract : Boolean := False;
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.      Pm_Error : PmError;
  31.  
  32.      PortMidiStream_Ptr : System.Address;
  33.  
  34.      OutputDriverInfo_Ptr : System.Address := Null_Address;
  35.      Time_Info_Ptr : System.Address;
  36.  
  37.  
  38.      Current_DeviceInfo : DeviceInfo;
  39.  
  40.  
  41.  
  42.  
  43.      Resolution : Integer := 1;
  44.      PtCallback,
  45.      UserData : System.Address := Null_Address;
  46.  
  47.      Pm_Event : PmEvent;
  48.  
  49.      Content : T_Message := (16#90#, 60, 100);
  50.  
  51.  
  52.  
  53.   begin
  54.  
  55.  
  56.  
  57.  
  58.      accept Initialize(Instrument : T_instrument) do
  59.         PortMidiStream_Ptr := Open_Handler(Instrument);
  60.         Put_line("Pm_OpenOutput... Ok !" );
  61.         delay 1.0;
  62.         if Pm_HasHostError(PortMidiStream_Ptr) /= 0 then
  63.            Put_line(To_Ada(Pm_GetErrorText(Pm_Error)));
  64.         else
  65.            Put_line("PortMidiStream... Ok !" );
  66.            Pm_Event.Message := Pm_Message(Content);
  67.            delay 1.0;
  68.         end if;
  69.      end Initialize;
  70.      while not End_Of_Task loop
  71.         accept Start do
  72.            Entract := False;
  73.         end Start;
  74.         loop
  75.            select
  76.               accept Receive(Partition : T_Partition) do
  77.                  null;
  78.               end Receive;
  79.            or
  80.               accept Tempo(Length : in Duration) do
  81.                  null;
  82.               end Tempo;
  83.            or
  84.               accept Sync do
  85.                  null;
  86.               end Sync;
  87.            or
  88.               accept Stop do
  89.                  Entract := True;
  90.               end Stop;
  91.            or
  92.               accept Halt do
  93.                  Pm_Error := Pm_Close(PortMidiStream => PortMidiStream_ptr);
  94.                  --Put_line(To_ada(Pm_GetErrorText(Pm_Error))); -- Cause Error C Terminator;
  95.                  Entract := True;
  96.                  End_Of_Task := True;
  97.               end Halt;
  98.            or
  99.               delay 0.0;
  100.               Pm_Event.PmTimestamp := Pt_time;
  101.               Pm_Error := Pm_WriteShort(PortMidiStream_Ptr, Pt_Time, Pm_Event.message);
  102.               if Pm_HasHostError(PortMidiStream_Ptr) /= 0 then
  103.                  Put_line(To_Ada(Pm_GetErrorText(Pm_Error)));
  104.               else
  105.                  Put_line("Pm_Write... Ok !" );
  106.               end if;
  107.            end select;
  108.            exit when Entract;
  109.         end loop;
  110.      end loop;
  111.   end T_Musician;
  112.  
  113.  
  114. end Musician;


 
Mais vraiment au pif.
 
Merci pour votre participation, votre aide.. et tout et tout.  :jap:


---------------
des gestes simples et ponctués, par quelques points presque importants, la précision coordonnée, d'une île déserte, des plans secrets, d'un architecte, à la retraite, passionné par son métier, refaire le monde, à son idée, tracer des routes, les emprunter
Reply

Marsh Posté le 13-08-2009 à 11:47:20   

Reply

Marsh Posté le 14-08-2009 à 14:47:42    

Bonjour,
 
Question de capacité intellectuelle, je me sans limité sur le coup !
 
Pour construire les message MIDI à envoyer, je doit me référer à la norme General MIDI.
N'ayant pas trouvé de document ressemblant à celui-ci  ::= RADIAS MIDI Implementation je vais donc m'en contenter pour le moment quitte à tout refaire plus tard, ça me fera un exercice. Mais, le problème c'est que j'ai beaucoup de mal à le comprendre. Il est plein de référence, c'est un vrai code.
 
Donc, si vous avez un connaissance du problème, ou le temps et l'envie de vous y intéresser... La question est : Comment dois-je m'y prendre pour modéliser les différents types utilisés ?
 
Je suis même pas certain de poser la bonne question  [:tinostar]


Message édité par The matrix le 14-08-2009 à 14:49:13

---------------
des gestes simples et ponctués, par quelques points presque importants, la précision coordonnée, d'une île déserte, des plans secrets, d'un architecte, à la retraite, passionné par son métier, refaire le monde, à son idée, tracer des routes, les emprunter
Reply

Marsh Posté le 15-08-2009 à 07:51:00    

Bonjour,
 
Je vous poste ce que j'ai commencer à faire dans le cadre de l'implémentation de la norme General MIDI, la critique sera plus facile...
 
En fait, il ne s'agit pas tout à fait de la General MIDI, mais de l'implémentation MIDI d'un instrument particulier, nommé Radias (Vois le doc ci-dessus)
 

Code :
  1. package Midi_Implementation is
  2.  
  3.   subtype T_Chanel is Natural range 0..15;
  4.  
  5.   subtype T_Note_Sens is Positive range 1..127;
  6.   subtype T_Note is Positive range 21..108;
  7.  
  8.   Note_Off : constant T_Note := 64;
  9.  
  10.   subtype T_Bank is Natural range 0..1;
  11.   subtype T_Program is Natural range 0..127;
  12.  
  13.   Arp_Off : constant Natural := 0;
  14.   Arp_On  : constant Natural := 127;
  15.   Latch_Off : constant Natural := 0;
  16.   Latch_On  : constant Natural := 127;
  17.  
  18.   Arp_Type_up : constant Natural := 16#0#;
  19.   Arp_Type_down : constant Natural := 16#15#;
  20.   Arp_Type_alt1 : constant Natural := 16#2A#;
  21.   Arp_Type_alt2 : constant Natural := 16#3F#;
  22.   Arp_Type_random : constant Natural := 16#54#;
  23.   Arp_Type_trigger : constant Natural := 16#69#;
  24.  
  25.   subtype T_Arp_Gate is Natural range 0..127;
  26.  
  27.   Arp_Select_Off : constant Natural := 0;
  28.   Arp_Select_arp : constant Natural := 1;
  29.   Arp_Select_Step_Seq_1 : constant Natural := 2;
  30.   Arp_Select_Step_Seq_2 : constant Natural := 3;
  31.  
  32.   Step_Seq_1_Latch_off : constant Natural := 0;
  33.   Step_Seq_1_Latch_on  : constant Natural := 127;
  34.  
  35.   subtype Step_Seq_1_Gate is Natural range 0..127;
  36.  
  37.   Step_Seq_2_Latch_off : constant Natural := 0;
  38.   Step_Seq_2_Latch_on  : constant Natural := 127;
  39.  
  40.   subtype Step_Seq_2_Gate is Natural range 0..127;
  41.  
  42. end Midi_Implementation;


 
Je suis carrément paumé là [:tinostar]

Reply

Marsh Posté le 15-08-2009 à 15:25:09    

Bonjour, pour l'implémentation midi de finalement ça prends plutôt la fomre suivante  :
 
j'ai fait ça :
 
midi_implementation.ads

Code :
  1. with Message;
  2. use Message;
  3.  
  4. package Midi_Implementation is
  5.  
  6.   subtype T_Chanel is Natural range 0..15;
  7.   subtype T_Note_Sens is Positive range 1..127;
  8.   subtype T_Note is Positive range 21..108;
  9.   function Note_On(Chanel : in T_Chanel;
  10.                    Note : in T_Note;
  11.                    Sens : in T_Note_Sens) return T_Message;
  12.  
  13.   function Note_Off (Chanel : in T_Chanel;
  14.                     Note : in T_Note) return T_Message;
  15.  
  16.   subtype T_Bank is Natural range 0..1;
  17.   subtype T_Program is Natural range 0..127;
  18.  
  19.   function Bank_Select_MSB(Chanel : in T_Chanel;
  20.                            Bank : in T_Bank) return T_Message;
  21.   function Bank_Select_LSB(Chanel : in T_Chanel;
  22.                            Program : in T_Program) return T_Message;
  23.  
  24.   function Program_Change(Chanel : in T_Chanel) return T_Message;
  25.  
  26.   subtype T_Value is Natural range 1..127;
  27.  
  28.   function NRPM_MSB (Chanel : in T_Chanel;
  29.                      Value : in T_Value) return T_Message;
  30.   function NRPM_LSB (Chanel : in T_Chanel;
  31.                      Value : in T_Value) return T_Message;
  32.   function Data_Entry_MSB (Chanel : in T_Chanel;
  33.                            Value : in T_Value) return T_Message;
  34.  
  35.  
  36. end Midi_Implementation;


 
midi_implementation.adb

Code :
  1. function Note_On(Chanel : in T_Chanel;
  2.                    Note : in T_Note;
  3.                    Sens : in T_Note_Sens) return T_Message is
  4.  
  5.      Message : T_Message := (16#90# + Chanel, Note, Sens);
  6.   begin
  7.  
  8.      return Message;
  9.   end;
  10.   function Note_Off (Chanel : in T_Chanel;
  11.                     Note : in T_Note) return T_Message is
  12.      Message : T_Message := (16#80# + Chanel, Note, 64);
  13.   begin
  14.  
  15.      return Message;
  16.   end;
  17.   function Bank_Select_MSB(Chanel : in T_Chanel;
  18.                            Bank : in T_Bank) return T_Message is
  19.  
  20.      Message : T_Message := (16#B0# + chanel, 0 , Bank);
  21.   begin
  22.  
  23.      return Message;
  24.   end;
  25.  
  26.   function Bank_Select_LSB(Chanel : in T_Chanel;
  27.                            Program : in T_Program) return T_Message is
  28.  
  29.      Message : T_Message := (16#B0# + chanel, 32 , Program);
  30.   begin
  31.  
  32.      return Message;
  33.   end;
  34.  
  35.   function Program_Change(Chanel : in T_Chanel) return T_Message is
  36.  
  37.      Message : T_Message := (16#B0# + chanel, 1, 0);
  38.   begin
  39.  
  40.      return Message;
  41.   end;
  42.  
  43.   function NRPM_MSB (Chanel : in T_Chanel;
  44.                      Value : in T_Value) return T_Message is
  45.  
  46.      Message : T_Message := (16#B0# + Chanel, 98, Value);
  47.   begin
  48.  
  49.      return Message;
  50.   end;
  51.  
  52.   function NRPM_LSB (Chanel : in T_Chanel;
  53.                      Value : in T_Value) return T_Message is
  54.  
  55.      Message : T_Message := (16#B0# + Chanel, 99, Value);
  56.   begin
  57.  
  58.      return Message;
  59.   end;
  60.   function Data_Entry_MSB (Chanel : in T_Chanel;
  61.                            Value : in T_Value) return T_Message is
  62.  
  63.      Message : T_Message := (16#B0# + Chanel, 6, Value);
  64.   begin
  65.  
  66.      return Message;
  67.   end;
  68.  
  69. end Midi_Implementation;


 
Et j'appelle comme ça :
 

Code :
  1. Oeuvre(1).Last_content := 1;
  2.      Oeuvre(1).Staff(4) := Bank_Select_MSB(15, 0);
  3.      Oeuvre(1).Staff(4) := Bank_Select_LSB(15, 14);
  4.      Oeuvre(1).Staff(4) := Program_change(15);
  5.      Oeuvre(1).Staff(4) := Note_On(0, 60, 100);


 
J'ai déjà testé un note-on, mais la le Bank_Select_MSB marche pas !
la lib midiport me dit

Citation :

PortMidi call failed...
  PortMidi: `Illegal error number'
type ENTER...


Message édité par Profil supprimé le 15-08-2009 à 15:26:23
Reply

Marsh Posté le 15-08-2009 à 15:40:37    

Citation :

#
euvre(1).Last_content := 1;
     Oeuvre(1).Staff(4) := Bank_Select_MSB(15, 0);
     Oeuvre(1).Staff(4) := Bank_Select_LSB(15, 14);
     Oeuvre(1).Staff(4) := Program_change(15);
     Oeuvre(1).Staff(4) := Note_On(0, 60, 100);


 
Tein, ça j'avais pas fait gaffe... Tous les message sont en 4ieme position de la partition. [:tinostar]
 
Flood, désolé !
 
Du coup, j'ai résolut mon problème. Merci  :D

Reply

Marsh Posté le 15-08-2009 à 16:18:32    

Yep !
 
J'ai un problème avec une boucle qui tourne pas. je devrais écrire 4 fois, et je n'en voie qu'un passer.
 
Voyez vous même :
 

Code :
  1. with Text_Io;
  2. with System;
  3. with System.Address_To_Access_Conversions;
  4. with Interfaces.C;
  5. with Portmidi, Porttime;
  6. use Text_Io;
  7. use System;
  8. use Interfaces.C;
  9. use Portmidi, Porttime;
  10.  
  11. with Queue;
  12.  
  13.  
  14. package body Musician is
  15.  
  16.   subtype SubString is Char_array(1..64);
  17.   package String_Address_Conversion is new System.Address_To_Access_Conversions(substring);
  18.   use String_Address_conversion;
  19.  
  20.   package Partition_Queue is new Queue(T_Partition);
  21.   use Partition_Queue;
  22.  
  23.  
  24.   task body T_Musician is
  25.      End_Of_Task : Boolean := False;
  26.      Entract : Boolean := False;
  27.  
  28.      Pm_Error : PmError;
  29.  
  30.      PortMidiStream_Ptr : System.Address;
  31.  
  32.      OutputDriverInfo_Ptr : System.Address := Null_Address;
  33.  
  34.      Resolution : Integer := 1;
  35.      PtCallback,
  36.      UserData : System.Address := Null_Address;
  37.  
  38.      Pm_Event : PmEvent;
  39.  
  40.  
  41.      wait : Duration := 0.03;
  42.      Index : Natural := 0;
  43.  
  44.      Current_Partition : T_Partition;
  45.      Queue_Of_Partition : T_Queue;
  46.  
  47.   begin
  48.  
  49.      accept Initialize(Instrument : T_instrument) do
  50.         Queue_Init(Queue_Of_Partition);
  51.         PortMidiStream_Ptr := Open_Handler(Instrument);
  52.         Put_line("Pm_OpenOutput... Ok !" );
  53.      end Initialize;
  54.      accept Adjust(Partition : T_Partition) do
  55.         Current_Partition := Partition;
  56.         Index := 1;
  57.      end Adjust;
  58.      while not End_Of_Task loop
  59.         accept Start do
  60.            Entract := False;
  61.         end Start;
  62.         loop
  63.            select
  64.               accept Receive(Partition : T_Partition) do
  65.                  Queue_Push(Queue_Of_Partition, Partition);
  66.               end Receive;
  67.            or
  68.               accept Tempo(Length : in Duration) do
  69.                  Wait := Length;
  70.               end Tempo;
  71.        or
  72.               accept Sync do
  73.                  null;
  74.               end Sync;
  75.            or
  76.               accept Stop do
  77.                  Entract := True;
  78.               end Stop;
  79.            or
  80.               accept Halt do
  81.                  Pm_Error := Pm_Close(PortMidiStream => PortMidiStream_ptr);
  82.                  --Put_line(To_ada(Pm_GetErrorText(Pm_Error))); -- Cause Error C Terminator;
  83.                  Entract := True;
  84.                  End_Of_Task := True;
  85.               end Halt;
  86.            or
  87.               delay 0.0;
  88.               if Index /= 0 then
  89.                  Pm_Event.Message := Pm_Message(Current_Partition.Staff(Index));
  90.                  Pm_Event.PmTimestamp := Pt_time;
  91.                  Pm_Error := Pm_WriteShort(PortMidiStream_Ptr, Pt_Time, Pm_Event.message);
  92.                  if Pm_HasHostError(PortMidiStream_Ptr) /= 0 then
  93.                     Put_line(To_Ada(Pm_GetErrorText(Pm_Error)));
  94.                  else
  95.                     Put_line("Pm_Write... Ok !" );
  96.                     if Index < Current_Partition.Last_Content then
  97.                        Index := Index + 1;
  98.                     else
  99.                        if not Queue_Empty(Queue_Of_Partition) then
  100.                           Queue_Pop(Queue_Of_Partition, Current_Partition);
  101.                           Index := 1;
  102.                        else
  103.                           Index := 0;
  104.                        end if;
  105.  
  106.                     end if;
  107.                  end if;
  108.                  delay Wait;
  109.               end if;
  110.            end select;
  111.            exit when Entract;
  112.         end loop;
  113.      end loop;
  114.   end T_Musician;


 
Merci !

Reply

Marsh Posté le 15-08-2009 à 16:35:18    

C'est la panique [:kernel panic]
 
Désolé, pas pris les bon réflexe encore. je vais tracer.  
 
 :o

Reply

Marsh Posté le 30-08-2009 à 22:40:52    

Bonsoir, Bonjour,
 
j'ai un problème avec mon séquenceur. Harmonie-0.1.0-2b.tar.gz pour Gnu/linux.
En effet, j'ai un gros problème de rendez-vous entre tache.
Mais je distingue trois phénomènes.
Le système peut ce caler sur la tache la plus lente.
Ou alors, si il y a une grande différence de longueur de note, ça semble passer.
Et si non, on dirait qu'il est impossible d'envoyer une donnée synthé sans une donné drum ou inversement.
Il faut regarder dans le fichier Great_Architect.adb
La longueur d'une note est modélisé par un delay dans les taches Drum et Synth.
Voila, C'est toujours un peu complexe... Avis au amateurs.
 
Merci pour votre aide, bien à vous !


Message édité par The matrix le 30-08-2009 à 22:41:42

---------------
des gestes simples et ponctués, par quelques points presque importants, la précision coordonnée, d'une île déserte, des plans secrets, d'un architecte, à la retraite, passionné par son métier, refaire le monde, à son idée, tracer des routes, les emprunter
Reply

Marsh Posté le 09-06-2010 à 10:17:19    

Bonjour à vous.
 
Je me casse la tête ce matin pour reconstruire un séquenceur.
J'avais dans l'idée de faire une queue par piste et de lire chaque piste en parallèle mais je me heurte au type de donnée à fournir.
J'ai tout un tas d'instruction midi à transmettre et toutes ces instructions sont formées de divers données comme entre autre le N° de piste.
Je me dis alors qu'il n'est pas possible de faire comme j'en avais l'intention.
 
Je viens donc poser pour réveiller l'analyste qui sommeille en vous (j'espère qu'à cette heure il soit tout de même bien réveillé) la question...
Qu'est-ce qu'un séquenceur Midi, comment est-ce construit ?
Merci pour votre contribution.
 

Reply

Marsh Posté le 20-02-2012 à 17:37:00    

Lutin, faut avoir la tête à ça pour répondre, si on le sais pas.
 
Bon, alors j'essaye de pondre.
 
C'est un espace de message MID géré en temps réel et partagé par deux processus dont l'un permet d'écrire dans l'espace de message MIDI et l'autre permet de transmettre les messages à instrument MIDI.
 
Pour le faire, je ferais deux espaces de message, un disponible en écriture pendant que l'autre l'est en lecture et je ferais une lecture/écriture et une rotation des espace en fonction du tempo.
 
Ok !

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed