Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
830 connectés 

  FORUM HardWare.fr
  Programmation
  Ada

  Séquenceur MIDI avec Ada

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Séquenceur MIDI avec Ada

n°1914716
The matrix
Chacun fait ce qu'il en veut.
Posté le 13-08-2009 à 11:47:20  profilanswer
 

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
mood
Publicité
Posté le 13-08-2009 à 11:47:20  profilanswer
 

n°1915156
The matrix
Chacun fait ce qu'il en veut.
Posté le 14-08-2009 à 14:47:42  profilanswer
 

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
n°1915343
Profil sup​primé
Posté le 15-08-2009 à 07:51:00  answer
 

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]

n°1915396
Profil sup​primé
Posté le 15-08-2009 à 15:25:09  answer
 

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
n°1915404
Profil sup​primé
Posté le 15-08-2009 à 15:40:37  answer
 

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

n°1915413
Profil sup​primé
Posté le 15-08-2009 à 16:18:32  answer
 

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 !

n°1915416
Profil sup​primé
Posté le 15-08-2009 à 16:35:18  answer
 

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

n°1919714
The matrix
Chacun fait ce qu'il en veut.
Posté le 30-08-2009 à 22:40:52  profilanswer
 

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
n°2000102
Profil sup​primé
Posté le 09-06-2010 à 10:17:19  answer
 

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.
 

n°2127330
Profil sup​primé
Posté le 20-02-2012 à 17:37:00  answer
 

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 !


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Ada

  Séquenceur MIDI avec Ada

 

Sujets relatifs
[Résolut]liaison Ada avec un .o Caccès à fonction importée à accè à fonction importé.
utilisation d'un librairie C avec Ada.[Ada] [Conception] Un compositeur interprète avec Ada.
[Divers][Lecture]Utilisation de la bibliothèque portmidi : Pm_Read()Interface C/Ada + SDL
Fonction C times en Ada.Faire des cadres en 'texte' avec Ada
Problème de Random pour Dichotomie 
Plus de sujets relatifs à : Séquenceur MIDI avec Ada


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR