פורמטים של נתונים

ב-Android נעשה שימוש במגוון רחב של פורמטים של נתוני אודיו באופן פנימי, וחלק מהם מוצגים ב-API גלוי לכולם, בפורמטים של קבצים ובשכבת הפשטת החומרה (HAL).

מאפיינים

פורמטים של נתוני אודיו מסווגים לפי המאפיינים שלהם:

דחיסה
לא דחוס, דחוס ללא אובדן נתונים או דחוס עם אובדן נתונים. PCM הוא פורמט האודיו הנפוץ ביותר ללא דחיסה. FLAC הוא פורמט דחוס ללא אובדן נתונים, ואילו MP3 ו-AAC הם פורמטים דחוסים עם אובדן נתונים.
עומק סיביות
מספר הביטים המשמעותיים לכל דגימת אודיו.
גודל הקונטיינר
מספר הביטים המשמשים לשמירת דגימה או לשליחתה. בדרך כלל הערך הזה זהה לעומק הביטים, אבל לפעמים מוקצים עוד ביטים של מילוי כדי לבצע התאמה. לדוגמה, דגימה של 24 ביט יכולה להיכלל במילה של 32 ביט.
יישור
אם גודל המאגר שווה בדיוק לעומק הביטים, הייצוג נקרא ארוז. אחרת, הייצוג פורק. בדרך כלל, הביטים המשמעותיים של הדגימה מותאמים לביט הימני ביותר (המשמעותי ביותר) או לביט הימני ביותר (המשמעותי פחות) של המאגר. מקובל להשתמש במונחים ארוז ולא ארוז רק כשעומק הביטים הוא לא חזקה של שתיים.
Signedness
הסטטוס של הדגימות: חתומות או לא חתומות.
ייצוג
נקודת ציון קבועה או נקודת ציון צפה. מידע נוסף מופיע בהמשך.

ייצוג של נקודות קבועות

נקודה קבועה היא הייצוג הנפוץ ביותר של נתוני אודיו לא דחוסים מסוג PCM, במיוחד בממשקי חומרה.

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

אנחנו מדברים על PCM שלם, כי בדרך כלל ערכים של נקודת קבועה מאוחסנים ומעובדים כערכים שלמים. הפרשנות כנקודה קבועה היא משתמעת.

אנחנו משתמשים בתוספת של שתי ספרות לכל ייצוג של נקודה קבועה עם סימן, כך שהתנאי הבא תקף, כאשר כל הערכים הם ביחידות של LSB אחד:

|largest negative value| = |largest positive value| + 1

סימון Q ו-U

