Audio Web pour visualiser et interagir avec les formes d'onde
-
14-11-2019 - |
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:
Des conseils sur la façon d'implémenter la forme d'onde?
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.
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
}