Android sử dụng nhiều định dạng dữ liệu âm thanh trong nội bộ và hiển thị một số định dạng trong số này trong các API công khai, định dạng tệp và Lớp trừu tượng phần cứng (HAL).
Thuộc tính
Các định dạng dữ liệu âm thanh được phân loại theo thuộc tính:
- Nén
- Chưa nén, nén không suy hao hoặc nén có suy hao. PCM là định dạng âm thanh không nén phổ biến nhất. FLAC là định dạng nén không tổn hao, còn MP3 và AAC là định dạng nén có tổn hao.
- Độ sâu bit
- Số bit có nghĩa trên mỗi mẫu âm thanh.
- Kích thước vùng chứa
- Số bit dùng để lưu trữ hoặc truyền một mẫu. Thông thường, giá trị này giống với độ sâu bit, nhưng đôi khi các bit khoảng đệm bổ sung được phân bổ để căn chỉnh. Ví dụ: một mẫu 24 bit có thể nằm trong một từ 32 bit.
- Căn chỉnh
- Nếu kích thước vùng chứa bằng chính xác độ sâu bit, thì cách biểu diễn này được gọi là đã đóng gói. Nếu không, nội dung đại diện sẽ được giải nén. Các bit có ý nghĩa của mẫu thường được căn chỉnh với bit ở ngoài cùng bên trái (có ý nghĩa nhất) hoặc bit ở ngoài cùng bên phải (có ý nghĩa ít nhất) của vùng chứa. Theo thông lệ, bạn chỉ nên sử dụng các thuật ngữ đã đóng gói và đã giải nén khi độ sâu bit không phải là lũy thừa của 2.
- Tính ký
- Liệu các mẫu có được ký hay không.
- Bản trình bày
- Điểm cố định hoặc dấu phẩy động; xem bên dưới.
Biểu diễn dấu phẩy cố định
Điểm cố định là cách biểu thị phổ biến nhất cho dữ liệu âm thanh PCM không nén, đặc biệt là ở các giao diện phần cứng.
Số dấu phẩy cố định có số chữ số cố định (không đổi) trước và sau dấu phẩy thập phân. Tất cả các cách biểu diễn của chúng ta đều sử dụng căn số 2, vì vậy, chúng ta sẽ thay thế bit cho số và dấu phẩy nhị phân hoặc đơn giản là dấu phẩy cho dấu phẩy thập lục phân. Các bit ở bên trái dấu phẩy là phần số nguyên và các bit ở bên phải dấu phẩy là phần thập phân.
Chúng ta nói đến PCM số nguyên vì các giá trị dấu phẩy cố định thường được lưu trữ và thao tác dưới dạng giá trị số nguyên. Cách diễn giải dưới dạng điểm cố định là ngầm ẩn.
Chúng ta sử dụng bổ trợ hai cho tất cả các đại diện dấu phẩy cố định, vì vậy, những giá trị sau đây được giữ nguyên trong đó tất cả các giá trị đều tính theo đơn vị LSB:
|largest negative value| = |largest positive value| + 1
Ký hiệu Q và U
Có nhiều ký hiệu để biểu thị dấu phẩy cố định trong số nguyên. Chúng ta sử dụng ký hiệu Q: Qm.n có nghĩa là m bit số nguyên và n bit số thập phân. "Q" được tính là một bit, mặc dù giá trị được biểu thị bằng số bổ trợ hai. Tổng số bit là m + n + 1.
Um.n dành cho số không dấu: m bit số nguyên và n bit thập phân, còn "U" được tính là 0 bit. Tổng số bit là m + n.
Phần số nguyên có thể được sử dụng trong kết quả cuối cùng hoặc là tạm thời. Trong trường hợp sau, các bit tạo nên phần số nguyên được gọi là bit bảo vệ. Bit bảo vệ cho phép phép tính trung gian tràn, miễn là giá trị cuối cùng nằm trong phạm vi hoặc có thể được kẹp để nằm trong phạm vi. Lưu ý rằng các bit bảo vệ dấu phẩy cố định nằm ở bên trái, còn số bảo vệ của đơn vị dấu phẩy động được dùng để giảm lỗi làm tròn và nằm ở bên phải.
Biểu diễn dấu phẩy động
Dấu phẩy động là một giải pháp thay thế cho dấu phẩy cố định, trong đó vị trí của dấu phẩy có thể thay đổi. Dưới đây là một số lợi thế chính của dấu phẩy động:
- Khoảng đầu vào và dải động lớn hơn; phép tính dấu phẩy động cho phép vượt quá phạm vi danh nghĩa trong quá trình tính toán trung gian và chỉ kẹp các giá trị ở cuối
- Hỗ trợ các giá trị đặc biệt như vô cực và NaN
- Dễ sử dụng hơn trong nhiều trường hợp
Trước đây, phép tính dấu phẩy động chậm hơn so với phép tính số nguyên hoặc dấu phẩy cố định, nhưng hiện tại, phép tính dấu phẩy động thường nhanh hơn, miễn là các quyết định về luồng kiểm soát không dựa trên giá trị của phép tính.
Định dạng Android dành cho âm thanh
Các định dạng âm thanh chính trên Android được liệt kê trong bảng dưới đây:
Thuộc tính | Câu hỏi 0.15 | Q0,7 1 | Q0,23 | Q0,31 | số thực dấu phẩy động | |
---|---|---|---|---|---|---|
Bit vùng chứa |
16 | 8 | 24 hoặc 32 2 | 32 | 32 | |
Bit có nghĩa bao gồm cả dấu |
16 | 8 | 24 | 24 hoặc 32 2 | 25 3 | |
Khoảng đầu phát tính bằng dB |
0 | 0 | 0 | 0 | 126 4 | |
Dải động tính bằng dB |
90 | 42 | 138 | 138 đến 186 | 900 5 |
Tất cả định dạng dấu phẩy cố định ở trên đều có phạm vi danh nghĩa từ -1,0 đến +1,0 trừ một LSB. Có một giá trị âm nhiều hơn giá trị dương do cách biểu diễn số bổ trợ của hai.
Chú thích cuối trang:
-
Tất cả định dạng ở trên đều thể hiện các giá trị mẫu đã ký.
Định dạng 8 bit thường được gọi là "không dấu", nhưng thực tế là một giá trị có dấu với độ lệch là
0.10000000
. - Q0.23 có thể được đóng gói thành 24 bit (3 byte 8 bit, little-endian) hoặc được giải nén thành 32 bit. Nếu được giải nén, các bit có nghĩa sẽ được căn phải về LSB với khoảng đệm mở rộng dấu về MSB (Q8.23), hoặc căn trái về MSB với khoảng đệm bằng 0 về LSB (Q0.31). Về mặt lý thuyết, Q0.31 cho phép tối đa 32 bit có ý nghĩa, nhưng các giao diện phần cứng chấp nhận Q0.31 hiếm khi sử dụng tất cả các bit.
- Dấu phẩy động có độ chính xác đơn có 23 bit rõ ràng cộng với một bit ẩn và bit dấu, tổng cộng là 25 bit có ý nghĩa. Số thực không chuẩn có ít bit có nghĩa hơn.
- Dấu phẩy động có độ chính xác đơn có thể biểu thị các giá trị lên đến ±1,7e+38, giải thích cho khoảng đầu vào lớn.
- Phạm vi động hiển thị là dành cho các giá trị không chuẩn hoá lên đến giá trị tối đa danh nghĩa ±1.0. Xin lưu ý rằng một số cách triển khai dấu phẩy động dành riêng cho cấu trúc như NEON không hỗ trợ số thực không chuẩn.
Lượt chuyển đổi
Phần này thảo luận về quy trình chuyển đổi dữ liệu giữa nhiều cách trình bày.
Chuyển đổi dấu phẩy động
Cách chuyển đổi một giá trị từ định dạng Qm.n sang dấu phẩy động:
- Chuyển đổi giá trị thành dấu phẩy động như thể đó là một số nguyên (bằng cách bỏ qua dấu phẩy).
- Nhân với 2-n.
Ví dụ: để chuyển đổi giá trị nội bộ Q4.27 thành dấu phẩy động, hãy sử dụng:
float = integer * (2 ^ -27)
Việc chuyển đổi từ dấu phẩy động sang dấu phẩy cố định tuân theo các quy tắc sau:
- Dấu phẩy động có độ chính xác đơn có phạm vi danh nghĩa là ±1,0, nhưng phạm vi đầy đủ cho các giá trị trung gian là ±1,7e+38. Việc chuyển đổi giữa dấu phẩy động và dấu phẩy cố định để biểu diễn bên ngoài (chẳng hạn như đầu ra cho thiết bị âm thanh) sẽ chỉ xem xét phạm vi danh nghĩa, với việc kẹp các giá trị vượt quá phạm vi đó. Cụ thể, khi +1.0 được chuyển đổi sang định dạng dấu phẩy cố định, giá trị này sẽ được cố định ở +1.0 trừ đi một LSB.
- Các số thực không chuẩn (subnormals) và cả +/- 0.0 đều được phép biểu diễn, nhưng có thể được chuyển đổi ngầm thành 0.0 trong quá trình xử lý.
- Số vô cực sẽ truyền qua các phép toán hoặc sẽ bị giới hạn cứng một cách âm thầm thành +/- 1.0. Thông thường, phương thức sau là để chuyển đổi sang định dạng dấu phẩy cố định.
- Hành vi NaN không được xác định: NaN có thể truyền dưới dạng NaN giống hệt hoặc có thể được chuyển đổi thành NaN mặc định, có thể bị giới hạn cứng một cách thầm lặng ở +/- 1.0 hoặc được chuyển đổi một cách thầm lặng thành 0.0 hoặc dẫn đến lỗi.
Chuyển đổi dấu phẩy cố định
Việc chuyển đổi giữa các định dạng Qm.n tuân theo các quy tắc sau:
- Khi m tăng lên, dấu sẽ mở rộng phần số nguyên ở bên trái.
- Khi m giảm, hãy kẹp phần số nguyên.
- Khi n tăng lên, số 0 sẽ mở rộng phần thập phân ở bên phải.
- Khi n giảm, hãy làm nhiễu, làm tròn hoặc cắt bớt các bit phân đoạn thừa ở bên phải.
Ví dụ: để chuyển đổi giá trị Q4.27 thành Q0.15 (không có nhiễu hoặc làm tròn), hãy dịch phải giá trị Q4.27 thêm 12 bit và kẹp mọi kết quả vượt quá phạm vi ký 16 bit. Thao tác này sẽ căn chỉnh điểm của biểu diễn Q.
Để chuyển đổi Q7.24 thành Q7.23, hãy chia cho 2 có dấu, hoặc tương đương với việc thêm bit dấu vào số nguyên Q7.24, sau đó dịch phải có dấu thêm 1. Xin lưu ý rằng một phép dịch phải có dấu đơn giản không tương đương với phép chia có dấu cho 2.
Chuyển đổi có tổn hao và không tổn hao
Một lượt chuyển đổi là không suy hao nếu lượt chuyển đổi đó có thể đảo ngược: lượt chuyển đổi từ A
sang B
sang C
sẽ dẫn đến A = C
.
Nếu không, quá trình chuyển đổi sẽ mất dữ liệu.
Lượt chuyển đổi không suy hao cho phép chuyển đổi định dạng khứ hồi.
Các lượt chuyển đổi từ cách biểu diễn dấu phẩy cố định có 25 bit có nghĩa trở xuống sang dấu phẩy động sẽ không bị mất dữ liệu. Các lượt chuyển đổi từ dấu phẩy động sang bất kỳ cách biểu thị dấu phẩy cố định phổ biến nào đều bị mất dữ liệu.