אודיו מרחבי

אודיו מרחבי הוא חוויית אודיו immersive שמציבה את המשתמשים במרכז הפעולה, וכך הופכת את התוכן למציאותי יותר. הצליל הוא 'מרחבי' כדי ליצור אפקט לריבוי רמקולים, בדומה להגדרה של צליל סראונד, אבל במקום זאת נעשה שימוש באוזניות.

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

אם התוכן שלכם נעשה בו שימוש בפורמט אודיו נתמך, תוכלו להוסיף אודיו מרחבי לאפליקציה החל מגרסה Android 13 (רמת API 33).

שליחת שאילתה לגבי יכולות

אפשר להשתמש בכיתה Spatializer כדי לשלוח שאילתות לגבי היכולות וההתנהגות של המכשיר בהקשר למיקום הפיזי. מתחילים באחזור מופע של Spatializer מה-AudioManager:

Kotlin

val spatializer = audioManager.spatializer

Java

Spatializer spatializer = AudioManager.getSpatializer();

אחרי שמקבלים את Spatializer, צריך לבדוק את ארבעת התנאים שצריכים להתקיים כדי שהמכשיר יפיק אודיו מרחבי:

קריטריונים בדיקה
האם המכשיר תומך במרחב? getImmersiveAudioLevel() לא שווה ל-SPATIALIZER_IMMERSIVE_LEVEL_NONE
האם אפשר להשתמש בהמרה למרחב?
הזמינות תלויה בתאימות לניתוב הנוכחי של פלט האודיו.
isAvailable() הוא true
האם ההמרה למרחב מופעלת? isEnabled() הוא true
האם אפשר ליצור אודיו מרחבי מטראק אודיו עם הפרמטרים הנתונים? הערך של canBeSpatialized() הוא true

ייתכן שהתנאים האלה לא יתקיימו, למשל אם הסטריאופוניה לא זמינה לטראק האודיו הנוכחי או שהיא מושבתת לגמרי במכשיר הפלט של האודיו.

מעקב אחר תנועות הראש

באוזניות נתמכות, הפלטפורמה יכולה לשנות את המיקום המרחבי של האודיו בהתאם למיקום הראש של המשתמש. כדי לבדוק אם מכשיר למעקב אחר תנועות הראש זמין לניתוב הנוכחי של פלט האודיו, צריך להפעיל את הפונקציה isHeadTrackerAvailable().

תוכן תואם

Spatializer.canBeSpatialized() מציין אם אפשר ליצור אודיו מרחבי עם המאפיינים הנתונים באמצעות הניתוב הנוכחי של מכשיר הפלט. השיטה מקבלת פרמטר AudioAttributes ופרמטר AudioFormat, שניהם מתוארים בהרחבה בהמשך.

AudioAttributes

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

כשקוראים ל-canBeSpatialized(), צריך להשתמש באותה מכונה של AudioAttributes שמוגדרת ל-Player. לדוגמה, אם אתם משתמשים בספרייה Jetpack Media3 ולא התאמתם אישית את AudioAttributes, השתמשו ב-AudioAttributes.DEFAULT.

השבתת אודיו מרחבי

כדי לציין שהתוכן כבר עבר עיבוד מרחבי, צריך להפעיל את הפונקציה setIsContentSpatialized(true) כדי שהאודיו לא יתבצע עיבוד כפול. לחלופין, אפשר לשנות את התנהגות המרחב כדי להשבית לגמרי את המרחב באמצעות קריאה ל-setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER).

AudioFormat

אובייקט AudioFormat מתאר פרטים על הפורמט ועל תצורת הערוץ של טראק של אודיו.

כשיוצרים את המכונה של AudioFormat כדי להעביר אותה אל canBeSpatialized(), צריך להגדיר את הקידוד כך שיהיה זהה לפורמט הפלט הצפוי מהפענוח. בנוסף, צריך להגדיר מסכת ערוץ שתואמת להגדרות הערוץ של התוכן. בקטע התנהגות ברירת המחדל של מיקום גיאוגרפי מפורטות הנחיות לגבי ערכים ספציפיים שאפשר להשתמש בהם.

האזנה לשינויים בSpatializer

כדי להאזין לשינויים במצב של Spatializer, אפשר להוסיף מאזין באמצעות Spatializer.addOnSpatializerStateChangedListener(). באופן דומה, כדי לשמוע על שינויים בזמינות של מכשיר למעקב אחר תנועות הראש, צריך להפעיל את הפונקציה Spatializer.addOnHeadTrackerAvailableListener().

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

ExoPlayer ואודיו מרחבי

בגרסאות האחרונות של ExoPlayer קל יותר להשתמש באודיו מרחבי. אם אתם משתמשים בספריית ExoPlayer העצמאית (שם החבילה com.google.android.exoplayer2), בגרסה 2.17 הפלטפורמה מוגדרת להפיק אודיו מרחבי, ובגרסה 2.18 נוספו אילוצים על מספר ערוצי האודיו. אם אתם משתמשים במודול ExoPlayer מהספרייה Media3‏ (שם החבילה androidx.media3), הגרסאות 1.0.0-beta01 ואילך כוללות את אותם עדכונים.

אחרי שמעדכנים את התלות של ExoPlayer לגרסה האחרונה, האפליקציה שלכם רק צריכה לכלול תוכן שניתן להתאים למרחב.

מגבלות על מספר ערוצי האודיו

כשכל ארבעת התנאים למילוי של אודיו מרחבי מתקיימים, מערכת ExoPlayer בוחרת טראק אודיו עם מספר ערוצים. אם לא, ExoPlayer בוחר בטראק סטריאו במקום זאת. אם המאפיינים של Spatializer ישתנו, ExoPlayer יפעיל בחירת טראק חדשה כדי לבחור טראק אודיו שמתאים למאפיינים הנוכחיים. שימו לב שבחירת הטראקים החדשה הזו עלולה לגרום לזמן אגירת נתונים קצר.

