افزونه های اندروید

OpenSL ES برای Android مشخصات OpenSL ES مرجع را گسترش می دهد تا با Android سازگار باشد و از قدرت و انعطاف پذیری پلت فرم اندروید بهره مند شود.

تعریف API برای برنامه‌های افزودنی Android در OpenSLES_Android.h و فایل‌های سرصفحه‌ای که شامل می‌شود قرار دارد. برای جزئیات بیشتر در مورد این افزونه ها با OpenSLES_Android.h مشورت کنید. این فایل در زیر ریشه نصب شما، در پوشه sysroot/usr/include/SLES قرار دارد. مگر اینکه غیر از این ذکر شده باشد، همه رابط ها صریح هستند.

این افزونه‌ها قابلیت حمل برنامه شما را به سایر پیاده‌سازی‌های OpenSL ES محدود می‌کنند، زیرا آن‌ها مختص اندروید هستند. می توانید با اجتناب از استفاده از افزونه ها یا با استفاده از #ifdef برای حذف آنها در زمان کامپایل، این مشکل را کاهش دهید.

جدول زیر رابط های خاص اندروید و مکان یاب داده را نشان می دهد که Android OpenSL ES برای هر نوع شی پشتیبانی می کند. مقادیر Yes در سلول ها رابط ها و مکان یاب داده ای را نشان می دهد که برای هر نوع شی در دسترس است.

ویژگی پخش کننده صدا ضبط کننده صدا موتور ترکیب خروجی
صف بافر اندروید بله: منبع (رمزگشایی) خیر خیر خیر
پیکربندی اندروید بله بله خیر خیر
افکت اندروید بله خیر خیر بله
قابلیت افکت اندروید خیر خیر بله خیر
ارسال افکت اندروید بله خیر خیر خیر
صف بافر ساده اندروید بله: منبع (پخش) یا سینک (رمزگشایی) بله خیر خیر
مکان یاب داده صف بافر اندروید بله: منبع (رمزگشایی) خیر خیر خیر
مکان یاب داده توصیفگر فایل اندروید بله: منبع خیر خیر خیر
یاب داده صف بافر ساده اندروید بله: منبع (پخش) یا سینک (رمزگشایی) بله: سینک خیر خیر

رابط پیکربندی اندروید

رابط پیکربندی Android وسیله ای برای تنظیم پارامترهای پلتفرم خاص برای اشیا فراهم می کند. این رابط با دیگر رابط‌های OpenSL ES 1.0.1 متفاوت است زیرا برنامه شما می‌تواند قبل از نمونه‌سازی شی مربوطه از آن استفاده کند. بنابراین، می توانید قبل از نمونه سازی شی، آن را پیکربندی کنید. فایل سرصفحه OpenSLES_AndroidConfiguration.h که در /sysroot/usr/include/SLES قرار دارد، کلیدهای پیکربندی موجود و مقادیر زیر را مستند می‌کند:

  • نوع جریان برای پخش‌کننده‌های صوتی (پیش‌فرض SL_ANDROID_STREAM_MEDIA ).
  • نمایه ضبط برای ضبط کننده های صوتی (پیش فرض SL_ANDROID_RECORDING_PRESET_GENERIC ).

قطعه کد زیر نمونه ای از نحوه تنظیم نوع جریان صوتی اندروید را در پخش کننده صوتی نشان می دهد:

// CreateAudioPlayer and specify SL_IID_ANDROIDCONFIGURATION
// in the required interface ID array. Do not realize player yet.
// ...
SLAndroidConfigurationItf playerConfig;
result = (*playerObject)->GetInterface(playerObject,
    SL_IID_ANDROIDCONFIGURATION, &playerConfig);
