Sebelum elemen <audio> HTML5, Flash atau plugin lain diperlukan
untuk memecah keheningan web. Meskipun audio di web tidak lagi
memerlukan plugin, tag audio memiliki batasan yang signifikan untuk
mengimplementasikan game canggih dan aplikasi interaktif.
Web Audio API adalah API JavaScript tingkat tinggi untuk memproses dan menyintesis audio dalam aplikasi web. Tujuan API ini adalah untuk menyertakan kemampuan yang ditemukan dalam mesin audio game modern dan beberapa tugas pencampuran, pemrosesan, dan pemfilteran yang ditemukan dalam aplikasi produksi audio desktop modern. Berikut adalah pengantar singkat tentang cara menggunakan API yang canggih ini.
Mulai menggunakan AudioContext
AudioContext digunakan untuk mengelola dan memutar semua suara. Untuk menghasilkan
suara menggunakan Web Audio API, buat satu atau beberapa sumber suara
dan hubungkan ke tujuan suara yang disediakan oleh instance
AudioContext. Koneksi ini tidak harus langsung, dan dapat melalui
sejumlah AudioNodes perantara yang bertindak sebagai modul
pemrosesan untuk sinyal audio. Pemilihan rute ini dijelaskan secara lebih
mendetail di spesifikasi Web Audio.
Satu instance AudioContext dapat mendukung beberapa input suara
dan grafik audio yang kompleks, jadi kita hanya memerlukan satu instance untuk setiap
aplikasi audio yang kita buat.
Cuplikan berikut membuat AudioContext:
var context;
window.addEventListener('load', init, false);
function init() {
try {
context = new AudioContext();
}
catch(e) {
alert('Web Audio API is not supported in this browser');
}
}
Untuk browser berbasis WebKit yang lebih lama, gunakan awalan webkit, seperti dengan
webkitAudioContext.
Banyak fungsi Web Audio API yang menarik, seperti membuat AudioNode dan mendekode data file audio, merupakan metode AudioContext.
Memuat suara
Web Audio API menggunakan AudioBuffer untuk suara berdurasi pendek hingga sedang. Pendekatan dasarnya adalah menggunakan XMLHttpRequest untuk mengambil file suara.
API ini mendukung pemuatan data file audio dalam berbagai format, seperti WAV, MP3, AAC, OGG, dan lainnya. Dukungan browser untuk berbagai format audio bervariasi.
Cuplikan berikut menunjukkan pemuatan sampel suara:
var dogBarkingBuffer = null;
var context = new AudioContext();
function loadDogSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
dogBarkingBuffer = buffer;
}, onError);
}
request.send();
}
Data file audio bersifat biner (bukan teks), jadi kita menetapkan responseType permintaan ke 'arraybuffer'. Untuk mengetahui informasi selengkapnya tentang
ArrayBuffers, lihat artikel tentang XHR2 ini.
Setelah data file audio (yang belum didekode) diterima, data tersebut dapat disimpan
untuk didekode nanti, atau dapat langsung didekode menggunakan
metode decodeAudioData() AudioContext. Metode ini mengambil
ArrayBuffer data file audio yang disimpan di request.response dan
mendekodenya secara asinkron (tidak memblokir thread eksekusi JavaScript
utama).
Setelah selesai, decodeAudioData() akan memanggil fungsi callback yang menyediakan data audio PCM yang didekode sebagai AudioBuffer.
Memutar suara
Setelah satu atau beberapa AudioBuffers dimuat, kita siap memutar
suara. Mari kita asumsikan bahwa kita baru saja memuat AudioBuffer dengan suara
menggonggong dan pemuatan telah selesai. Kemudian, kita dapat memutar
buffer ini dengan kode berikut.
var context = new AudioContext();
function playSound(buffer) {
var source = context.createBufferSource(); // creates a sound source
source.buffer = buffer; // tell the source which sound to play
source.connect(context.destination); // connect the source to the context's destination (the speakers)
source.noteOn(0); // play the source now
}
Fungsi playSound() ini dapat dipanggil setiap kali seseorang menekan tombol atau
mengklik sesuatu dengan mouse.
Fungsi noteOn(time) memudahkan penjadwalan pemutaran suara yang akurat untuk game dan aplikasi lain yang memerlukan ketepatan waktu. Namun, agar
penjadwalan ini berfungsi dengan baik, pastikan buffer suara Anda
telah dimuat sebelumnya.
Mengabstraksi Web Audio API
Tentu saja, akan lebih baik untuk membuat sistem pemuatan yang lebih umum yang tidak di-hardcode untuk memuat suara tertentu ini. Ada banyak pendekatan untuk menangani banyak suara berdurasi pendek hingga sedang yang akan digunakan oleh aplikasi atau game audio–berikut salah satu cara menggunakan BufferLoader (bukan bagian dari standar web).
Berikut adalah contoh cara menggunakan class BufferLoader.
Mari kita buat dua AudioBuffers; dan, segera setelah dimuat,
mari kita putar kembali secara bersamaan.
window.onload = init;
var context;
var bufferLoader;
function init() {
context = new AudioContext();
bufferLoader = new BufferLoader(
context,
[
'../sounds/hyper-reality/br-jam-loop.wav',
'../sounds/hyper-reality/laughter.wav',
],
finishedLoading
);
bufferLoader.load();
}
function finishedLoading(bufferList) {
// Create two sources and play them both together.
var source1 = context.createBufferSource();
var source2 = context.createBufferSource();
source1.buffer = bufferList[0];
source2.buffer = bufferList[1];
source1.connect(context.destination);
source2.connect(context.destination);
source1.noteOn(0);
source2.noteOn(0);
}
Menangani waktu: Memutar suara dengan ritme
Web Audio API memungkinkan developer menjadwalkan pemutaran dengan tepat. Untuk mendemonstrasikannya, mari kita siapkan trek ritme sederhana. Mungkin pola drumkit yang paling dikenal luas adalah sebagai berikut:
dengan hihat dimainkan setiap not seperdelapan, serta kick dan snare dimainkan bergantian setiap not seperempat, dalam birama 4/4.
Dengan asumsi kita telah memuat buffer kick, snare, dan hihat, kode untuk melakukannya sangat sederhana:
for (var bar = 0; bar < 2; bar++) {
var time = startTime + bar * 8 * eighthNoteTime;
// Play the bass (kick) drum on beats 1, 5
playSound(kick, time);
playSound(kick, time + 4 * eighthNoteTime);
// Play the snare drum on beats 3, 7
playSound(snare, time + 2 * eighthNoteTime);
playSound(snare, time + 6 * eighthNoteTime);
// Play the hi-hat every eighth note.
for (var i = 0; i < 8; ++i) {
playSound(hihat, time + i * eighthNoteTime);
}
}
Di sini, kita hanya melakukan satu pengulangan, bukan pengulangan tanpa batas yang kita lihat di
partitur. Fungsi playSound adalah metode yang memutar
buffer pada waktu yang ditentukan, sebagai berikut:
function playSound(buffer, time) {
var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.noteOn(time);
}
Mengubah volume suara
Salah satu operasi paling dasar yang mungkin ingin Anda lakukan pada suara adalah mengubah volumenya. Dengan menggunakan Web Audio API, kita dapat mengarahkan sumber ke tujuannya melalui AudioGainNode untuk memanipulasi volume:

