OpenSL ES ל-Android

הדף הזה מספק פרטים על האופן שבו הטמעת OpenSL של NDK ESTM שונה ממפרט ההפניה של OpenSL ES 1.0.1. כשמשתמשים בקוד לדוגמה המפרט, ייתכן שיהיה עליך לשנות אותו כדי שיעבוד ב-Android.

אלא אם צוין אחרת, כל התכונות זמינות ב-Android מגרסה 2.3 (API ברמה 9) ואילך. חלק מהתכונות זמינות רק ב-Android 4.0 (רמת API 14). הנושאים האלה מצוינים.

הערה: מסמך הגדרת התאימות של Android (CDD) סופר את החומרה והתוכנה הדרישות של מכשיר Android תואם. צפייה תאימות ל-Android לקבלת מידע נוסף על תוכנית התאימות הכוללת, CDD למסמך ה-CDD עצמו.

OpenSL ES מספק C ממשק שפה שניתן לגשת אליו גם באמצעות C++. הוא חושף תכונות שדומות לאודיו חלקים מממשקי ה-API האלה של Android Java:

כמו בכל ערכת הפיתוח המקורית של Android (NDK), המטרה העיקרית של OpenSL ES היא מערכת Android מאפשרת להטמיע ספריות משותפות שרוצים לקרוא באמצעות ה-Java Native ממשק (JNI) ). NDK לא מיועד לכתיבת אפליקציות C/C++ בלבד. עם זאת, OpenSL ES היא עם כל הפיצ'רים של ממשק ה-API, ואנו צופים שתהיה לך אפשרות להשיג את רוב צורכי האודיו שלך באמצעות ה-API הזה בלבד, בלי קריאות קבועות לקוד שפועל בסביבת זמן הריצה של Android.

הערה: למרות שמבוסס על OpenSL ES, ה-API של אודיו מקורי של Android (אודיו עם ביצועים גבוהים) אינו תאימות של כל פרופיל OpenSL ES 1.0.1 (משחק, מוזיקה או טלפון). הסיבה לכך היא מערכת Android לא מטמיעה את כל התכונות שנדרשות על ידי אף אחד מהפרופילים. מקרים ידועים שבהם מערכת Android מתנהגת באופן שונה מהמפרט שמתואר הדף תוספי Android.

תכונות שעברו בירושה ממפרט ההפניה

יישום OpenSL ES ב-Android NDK יורש חלק גדול מקבוצת התכונות המפרט של קובץ העזר, עם מגבלות מסוימות.

נקודות כניסה גלובליות

OpenSL ES ל-Android תומך בכל נקודות הכניסה הגלובליות במפרט של Android. נקודות הכניסה האלה כוללות:

  • slCreateEngine
  • slQueryNumSupportedEngineInterfaces
  • slQuerySupportedEngineInterfaces

אובייקטים וממשקים

בטבלה הבאה מוצגים האובייקטים והממשקים שבהם הטמעת את Android NDK OpenSL ES נתמך. אם המילה כן מופיעה בתא, התכונה הזאת זמינה בתא. יישום בפועל.

תמיכה ב-Android NDK לאובייקטים ולממשקים.

תכונה נגן אודיו הקלטת אודיו מנוע תמהיל הפלט
הגברת הבס כן לא לא כן
תור במאגר נתונים זמני כן לא לא לא
מאתר הנתונים בתור מאגר נתונים זמני כן: מקור לא לא לא
ניהול ממשק דינמי כן כן כן כן
שליחת אפקט כן לא לא לא
מנוע לא לא כן לא
הדהוד סביבתי לא לא לא כן
אקולייזר כן לא לא כן
מאתר נתונים של מכשיר קלט/פלט (I/O) לא כן: מקור לא לא
חילוץ מטא-נתונים כן: פענוח ל-PCM לא לא לא
השתקה של לבד כן לא לא לא
אובייקט כן כן כן כן
מאתר תמהיל הפלט כן: כיור לא לא לא
הפעלה כן לא לא לא
קצב ההפעלה כן לא לא לא
סטטוס השליפה מראש (prefetch) כן לא לא לא
הדהוד מוגדר מראש לא לא לא כן
הקלטה לא כן לא לא
חפש כן לא לא לא
מאתר נתונים של URI כן: מקור לא לא לא
Virtualizer כן לא לא כן
עוצמת הקול כן לא לא לא

