Editeur midi

Résolu
Teclis01 Messages postés 1423 Date d'inscription mardi 14 décembre 2004 Statut Membre Dernière intervention 29 décembre 2012 - 4 juil. 2005 à 20:30
syl20dies Messages postés 13 Date d'inscription mardi 21 octobre 2008 Statut Membre Dernière intervention 29 janvier 2009 - 20 mars 2009 à 22:13
Voilà en fait je me posais la question s'il etait possible d'editer un fichier midi en php et si cela existait deja
Merci d'avance


-------------------------------------------------------------------------------------------------------
Il vaut mieux poser une question et passer pour bête que le rester toute sa vie

4 réponses

cs_grandvizir Messages postés 1106 Date d'inscription samedi 8 novembre 2003 Statut Membre Dernière intervention 3 septembre 2006 22
4 juil. 2005 à 21:18
Déjà que sous développement Windows c'est chaud, alors PHP laisse tomber. Personnellement, je n'y crois pas.
1) Trop compliqué
2) PHP ne convient pas
3) Apache ne propose pas d'extensions adapatée

A la limite, tu peux faire des renommeurs de pistes, mais bof...

Si tu veux un bon éditeur simple en 16 bis Win3.1, débrouille toi pour trouver Midisoft Recording Session. C'est tellement bien qu'il n'y a en fait pas besoin d'installateur. Par contre, c'est tellement vieux qu'il ne doit plus être en vente.

===========
Validez les réponses si ok...

ViewVite : HTML
3
Teclis01 Messages postés 1423 Date d'inscription mardi 14 décembre 2004 Statut Membre Dernière intervention 29 décembre 2012 4
4 juil. 2005 à 21:43
ok merci je vais voir cke je peux faire de tt ce que tu as repondu!
Teclis


-------------------------------------------------------------------------------------------------------
Il vaut mieux poser une question et passer pour bête que le rester toute sa vie
0
syl20dies Messages postés 13 Date d'inscription mardi 21 octobre 2008 Statut Membre Dernière intervention 29 janvier 2009
20 mars 2009 à 22:04
Bonjour post tres ancien et accepté mais j'y suis tombé dessus parcque ca m'interessait pour une appli que je souhaite dévellopper,donc je pense que c'est le meilleur endroit pour donner ma contribution.

voilà mon but est de créer un algo pour composer de la musique à partir de l'analyse de gamme, accords intervalles et toutes notions de théorie musicale, bref vaste projet, mais bon voila avant d'en arriver là la premiere question que je me suis posé c'est que va sortir mon algo pour que je puisse voir(entendre plutot) le résultat.
j'ai un piano numerique et quelques soft d'edition midi, mais voila impossible de saisir une liste complete d'evenements de notes autrement que note par note
je me suis donc dis "et bien je croie que je vais pas avoir le choix que de générer mes propres fichiers midi contenant toutes les notes issues de mon algo".
je m'y suis donc collé et je vous propose donc ce code pour ecrire un fichier midi à partir d'un tableau de notes telles qu'on peut les trouver dans la vue liste d'evenement d'un sequenceur midi.
c'est une version tres simpliste dans mon cas puisque je ne traite que de note/on note/off velocity-in et placage temporel tres sommaire(16ieme de note au plus fin) mais ca peut donner des idées.

1) formatage du fichier midi

extrait légerement modifié inspiré de http://jedi.ks.uiuc.edu/~johns/links/music/midifile.html

à voir pour plus de detail sur le codage d'un fichier midi que j'ai ici
simplifié à outrance pour ne garder que ce qui m'interessait : les note/on et note/off


  4D 54 68 64                        MThd

 00 00 00 06                         chunk length

 00 00                                    format 0

 00 01                                    one track

 00 60                                   96 per quarter-note

Then, the
track chunk. Its header, followed by the events:


        4D 54 72 6B                     MTrk

        00 00 00 3B                       chunk length (44)

Delta-time(var-length hex) Event                             Comments

00                                 90 30 60                        
90:noteon ,30(hex)=48(dec) = +48 semitones from C0=C4, 60 hex val for
velocity in

60                                 90 43 40

60                                 90 4C 20

81 40                             80 30 40                        
two-byte delta-time,80:noteoff ,30(hex)=48(dec) = +48 semitones from
C0=C4, 40 hex val for velocity off

00                                 80 43 40

00                                 80 4C 40

00 FF 2F 00                                                           //fin de track

2) le code

<?
 function completechaine($pstr,$d){
 //formate la chaine $pstr en placant des "0" devant pour obtenir la longueur minimale donnée par $d
 //utile pour obtenir un hexadecimal inferieur à 16(dec) sur 2 charactères
 //ex :dechex(15)retourne F,
 //completechaine(dechex(15),2) retourne "0F"
 $newstr=$pstr;
while(strlen($newstr)<$d){$newstr="0".$newstr;}
return $newstr;
}

function varlen($hex){
//retourne une chaine hexadécimale sous forme de valeur à longueur variable (VLK) cf http://en.wikipedia.org/wiki/Variable_length_unsigned_integer
$a=decbin(hexdec($hex));
$nbbytes=ceil(strlen($a)/7);
$a=completechaine($a,$nbbytes*7);
$mywords=array($nbbytes);
for($i=0;$i<$nbbytes;$i++){
$mywords[$i]=(($i<$nbbytes-1)?"1":"0").substr($a,$i*7,7);
}
$result=implode($mywords);
return completechaine(dechex(bindec($result)),2);
}

function findhexnote($strnote){
//retourne la valeur hexadécimale de la hauteur d'une note donnée en parametre
$notedecal=array("C"=>0,"D"=>2,"E"=>4,"F"=>5,"G"=>7,"A"=>9,"B"=>11,"C#"=>1,"D#"=>3,"F#"=>6,"G#"=>8,"A#"=>9,"B"=>11);
$decdies=intval(($strnote[1]=="#"))+1;//valeur booléenne entiere augmentée de 1 (si "#" : 2 sinon 1);
return completechaine(dechex($notedecal[substr($strnote,0,$decdies)]+intval(substr($strnote,$decdies,strlen($strnote-$decdies)))*12),2);
//multiplie le nombre de l'octave(souschaine de $strnote position 2 à fin si #, sinon position 1 à fin) par 12 et ajoute le decalage de la note dans l'octave, puis converti le tout en valeur hexadecimale sur 2 characteres
}

function convertnotes($mesnotes){
//pour obtenir le code sous la forme [decalage temporel(VLK)][noteon/noteoff(90/80)][hauteur note(hex)][velocité(hex)] à partir d'un tableau de note sous la forme :
//                                            [note(string)][velocité(dec 0 -127)][time(M:1/4note:1/16note)][duree(M:1/4note:1/16note)]
    $hexanotes="";
    $timepassed=0;
    $evts=array(count($mesnotes)*2);//initialise un tableu de longueur double à celui des notes donnée en parametre de sorte à obtenir un evenement note on et un evenenment noteoff
    for($i=0;$i<count($mesnotes);$i++){
        $tdeb=split(':',$mesnotes[$i][2]);
        $tdur=split(':',$mesnotes[$i][3]);
       
        //convertion de la chaine temps de la note en entier(96 batements par quart de note tel que defini dans l'entete du fichier midi);
        $evts[$i*2]=$tdeb[0]*96*4+$tdeb[1]*96+$tdeb[2]*96/4;
       
        //convertion de temps + duree en temps absolu entier comme precedement correspondant au temps absolu de l'evenement note off;
        $evts[$i*2+1]=(intval($tdeb[2])+intval($tdur[2]))*96/4+(intval($tdeb[1])+intval($tdur[1]))*96+(intval($tdeb[0])+intval($tdur[0]))*96*4;
       
        // j'ai ainsi affecté le temps absolu du debut de la note au indices pairs du tableau evts, le temps absolu de la fin de la note au indices impairs;
    }
    //tri selon le temps en conservant l'association avec les index
    asort($evts,SORT_NUMERIC);
   
    foreach ($evts as $key => $val) {
        //constitution de la trame formatée, la correlation avec le tableau de note d'origine est donnée par floor($key/2) qui donne l'index de la note associée au temps $val
        //j'utilise succesivement les fonctions definie avant pour obtenir le formatage correct des données:
        //varlen(dechex($val-$timepassed)) pour obtenir un decalage par rapport à l'evenement precedant sous forme VLK,
        //index pair ou impair pour evenement noteon ou noteoff
        //findhexnote pour la hauteur de la note en hexa
        //pour la velocité je n'utilise ici que la velocité-in et 0 pour la velocité off(pas de difference sur mon piano numerique)
        $hexanotes.=varlen(dechex($val-$timepassed)).(($key%2==0)?"90":"80").findhexnote($mesnotes[floor($key/2)][0]).(($key%2==0)?completechaine(dechex($mesnotes[floor($key/2)][1]),2):"00");
        $timepassed=$val;
    }
       return $hexanotes;   
}

//entete typique de fichier midi (MTHD) au format 0 une piste 96beats/quarternote + entete de bloc MTrk
//il manque la checksum que je calculerais plus tard
$entete="4D546864000000060000000100604D54726B";
$fin="00FF2F00";

//exemple de notes, à récupérer d'un formulaire ou tout ce que vous voudrez
$mesnotes=array();
$mesnotes[0]=array("C4",127,"0:0:0","1:0:0");
$mesnotes[1]=array("C5",80,"0:2:0","0:1:0");
$mesnotes[2]=array("G4",80,"0:1:0","0:1:0");
$mesnotes[3]=array("D#4",80,"0:3:0","0:1:0");
$mesnotes[4]=array("G4",127,"1:0:0","1:0:0");
$mesnotes[5]=array("G5",127,"1:0:0","1:0:0");

//obtention de la liste d'evenements noteon et note off
$blocnotes=convertnotes($mesnotes);

//calcul de la checksum
// à verifier j'ai compté ici la fin de bloc et la checksum elle même mais pas l'entete de track
// ca ne pose pas de probleme à mon sequenceur j'assume donc ca comme juste
$checksum=completechaine(dechex((strlen($blocnotes)/2+8)),8)

// concatenation des elements du fichiers
$myhexdata=$entete.$checksum.$blocnotes.$fin;

//conversion du contenu string hexa en bytes ascii
$content="";
  for($i=0;$i<strlen($myhexdata);$i+=2){
$content.=chr(hexdec($myhexdata[$i].$myhexdata[$i+1]));
}

//ecriture du fichier
 $fp=fopen("myown.mid",'w');
fwrite($fp,$content);
fclose($fp);

?>
0
syl20dies Messages postés 13 Date d'inscription mardi 21 octobre 2008 Statut Membre Dernière intervention 29 janvier 2009
20 mars 2009 à 22:13
oups! j'ai oublié un point virgule au calcul de la checksum.voila ce que c'est quand on veut séparer un peu les lignes pour gagner en lisibilité...
 
0
Rejoignez-nous