עדכונים של אודיו באינטרנט ב-Chrome 49

Chris Wilson
Chris Wilson

אנחנו משפרים את התמיכה ב-Web Audio API ב-Chrome באופן שוטף ובשקט. ב-Chrome 49 (גרסת בטא נכון לפברואר 2016, גרסת יציבה צפויה לצאת במרץ 2016) עדכנו כמה תכונות כדי לעקוב אחרי המפרט, והוספנו גם צומת חדש אחד.

הפונקציה decodeAudioData() מחזירה עכשיו promise

השיטה decodeAudioData()‎ ב-AudioContext מחזירה עכשיו Promise, ומאפשרת טיפול בסטרימינג אסינכרוני מבוסס-Promise. ה-method ‏decodeAudioData() תמיד קיבל פונקציות קריאה חוזרת (callbacks) של הצלחה ושגיאה כפרמטרים:

context.decodeAudioData( arraybufferData, onSuccess, onError);

אבל עכשיו אפשר להשתמש במקום זאת בשיטת Promise רגילה כדי לטפל בטבע האסינכרוני של פענוח נתוני האודיו:

context.decodeAudioData( arraybufferData ).then(
        (buffer) => { /* store the buffer */ },
        (reason) => { console.log("decode failed! " + reason) });

בדוגמה אחת זה נראה מפורט יותר, אבל ה-Promises מאפשרים לבצע תכנות אסינכרוני בקלות ובאופן עקבי יותר. מטעמי תאימות, עדיין יש תמיכה בפונקציות הקריאה החוזרת (callbacks) של הצלחה ושל שגיאה, בהתאם למפרט.

OfflineAudioContext תומך עכשיו ב-suspend() וב-resume()

במבט ראשון, יכול להיות שייראה מוזר להשתמש ב-suspend() ב-OfflineAudioContext. אחרי הכל, suspend() נוסף ל-AudioContext כדי לאפשר להעביר את חומרת האודיו למצב המתנה, וזה נראה חסר טעם בתרחישים שבהם מבצעים עיבוד (לזה מיועד OfflineAudioContext, כמובן). עם זאת, המטרה של התכונה הזו היא לאפשר ליצור רק חלק מ'הניקוד' בכל פעם, כדי למזער את השימוש בזיכרון. אפשר ליצור צמתים נוספים בזמן ההשהיה באמצע הרינדור.

לדוגמה, סונטת הירח של בטהובן מכילה כ-6,500 תווים. סביר להניח שכל 'הערה' מפורקת לפחות לשני צמתים בתרשים האודיו (למשל, צומת AudioBuffer וצומת Gain). אם רוצים ליצור עיבוד של כל שבע וחצי הדקות במאגר באמצעות OfflineAudioContext, סביר להניח שלא רוצים ליצור את כל הצמתים האלה בבת אחת. במקום זאת, אפשר ליצור אותם בקטעים של זמן:

var context = new OfflineAudioContext(2, length, sampleRate);
scheduleNextBlock();
context.startRendering().then( (buffer) => { /* store the buffer */ } );

function scheduleNextBlock() {
    // create any notes for the next blockSize number of seconds here
    // ...

    // make sure to tell the context to suspend again after this block;
    context.suspend(context.currentTime + blockSize).then( scheduleNextBlock );

    context.resume();
}

כך תוכלו לצמצם את מספר הצמתים שצריך ליצור מראש בתחילת העיבוד, ולצמצם את דרישות הזיכרון.

IIRFilterNode

למפרט נוספ צולב לאוהבי אודיו שרוצים ליצור תגובה מיידית אינסופית משלהם שמוגדרת במדויק: IIRFilterNode. המסנן הזה משלים את BiquadFilterNode, אבל מאפשר לציין באופן מלא את הפרמטרים של תגובת המסנן (במקום AudioParams של BiquadFilterNode, שקל להשתמש בו כדי לציין את הסוג, התדר, הערך Q וכו'). ה-IIRFilterNode מאפשר לציין מסננים בצורה מדויקת שלא ניתן היה ליצור בעבר, כמו מסננים מסדר יחיד. עם זאת, כדי להשתמש ב-IIRFilterNode צריך ידע מעמיק לגבי אופן הפעולה של מסנני IIR, וגם אי אפשר לתזמן אותם כמו BiquadFilterNodes.

שינויים קודמים

רציתי גם לציין כמה שיפורים שנוספו בעבר: ב-Chrome 48, האוטומציה של צמתים מסוג BiquadFilter התחילה לפעול בקצב אודיו. ממשק ה-API לא השתנה כלל כדי לעשות זאת, אבל זה אומר שהסינון של הצלילים יהיה חלק יותר. בנוסף, ב-Chrome 48 הוספנו שרשרת לשיטה AudioNode.connect() על ידי החזרת הצומת שאליו אנחנו מתחברים. כך קל יותר ליצור רשתות של צמתים, כמו בדוגמה הזו:

sourceNode.connect(gainNode).connect(filterNode).connect(context.destination);

זה הכול בינתיים, ושיהיה לך המשך יום מצוין!