בקטע הבא מוסבר על המגבלות של חלק מהתכונות האלה.

מגבלות

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

ניהול ממשק דינמי

OpenSL ES ל-Android לא תומך ב-RemoveInterface או ResumeInterface.

שילובי אפקטים: הדהוד בסביבה והדהוד מוגדר מראש

לא ניתן להפעיל גם הדהוד סביבתי וגם הדהוד מוגדרת מראש באותו תמהיל פלט.

הפלטפורמה עשויה להתעלם מבקשות להשפעה אם היא מעריכה שה העומס על ה-CPU יהיה גבוה מדי.

שליחת אפקט

ב-SetSendLevel() יש תמיכה ברמת שליחה אחת לכל נגן אודיו.

הדהוד סביבתי

הדהוד סביבתי לא תומך ב-reflectionsDelay, reflectionsLevel, או reverbDelay שדות של המבנה SLEnvironmentalReverbSettings.

פורמט נתוני MIME

אפשר להשתמש בפורמט נתוני MIME רק עם מאתר הנתונים URI, ורק עבור אודיו נגן. לא ניתן להשתמש בפורמט הנתונים הזה עבור הקלטת אודיו.

כדי להטמיע את OpenSL ES ב-Android, צריך לאתחל את mimeType ל-NULL או למחרוזת UTF-8 חוקית. צריך גם לאתחל containerType לערך חוקי. בהיעדר שיקולים אחרים, כגון ניידות או פורמטים של תוכן שאפליקציות לא יכולות לזהות לפי הכותרת, מומלץ הגדרה של mimeType לערך NULL ולערך containerType אל SL_CONTAINERTYPE_UNSPECIFIED.

OpenSL ES ל-Android תומך בפורמטים הבאים של אודיו, כל עוד גם פלטפורמת Android תומכת בהם:

  • PCM WAV.
  • WAV.
  • WAV.
  • MP3 Ogg Vorbis.
  • AAC LC.
  • HE-AACv1 (AAC+).
  • HE-AACv2 (AAC+ משופר).
  • AMR.
  • FLAC

הערה: כאן אפשר למצוא רשימה של פורמטים של אודיו שנתמכים ב-Android. פורמטים נתמכים של מדיה.

המגבלות הבאות חלות על הטיפול בפורמטים האלה ובפורמטים אחרים יישום OpenSL ES:

  • AAC הפורמטים חייבים להיכלל במאגר MP4 או ADTS.
  • אין תמיכה ב-OpenSL ES ל-Android MIDI
  • WMA הוא לא חלק מ-AOSP, לא אימתו את התאימות של OpenSL ES ל-Android.
  • יישום OpenSL ES ל-Android NDK לא תומך באופן ישיר הפעלה של DRM או תוכן מוצפן. כדי להפעיל תוכן אודיו מוגן, צריך מפענחים אותו באפליקציה לפני המשחק, כשהאפליקציה אוכפת זכויות DRM ההגבלות.

ב-OpenSL ES ל-Android אין תמיכה בשיטות הבאות לתמרן אובייקטים:

  • Resume()
  • RegisterCallback()
  • AbortAsyncOperation()
  • SetPriority()
  • GetPriority()
  • SetLossOfControlInterfaces()

פורמט נתוני PCM

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

  • 8 ביט לא חתום או 16 ביט חתומים.
  • מונו או סטריאו.
  • סדר בייטים קטנים.
  • תדירות דגימה של:
    • 8,000 Hz
    • 11,025 Hz
    • 12,000 Hz
    • 16,000 Hz
    • 22,050Hz
    • 24,000Hz
    • 32,000 Hz
    • 44,100Hz
    • 48,000 Hz

ההגדרות שבהן OpenSL ES ל-Android תומכת להקלטה הן תלוי-מכשיר; בדרך כלל, אפשר להשתמש בחתימה של 16,000 Hz מונו/16 ביט, ללא קשר למכשיר.

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

