Web Audio API'sını kullanmaya başlama

Boris Smus
Boris Smus

HTML5 <audio> öğesinden önce Flash veya başka bir eklenti gerekiyordu web'in sessizliğini bozar. Web'de ses artık kullanılamıyor ses etiketi bir eklenti gerektirirse, ses etiketi gelişmiş oyunların ve etkileşimli uygulamaların nasıl kullanılacağına odaklanıyor.

Web Audio API, veri işleme ve analiz için üst düzey bir JavaScript API'dir. web uygulamalarında ses sentezleme. Bu API'nin amacı, modern oyun ses motorlarında ve bazı oyunlarda modern masaüstü bilgisayarlarda bulunan görevleri karıştırma, işleme ve filtreleme ses prodüksiyonu uygulamaları için de geçerlidir. Şimdi ne kadar ufak bir bu güçlü API'yi kullanın.

AudioContext'i kullanmaya başlama

AudioContext, tüm sesleri yönetmek ve çalmak için kullanılır. Üretim Web Audio API'sını kullanarak bir ses kullanıyorsanız, bir veya daha fazla ses kaynağı oluşturun ve bunları AudioContext tarafından sağlanan ses hedefine bağlayın örneğidir. Bu bağlantının doğrudan olması gerekmez ve işleme işlevi gören herhangi bir sayıda ara AudioNodes modüllerin de dahil edilmesi gerekir. Bu yönlendirme, ayrıntıları için web Audio spesifikasyonuna bakın.

Tek bir AudioContext örneği birden fazla ses girişini destekleyebilir Bu nedenle, her bir görsel için bunlardan yalnızca birine ihtiyacımız olacak. ses uygulaması var.

Aşağıdaki snippet bir AudioContext oluşturur:

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

