2012-03-01 20 views
20

¿Cómo escribo un programa JavaScript para mostrar una forma de onda desde un archivo de audio? Quiero usar Web Audio y Canvas.Audio web para visualizar e interactuar con formas de onda

yo probamos este código:

(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); 
    } 
}); 

Pero el resultado está lejos de lo que yo quiero (es decir, la imagen no es suave ya que estoy dibujando con rectángulos). Yo quiero que se vea suave como esta imagen:

Waveform example

¿Alguna pista sobre cómo implementar la forma de onda?

+0

Quizás este es un punto de partida: http://www.storiesinflight.com/jsfft/visualizer/index.html – Mika

+0

@Mika, suena una campana de demostración distante. – katspaugh

+0

Esto está en el tema en: http://softwarerecs.stackexchange.com/ – kenorb

Respuesta

9

Puede que le interese el AudioJedit. Este es un proyecto de código abierto hosted at GitHub. Tiene una pequeña secuencia de comandos node.js del lado del servidor para cargar archivos de audio, pero toda la interacción con el audio se implementa en JavaScript del lado del cliente. Creo que esto es similar a lo que estás buscando.

+0

Vadim, es casi lo que quería. No generan gráficos de forma de onda (se carga desde SoundCloud), pero es fácil de agregar con ['RealtimeAnalyserNode'] (https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification. html # dfn-getByteTimeDomainData). ¡Muchas gracias! – katspaugh

39

Desarrollado mi propia biblioteca después de todo: wavesurfer.js.

Dibuja una forma de onda a partir de datos PCM y busca regiones del audio haciendo clic en él.

Imgur

+0

¿Cómo puedo trazar la forma de onda de los archivos de audio locales (que no están alojados en el servidor pero están disponibles en algún otro directorio de mi PC)? ¿Es posible con tu js? – madLokesh

+0

@madLokesh, sí, es posible trazar archivos utilizando File API (http://dev.w3.org/2006/webapi/FileAPI/). – katspaugh

+0

Estoy usando Cordova, así que supongo que debo usar File API of Cordova para acceder al archivo, pero ¿cómo debo pasar el archivo de audio como. Como UR1 codificada en base64 o como Buffer de matriz – madLokesh

2

Para una (esperemos ) un uso sencillo e integración de una forma de onda con su aplicación es posible que desee comprobar lo que estamos haciendo en el IRCAM, especialmente la forma de onda-vis en este caso particular.

Todo es de código abierto y dirigido para la modularidad (y el trabajo en curso)

Puede encontrar una demo over here
y la correspondiente githug repository

+0

Bien, gracias ! – katspaugh

+0

Upvote para cuddly git = D – CoDEmanX

+1

Ambos enlaces son 404. –

0

Su rendir código es extremadamente ineficiente, ya que hará que 44100 píxeles para cada segundo de audio. Desea representar de preferencia a lo sumo el ancho de la ventana gráfica con un conjunto reducido de datos.

El rango de muestra por píxel necesario para ajustar la forma de onda en la ventana gráfica se puede calcular con audioDurationSeconds * samplerate/viewPortWidthPx. Entonces para una ventana gráfica de 1000px y un archivo de audio de 2 segundos a 44100 samplerate las muestras por píxel = (2 * 44100)/1000 = ~ 88. Para cada píxel en la pantalla se toma el valor mínimo y máximo de ese rango de muestra, se usan estos datos para dibujar la forma de onda.

Aquí hay un algoritmo de ejemplo que hace esto pero que le permite dar las muestras por píxel como argumento, así como una posición de desplazamiento para permitir el desplazamiento y el acercamiento virtual. Incluye un parámetro de resolución se puede ajustar para el rendimiento, esto indica cuántas muestras se deben tomar muestrario de píxeles: Drawing zoomable audio waveform timeline in Javascript

El método de sorteo no es similar a la suya, con el fin de suavizarlo es necesario utilizar lineTo vez de fillRect.Esta diferencia en realidad no debería ser tan grande, creo que quizás te olvides de establecer los atributos de ancho y alto en el lienzo. Al establecer esto en css causa un dibujo borroso, debe establecer los atributos.

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 
} 
Cuestiones relacionadas