אודיו מרחבי

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

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

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

  • 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)