יש כמה סימנים לייצוג של נקודת קבועה במספר שלם. אנחנו משתמשים בסימון Q:‏ Qm.n פירושו m ביט של מספר שלם ו-n ביט של ספרות עשרוניות. השדה 'Q' נספר כביט אחד, אבל הערך מתואר כמספר בינארי משולב (two's complement). המספר הכולל של הביטים הוא m + n + 1.

Um.n מיועד למספרים ללא סימן: m ביטים שלמים ו-n ביטים עשרוניים, והאות U נספרת כביט אפס. המספר הכולל של הביטים הוא m + n.

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

ייצוג של נקודה צפה (floating-point)

נקודה צפה היא חלופה לנקודה קבועה, שבה המיקום של הנקודה יכול להשתנות. היתרונות העיקריים של נקודה צפה כוללים:

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

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

פורמטים של אודיו ל-Android

הפורמטים העיקריים של אודיו ב-Android מפורטים בטבלה הבאה:

סימון
נכס ש0.15 שאלה 0.7 1 Q0.23 Q0.31 float
ביטים של קונטיינר
16 8 24 או 32 2 32 32
ביטים משמעותיים
כולל סימן
16 8 24 24 או 32 2 25 3
מרווח ביטחון
בדציבלים
0 0 0 0 126 4
טווח דינמי
בדציבלים
90 42 138 138 עד 186 900 5

לכל הפורמטים של נקודת קבועה שצוינו למעלה יש טווח נומינלי של -1.0 עד +1.0 פחות LSB אחד. יש ערך שלילי אחד יותר מערך חיובי בגלל הייצוג של השלמה לשניים.

הערות שוליים:

  1. כל הפורמטים שלמעלה מייצגים ערכים חתומים לדוגמה. הפורמט של 8 ביט נקרא בדרך כלל 'ללא סימן', אבל הוא למעשה ערך עם סימן עם הטיה של 0.10000000.
  2. אפשר לארוז את Q0.23 ב-24 ביט (שלושה בייטים של 8 ביט, בסדר little-endian) או לפרוס אותו ב-32 ביט. אם הנתונים לא פורקו, הביטים המשמעותיים ממורכזים בצד שמאל לכיוון ה-LSB עם תוספת של סימן להרחבת ביטים לכיוון ה-MSB (Q8.23), או ממורכזים בצד ימין לכיוון ה-MSB עם מילוי באפסים לכיוון ה-LSB (Q0.31). באופן תיאורטי, פורמט Q0.31 מאפשר עד 32 ביט משמעותיים, אבל ממשקי חומרה שמקבלים פורמט Q0.31 משתמשים רק לעתים רחוקות בכל הביטים.
  3. בנקודה צפה (floating point) עם דיוק יחיד יש 23 סיביות מפורשות, סיבית מוסתרת אחת וסיבית סימן אחת, כך שיש בסך הכול 25 סיביות משמעותיות. למספרים לא רגילים יש פחות ביטים משמעותיים.
  4. נקודה צפה (floating point) עם דיוק יחיד יכולה לבטא ערכים של עד ±1.7e+38, ולכן יש לה מרווח גדול.
  5. הטווח הדינמי שמוצג הוא לערכים לא רגילים (denormals) עד לערך המקסימלי הנומינלי ±1.0. חשוב לזכור שחלק מהטמעות של נקודות צפות ספציפיות לארכיטקטורה, כמו NEON, לא תומכות ב-denormals.

המרות

בקטע הזה נדון בהמרות נתונים בין ייצוגים שונים.

המרות של נקודה צפה (floating-point)

כדי להמיר ערך מפורמט Qm.n לנקודה צפה:

  1. ממירים את הערך לנקודה צפה כאילו הוא מספר שלם (בהתעלמות מהנקודה).
  2. מכפילים ב-2-n.

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

float = integer * (2 ^ -27)

ההמרות מנקודה צפה לנקודה קבועה פועלות לפי הכללים הבאים:

  • ל-float עם דיוק יחיד יש טווח נומינלי של ±1.0, אבל הטווח המלא לערכים ביניים הוא ±1.7e+38. המרה בין נקודת צפה לנקודה קבועה לייצוג חיצוני (כמו פלט למכשירי אודיו) תתייחס רק לטווח הנומינלי, עם צמצום (clamping) של ערכים שחורגים מהטווח הזה. באופן ספציפי, כשממירים את הערך +1.0 לפורמט של נקודה קבועה, הוא נדחס לערך +1.0 מינוס LSB אחד.
  • מותר להציג מספרים לא רגילים (subnormals) וגם את הערכים +/- 0.0, אבל יכול להיות שהם יומרו ל-0.0 ללא הודעה במהלך העיבוד.
  • ערכים אינסופיים יעברו דרך הפעולות או ימוגדר להם מגבלה קשיחה של +/- 1.0. בדרך כלל, האפשרות השנייה מיועדת להמרה לפורמט של נקודה קבועה.
  • ההתנהגות של NaN לא מוגדרת: NaN עשוי להופיע כ-NaN זהה, או להפוך ל-NaN ברירת המחדל, או להופיע כ-0.0 ללא התראה, או להוביל לשגיאה.

המרות של נקודות קבועות

המרות בין פורמטים שונים של Qm.n פועלות לפי הכללים הבאים:

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

לדוגמה, כדי להמיר ערך Q4.27 לערך Q0.15 (ללא דיטיר או עיגול), מעבירים את ערך Q4.27 משמאל לימין ב-12 ביט, ומצמידים את התוצאות שחורגות מהטווח החתום של 16 ביט. כך מתואמת הנקודה של הייצוג של Q.

כדי להמיר את Q7.24 ל-Q7.23, מבצעים חלוקה עם סימן ב-2, או שאפשר להוסיף את ביט הסימן למספר השלם Q7.24 ואז לבצע הזזה ימינה עם סימן ב-1. חשוב לזכור שזזת ביט ימינה עם סימן לא שווה לחלוקה של מספר עם סימן ב-2.

המרות עם אובדן נתונים והמרות ללא אובדן נתונים

המרה היא ללא אובדן נתונים אם היא ניתנת להפיכה: המרה מ-A ל-B ל-C מניבה את הערך A = C. אחרת, ההמרה היא לא יעילה.

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

המרות מנקודה קבועה עם 25 ביט משמעותיים או פחות לנקודה צפה הן ללא אובדן נתונים. המרות מנקודת צפה לכל ייצוג נפוץ של נקודה קבועה הן עם אובדן נתונים.