2012-03-01 35 views
20

Làm cách nào để viết chương trình JavaScript để hiển thị dạng sóng từ tệp âm thanh? Tôi muốn sử dụng Web Âm thanh và Canvas.Âm thanh web để trực quan hóa và tương tác với dạng sóng

Tôi đã thử mã này:

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

Nhưng kết quả là xa những gì tôi muốn (cụ thể là, hình ảnh không rõ nét kể từ khi tôi đang vẽ với hình chữ nhật). Tôi muốn nó trông mịn như hình ảnh này:

Waveform example

Bất kỳ gợi ý về làm thế nào để thực hiện các dạng sóng?

+0

Có thể đây là điểm bắt đầu: http://www.storiesinflight.com/jsfft/visualizer/index.html – Mika

+0

@Mika, nó đổ chuông báo ở xa. – katspaugh

+0

Đây là chủ đề tại: http://softwarerecs.stackexchange.com/ – kenorb

Trả lời

9

Bạn có thể quan tâm đến AudioJedit. Đây là một dự án mã nguồn mở hosted at GitHub. Nó có kịch bản lệnh node.js phía máy chủ nhỏ để tải các tệp âm thanh, nhưng tất cả tương tác với âm thanh được triển khai trong JavaScript phía máy khách. Tôi nghĩ điều này tương tự như những gì bạn đang tìm kiếm.

+0

Vadim, nó gần như những gì tôi muốn. Họ không tạo ra đồ họa dạng sóng (nó được tải từ SoundCloud), nhưng thật dễ dàng để thêm vào với ['RealtimeAnalyserNode'] (https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification. html # dfn-getByteTimeDomainData). Cảm ơn rất nhiều! – katspaugh

39

Đã cuộn hoàn toàn thư viện của riêng tôi: wavesurfer.js.

Nó vẽ dạng sóng từ dữ liệu PCM và tìm vùng của âm thanh bằng cách nhấp vào nó.

Imgur

+0

Làm cách nào tôi có thể vẽ dạng sóng của tệp âm thanh cục bộ (không được lưu trữ trên máy chủ nhưng có sẵn trong một số thư mục khác của PC của tôi). Có thể với js của bạn? – madLokesh

+0

@madLokesh, vâng, có thể vẽ các tệp bằng cách sử dụng API tệp (http://dev.w3.org/2006/webapi/FileAPI/). – katspaugh

+0

Tôi đang sử dụng Cordova vì vậy tôi đoán tôi phải sử dụng API tệp của Cordova để truy cập tệp nhưng tôi nên chuyển tệp âm thanh như thế nào. Là một URl được mã hóa base64 hoặc như một bộ đệm Array – madLokesh

2

Đối với một (hy vọng) sử dụng đơn giản và hội nhập của một dạng sóng với ứng dụng của bạn, bạn có thể muốn kiểm tra những gì chúng tôi đang làm tại IRCAM, đặc biệt các dạng sóng-vis trong trường hợp đặc biệt này.

Đó là tất cả mã nguồn mở và nhắm vào mô đun (và làm việc cơ bản dở dang)

Bạn có thể tìm thấy một demo over here
Và tương ứng githug repository

+0

Rất tốt, cảm ơn bạn ! – katspaugh

+0

Upvote for cuddly git = D – CoDEmanX

+1

Cả hai liên kết đều là 404. –

0

bạn mã render là cực kỳ không hiệu quả bởi vì nó sẽ làm cho 44.100 pixel cho mỗi giây của âm thanh. Bạn muốn tốt nhất hiển thị tối đa chiều rộng khung nhìn với tập dữ liệu đã giảm.

Phạm vi mẫu trên mỗi pixel cần thiết để phù hợp với dạng sóng trong chế độ xem có thể được tính bằng audioDurationSeconds * samplerate/viewPortWidthPx. Vì vậy, đối với một khung nhìn 1000px và một tệp âm thanh của 2 giây tại 44100 lấy mẫu các mẫu trên mỗi pixel = (2 * 44100)/1000 = ~ 88. Đối với mỗi pixel trên màn hình, bạn lấy giá trị nhỏ nhất và tối đa từ phạm vi mẫu đó, bạn sử dụng dữ liệu này để vẽ dạng sóng.

Dưới đây là một thuật toán ví dụ thực hiện điều này nhưng cho phép bạn cung cấp mẫu cho mỗi pixel làm đối số cũng như vị trí cuộn để cho phép cuộn và thu phóng ảo. Nó bao gồm thông số phân giải mà bạn có thể tinh chỉnh cho hiệu suất, điều này cho biết số lượng mẫu cần lấy cho mỗi phạm vi mẫu pixel: Drawing zoomable audio waveform timeline in Javascript

Phương pháp vẽ tương tự như phương pháp vẽ của bạn, để làm mịn nó, bạn cần sử dụng lineTo của fillRect. Sự khác biệt này không thực sự lớn đến vậy, tôi nghĩ bạn có thể quên đặt thuộc tính chiều rộng và chiều cao trên canvas. Thiết lập điều này trong nguyên nhân css cho bản vẽ mờ, bạn cần phải thiết lập các thuộc tính.

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 
} 
Các vấn đề liên quan