תמיכה ב-Android 5.0 (רמת API 21) ואילך נתוני נקודה צפה (floating-point)

קצב ההפעלה

שיעור ההפעלה של OpenSL ES מציין את המהירות שבה מציג נתונים שמבוטאים באלפי מהירות רגילה, או אלף. לדוגמה, קצב הפעלה של 1,000 לאלף צפיות הוא 1,000/1,000, כלומר מהירות רגילה. טווח קצבים הוא מרווח סגור שמבטא טווח של קצבי הפעלה אפשריים.

התמיכה בטווחי קצב ההפעלה וביכולות נוספות עשויה להשתנות בהתאם בגרסה ובהטמעה של הפלטפורמה. האפליקציה יכולה לקבוע את היכולות האלה בזמן הריצה על ידי באמצעות PlaybackRate::GetRateRange() או PlaybackRate::GetCapabilitiesOfRate() כדי לשלוח שאילתה על המכשיר.

מכשיר בדרך כלל תומך באותו טווח תעריפים של מקור נתונים בפורמט PCM ובקצב אחד טווח של 1,000 לאלף חשיפות עד 1,000 לאלף חשיפות בפורמטים אחרים. כלומר, טווח קצב האחדות הוא בפועל בערך אחד.

הקלטה

OpenSL ES ל-Android לא תומך ב-SL_RECORDEVENT_HEADATLIMIT או SL_RECORDEVENT_HEADMOVING אירועים.

חפש

ה-method SetLoop() מאפשרת הפעלה בלופ של כל הקבצים. כדי להפעיל את ההפעלה בלופ, מגדירים את הערך 0 בפרמטר startPos ואת הפרמטר endPos אל SL_TIME_UNKNOWN.

מאתר הנתונים בתור מאגר נתונים זמני

נגן אודיו או מקליט עם מאתר נתונים לתור למאגר נתונים זמני תומכים רק בפורמט נתוני PCM.

מאתר נתונים של מכשיר קלט/פלט (I/O)

OpenSL ES ל-Android תומך בשימוש במאתר נתונים של מכשיר קלט/פלט (I/O) רק כשיש ציינת את המאתר כמקור הנתונים של Engine::CreateAudioRecorder(). מפעילים את מאתר הנתונים של המכשיר באמצעות הערכים שנכללים בקטע הקוד הבא:

SLDataLocator_IODevice loc_dev =
  {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
  SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};

מאתר נתונים של URI

OpenSL ES ל-Android יכול להשתמש במאתר הנתונים URI רק עם פורמט נתוני MIME, ורק לנגן אודיו. לא ניתן להשתמש במאתר הנתונים URI עבור הקלטת אודיו. ה-URI יכול רק משתמשים בסכמות http: ו-file:. סכמות אחרות, כמו https:, ftp:, או אסור להשתמש ב-content:.

לא אימתנו תמיכה ב-rtsp: עם אודיו בפלטפורמת Android.

מבני נתונים

Android תומך במבני הנתונים הבאים מסוג OpenSL ES 1.0.1:

  • SLDataFormat_MIME
  • SLDataFormat_PCM
  • SLDataLocator_BufferQueue
  • SLDataLocator_IODevice
  • SLDataLocator_OutputMix
  • SLDataLocator_URI
  • SLDataSink
  • SLDataSource
  • SLEngineOption
  • SLEnvironmentalReverbSettings
  • SLInterfaceID

הגדרת הפלטפורמה

OpenSL ES ל-Android מיועד לאפליקציות עם שרשורים מרובים והוא בטוח לשימוש בשרשורים. הוא תומך מנוע אחד לאפליקציה ועד 32 אובייקטים לכל מנוע. הזיכרון והמעבד (CPU) הזמינים במכשיר עשויים להיות זמינים ולהגביל עוד יותר את מספר האובייקטים שאפשר להשתמש בהם.

אפשרויות המנוע האלה מזוהות, אבל slCreateEngine מתעלם מהן:

  • SL_ENGINEOPTION_THREADSAFE
  • SL_ENGINEOPTION_LOSSOFCONTROL

