صوتی فضایی

صدای فضایی یک تجربه صوتی فراگیر است که کاربران شما را در مرکز عمل قرار می دهد و محتوای شما را واقعی تر می کند. صدا برای ایجاد یک افکت چند بلندگو، شبیه به تنظیم صدای فراگیر، اما در عوض از طریق هدفون، "فضایی" شده است.

به عنوان مثال، در یک فیلم، صدای یک ماشین ممکن است از پشت کاربر شروع شود، به جلو حرکت کند و به دوردست ها ادامه یابد. در یک چت ویدیویی، صداها را می توان از هم جدا کرد و در اطراف کاربر قرار داد و تشخیص بلندگوها را آسان تر می کند.

اگر محتوای شما از فرمت صوتی پشتیبانی‌شده استفاده می‌کند، می‌توانید با شروع Android 13 (سطح API 33) صدای مکانی را به برنامه خود اضافه کنید.

پرس و جو برای قابلیت ها

از کلاس Spatializer برای پرس و جو در مورد قابلیت ها و رفتار فضایی دستگاه استفاده کنید. با بازیابی یک نمونه از Spatializer از AudioManager شروع کنید:

کاتلین

val spatializer = audioManager.spatializer

جاوا

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() را فراخوانی کنید.

اگر بخواهید انتخاب آهنگ خود را در حین پخش با استفاده از تماس های شنونده تنظیم کنید، می تواند مفید باشد. به عنوان مثال، هنگامی که یک کاربر هدست خود را از دستگاه متصل می کند یا آن را جدا می کند، پاسخ تماس 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 یک انتخاب آهنگ جدید را برای انتخاب یک آهنگ صوتی که با ویژگی‌های فعلی مطابقت دارد، راه‌اندازی می‌کند. توجه داشته باشید که این انتخاب آهنگ جدید ممکن است باعث یک دوره ذخیره مجدد کوتاه شود.

برای غیرفعال کردن محدودیت های تعداد کانال های صوتی، پارامترهای انتخاب آهنگ را بر روی پخش کننده مطابق شکل زیر تنظیم کنید:

کاتلین

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

جاوا

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

به طور مشابه، می‌توانید پارامترهای انتخابگر آهنگ موجود را برای غیرفعال کردن محدودیت‌های تعداد کانال صوتی به‌صورت زیر به‌روزرسانی کنید:

کاتلین

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

جاوا

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

با غیرفعال شدن محدودیت های شمارش کانال های صوتی، اگر محتوا دارای چندین تراک صوتی باشد، ExoPlayer در ابتدا آهنگی را انتخاب می کند که بیشترین تعداد کانال را دارد و از دستگاه قابل پخش است. برای مثال، اگر محتوا حاوی یک تراک صوتی چند کاناله و یک تراک صوتی استریو باشد و دستگاه از پخش هر دو پشتیبانی کند، ExoPlayer آهنگ چند کاناله را انتخاب می کند. برای جزئیات در مورد نحوه سفارشی کردن این رفتار، به انتخاب آهنگ صوتی مراجعه کنید.

انتخاب آهنگ صوتی

وقتی رفتار محدودیت‌های شمارش کانال صوتی ExoPlayer غیرفعال است، ExoPlayer به طور خودکار آهنگ صوتی را انتخاب نمی‌کند که با ویژگی‌های فضاساز دستگاه مطابقت داشته باشد. در عوض، می‌توانید منطق انتخاب آهنگ ExoPlayer را با تنظیم پارامترهای انتخاب آهنگ قبل یا در حین پخش سفارشی کنید. به‌طور پیش‌فرض، ExoPlayer آهنگ‌های صوتی را انتخاب می‌کند که با توجه به نوع MIME (رمزگذاری)، تعداد کانال و نرخ نمونه مشابه آهنگ اولیه هستند.

تغییر پارامترهای انتخاب آهنگ

برای تغییر پارامترهای انتخاب آهنگ ExoPlayer، از Player.setTrackSelectionParameters() استفاده کنید. به همین ترتیب، می توانید پارامترهای فعلی ExoPlayer را با Player.getTrackSelectionParameters() دریافت کنید. به عنوان مثال، برای انتخاب یک تراک صوتی استریو در اواسط پخش:

کاتلین

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

جاوا

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

توجه داشته باشید که تغییر پارامترهای انتخاب آهنگ در اواسط پخش ممکن است باعث وقفه در پخش شود. اطلاعات بیشتر در مورد تنظیم پارامترهای انتخاب آهنگ پخش کننده در بخش انتخاب آهنگ در اسناد ExoPlayer موجود است.

رفتار فضایی سازی پیش فرض

رفتار فضایی سازی پیش فرض در Android شامل رفتارهای زیر است که ممکن است توسط OEM ها سفارشی شود:

  • فقط محتوای چند کاناله فضایی است، نه محتوای استریو. اگر از ExoPlayer استفاده نمی‌کنید، بسته به فرمت محتوای صوتی چند کانالی خود، ممکن است نیاز باشد حداکثر تعداد کانال‌هایی را که می‌تواند توسط رمزگشای صوتی خروجی می‌شود، به تعداد زیادی پیکربندی کنید. این تضمین می کند که رمزگشای صوتی PCM چند کاناله را برای فضایی شدن پلت فرم خروجی می دهد.

    کاتلین

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

    جاوا

    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) برای تبدیل تعداد کانال به ماسک کانال استفاده کنید.

    علاوه بر این، اگر رمزگشا را برای خروجی PCM چند کاناله پیکربندی کرده اید، کدگذاری را روی AudioFormat.ENCODING_PCM_16BIT تنظیم کنید.

    کاتلین

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

    جاوا

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

تست صوت مکانی

مطمئن شوید که صدای مکانی در دستگاه آزمایشی شما فعال است:

  • برای هدست های سیمی، به تنظیمات سیستم > صدا و لرزش > صدای فضایی بروید.
  • برای هدست های بی سیم، به تنظیمات سیستم > دستگاه های متصل > نماد چرخ دنده برای دستگاه بی سیم خود > صدای فضایی بروید.

برای بررسی در دسترس بودن Spatial Audio برای مسیریابی فعلی، دستور adb shell dumpsys audio در دستگاه خود اجرا کنید. هنگامی که پخش فعال است، باید پارامترهای زیر را در خروجی مشاهده کنید:

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