Penyiapan koneksi ini dapat dilakukan sebagai berikut:
// Create a gain node.
var gainNode = context.createGainNode();
// Connect the source to the gain node.
source.connect(gainNode);
// Connect the gain node to the destination.
gainNode.connect(context.destination);
Setelah grafik disiapkan, Anda dapat mengubah volume secara terprogram dengan memanipulasi gainNode.gain.value sebagai berikut:
// Reduce the volume.
gainNode.gain.value = 0.5;
Cross-fade antara dua suara
Sekarang, misalkan kita memiliki skenario yang sedikit lebih kompleks, yaitu kita memutar beberapa suara, tetapi ingin melakukan cross fade di antaranya. Ini adalah kasus umum dalam aplikasi seperti DJ, di mana kita memiliki dua turntable dan ingin dapat menggeser dari satu sumber suara ke sumber suara lainnya.
Hal ini dapat dilakukan dengan grafik audio berikut:
Untuk menyiapkannya, kita cukup membuat dua AudioGainNodes, dan menghubungkan setiap sumber melalui node, menggunakan fungsi seperti ini:
function createSource(buffer) {
var source = context.createBufferSource();
// Create a gain node.
var gainNode = context.createGainNode();
source.buffer = buffer;
// Turn on looping.
source.loop = true;
// Connect source to gain.
source.connect(gainNode);
// Connect gain to destination.
gainNode.connect(context.destination);
return {
source: source,
gainNode: gainNode
};
}
Crossfade daya yang sama
Pendekatan crossfade linear yang sederhana menunjukkan penurunan volume saat Anda menggeser di antara sampel.
Untuk mengatasi masalah ini, kami menggunakan kurva daya yang sama, dengan kurva penguatan yang sesuai bersifat non-linear, dan berpotongan pada amplitudo yang lebih tinggi. Hal ini meminimalkan penurunan volume di antara region audio, sehingga menghasilkan crossfade yang lebih merata di antara region yang mungkin memiliki level yang sedikit berbeda.
Crossfade playlist
Aplikasi crossfader umum lainnya adalah untuk aplikasi pemutar musik.
Saat lagu berubah, kita ingin memudarkan trek saat ini, dan memudarkan
trek baru, untuk menghindari transisi yang mengganggu. Untuk melakukannya, jadwalkan
crossfade untuk waktu mendatang. Meskipun kita dapat menggunakan setTimeout untuk melakukan penjadwalan ini, cara ini tidak akurat. Dengan Web Audio API, kita
dapat menggunakan antarmuka AudioParam untuk menjadwalkan nilai mendatang untuk
parameter seperti nilai penguatan AudioGainNode.
Jadi, dengan playlist tertentu, kita dapat beralih antar-trek dengan menjadwalkan penurunan gain pada trek yang sedang diputar, dan peningkatan gain pada trek berikutnya, keduanya sedikit sebelum trek saat ini selesai diputar:
function playHelper(bufferNow, bufferLater) {
var playNow = createSource(bufferNow);
var source = playNow.source;
var gainNode = playNow.gainNode;
var duration = bufferNow.duration;
var currTime = context.currentTime;
// Fade the playNow track in.
gainNode.gain.linearRampToValueAtTime(0, currTime);
gainNode.gain.linearRampToValueAtTime(1, currTime + ctx.FADE_TIME);
// Play the playNow track.
source.noteOn(0);
// At the end of the track, fade it out.
gainNode.gain.linearRampToValueAtTime(1, currTime + duration-ctx.FADE_TIME);
gainNode.gain.linearRampToValueAtTime(0, currTime + duration);
// Schedule a recursive track change with the tracks swapped.
var recurse = arguments.callee;
ctx.timer = setTimeout(function() {
recurse(bufferLater, bufferNow);
}, (duration - ctx.FADE_TIME) - 1000);
}
Web Audio API menyediakan serangkaian metode RampToValue yang praktis untuk
mengubah nilai parameter secara bertahap, seperti
linearRampToValueAtTime dan exponentialRampToValueAtTime.
Meskipun fungsi pengaturan waktu transisi dapat dipilih dari fungsi linear dan eksponensial bawaan (seperti di atas), Anda juga dapat menentukan kurva nilai Anda sendiri melalui array nilai menggunakan fungsi setValueCurveAtTime.
Menerapkan efek filter sederhana ke suara