ניתן להשתמש ב-OpenMAX AL וב-OpenSL ES יחד באותה אפליקציה. במקרה הזה, יש אובייקט משותף אחד של מנוע חיפוש באופן פנימי, ומגבלת 32 האובייקטים משותפת בין OpenMAX AL ו-OpenSL ES. האפליקציה צריכה ליצור את שני המנועים, להשתמש בשני המנועים ולבסוף להשמד את שני המנועים. ההטמעה שומרת על ספירת ההפניות במנוע המשותף, כך הוא מושמד בצורה נכונה במהלך פעולת ההשמדה השנייה.

הערות תכנות

הערות תכנות של OpenSL ES מספק מידע משלים כדי להבטיח הטמעה תקינה של OpenSL ES.

הערה: לנוחותך, צירפנו עותק של מפרט OpenSL ES 1.0.1 עם NDK ב: docs/opensles/OpenSL_ES_Specification_1.0.1.pdf.

בעיות בפלטפורמה

בקטע הזה מתוארות בעיות ידועות בגרסת הפלטפורמה הראשונית שתומכת בממשקי ה-API האלה.

ניהול ממשק דינמי

DynamicInterfaceManagement::AddInterface לא פועלת. במקום זאת, ציינו את הממשק המערך שמועבר אל Create(), כפי שמוצג בקוד לדוגמה של הדהוד סביבתי.

תוכנית לגרסאות עתידיות של OpenSL ES

ממשקי ה-API של Android עם ביצועים גבוהים מבוססים על Khronos Group OpenSL ES 1.0.1. חברת Khronos פרסמה גרסה 1.1 מתוקנת של התקן. הגרסה המעודכנת כוללת תכונות חדשות, הבהרות, תיקונים של שגיאות טיפוגרפיות אי התאמות מסוימות. רוב אי ההתאמות הצפויות הן קלות יחסית או אזורים של OpenSL ES שאינם נתמכים על ידי Android.

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

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

תוכנית לתאימות בינארית

מומלץ לפעול לפי ההנחיות הבאות כדי לשפר את התאימות הבינארית בעתיד:

  • יש להשתמש רק בקבוצת המשנה המתועדת של התכונות הנתמכות ב-Android מ-OpenSL ES 1.0.1.
  • אל תסתמכו על קוד תוצאה מסוים עבור פעולה שנכשלה; להיות מוכנים להתמודד עם עם קוד תוצאה אחר.
  • גורמים המטפלים בקריאה חוזרת (callback) של אפליקציה פועלים בדרך כלל בהקשר מוגבל. צריך לכתוב אותן כדי לבצע את העבודה במהירות, ואז לחזור בהקדם האפשרי. לא להריץ פעולות מורכבות בתוך handler של קריאה חוזרת. לדוגמה, בתוך קריאה חוזרת להשלמת תור של מאגר נתונים זמני, תוכלו להעביר מאגר נתונים זמני נוסף לתור, אבל לא ליצור נגן אודיו.
  • הגורמים המטפלים בקריאות חוזרות צריכים להיות מוכנים להתקשרות בתדירות גבוהה או נמוכה יותר, כדי לקבל סוגי אירועים נוספים. הם צריכים להתעלם מסוגי אירועים שאינם מזהים. התקשרות חזרה אשר מוגדרים עם מסכת אירועים שמורכבת מסוגי אירועים פעילים, חייבים להיות מוכנים לקריאה עם מספר ביטים מסוג אירוע שמוגדרים בו-זמנית. שימוש בסימן '&' לבדוק כל ביט של אירוע במקום מקרה מעבר.
  • שימוש בסטטוס שליפה מראש (prefetch) ובקריאות חוזרות (callbacks) כאינדיקציה כללית להתקדמות, אבל אין להסתמך על רמות מילוי ספציפיות בתוך הקוד או רצפי קריאה חוזרת. המשמעות של מילוי הסטטוס של השליפה מראש (prefetch) גבוהה. ההתנהגות של שגיאות שזוהו במהלך השליפה מראש עשויה להשתנות.