כדי להשבית את האילוצים על מספר ערוצי האודיו, מגדירים את הפרמטרים של בחירת הטראק בנגן, כפי שמתואר בהמשך:

Kotlin

exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context)
  .setConstrainAudioChannelCountToDeviceCapabilities(false)
  .build()

Java

exoPlayer.setTrackSelectionParameters(
  new DefaultTrackSelector.Parameters.Builder(context)
    .setConstrainAudioChannelCountToDeviceCapabilities(false)
    .build()
);

באופן דומה, אפשר לעדכן את הפרמטרים של בורר טראקים קיים כדי להשבית את האילוצים על מספר ערוצי האודיו באופן הבא:

Kotlin

val trackSelector = DefaultTrackSelector(context)
...
trackSelector.parameters = trackSelector.buildUponParameters()
  .setConstrainAudioChannelCountToDeviceCapabilities(false)
  .build()

Java

DefaultTrackSelector trackSelector = new DefaultTrackSelector(context);
...
trackSelector.setParameters(
  trackSelector
    .buildUponParameters()
    .setConstrainAudioChannelCountToDeviceCapabilities(false)
    .build()
);

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

בחירת טראק של אודיו

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

שינוי הפרמטרים לבחירת טראקים

כדי לשנות את הפרמטרים של בחירת הטראק ב-exoPlayer, משתמשים ב-Player.setTrackSelectionParameters(). באותו אופן, אפשר לקבל את הפרמטרים הנוכחיים של ExoPlayer באמצעות Player.getTrackSelectionParameters(). לדוגמה, כדי לבחור טראק אודיו סטריאופוני במהלך ההפעלה:

Kotlin

exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters
  .buildUpon()
  .setMaxAudioChannelCount(2)
  .build()

Java

exoPlayer.setTrackSelectionParameters(
  exoPlayer.getTrackSelectionParameters()
    .buildUpon()
    .setMaxAudioChannelCount(2)
    .build()
);

שימו לב ששינוי הפרמטרים של בחירת הטראק במהלך ההפעלה עלול לגרום להפרעה בהפעלה. מידע נוסף על שינוי הפרמטרים של בחירת הטראקים בנגן זמין בקטע בחירת טראקים במסמכי העזרה של ExoPlayer.

התנהגות ברירת המחדל של הפריסה המרחבית

התנהגות ברירת המחדל של המיקום המרחבי ב-Android כוללת את ההתנהגויות הבאות, ש-OEM יכולים להתאים אישית:

  • רק תוכן מרובה ערוצים מקבל עיבוד מרחבי, ולא תוכן סטריאו. אם אתם לא משתמשים ב-ExoPlayer, בהתאם לפורמט של תוכן האודיו עם מספר ערוצים, יכול להיות שתצטרכו להגדיר מספר גדול של ערוצים מקסימליים שיכולים להופיע בפלט של מקודד האודיו. כך מוודאים שמפענח האודיו יפיק PCM במספר ערוצים כדי שהפלטפורמה תוכל לבצע מיקום מרחבי.

    Kotlin

    val mediaFormat = MediaFormat()
    mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99)

    Java

    MediaFormat mediaFormat = new MediaFormat();
    mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99);

    כדי לראות דוגמה בפעולה, אפשר לעיין ב-MediaCodecAudioRenderer.java של ExoPlayer. כדי להשבית את הסטריאופוניה בעצמכם, ללא קשר להתאמה אישית של יצרן הציוד המקורי, תוכלו לעיין במאמר השבתה של אודיו מרחבי.

  • AudioAttributes: אפשר להשתמש באודיו מרחבי אם האפשרות usage מוגדרת לערך USAGE_MEDIA או USAGE_GAME.

  • AudioFormat: כדי שהאודיו יהיה מתאים להמרה למרחב סראונד, צריך להשתמש במסכת ערוצים שמכילה לפחות את הערוצים AudioFormat.CHANNEL_OUT_QUAD (שמאל קדמי, שמאל אחורי, ימין קדמי וימין אחורי). בדוגמה הבאה, אנחנו משתמשים ב-AudioFormat.CHANNEL_OUT_5POINT1 לטראק אודיו 5.1. לטראק אודיו סטריאופוני, משתמשים ב-AudioFormat.CHANNEL_OUT_STEREO.

    אם אתם משתמשים ב-Media3, תוכלו להשתמש ב-Util.getAudioTrackChannelConfig(int channelCount) כדי להמיר את מספר הערוצים למסכת ערוצים.

    בנוסף, מגדירים את הקידוד ל-AudioFormat.ENCODING_PCM_16BIT אם הגדרתם את המפענח להפיק PCM מרובה-ערוצים.

    Kotlin

    val audioFormat = AudioFormat.Builder()
      .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
      .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1)
      .build()

    Java

    AudioFormat audioFormat = new AudioFormat.Builder()
      .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
      .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1)
      .build();

בדיקת אודיו מרחבי

מוודאים שהאודיו המרחבי מופעל במכשיר הבדיקה:

  • באוזניות קוויות, עוברים אל הגדרות מערכת > צליל ורטט > אודיו מרחבי.
  • באוזניות אלחוטיות, עוברים אל הגדרות המערכת > מכשירים מחוברים > סמל גלגל השיניים של המכשיר האלחוטי > אודיו מרחבי.

כדי לבדוק אם האודיו המרחבי זמין במסלול הנוכחי, מריצים את הפקודה adb shell dumpsys audio במכשיר. הפרמטרים הבאים אמורים להופיע בפלט בזמן שההפעלה פעילה:

Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)