WebKit tabanlı eski tarayıcılar için webkit önekini kullanın (örneğin, webkitAudioContext.

Video oluşturma ve ses dosyası oluşturma gibi AudioNode'lar ve ses dosyası verilerinin kodunu çözme AudioContext yöntemleridir.

Sesler yükleniyor

Web Audio API'sı, kısa ila orta uzunluktaki videolar için bir AudioBuffer kullanır seslere dokunun. Temel yaklaşım, bir istek için XMLHttpRequest değerini ses dosyaları getiriliyor.

API, ses dosyası verilerinin birden çok biçimde yüklenmesini destekler. Örneğin: WAV, MP3, AAC, OGG ve diğerleri. Farklı cihazlar için tarayıcı desteği ses biçimleri değişiklik gösterir.

Aşağıdaki snippet'te bir ses örneğinin yüklenmesi gösterilmektedir:

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

Ses dosyası verileri ikili olduğundan (metin değil), bu nedenle responseType değerini ('arraybuffer') adlı kullanıcıya gönderilen talebin tamamı. Daha fazla bilgi için ArrayBuffers, XHR2 ile ilgili bu makaleyi inceleyin.

Kodu çözülmüş ses dosyası verileri alındıktan sonra saklanabilir. veya daha sonra kodu çözmek için AudioContext decodeAudioData() yöntemi. Bu yöntem Ses dosyası verilerinin ArrayBuffer kadarı request.response ve kodunu eşzamansız olarak çözer (ana JavaScript'in yürütülmesini engellemez) ileti dizisinde gösterilir).

decodeAudioData() tamamlandığında, bir geri çağırma işlevini çağırır. kodu çözülmüş PCM ses verilerini AudioBuffer olarak sağlar.

Ses çalınıyor

Basit bir ses grafiği
Basit bir ses grafiği

Bir veya daha fazla AudioBuffers yüklendikten sonra oynamaya hazırız seslere dokunun. Sesli bir AudioBuffer yüklediğimizi varsayalım. yüklemenin sona erdiğini görebilirsiniz. Sonra oynayabiliriz aşağıdaki kodla değiştirin.

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
}

Bu playSound() işlevi, kullanıcı bir tuşa her bastığında veya fare ile bir şeyi tıkladığında.

noteOn(time) işlevi, sesin hassas bir şekilde planlanmasını kolaylaştırır ve zaman açısından kritik olan diğer uygulamalarda video oynatabilir. Ancak, bu programlama düzgün şekilde çalışıyorsa ses arabelleklerinizin önceden yüklü olarak gelir.

Web Audio API'sını Soyutlama

Tabii ki daha genel bir yükleme sistemi oluşturmak Bu ses yüklemek için sabit kodlu değildir. Pek çok ses ve görüntü kalitesinin daha da yüksek olmasını sağlayan kısa ve orta uzunlukta veya oyunun kullanacağı bir ses uygulaması vardır. Burada bir BufferLoader kullanmanın bir yolu anlatılmıştır (web standardının bir parçası değildir).

Aşağıda, BufferLoader sınıfını nasıl kullanabileceğinize dair bir örnek verilmiştir. İki AudioBuffers oluşturalım; ve yüklenir yüklenmez aynı anda oynatalım.

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

Zamanla uğraşmak: Sesleri ritimli çalma

Web Audio API'sı, geliştiricilerin oynatmayı hassas bir şekilde programlamasını sağlar. Alıcı: basit bir ritim parçası oluşturalım. Muhtemelen en yaygın drumkit deseni şudur:

Sade bir rock davul modeli
Basit bir rock davul deseni

her sekiz notada bir hihat çalınır, vuruşlar ve tuzaklar ise 4'te 4'lük dilimde oynanıyor.

kick, snare ve hihat tamponlarını yüklediğimizi varsayalım. oldukça basit bir kodla bunu yapabilirsiniz:

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

Bu örnekte, sürekli olarak gördüğümüz sınırsız döngü yerine tek bir tekrar nota kağıtları. playSound fonksiyonu, bir arabellekte aşağıdaki gibi uygulanır:

function playSound(buffer, time) {
    var source = context.createBufferSource();
    source.buffer = buffer;
    source.connect(context.destination);
    source.noteOn(time);
}

Sesin ses düzeyini değiştirme

Ses üzerinde yapmak isteyebileceğiniz en temel işlemlerden biri ses düzeyini değiştirin. Web Audio API'sını kullanarak kaynağımızı manipüle etmek için hedefin bir AudioGainNode ses seviyesi:

Kazanç düğümlü ses grafiği
Kazanç düğümlü ses grafiği

Bu bağlantı kurulumu aşağıdaki gibi yapılabilir:

// 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);

Grafik oluşturulduktan sonra, mevcut değişikliklerini programlı olarak gainNode.gain.value aşağıdaki gibi değişiklikler yaparak hacmi şu şekilde değiştirebilirsiniz:

// Reduce the volume.
gainNode.gain.value = 0.5;

İki ses arasında geçiş

Şimdi, biraz daha karmaşık bir senaryomuzun mevcut olduğunu varsayalım. birden fazla ses çalıyor ancak sesler arasında geçiş yapmak istiyorum. Bu, DJ benzeri bir uygulamada, iki pikap ve 2 pikap bir ses kaynağından diğerine yatay kaydırabilmek istiyorsanız.

Bu, aşağıdaki ses grafiğiyle yapılabilir:

Kazanç düğümleri üzerinden bağlı iki kaynak içeren ses grafiği
Kazanç düğümleri üzerinden birbirine bağlı iki kaynak içeren ses grafiği

Bunu ayarlamak için iki AudioGainNodes oluşturup her kaynağı düğümler aracılığıyla test edin. Bunun için aşağıdaki işlevi kullanabilirsiniz:

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

Eşit güç geçişi

Naif doğrusal çapraz geçiş yaklaşımında, siz yatay olarak kaydırdıkça hacimde bir düşüş gözlemlenir örneklemlerde çalışır.

Doğrusal bir çapraz geçiş
Doğrusal bir çapraz geçiş

Bu sorunu çözmek için, eşit bir güç eğrisi kullanırız. Burada, karşılık gelen kazanç eğrileri doğrusal değildir ve daha yüksek bir genlik değeri. Bu şekilde ses bölgeleri arasındaki ses düşüşleri en aza indirilir ve böylece bölgeler arasında daha dengeli bir geçişe farklı seviyededir.

Eşit güç geçişi.
Güç geçişinin eşit olması

Oynatma listesi çapraz geçişleri

Yaygın olarak kullanılan diğer bir çapraz geçiş uygulaması, müzik çalar uygulamasıdır. Bir şarkı değiştiğinde, mevcut parçayı soldurmak ve arka planı kasvetli bir geçiş yapılması gerekir. Bunu yapmak için bir geleceğe doğru gidebiliyor. Bunu yapmak için setTimeout kullanabiliriz. bu hassas değildir. Web Audio API'sıyla, AudioParam arayüzünü kullanarak AudioGainNode kazanç değeri gibi parametreleri dahil eder.

Böylece, bir oynatma listesinde bir parçayı planlayarak o anda oynatılan parçada düşüş, müzik dinlerken de parçanın çalınması bitmeden önce her ikisi de çalmaya başlar:

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'sı, aşağıdakileri yapmak için uygun bir RampToValue yöntem grubu sağlar parametrenin değerini kademeli olarak değiştirin: linearRampToValueAtTime ve exponentialRampToValueAtTime.

Geçiş zamanlaması işlevi, yerleşik doğrusaldan seçilebilir. üstel olanlarla (yukarıda belirtildiği gibi) kendi değerinizi de eğrisini oluşturabilirsiniz.setValueCurveAtTime

Sese basit bir filtre efekti uygulama

BiquadFilterNode içeren ses grafiği
BiquadFilterNode ile ses grafiği

Web Audio API'sı, sesi bir ses düğümünden diğerine aktarmanızı sağlar. daha karmaşık işlemler için karmaşık olabilecek bir işlemci zinciri ses efektleri kullanabilirsiniz.

Bunu yapmanın bir yolu sesinizin arasına BiquadFilterNode'ları yerleştirmektir kaynak ve hedef. Bu tür ses düğümü, çeşitli işlemler yapabilir. grafik ekolayzerleri ve hatta ses efektleri oluşturmak için kullanılabilecek düşük daha karmaşık efektler içerir. Bu, genellikle reklamın hangi kısımlarının bir sesin vurgulanacak ve azaltılacak frekans spektrumu.

Desteklenen filtre türleri şunlardır:

  • Düşük geçiş filtresi
  • Yüksek geçiş filtresi
  • Bant kartı filtresi
  • Düşük raf filtresi
  • Yüksek raf filtresi
  • Odak boyama filtresi
  • Çentik filtresi
  • Tüm kartlar filtresi

Tüm filtreler, kazanç, filtrenin uygulanma sıklığı ve kalite faktörü. Düşük geçiş filtresi, düşük frekans aralığını korur ancak yüksek olanı siler göstermenizi sağlar. Ayrılma noktası, sıklık değerine göre belirlenir. Q faktörü birimsizdir ve maddenin şeklinin grafiğe dönüştürülebilir. Bu kazanç yalnızca bazı filtreleri etkiler. Örneğin, filtre filtrelerine dikkat edin.

Basit bir düşük geçiş filtresi kullanarak bir öğeden yalnızca temelleri ses örneği:

// 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);

Genel olarak, aynı frekansta çalışmaya devam etmesi için logaritmik ölçek, insan işitmesi aynı ilkeye sahiptir ve (Yani A4 440 Hz, A5 ise 880 Hz'dir). Daha fazla bilgi için Yukarıdaki kaynak kodu bağlantısında FilterSample.changeFrequency işlevi.

Son olarak, örnek kodun Google Analytics 4'e bağlanmanızı ve dinamik olarak değiştiren bir dizi filtre kullanabilirsiniz. Bağlantıyı kesebiliriz node.disconnect(outputNumber) çağırarak grafikteki AudioNode'lar. Örneğin, grafiği bir filtreden geçecek şekilde yeniden yönlendirmek için, doğrudan bağlantı varsa, aşağıdakileri yapabiliriz:

// Disconnect the source and filter.
source.disconnect(0);
filter.disconnect(0);
// Connect the source directly.
source.connect(context.destination);

Daha fazla dinleme

Ses yükleme ve çalma da dahil olmak üzere API'nın temel özelliklerini ele aldık kullanabilirsiniz. Kazanç düğümleri ve filtreler içeren ses grafikleri oluşturduk ve yaygın sesleri etkinleştirmek için planlanmış sesler ve ses parametresi değişiklikleri hoşuma gidiyor. Bu noktada, temiz bir web sitesi oluşturmaya hazırsınız. ses uygulamaları!

İlham arıyorsanız, birçok geliştirici halihazırda Web Audio API'sını kullanarak harika bir iş çıkardınız. Beğendiklerim şunlardır:

  • AudioJedit adlı tarayıcı içi ses birleştirme aracı SoundCloud kalıcı bağlantıları.
  • ToneCraft, seslerin üst üste dizilmiş 3D bloklar oluşturur.
  • Plink, Web Sesi ve Web kullanılarak ortaklaşa bir müzik yapma oyunu Yuvalar.