הערה: אפשר לעיין ב התנהגות התור של מאגר הנתונים הזמני לקבלת פרטים נוספים.

תוכנית לתאימות של מקורות

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

  • צפויים שינויים משמעותיים בממשק התור של מאגר הנתונים הזמני, במיוחד באזורים של BufferQueue::Enqueue, רשימת הפרמטרים של slBufferQueueCallback שם השדה SLBufferQueueState.playIndex. אנחנו ממליצים שקוד האפליקציה שלך ישתמש במקום זאת, תורים במאגרי נתונים זמניים פשוטים ב-Android. בדוגמה שמוצגת של הקוד שסופק עם ה-NDK, השתמשנו בתורים למאגר נתונים זמני פשוט ב-Android לצורך הפעלה מסיבה זו. (אנחנו משתמשים גם בתור מאגר נתונים זמני פשוט ב-Android להקלטה ופענוח ל-PCM, הסיבה לכך היא שגרסה 1.0.1 הרגילה של OpenSL ES לא תומכת בהקלטה או בפענוח של נתונים בתור מאגר נתונים זמני לשקוע.)
  • תתבצע הוספה של const לפרמטרים של הקלט שמועברים בהפניה, וגם ל-SLchar * שדות מבניים שמשמשים כערכי קלט. זה לא אמור לחייב שינוי כלשהו בקוד שלכם.
  • בחלק מהפרמטרים שחתומים כרגע יוחלף בסוגים לא חתומים. יכול להיות שתצטרכו לשנות את סוג הפרמטר מ-SLint32 ל-SLuint32 או דומה לו, או להוסיף העברה.
  • המחרוזת Equalizer::GetPresetName מעתיקה את המחרוזת לזיכרון של האפליקציה במקום להחזיר אותה מצביע לזיכרון ההטמעה. זה יהיה שינוי משמעותי, לכן אנחנו ממליצים לך עדיף לא לקרוא לשיטה הזו או לבודד את השימוש שלכם בה.
  • בסוגי הבניינים יהיו שדות נוספים. לפרמטרים של הפלט, השדות החדשים האלה אך עבור פרמטרים של קלט, יהיה צורך לאתחל את השדות החדשים. למזלנו, כל השדות האלה צפויים להיות באזורים שלא נתמכים על ידי Android.
  • ממשק מזהי GUID ישתנו. יש להתייחס לממשקים לפי שם סימבולי ולא לפי GUID כדי להימנע של יחסי התלות.
  • SLchar ישתנה מ-unsigned char ל-char. הדבר משפיע בעיקר מאתר הנתונים URI ופורמט הנתונים MIME.
  • השם של SLDataFormat_MIME.mimeType ישתנה ל-pMimeType, השם של SLDataLocator_URI.URI ישתנה ל-pURI. אנחנו ממליצים לאתחל את מבני הנתונים SLDataFormat_MIME ו-SLDataLocator_URI באמצעות רשימת ערכים מוקפת בסוגריים מסולסלים, במקום לפי שם שדה, כדי לבודד את הקוד מהשינוי הזה. השיטה הזו מיושמת בקוד לדוגמה.
  • SL_DATAFORMAT_PCM לא מאפשר לאפליקציה לציין ייצוג של את הנתונים כמספר שלם חתום, מספר שלם לא חתום או נקודה צפה (floating-point). ההטמעה של Android ההנחה היא שנתוני 8 סיביות הם מספר שלם לא חתום ו-16 סיביות הוא מספר שלם חתום. בנוסף, השדה samplesPerSec הוא שגוי, כי היחידות בפועל הן מילי-הרץ. הבעיות האלה צפויות יטופלו בגרסה הבאה של OpenSL ES, שתביא להצגת נתוני PCM מורחבים חדשים שמאפשר לאפליקציה לציין במפורש את הייצוג ומתקן את שם השדה. זה יהיה פורמט נתונים חדש, ופורמט הנתונים הנוכחי של ה-PCM עדיין יהיה (אם כי הוצא משימוש), הוא לא אמור לחייב שינויים מיידיים בקוד.