IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Delphi Discussion :

Générer un fichier midi à partir d'une liste de notes


Sujet :

Contribuez Delphi

  1. #1
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    mai 2002
    Messages
    2 623
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mai 2002
    Messages : 2 623
    Points : 6 492
    Points
    6 492
    Par défaut Générer un fichier midi à partir d'une liste de notes
    A la demande générale (http://www.developpez.net/forums/d14...-fichier-midi/), voici une petite fonction pour générer un fichier midi à partir d'une liste de notes.
    Je précise que mon code n'est probablement pas optimisé, mais ça pourra servir de base à ceux qui voudraient s'y mettre (les docs techniques sur la structure du fichier midi sont rares et peu détaillées).

    Voici déjà la fonction, avec juste ce qu'il faut pour jouer des notes simples (j'ai enlevé tout le reste pour ne pas compliquer la compréhension):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    function GenererFichierMidi(out nNbNotes: Integer; const szFichier: String): String;
       function HexByte(szHexa: String): Byte;
       var
          i: Byte;
          nSomme, nChiffre: Integer;
          szTmp: String;
          Car: Char;
       begin
          szTmp := '';
          nSomme := 0;
     
          if Length(szHexa) >= 2 then
             szTmp := Copy(szHexa, 1, 4)
          else if Length(szHexa) < 2 then
          begin
             while Length(szHexa) < 2 do
                szHexa := '0' + szHexa;
          end;
     
          for i:=2 downto 1 do
          begin
             Car := szHexa[i];
             nChiffre := 0;
     
             if(Car in ['0'..'9']) then
                nChiffre := Ord(Car) - 48
             else if(Car in ['A'..'F']) then
                nChiffre := Ord(Car) - 55;
     
             case i of
                1:
                   nSomme := nSomme + (nChiffre * 16);
                2:
                   nSomme := nSomme + nChiffre;
             end;
          end;
     
          Result := Byte(nSomme);
       end;
     
       function FormatTaille6(const nTaille: Integer): String;
       var
          szTaille: String;
       begin
          szTaille := IntToHex(nTaille, 6);         
          Result := Chr(HexByte(LeftStr(szTaille, 2))) + Chr(HexByte(Copy(szTaille, 3, 2))) + Chr(HexByte(RightStr(szTaille, 2)));
       end;
     
       function FormatTaille2(const nValeur: Integer): String;
       var
          szValeur: String;
       begin
          szValeur := IntToHex(nValeur, 2);
          Result := Chr(HexByte(szValeur));
       end;
     
       function GetRepertoireTemp: String;
       var
          Valeur: Array[0..MAX_PATH] of Char;
       begin
          GetTempPath(Length(Valeur), @Valeur);
          Result := Valeur;
       end;
    const
       MTRK_TITRE = #3;
       MTRK_TEMPO = #81;
       MTRK_MESURE = #88;
       MTRK_DUREE_NOIRE = #8;      // Durée d'une noire 8/32 = 1/4.
       MTRK_NOM_INSTRUMENT = #4;
       MTRK_NOTE_OFF = '8';
       MTRK_NOTE_ON = '9';
       MTRK_INSTRUMENT = 'C';
       MTRK_EVENEMENT_CONTROLE = 'B';
       MTRK_VOLUME = '7';
       MTRK_FIN = #47;
       CANAL_0 = '0';
    var
       szNbPistes, szRythme, szLongueurTitre, szTitre, szTempo, szLongueurTempo, szMesure, szLongueurMesure, szMtrk1: String;
       szLongeurNomInstrument, szNomInstrument, szInstrumentMidi, szControleVolume, szVolume, szNotes, szMtrk2: String;
       i, j, k, nTailleMTrk1, nTailleMTrk2, nDureeDelta: Integer; 
       Note: TNote;
       DureeDelta: Char;
       ListeNotesPosition: TObjectList;
       F: TextFile;
    begin
       Result := '';
     
       // Si portée.
       if _ListeElements.Count > 0 then
       begin
          // --------------------------------------------------- Mtrk 1 ---------------------------------------------------
          szNbPistes := #2;
          szRythme := FormatTaille2(_nRythme);      // Battements par quart de note.
          szTitre := IfThen(_szTitre = '', ' ', LeftStr(_szTitre, 255));      szLongueurTitre := FormatTaille2(Length(szTitre));
          szTempo := FormatTaille6(60000000 div _nTempo);      szLongueurTempo := #3;      // Battements (noires) par minute.
          szMesure := #4#2#24 + MTRK_DUREE_NOIRE;      szLongueurMesure := #4;      // Métronome.         
     
          // Préparation Mtrk1.
          szMtrk1 := #0#255 + MTRK_TITRE + szLongueurTitre + szTitre;                         
          szMtrk1 := szMtrk1 + #0#255 + MTRK_TEMPO + szLongueurTempo + szTempo;               
          szMtrk1 := szMtrk1 + #0#255 + MTRK_MESURE + szLongueurMesure + szMesure + #176;     
          szMtrk1 := szMtrk1 + #0#255 + MTRK_FIN + #0;                                        
          nTailleMTrk1 := Length(szMtrk1);
     
          // --------------------------------------------------- Mtrk 2 ---------------------------------------------------
          szNomInstrument := (_ListeInstruments[0] as TInstrument)._szNomInstrument;      szLongeurNomInstrument := FormatTaille2(Length(szNomInstrument));
          szInstrumentMidi := FormatTaille2((_ListeInstruments[0] as TInstrument)._nInstrumentMidi - 1);      // Programme (patch).
          szControleVolume := Chr(HexByte(MTRK_VOLUME));
          szVolume := FormatTaille2(_nVolume);
          szNotes := '';      nNbNotes := 0;    
          DureeDelta := #0;
          ListeNotesPosition := TObjectList.Create;
          try
             // Parcours des notes.
             for i:=0 to Pred(_ListeIndexPortee.Count) do
             begin
                // Parcours des éléments de la position.
                for j:=0 to Pred((_ListeIndexPortee[i] as TIndexPortee)._ListeElements.Count) do
                begin
                   // Si note.
                   if((_ListeIndexPortee[i] as TIndexPortee)._ListeElements[j] as TElement).GetTypeElement = eNote then
                   begin
                      Note := ((_ListeIndexPortee[i] as TIndexPortee)._ListeElements[j] as TNote);
     
                      szNotes := szNotes + DureeDelta + Chr(HexByte(MTRK_NOTE_ON + IntToStr(j))) + Note._NoteMidi + FormatTaille2(Note._nVelocite);
                      DureeDelta := Note.GetDureeMidi;      // Durée delta note-off.
     
                      szNotes := szNotes + DureeDelta + Chr(HexByte(MTRK_NOTE_OFF + IntToStr(j))) + Note._NoteMidi + FormatTaille2(Note._nVelocite);
                      DureeDelta := #0;
     
                      Inc(nNbNotes);
                   end
                   else if((_ListeIndexPortee[i] as TIndexPortee)._ListeElements[j] as TElement).GetTypeElement = eSilence then      // Si silence.
                   begin
                      // Si silences successifs.
                      if DureeDelta <> #0 then
                         DureeDelta := Chr(Ord(DureeDelta) + Ord(((_ListeIndexPortee[i] as TIndexPortee)._ListeElements[j] as TSilence).GetDureeMidi))
                      else
                         DureeDelta := ((_ListeIndexPortee[i] as TIndexPortee)._ListeElements[j] as TSilence).GetDureeMidi;
                   end;
                end;
             end;
             szNotes := szNotes + #0#144;
          finally
             ListeNotesPosition.Free;
          end;
     
          // Préparation Mtrk2.
          szMtrk2 := #0#255#33#1#1;                                                                                                 
          szMtrk2 := szMtrk2 + #0#255 + MTRK_NOM_INSTRUMENT + szLongeurNomInstrument + szNomInstrument;                             
          szMtrk2 := szMtrk2 + #0 + Chr(HexByte(MTRK_INSTRUMENT + CANAL_0)) + szInstrumentMidi;      // C0 = #12 + canal 0.
          AjoutLogFichierMidi('', '', #0 + Chr(HexByte(MTRK_INSTRUMENT + CANAL_0)) + szInstrumentMidi, '');
          szMtrk2 := szMtrk2 + #0 + Chr(HexByte(MTRK_EVENEMENT_CONTROLE + CANAL_0)) + szControleVolume + szVolume;                    
          szMtrk2 := szMtrk2 + szNotes;                                                                                              
          szMtrk2 := szMtrk2 + #153#96#16#128#153#96;                                                                                
          szMtrk2 := szMtrk2 + #0#255 + MTRK_FIN + #0;                                                                               
          nTailleMTrk2 := Length(szMtrk2);                                                                                             
       end
       else
          Exit;
     
       // --------------------------------------------------- Fichier ---------------------------------------------------
       if szFichier = '' then
          Result := GetRepertoireTemp + 'Test.mid'
       else
          Result := szFichier;
     
       // Génération du fichier.
       AssignFile(F, Result);
       try
          Rewrite(F);
          Write(F, 'MThd' + #0#0#0#6);
          Write(F, #0#1);         // SMF1 :  plusieurs pistes successives, jouées simultanément. 
          Write(F, #0 + szNbPistes);                                
          Write(F, #0 + szRythme);                                  
          Write(F, 'MTrk' + #0 + FormatTaille6(nTailleMTrk1));
          Write(F, szMtrk1);
          Write(F, 'MTrk' + #0 + FormatTaille6(nTailleMTrk2));
          Write(F, szMtrk2);
       finally
          CloseFile(F);
       end;
    end;
    Donc, on retrouve la préparation de l'en-tête MThd et de deux zones MTrk.
    La deuxième zone MTrk étant la liste des notes (qui sont des suites de note-on et de note-off) que je trouve en balayant ma liste _ListeElements (la liste _ListeIndexPortee, j'en parlerais plus tard).
    A la fin, je génère le fichier midi, qu'il ne reste plus qu'à donner à manger à un TMediaPlayer par exemple.

    j'ai choisis de travailler en décimal et non en hexadécimal comme sont habituellement notés les codes dans les docs.
    Je ne sais pas si mon code est suffisamment clair et compréhensible. S'il faut rajouter quelques précisions, dites-le moi (mais je ne garanti pas d'avoir réponse à tout, ni de ne pas me tromper ).
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise
    OpenGL 2.1 - Oracle 10g - Interbase (7 - XE) - PostgreSQL 11.6

  2. #2
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    mai 2002
    Messages
    2 623
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mai 2002
    Messages : 2 623
    Points : 6 492
    Points
    6 492
    Par défaut
    Et voici la même, mais en gérant en plus les notes jouées en même temps :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    function GenererFichierMidi(out nNbNotes: Integer; const szFichier: String): String;
       function CompareNotesPosition(Item1, Item2: Pointer): Integer;
       begin
          if TNotePos(Item1)._nDelta > TNotePos(Item2)._nDelta then
             Result := 1
          else if TNotePos(Item1)._nDelta < TNotePos(Item2)._nDelta then
             Result := -1
          else
             Result := 0;
       end;
     
       function HexByte(szHexa: String): Byte;
       var
          i: Byte;
          nSomme, nChiffre: Integer;
          szTmp: String;
          Car: Char;
       begin
          szTmp := '';
          nSomme := 0;
     
          if Length(szHexa) >= 2 then
             szTmp := Copy(szHexa, 1, 4)
          else if Length(szHexa) < 2 then
          begin
             while Length(szHexa) < 2 do
                szHexa := '0' + szHexa;
          end;
     
          for i:=2 downto 1 do
          begin
             Car := szHexa[i];
             nChiffre := 0;
     
             if(Car in ['0'..'9']) then
                nChiffre := Ord(Car) - 48
             else if(Car in ['A'..'F']) then
                nChiffre := Ord(Car) - 55;
     
             case i of
                1:
                   nSomme := nSomme + (nChiffre * 16);
                2:
                   nSomme := nSomme + nChiffre;
             end;
          end;
     
          Result := Byte(nSomme);
       end;
     
       function FormatTaille6(const nTaille: Integer): String;
       var
          szTaille: String;
       begin
          szTaille := IntToHex(nTaille, 6);         
          Result := Chr(HexByte(LeftStr(szTaille, 2))) + Chr(HexByte(Copy(szTaille, 3, 2))) + Chr(HexByte(RightStr(szTaille, 2)));
       end;
     
       function FormatTaille2(const nValeur: Integer): String;
       var
          szValeur: String;
       begin
          szValeur := IntToHex(nValeur, 2);
          Result := Chr(HexByte(szValeur));
       end;
     
       function GetRepertoireTemp: String;
       var
          Valeur: Array[0..MAX_PATH] of Char;
       begin
          GetTempPath(Length(Valeur), @Valeur);
          Result := Valeur;
       end;
    const
       MTRK_TITRE = #3;
       MTRK_TEMPO = #81;
       MTRK_MESURE = #88;
       MTRK_DUREE_NOIRE = #8;      // Durée d'une noire 8/32 = 1/4.
       MTRK_NOM_INSTRUMENT = #4;
       MTRK_NOTE_OFF = '8';
       MTRK_NOTE_ON = '9';
       MTRK_INSTRUMENT = 'C';
       MTRK_EVENEMENT_CONTROLE = 'B';
       MTRK_VOLUME = '7';
       MTRK_FIN = #47;
       CANAL_0 = '0';
    var
       szNbPistes, szRythme, szLongueurTitre, szTitre, szTempo, szLongueurTempo, szMesure, szLongueurMesure, szMtrk1: String;
       szLongeurNomInstrument, szNomInstrument, szInstrumentMidi, szControleVolume, szVolume, szNotes, szMtrk2: String;
       i, j, k, nTailleMTrk1, nTailleMTrk2, nDureeDelta: Integer; 
       Note: TNote;
       DureeDelta: Char;
       ListeNotesPosition: TObjectList;
       F: TextFile;
    begin
       Result := '';
     
       // Si portée.
       if _ListeElements.Count > 0 then
       begin
          // --------------------------------------------------- Mtrk 1 ---------------------------------------------------
          szNbPistes := #2;
          szRythme := FormatTaille2(_nRythme);      // Battements par quart de note.
          szTitre := IfThen(_szTitre = '', ' ', LeftStr(_szTitre, 255));      szLongueurTitre := FormatTaille2(Length(szTitre));
          szTempo := FormatTaille6(60000000 div _nTempo);      szLongueurTempo := #3;      // Battements (noires) par minute.
          szMesure := #4#2#24 + MTRK_DUREE_NOIRE;      szLongueurMesure := #4;      // Métronome.         
     
          // Préparation Mtrk1.
          szMtrk1 := #0#255 + MTRK_TITRE + szLongueurTitre + szTitre;                         
          szMtrk1 := szMtrk1 + #0#255 + MTRK_TEMPO + szLongueurTempo + szTempo;               
          szMtrk1 := szMtrk1 + #0#255 + MTRK_MESURE + szLongueurMesure + szMesure + #176;     
          szMtrk1 := szMtrk1 + #0#255 + MTRK_FIN + #0;                                        
          nTailleMTrk1 := Length(szMtrk1);
     
          // --------------------------------------------------- Mtrk 2 ---------------------------------------------------
          szNomInstrument := (_ListeInstruments[0] as TInstrument)._szNomInstrument;      szLongeurNomInstrument := FormatTaille2(Length(szNomInstrument));
          szInstrumentMidi := FormatTaille2((_ListeInstruments[0] as TInstrument)._nInstrumentMidi - 1);      // Programme (patch).
          szControleVolume := Chr(HexByte(MTRK_VOLUME));
          szVolume := FormatTaille2(_nVolume);
          szNotes := '';      nNbNotes := 0;    
          DureeDelta := #0;
          ListeNotesPosition := TObjectList.Create;
          try
             // Parcours des notes.
             for i:=0 to Pred(_ListeIndexPortee.Count) do
             begin
                // Parcours des éléments de la position.
                for j:=0 to Pred((_ListeIndexPortee[i] as TIndexPortee)._ListeElements.Count) do
                begin
                   // Si note.
                   if((_ListeIndexPortee[i] as TIndexPortee)._ListeElements[j] as TElement).GetTypeElement = eNote then
                   begin
                      Note := ((_ListeIndexPortee[i] as TIndexPortee)._ListeElements[j] as TNote);
     
                      szNotes := szNotes + DureeDelta + Chr(HexByte(MTRK_NOTE_ON + IntToStr(j))) + Note._NoteMidi + FormatTaille2(Note._nVelocite);
     
                      // Si plus d'un élément.
                      if(_ListeIndexPortee[i] as TIndexPortee)._ListeElements.Count > 1 then
                      begin
                         ListeNotesPosition.Add(TNotePos.Create(Chr(HexByte(MTRK_NOTE_OFF + IntToStr(j))) + Note._NoteMidi + FormatTaille2(Note._nVelocite), Integer(Note.GetDureeMidi)));
                         DureeDelta := #0;
                      end
                      else
                         DureeDelta := Note.GetDureeMidi;      // Durée delta note-off.
     
                      // Si un seul élément.
                      if(_ListeIndexPortee[i] as TIndexPortee)._ListeElements.Count = 1 then
                      begin
                         szNotes := szNotes + DureeDelta + Chr(HexByte(MTRK_NOTE_OFF + IntToStr(j))) + Note._NoteMidi + FormatTaille2(Note._nVelocite);
                         DureeDelta := #0;
                      end;
     
                      Inc(nNbNotes);
                   end
                   else if((_ListeIndexPortee[i] as TIndexPortee)._ListeElements[j] as TElement).GetTypeElement = eSilence then      // Si silence.
                   begin
                      // Si silences successifs.
                      if DureeDelta <> #0 then
                         DureeDelta := Chr(Ord(DureeDelta) + Ord(((_ListeIndexPortee[i] as TIndexPortee)._ListeElements[j] as TSilence).GetDureeMidi))
                      else
                         DureeDelta := ((_ListeIndexPortee[i] as TIndexPortee)._ListeElements[j] as TSilence).GetDureeMidi;
                   end;
     
                   // Si dernier des éléments.
                   if((_ListeIndexPortee[i] as TIndexPortee)._ListeElements.Count > 1) and (j = Pred((_ListeIndexPortee[i] as TIndexPortee)._ListeElements.Count)) then
                   begin
                      // Tri de la liste.
                      ListeNotesPosition.Sort(@CompareNotesPosition);
     
                      nDureeDelta := 0;
                      for k:=0 to Pred(ListeNotesPosition.Count) do
                      begin
                         if k = 0 then
                            nDureeDelta := (ListeNotesPosition[k] as TNotePos)._nDelta
                         else
                            nDureeDelta := ((ListeNotesPosition[k] as TNotePos)._nDelta - nDureeDelta);
                         DureeDelta := Char(nDureeDelta);
     
                         szNotes := szNotes + DureeDelta + (ListeNotesPosition[k] as TNotePos)._szNoteOff;
                      end;
     
                      ListeNotesPosition.Clear;
                   end;
                end;
             end;
             szNotes := szNotes + #0#144;
          finally
             ListeNotesPosition.Free;
          end;
     
          // Préparation Mtrk2.
          szMtrk2 := #0#255#33#1#1;                                                                                                 
          szMtrk2 := szMtrk2 + #0#255 + MTRK_NOM_INSTRUMENT + szLongeurNomInstrument + szNomInstrument;                             
          szMtrk2 := szMtrk2 + #0 + Chr(HexByte(MTRK_INSTRUMENT + CANAL_0)) + szInstrumentMidi;      // C0 = #12 + canal 0.
          AjoutLogFichierMidi('', '', #0 + Chr(HexByte(MTRK_INSTRUMENT + CANAL_0)) + szInstrumentMidi, '');
          szMtrk2 := szMtrk2 + #0 + Chr(HexByte(MTRK_EVENEMENT_CONTROLE + CANAL_0)) + szControleVolume + szVolume;                    
          szMtrk2 := szMtrk2 + szNotes;                                                                                              
          szMtrk2 := szMtrk2 + #153#96#16#128#153#96;                                                                                
          szMtrk2 := szMtrk2 + #0#255 + MTRK_FIN + #0;                                                                               
          nTailleMTrk2 := Length(szMtrk2);                                                                                             
       end
       else
          Exit;
     
       // --------------------------------------------------- Fichier ---------------------------------------------------
       if szFichier = '' then
          Result := GetRepertoireTemp + 'Test.mid'
       else
          Result := szFichier;
     
       // Génération du fichier.
       AssignFile(F, Result);
       try
          Rewrite(F);
          Write(F, 'MThd' + #0#0#0#6);
          Write(F, #0#1);         // SMF1 :  plusieurs pistes successives, jouées simultanément. 
          Write(F, #0 + szNbPistes);                                
          Write(F, #0 + szRythme);                                  
          Write(F, 'MTrk' + #0 + FormatTaille6(nTailleMTrk1));
          Write(F, szMtrk1);
          Write(F, 'MTrk' + #0 + FormatTaille6(nTailleMTrk2));
          Write(F, szMtrk2);
       finally
          CloseFile(F);
       end;
    end;
    Voilà à quoi sert la fameuse liste _ListeIndexPortee. Elle correspond à une position sur la partition. Et à chaque position, _ListeElements contient la liste d'éléments (notes, silences, ...).

    Pour la gestion des liaisons de prolongation, je suis en train de travailler dessus (ça viendra plus tard).
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise
    OpenGL 2.1 - Oracle 10g - Interbase (7 - XE) - PostgreSQL 11.6

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Débutant en informatique
    Inscrit en
    avril 2014
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Débutant en informatique

    Informations forums :
    Inscription : avril 2014
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    Bonjour,
    Très bon tuto, est ce qu'il est possible d'arriver à ce résultat en utilisant vb6.
    Merci

  4. #4
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    mars 2005
    Messages
    3 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : mars 2005
    Messages : 3 689
    Points : 10 644
    Points
    10 644
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    Je ne pense pas que la conversion soit difficile, à condition de connaître le Pascal et le Basic ! Heureusement, ils sont fort proches. Si tu as des problèmes, ouvre une discussion pour les exposer.
    Delphi 5 Pro - Delphi 10.4 Rio Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  5. #5
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 913
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 913
    Points : 13 989
    Points
    13 989
    Billets dans le blog
    8
    Par défaut
    Bonjour !

    @Lung

    Merci pour cette contribution.

    Pourrions-nous avoir un exemple de fichier avec des notes, pour savoir quel est le format ?

    Que penses-tu de la notation ABC ?

    Le sujet m'intéresse bien parce que je fabrique de temps en temps des fichiers MIDI à partir de partitions pour une chorale. Pour le moment j'utilise un logiciel (Anvil Studio) mais j'aimerais bien créer plutôt des fichiers texte et les convertir. Si je pouvais en plus faire la conversion avec un programme dont j'aurais le code, ce serait parfait.

  6. #6
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    mai 2002
    Messages
    2 623
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mai 2002
    Messages : 2 623
    Points : 6 492
    Points
    6 492
    Par défaut
    Citation Envoyé par Roland Chastain Voir le message
    Pourrions-nous avoir un exemple de fichier avec des notes, pour savoir quel est le format ?
    En fait, j'ai inventé mon propre format. Je l'enrichie au fur et à mesure. A côté du reste, ce n'était pas le plus compliqué.
    Pour l'instant, ce sont de simples fichiers textes.
    Voici un extrait :
    #Canon (Pachelbel)¤18¤69¤4/4¤
    §1/8¤1¤1¤0¤50¤SOL¤¤
    §1/8¤1¤2¤0¤50¤FA¤¤
    §1/8¤2¤1¤0¤50¤FA¤¤
    ||¤0¤75¤
    Rɤ1¤1¤0¤4¤100¤26¤¤1/2¤¤64¤H¤¤¤
    Rɤ1¤2¤0¤2¤100¤68¤¤1/2¤¤64¤¤¤¤
    Rɤ2¤1¤0¤2¤100¤68¤¤1/2¤¤64¤H¤¤¤
    DO¤1¤1¤0¤4¤125¤30¤#¤1/2¤¤64¤H¤¤¤
    LA¤1¤2¤0¤1¤125¤77¤¤1/2¤¤64¤¤¤¤
    LA¤2¤1¤0¤1¤125¤77¤¤1/2¤¤64¤H¤¤¤
    |¤0¤150¤
    SI¤1¤1¤0¤3¤175¤32¤¤1/2¤¤64¤H¤¤¤
    SI¤1¤2¤0¤1¤175¤74¤¤1/2¤¤64¤B¤¤¤
    SI¤2¤1¤0¤1¤175¤74¤¤1/2¤¤64¤H¤¤¤
    LA¤1¤1¤0¤3¤200¤35¤¤1/2¤¤64¤¤¤¤
    FA¤1¤2¤0¤1¤200¤83¤#¤1/2¤¤64¤¤¤¤
    FA¤2¤1¤0¤1¤200¤83¤#¤1/2¤¤64¤H¤¤¤
    |¤0¤225¤
    En gros, je stocke chaque note, son instrument, sa main, sa portée, sa position, sa durée, son altération, sa vélocité, ...
    Même chose pour les silences (avec leur propriétés respectives).
    ...
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise
    OpenGL 2.1 - Oracle 10g - Interbase (7 - XE) - PostgreSQL 11.6

Discussions similaires

  1. [Python 3.X] Générer un fichier CSV à partir d'une liste
    Par blueice dans le forum Général Python
    Réponses: 1
    Dernier message: 20/04/2015, 15h38
  2. [FPDF] Générer deux fichiers PDF à partir d'une classe
    Par doreen07 dans le forum Bibliothèques et frameworks
    Réponses: 5
    Dernier message: 31/10/2007, 11h17
  3. Réponses: 1
    Dernier message: 02/04/2007, 11h23
  4. [.NET]réécriture d'un fichier a partir d'une list box
    Par scorpking dans le forum VC++ .NET
    Réponses: 14
    Dernier message: 24/04/2006, 14h16
  5. Réponses: 4
    Dernier message: 02/05/2005, 20h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo