2010-11-09 24 views
0

J'ai créé du code javascript qui génère des fichiers midi basés sur une note et une octave passées. Pour la plupart, cela fonctionne plutôt bien. Le problème est que la note C (note = 0) est beaucoup plus courte que n'importe quelle autre note (1 (C#) à 11 (B)).généré midi note longueur

Voici mon code:

function play(note, octave, program){ 
    var note = (octave*12 + note).toString(16); 
    var velocity = 'ff'; 
    var MIDI_DATA = 
     'MThd%00%00%00%06%00%01%00%01%00%C0' + // midi header 
     'MTrk%00%00%00%0E' + // track header 
     '%00%C0%'+program+ 
     '%00%90%'+note+'%'+velocity+ 
     '%70%30%00' + 
     '%00%FF%2F%00'; 

    MIDI_DATA = btoa(unescape(MIDI_DATA)); 
    var e = document.createElement('embed'); 
    e.src = "data:audio/mid;base64,"+MIDI_DATA; 
    e.type = "video/quicktime"; 
    document.body.appendChild(e); 
    return e; 
} 

Pourquoi une note de C - jouer (0, 4, '18') son tellement plus court que tout autre - jouer (1, 4, '18') ? La hauteur semble correcte, juste la longueur de la note.

Je pense que cela peut avoir quelque chose à voir avec C étant de valeur 0, mais je ne sais pas assez ce que je fais ici avec midi pour repérer un problème.

REMARQUE: ce code ne fonctionne pas dans IE (toute version).

+0

Et ce qui se passe lorsque vous appelez le midi fichier directement dans le navigateur/quicktime sans utiliser la balise embed? Est-ce que ça joue le bon temps? – epascarello

+1

Je ne peux pas reproduire ce comportement - toutes les notes sont jouées pendant la même durée. Mettez à jour votre version QT? – LesterDove

+0

Il semble que ce soit un problème avec ma carte son. J'ai testé sur plusieurs combinaisons OS/navigateur, mais pas plusieurs ordinateurs. Merci d'avoir attiré mon attention là-dessus. J'aurais dû vérifier cela avant. – marshallpenguin

Répondre

1

Si je me souviens bien, les notes MIDI sont jouées en donnant un terrain et une vitesse (c.-à-volume) entre 1 et 127, et se sont arrêtés en donnant le même pas avec une vitesse de 0.

+0

Vous avez raison, les codes au-dessus de 127 sont des codes de contrôle, pas des données. La vélocité devrait être '7f' plutôt que' ff'. – Guffa

+0

Le passage de ff à 7f n'a eu aucun effet. Mais merci. – marshallpenguin

0

Lorsque la note Si la valeur est inférieure à 16, vous obtiendrez une séquence d'échappement invalide, c'est-à-dire %0 au lieu de %00. La fonction unescape ne transforme pas cela en caractère, mais le laisse inchangé. Comme il s'agit de deux caractères au lieu d'un, il déborde dans l'octet de vélocité et le reste du code MIDI est désynchronisé.

Vous pouvez utiliser le code comme celui-ci pour formater un nombre en deux chiffres hexadécimaux:

function toHex(n) { 
    var code = '0' + n.toString(16); 
    return code.substr(code.length - 2, 2); 
} 

Utilisez-le pour rendre la valeur de note deux chiffres:

var note = toHex(octave*12 + note); 
+0

Merci Guffa, mais votre code fourni ne change rien. J'ai oublié de mentionner, la coupure ne se produit que sur la 4ème octave. – marshallpenguin

+0

Lorsque la note a une valeur hexadécimale de '30', la note est coupée. – marshallpenguin