assert(SL_RESULT_SUCCESS == result);
SLint32 streamType = SL_ANDROID_STREAM_ALARM;
result = (*playerConfig)->SetConfiguration(playerConfig,
    SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
assert(SL_RESULT_SUCCESS == result);
// ...
// Now realize the player here.

می‌توانید از کد مشابهی برای پیکربندی پیش‌تنظیم ضبط‌کننده صدا استفاده کنید:

// ... obtain the configuration interface as the first four lines above, then:
SLuint32 presetValue = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
result = (*playerConfig)->SetConfiguration(playerConfig,
    RECORDING_PRESET, &presetValue, sizeof(SLuint32));

رابط های افکت اندروید

رابط‌های قابلیت‌های افکت، ارسال افکت و افکت اندروید مکانیزمی کلی برای درخواست و استفاده از جلوه‌های صوتی خاص دستگاه برای یک برنامه فراهم می‌کنند. سازندگان دستگاه باید جلوه‌های صوتی خاص دستگاه را که ارائه می‌کنند مستند کنند.

برنامه‌های قابل حمل باید از APIهای OpenSL ES 1.0.1 برای جلوه‌های صوتی به جای برنامه‌های افزودنی افکت Android استفاده کنند.

مکان یاب داده توصیفگر فایل اندروید

مکان یاب داده توصیفگر فایل Android به شما امکان می دهد منبع یک پخش کننده صوتی را به عنوان یک توصیف کننده فایل باز با دسترسی خواندن مشخص کنید. فرمت داده باید MIME باشد.

این برنامه افزودنی به ویژه در ارتباط با مدیر دارایی بومی مفید است، زیرا برنامه دارایی ها را از APK از طریق یک توصیفگر فایل می خواند.

یاب و رابط داده صف بافر ساده اندروید

در مشخصات مرجع OpenSL ES 1.0.1، صف های بافر فقط برای پخش کننده های صوتی قابل استفاده هستند و با PCM و سایر فرمت های داده سازگار هستند. مشخصات یاب داده صف بافر ساده اندروید و مشخصات رابط با مشخصات مرجع یکسان است، با دو استثنا:

  • می توانید از صف های بافر ساده اندروید با ضبط کننده های صوتی و پخش کننده های صوتی استفاده کنید.
  • شما فقط می توانید از فرمت داده PCM با این صف ها استفاده کنید.

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

پخش به همین صورت عمل می کند. با این حال، برای سازگاری کد منبع در آینده، پیشنهاد می‌کنیم که برنامه‌ها از صف‌های بافر ساده Android به جای صف‌های بافر OpenSL ES 1.0.1 استفاده کنند.

رفتار صف بافر

اجرای Android شامل الزامات مشخصات مرجع نیست که نشانگر پخش به ابتدای بافر در حال پخش فعلی بازگردد، زمانی که پخش وارد حالت SL_PLAYSTATE_STOPPED شد. این پیاده‌سازی می‌تواند با آن رفتار مطابقت داشته باشد، یا می‌تواند مکان مکان‌نمای بازی را بدون تغییر باقی بگذارد. در نتیجه، برنامه شما نمی تواند فرض کند که هر یک از این رفتارها رخ می دهد. بنابراین، شما باید به صراحت BufferQueue::Clear() پس از انتقال به SL_PLAYSTATE_STOPPED فراخوانی کنید. با انجام این کار، صف بافر در حالت شناخته شده قرار می گیرد.

به طور مشابه، هیچ مشخصه ای وجود ندارد که نشان دهد ماشه برای پاسخ به تماس صف بافر باید انتقال به SL_PLAYSTATE_STOPPED یا اجرای BufferQueue::Clear() باشد. بنابراین، توصیه می کنیم که وابستگی به یکی یا دیگری ایجاد نکنید. در عوض، برنامه شما باید بتواند هر دو را مدیریت کند.

رابط های پویا در ایجاد شی

برای راحتی، پیاده‌سازی Android OpenSL ES 1.0.1 به برنامه شما اجازه می‌دهد تا هنگامی که یک شی را نمونه‌سازی می‌کند، رابط‌های پویا را مشخص کند. این جایگزینی برای استفاده از DynamicInterfaceManagement::AddInterface() برای افزودن این رابط ها پس از نمونه سازی است.

گزارش برنامه های افزودنی

سه روش برای پرس و جو وجود دارد که آیا پلتفرم از برنامه های افزودنی اندروید پشتیبانی می کند یا خیر. این روش ها عبارتند از:

  • Engine::QueryNumSupportedExtensions()
  • Engine::QuerySupportedExtension()
  • Engine::IsExtensionSupported()

هر یک از این روش‌ها ANDROID_SDK_LEVEL_<API-level> را برمی‌گرداند، که در آن API-level سطح API پلتفرم است. برای مثال، ANDROID_SDK_LEVEL_23 . سطح API پلتفرم 9 یا بالاتر به این معنی است که پلتفرم از برنامه‌های افزودنی پشتیبانی می‌کند.

رمزگشایی صدا به PCM

این بخش یک برنامه افزودنی خاص Android منسوخ شده برای OpenSL ES 1.0.1 را برای رمزگشایی یک جریان رمزگذاری شده به PCM بدون پخش فوری توضیح می دهد. جدول زیر توصیه هایی را برای استفاده از این افزونه و جایگزین ها ارائه می دهد.

سطح API جایگزین ها
15 و پایین تر یک کدک منبع باز با مجوز مناسب
16 تا 20 کلاس MediaCodec یا یک کدک منبع باز با مجوز مناسب
21 و بالاتر NDK MediaCodec در فایل‌های هدر <media/NdkMedia*.h> ، کلاس MediaCodec یا یک کدک منبع باز با مجوز مناسب

توجه: در حال حاضر هیچ سندی برای نسخه NDK MediaCodec API وجود ندارد. با این حال، می توانید برای نمونه به کد نمونه کدک داخلی مراجعه کنید.

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

این ویژگی در درجه اول برای بازی ها در نظر گرفته شده است تا دارایی های صوتی خود را در هنگام تغییر به سطح بازی جدید از قبل بارگذاری کنند، که مشابه عملکردی است که کلاس SoundPool ارائه می دهد.

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

منبع داده به طور ضمنی پایان جریان (EOS) را با ارائه یک رویداد SL_PLAYEVENT_HEADATEND در پایان جریان گزارش می‌کند. پس از اینکه برنامه تمام داده‌های دریافتی خود را رمزگشایی کرد، دیگر با پاسخ به تماس صف بافر ساده اندروید تماسی برقرار نمی‌کند.

فرمت داده PCM سینک معمولاً با منبع داده کدگذاری شده با توجه به نرخ نمونه، تعداد کانال و عمق بیت مطابقت دارد. با این حال، می‌توانید با نرخ نمونه، تعداد کانال یا عمق بیت متفاوت رمزگشایی کنید. برای اطلاعات در مورد یک ماده برای تشخیص قالب PCM واقعی، به تعیین قالب داده های PCM رمزگشایی شده از طریق ابرداده مراجعه کنید.

OpenSL ES برای ویژگی رمزگشایی PCM اندروید از مکث و جستجوی اولیه پشتیبانی می کند. از کنترل صدا، افکت ها، حلقه زدن یا نرخ پخش پشتیبانی نمی کند.

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

توجه: برای رمزگشایی یک جریان رمزگذاری شده در PCM اما عدم پخش فوری، برای برنامه‌هایی که روی Android 4.x (سطوح API 16 تا 20) اجرا می‌شوند، توصیه می‌کنیم از کلاس MediaCodec استفاده کنید. برای برنامه‌های جدید که روی Android نسخه 5.0 (سطح API 21) یا بالاتر اجرا می‌شوند، توصیه می‌کنیم از معادل NDK، <NdkMedia*.h> استفاده کنید. این فایل‌های هدر در فهرست media/ در زیر ریشه نصب شما قرار دارند.

رمزگشایی جریان ADTS AAC به PCM

اگر منبع داده یک مکان یاب داده صف بافر اندروید باشد که از فرمت داده MIME استفاده می کند، پخش کننده صوتی به عنوان رمزگشای جریان عمل می کند، و سینک داده یک مکان یاب داده صف بافر ساده اندروید است که از قالب داده PCM استفاده می کند. فرمت داده MIME را به صورت زیر پیکربندی کنید:

  • ظرف: SL_CONTAINERTYPE_RAW
  • رشته نوع MIME: SL_ANDROID_MIME_AACADTS

این ویژگی در درجه اول برای برنامه های پخش رسانه ای است که با صدای AAC سروکار دارند اما قبل از پخش باید پردازش صوتی سفارشی انجام دهند. اکثر برنامه هایی که نیاز به رمزگشایی صدا به PCM دارند باید از روشی استفاده کنند که Decode audio to PCM توضیح می دهد، زیرا این روش ساده تر است و فرمت های صوتی بیشتری را مدیریت می کند. تکنیکی که در اینجا توضیح داده شده یک رویکرد تخصصی تری است که فقط در صورت اعمال هر دو شرایط زیر قابل استفاده است:

  • منبع صوتی فشرده جریانی از فریم‌های AAC است که در سرفصل‌های ADTS موجود است.
  • برنامه این جریان را مدیریت می کند. داده ها در یک منبع شبکه که شناسه آن یک URI است یا در یک فایل محلی که شناسه آن توصیفگر فایل است، قرار ندارد .

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

توصیه می کنیم حتما بافرهای کامل ADTS AAC را تهیه کنید تا از گرسنگی رسیور جلوگیری کنید. این ممکن است اتفاق بیفتد، به عنوان مثال، اگر برنامه شما از صف بافر Android بدون قرار گرفتن در صف بافر کامل دیگر بازگردد. نتیجه گرسنگی رسیور نامشخص است.

از همه جهات به جز منبع داده، روش رمزگشایی جریانی همان روشی است که Decode audio to PCM توضیح می‌دهد.

با وجود شباهت در نام‌ها، صف بافر اندروید با صف بافر ساده اندروید یکسان نیست . رمزگشای جریان از هر دو نوع صف بافر استفاده می کند: یک صف بافر اندروید برای منبع داده ADTS AAC و یک صف بافر ساده اندروید برای سینک داده PCM. برای اطلاعات بیشتر درباره API صف بافر ساده Android، به مکان یاب و رابط داده صف بافر ساده Android مراجعه کنید. برای اطلاعات بیشتر درباره API صف بافر Android، فایل index.html را در فهرست راهنمای docs/Additional_library_docs/openmaxal/ در زیر ریشه نصب ببینید.

فرمت داده های PCM رمزگشایی شده را از طریق ابرداده تعیین کنید

رابط SLMetadataExtractionItf بخشی از مشخصات مرجع است. با این حال، کلیدهای ابرداده که فرمت واقعی داده‌های PCM رمزگشایی شده را نشان می‌دهند، مختص اندروید هستند. فایل هدر OpenSLES_AndroidMetadata.h این کلیدهای فراداده را تعریف می کند. این فایل هدر در زیر ریشه نصب شما، در پوشه /sysroot/usr/include/SLES قرار دارد.

شاخص های کلید فراداده بلافاصله پس از پایان اجرای متد Object::Realize() در دسترس هستند. با این حال، مقادیر مرتبط تا زمانی که برنامه اولین داده های رمزگذاری شده را رمزگشایی کند، در دسترس نیستند. یک تمرین خوب این است که پس از فراخوانی Object::Realize شاخص‌های کلیدی را در رشته اصلی جستجو کنید و در هنگام فراخوانی برای اولین بار، مقادیر فراداده قالب PCM را در کنترل‌کننده پاسخ تماس صف بافر ساده اندروید بخوانید. برای نمونه هایی از کار با این رابط، به کد نمونه موجود در بسته NDK مراجعه کنید.

نام‌های کلید فراداده پایدار هستند، اما شاخص‌های کلیدی مستند نیستند و ممکن است تغییر کنند. یک برنامه نباید فرض کند که شاخص‌ها در اجرای مختلف اجرا می‌شوند و نباید فرض کند که نمونه‌های شی چندگانه در یک اجرا شاخص‌ها را به اشتراک می‌گذارند.

داده های ممیز شناور

برنامه‌ای که بر روی Android نسخه 5.0 (سطح API 21) و بالاتر اجرا می‌شود، می‌تواند داده‌ها را در قالب تک دقیق و ممیز شناور به AudioPlayer ارائه دهد.

در کد مثال زیر، متد Engine::CreateAudioPlayer() یک پخش کننده صوتی ایجاد می کند که از داده های ممیز شناور استفاده می کند:

#include <SLES/OpenSLES_Android.h>
...
SLAndroidDataFormat_PCM_EX pcm;
pcm.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
pcm.numChannels = 2;
pcm.sampleRate = SL_SAMPLINGRATE_44_1;
pcm.bitsPerSample = 32;
pcm.containerSize = 32;
pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
pcm.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
...
SLDataSource audiosrc;
audiosrc.pLocator = ...
audiosrc.pFormat = &pcm;
درباره صدای ممیز شناور در صفحه Sampling Audio بیشتر بخوانید.