אודיו מרחבי

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

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

אם התוכן שלכם נעשה בו שימוש בפורמט אודיו נתמך, תוכלו להוסיף אודיו מרחבי לאפליקציה החל מגרסה 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().

האפשרות הזו שימושית אם רוצים לשנות את בחירת הטראק במהלך ההפעלה באמצעות הקריאות החוזרות (callback) של המאזין. לדוגמה, כשמשתמש מחבר או מנתק את אוזניות מהמכשיר, onSpatializerAvailableChanged קריאה חוזרת (callback) מציינת אם אפקט המרחב המשותף זמין ניתוב פלט אודיו. בשלב הזה, כדאי לעדכן את הלוגיקה של בחירת הטראקים בנגן כך שתתאים ליכולות החדשות של המכשיר. פרטים על אופן הבחירה של הטראקים ב-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 במכשיר. במקום זאת, אפשר להתאים אישית את הלוגיקה של בחירת הטראקים ב-ExpoPlayer על ידי הגדרה של בחירת הטראק פרמטרים לפני ההפעלה או במהלכה. כברירת מחדל, 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 כוללת את ההתנהגויות הבאות שעשוי להיות מותאם אישית על ידי יצרני ציוד מקורי:

  • רק תוכן מרובה ערוצים מותאם למרחב, ולא תוכן סטריאו. אם אתם לא משתמשים ב-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)