Web Audio API memungkinkan Anda menyalurkan suara dari satu node audio ke node audio lainnya, sehingga menciptakan rantai pemroses yang berpotensi kompleks untuk menambahkan efek kompleks ke bentuk suara Anda.
Salah satu cara untuk melakukannya adalah dengan menempatkan BiquadFilterNode di antara sumber dan tujuan suara Anda. Jenis node audio ini dapat melakukan berbagai filter tingkat rendah yang dapat digunakan untuk membuat equalizer grafis dan bahkan efek yang lebih kompleks, sebagian besar berkaitan dengan pemilihan bagian spektrum frekuensi suara yang akan ditekankan dan yang akan diredam.
Jenis filter yang didukung mencakup:
- Filter low pass
- Filter high pass
- Filter band pass
- Filter low shelf
- Filter high shelf
- Filter peaking
- Filter notch
- Filter semua lolos
Dan semua filter menyertakan parameter untuk menentukan sejumlah gain, frekuensi penerapan filter, dan faktor kualitas. Filter low-pass mempertahankan rentang frekuensi yang lebih rendah, tetapi membuang frekuensi tinggi. Titik pemutusan ditentukan oleh nilai frekuensi, dan faktor Q tidak memiliki satuan, dan menentukan bentuk grafik. Gain hanya memengaruhi filter tertentu, seperti filter low-shelf dan peaking, dan bukan filter low-pass ini.
Mari kita siapkan filter low-pass sederhana untuk mengekstrak hanya bass dari sampel suara:
// Create the filter
var filter = context.createBiquadFilter();
// Create the audio graph.
source.connect(filter);
filter.connect(context.destination);
// Create and specify parameters for the low-pass filter.
filter.type = 0; // Low-pass filter. See BiquadFilterNode docs
filter.frequency.value = 440; // Set cutoff to 440 HZ
// Playback the sound.
source.noteOn(0);
Secara umum, kontrol frekuensi perlu disesuaikan agar berfungsi pada
skala logaritmik karena pendengaran manusia sendiri bekerja berdasarkan prinsip yang sama
(yaitu, A4 adalah 440 hz, dan A5 adalah 880 hz). Untuk mengetahui detail selengkapnya, lihat
fungsi FilterSample.changeFrequency di link kode sumber di atas.
Terakhir, perhatikan bahwa kode contoh memungkinkan Anda menghubungkan dan memutuskan koneksi
filter, sehingga mengubah grafik AudioContext secara dinamis. Kita dapat memutuskan koneksi
AudioNode dari grafik dengan memanggil node.disconnect(outputNumber).
Misalnya, untuk mengalihkan rute grafik dari melewati filter ke koneksi langsung, kita dapat melakukan hal berikut:
// Disconnect the source and filter.
source.disconnect(0);
filter.disconnect(0);
// Connect the source directly.
source.connect(context.destination);
Bacaan lebih lanjut
Kami telah membahas dasar-dasar API, termasuk memuat dan memutar sampel audio. Kami telah membuat grafik audio dengan node penguatan dan filter, serta menjadwalkan suara dan penyesuaian parameter audio untuk mengaktifkan beberapa efek suara umum. Pada tahap ini, Anda siap untuk membuat beberapa aplikasi audio web yang menarik.
Jika Anda mencari inspirasi, banyak developer telah membuat karya hebat menggunakan Web Audio API. Beberapa favorit saya antara lain:
- AudioJedit, alat penyambung suara dalam browser yang menggunakan permalink SoundCloud.
- ToneCraft, sequencer suara tempat suara dibuat dengan menumpuk blok 3D.
- Plink, game pembuatan musik kolaboratif yang menggunakan Web Audio dan Web Socket.