Question

Comment écrire un programme JavaScript pour afficher une forme d'onde à partir d'un fichier audio? Je souhaite utiliser l'audio Web et le canevas.

J'ai essayé ce code:

(new window.AudioContext).decodeAudioData(audioFile, function (data) {
   var channel = data.getChannelData(0);
   for (var i = 0; i < channel; i++) {
       canvas.getContext('2d').fillRect(i, 1, 40 - channel[i], 40);
   }
});

Mais le résultat est loin de ce que je veux (à savoir, l'image n'est pas fluide car je dessine avec des rectangles). Je veux qu'il ressemble à cette image:

Waveform example

Des conseils sur la façon d'implémenter la forme d'onde?

Était-ce utile?

La solution

Vous etes peut etre intéressé Audiojedit. Ceci est un projet open source Hébergé chez Github. Il a un petit script Node.js côté serveur pour charger des fichiers audio, mais toute interaction avec l'audio implémentée dans JavaScript côté client. Je pense que c'est similaire à ce que vous recherchez.

Autres conseils

Déployé ma propre bibliothèque après tout: wavesurfer.js.

Il dessine une forme d'onde à partir des données PCM et cherche les régions de l'audio en cliquant dessus.

Imgur

Pour un (avec un peu de chance) Utilisation et intégration simple d'une forme d'onde avec votre application Vous voudrez peut-être vérifier ce que nous faisons chez IRCAM, en particulier la forme de la forme d'onde dans ce cas particulier.

Tout est open source et destiné à la modularité (et au travail en cours)

Vous pouvez trouver un démo ici
Et le correspondant Référentiel GitHug

Votre code de rendu est extrêmement inefficace car il rendra 44100 pixels pour chaque seconde d'audio. Vous souhaitez rendre de préférence au plus la largeur de la fenêtre avec un ensemble de données réduit.

La plage d'échantillonnage par pixel nécessaire pour s'adapter à la forme d'onde dans la fenêtre peut être calculée avec AudiodUrationsCondes * Samplerate / ViewportWidTHPX. Ainsi, pour une fenêtre de 1000px et un fichier audio de 2 secondes à 44100 samplérate les échantillons par pixel = (2 * 44100) / 1000 = ~ 88. Pour chaque pixel à l'écran, vous prenez la valeur min et max de cette plage d'échantillons, vous utilisez ces données pour dessiner la forme d'onde.

Voici un exemple d'algorithme qui le fait mais vous permet de donner les échantillons par pixel comme argument ainsi qu'une position de défilement pour permettre un défilement virtuel et un zoom. Il comprend un paramètre de résolution que vous pouvez modifier pour les performances, cela indique le nombre d'échantillons qu'il devrait prendre par plage d'échantillonnage par pixel:Dessin timeline de forme d'onde audio zoomable en javascript

La méthode de dessin est similaire à la vôtre, afin de la lisser, vous devez utiliser Lineto au lieu de Fillrect. Cette différence ne devrait pas être aussi énorme, je pense que vous oubliez peut-être de définir les attributs de largeur et de hauteur sur la toile. Le réglage dans CSS provoque un dessin flou, vous devez définir les attributs.

let drawWaveform = function(canvas, drawData, width, height) {
   let ctx = canvas.getContext('2d');
   let drawHeight = height / 2;

   // clear canvas incase there is already something drawn
   ctx.clearRect(0, 0, width, height);

   ctx.beginPath();
   ctx.moveTo(0, drawHeight);
   for(let i = 0; i < width; i++) {
      // transform data points to pixel height and move to centre
      let minPixel = drawData[i][0] * drawHeigth + drawHeight;
      ctx.lineTo(i, minPixel);
   }
   ctx.lineTo(width, drawHeight);
   ctx.moveTo(0, drawHeight);
   for(let i = 0; i < width; i++) {
      // transform data points to pixel height and move to centre
      let maxPixel = drawData[i][1] * drawHeigth + drawHeight;
      ctx.lineTo(i, maxPixel);
   }
   ctx.lineTo(width, drawHeight);
   ctx.closePath();
   ctx.fill(); // can do ctx.stroke() for an outline of the waveform
} 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top