2013-02-12 75 views
36

Tôi hiện đang cố gắng để giảm thiểu độ trễ âm thanh cho một ứng dụng đơn giản:phát lại âm thanh thấp độ trễ trên Android

Tôi có một đoạn video trên PC, và tôi đang truyền âm thanh của video qua RTP với một khách hàng điện thoại di động . Với một thuật toán đệm tương tự, tôi có thể đạt được 90ms độ trễ trên iOS, nhưng đáng sợ là ± 180ms trên Android.

Tôi đoán sự khác biệt bắt nguồn từ độ trễ well-known độ trễ issues trên Android.

Tuy nhiên, sau khi đọc xung quanh một chút, I came upon this article, trong đó nêu rằng:

  1. thấp độ trễ âm thanh có sẵn kể từ Android 4.1/4.2 trong các thiết bị nhất định.

  2. Âm thanh có độ trễ thấp có thể đạt được bằng cách sử dụng libpd, which is Pure Data library for Android.

Tôi đã 2 câu hỏi, liên quan trực tiếp đến những 2 báo cáo:

  1. Tôi có thể tìm thêm thông tin về âm thanh có độ trễ thấp mới trong Jellybean ở đâu? This is all I can find but it's sorely lacking in specific information. Các thay đổi có nên minh bạch với tôi hay có một số cuộc gọi API/lớp học mới mà tôi nên triển khai để tôi có thể nhận thấy bất kỳ thay đổi nào trong đơn đăng ký của mình không? Tôi đang sử dụng API AudioTrack và tôi thậm chí không chắc liệu nó có thu được lợi ích từ cải tiến này hay không hoặc liệu tôi có nên xem xét một số cơ chế khác để phát lại âm thanh hay không.

  2. Tôi có nên xem xét sử dụng libpd không? Có vẻ như tôi là cơ hội duy nhất để đạt được độ trễ thấp hơn, nhưng vì tôi luôn nghĩ PD là một tiện ích tổng hợp âm thanh, nó thực sự phù hợp cho một dự án chỉ lấy khung từ một luồng mạng và phát lại chúng ? Tôi không thực sự làm bất kỳ tổng hợp nào. Tôi có đi theo đường mòn sai không?

Là một lưu ý bổ sung, trước khi ai đó đề cập OpenSL ES, this article makes it quite clear that no improvements in latency should be expected from using it:

"Như OpenSL ES là một C API bản xứ,-Dalvik không áp dụng chủ đề mà OpenSL gọi ES không có Dalvik Tuy nhiên, không có lợi ích hiệu suất bổ sung cho việc sử dụng OpenSL ES ngoài điều này.Đặc biệt, việc sử dụng OpenSL ES không dẫn đến độ trễ âm thanh thấp hơn, ưu tiên lên lịch cao hơn,.210, vv so với những gì nền tảng này thường cung cấp "

+10

Tôi là một thành viên của nhóm Android và tôi làm việc chặt chẽ với các tác giả của bài viết bạn trích dẫn. Đoạn bạn trích dẫn không còn đúng nữa. Khi bài viết được viết, các bộ đệm nhỏ nhất có sẵn cho OpenSL vẫn còn khá lớn. Bây giờ kích thước bộ đệm đã được giảm trong Jellybean, độ trễ đã giảm xuống đến điểm mà "chi phí liên quan đến Dalvik như thu gom rác tạm dừng" là một sự cân nhắc rất quan trọng. Cách duy nhất để tận dụng lợi thế của các bộ đệm Jellybean nhỏ hơn là sử dụng OpenSL. –

Trả lời

60

Đối với độ trễ thấp nhất trên Android như các phiên bản 4.2.2, bạn nên làm như sau, ra lệnh từ ít đến rõ ràng nhất:

  1. Chọn một thiết bị hỗ trợ FEATURE_AUDIO_PRO nếu có thể, hoặc FEATURE_AUDIO_LOW_LATENCY nếu không muốn nói. ("Độ trễ thấp" là 50ms một chiều; pro là < chuyến đi khứ hồi 20ms.)

  2. Sử dụng OpenSL. Các Dalvik GC có một chi phí phân bổ thấp, nhưng khi nó chạy nó mất nhiều thời gian hơn một sợi âm thanh có độ trễ thấp có thể cho phép.

  3. Xử lý âm thanh trong cuộc gọi lại hàng đợi bộ đệm. Hệ thống chạy các cuộc gọi lại trong hàng đợi đệm trong một chuỗi có lịch trình thuận lợi hơn các chuỗi chế độ người dùng bình thường.

  4. Biến kích thước bộ đệm thành bội số của AudioManager.getProperty (PROPERTY_OUTPUT_FRAMES_PER_BUFFER). Nếu không, cuộc gọi lại của bạn đôi khi sẽ nhận được hai cuộc gọi mỗi lần thay vì một lần. Trừ khi sử dụng CPU của bạn thực sự là ánh sáng, điều này có thể sẽ kết thúc. (Trên Android M, điều rất quan trọng là sử dụng CHÍNH XÁC kích thước bộ đệm hệ thống, do lỗi trong mã xử lý bộ đệm.)

  5. Sử dụng tốc độ mẫu do AudioManager.getProperty (PROPERTY_OUTPUT_SAMPLE_RATE) cung cấp. Nếu không, bộ đệm của bạn sẽ đi vòng qua bộ lấy mẫu hệ thống.

  6. Không bao giờ tạo syscall hoặc khóa đối tượng đồng bộ hóa bên trong cuộc gọi đệm. Nếu bạn phải đồng bộ hóa, hãy sử dụng cấu trúc không khóa. Để có kết quả tốt nhất, hãy sử dụng cấu trúc hoàn toàn miễn phí như bộ đệm vòng một đầu đọc đơn. Tải của các nhà phát triển có được điều này sai và kết thúc với ổn định mà không thể đoán trước và khó gỡ lỗi.

  7. Sử dụng hướng dẫn vectơ như NEON, SSE hoặc bất kỳ bộ chỉ lệnh tương đương nào trên bộ xử lý đích của bạn.

  8. Kiểm tra và đo lường mã của bạn. Theo dõi phải mất bao lâu để chạy - và hãy nhớ rằng bạn cần biết hiệu suất xấu nhất, không phải mức trung bình, bởi vì trường hợp xấu nhất là nguyên nhân gây ra sự cố. Và bảo thủ. Bạn đã biết rằng nếu mất nhiều thời gian hơn để xử lý âm thanh của bạn hơn là để chơi nó, bạn sẽ không bao giờ có độ trễ thấp. Nhưng trên Android, điều này thậm chí còn quan trọng hơn, bởi vì tần số CPU dao động rất nhiều.Bạn có thể sử dụng 60-70% CPU cho âm thanh, nhưng hãy nhớ rằng điều này sẽ thay đổi khi thiết bị trở nên nóng hơn hoặc mát hơn hoặc khi radio wifi hoặc LTE bắt đầu và dừng, v.v.

Âm thanh độ trễ thấp không còn là tính năng mới cho Android, nhưng vẫn yêu cầu thay đổi thiết bị trong phần cứng, trình điều khiển, hạt nhân và khung để tắt. Điều này có nghĩa là có rất nhiều biến thể về độ trễ mà bạn có thể mong đợi từ các thiết bị khác nhau và có bao nhiêu giá điện thoại Android khác nhau bán ở đó, có thể sẽ luôn có sự khác biệt. Tìm FEATURE_AUDIO_PRO hoặc FEATURE_AUDIO_LOW_LATENCY để xác định các thiết bị đáp ứng tiêu chí độ trễ mà ứng dụng của bạn yêu cầu.

+0

Re điểm 5. Nếu âm thanh nguồn được ghi âm tại nói 44100 nhưng PROPERTY_OUTPUT_SAMPLE_RATE là 48000 thì âm thanh sẽ phát quá nhanh. Cách tốt nhất xung quanh điều này là gì? – Ian1971

+0

Ian, tôi tin rằng PROPERTY_OUTPUT_SAMPLE_RATE (POSR) đề cập đến tỷ lệ lấy mẫu âm thanh gốc của bộ xử lý âm thanh của thiết bị của bạn. Điều này có nghĩa là nếu bạn cho nó lấy mẫu âm thanh ở 48kHz và POSR của thiết bị của bạn là 48kHz, thì hệ thống sẽ không phải thực hiện bất kỳ "công việc bổ sung" nào và do đó có thể phát mà không có độ trễ bổ sung. – rmigneco

+0

Cho phép lấy mẫu âm thanh ở mức 44,1kHz nghĩa là nó sẽ được phát ở tốc độ khác, nhưng bạn yêu cầu hệ điều hành/thiết bị thực hiện bước lấy mẫu bổ sung để xử lý âm thanh ở 48kHz, làm tăng độ trễ. – rmigneco

3

Từ liên kết ở quan điểm của bạn 1:

". Low-độ trễ âm thanh

Android 4.2 cải thiện hỗ trợ cho âm thanh có độ trễ thấp phát lại, bắt đầu từ từ những cải thiện được thực hiện trong bản phát hành Android 4.1 cho đầu ra âm thanh độ trễ bằng cách sử dụng API OpenSL ES, Soundpool và trình tạo giai điệu.Những cải thiện phụ thuộc vào sự hỗ trợ phần cứng - thiết bị cung cấp các tính năng âm thanh có độ trễ thấp có thể quảng cáo ủng hộ của họ cho các ứng dụng thông qua một hằng số tính năng phần cứng "

trích dẫn của bạn ở dạng hoàn chỉnh:

. "Hiệu suất

Vì OpenSL ES là một API C gốc, các chủ đề ứng dụng không phải Dalvik mà gọi OpenSL ES không có chi phí liên quan đến Dalvik như rác coll ection tạm dừng. Tuy nhiên, không có lợi ích hiệu suất bổ sung đối với việc sử dụng OpenSL ES ngoài điều này. Đặc biệt, việc sử dụng OpenSL ES không dẫn đến độ trễ âm thanh thấp hơn, ưu tiên lên lịch cao hơn, v.v. so với nền tảng thường cung cấp. Mặt khác, như nền tảng và thiết bị cụ thể triển khai Android tiếp tục tiến hóa, một ứng dụng OpenSL ES có thể mong đợi để được hưởng lợi từ bất kỳ cải thiện hiệu năng hệ thống trong tương lai."

Vì vậy, các api để comunicate với trình điều khiển và sau đó hw là OpenSl (trong cùng Opengl thời trang với đồ họa) Các phiên bản trước của Android có thiết kế kém trong trình điều khiển và/hoặc hw, mặc dù vậy, những vấn đề này đã được giải quyết và sửa chữa với phiên bản 4.1 và 4.2, vì vậy nếu hd có sức mạnh, bạn có độ trễ thấp bằng cách sử dụng OpenSL.

Một lần nữa, từ ghi chú này từ trang web thư viện puredata, hiển nhiên là thư viện rary sử dụng OpenSL bản thân để đạt được độ trễ thấp:

hỗ trợ độ trễ thấp cho các thiết bị phù hợp Phiên bản mới nhất của Pd cho Android (như của 2012/12/28) hỗ trợ âm thanh có độ trễ thấp cho phù hợp thiết bị Android. Khi cập nhật bản sao của bạn, hãy đảm bảo kéo phiên bản mới nhất của cả hai mô-đun con pd-for-android và libpd từ GitHub.

Tại thời điểm viết, Galaxy Nexus, Nexus 4 và Nexus 10 cung cấp theo dõi độ trễ thấp cho đầu ra âm thanh. Để đạt được độ trễ thấp theo dõi , ứng dụng phải sử dụng OpenSL và ứng dụng phải hoạt động ở đúng tỷ lệ mẫu và kích thước bộ đệm . Các thông số đó phụ thuộc vào thiết bị (Galaxy Nexus và Nexus 10 hoạt động ở 44100Hz, trong khi Nexus 4 hoạt động ở 48000Hz; kích thước bộ đệm khác nhau đối với mỗi thiết bị).

Như là sẽ không của nó, Pd cho giấy tờ Android trên tất cả những phức tạp như nhiều càng tốt, cung cấp quyền truy cập vào các tính năng độ trễ thấp mới when available trong khi vẫn tương thích ngược với phiên bản trước của Android. Dưới mui xe, các thành phần âm thanh của Pd cho Android sẽ sử dụng OpenSL trên Android 2.3 trở lên, trong khi giảm xuống trên API AudioTrack/AudioRecord cũ trong Java trên Android 2.2 và trước đó.

5

Khi sử dụng OpenSL ES bạn cần thỏa mãn các yêu cầu sau đây để có được đầu ra độ trễ thấp trên Jellybean và các phiên bản sau của Android:

  • Âm thanh nên mono hay stereo, PCM tuyến tính.

  • Tỷ lệ mẫu âm thanh nên tỷ lệ mẫu tương tự như tỷ lệ mẹ đẻ của đầu ra (điều này có thể không thực sự được yêu cầu trên một số thiết bị, bởi vì FastMixer khả năng resampling nếu các nhà cung cấp cấu hình nó để làm như vậy. Nhưng trong các thử nghiệm của tôi, tôi nhận được các hiện vật rất đáng chú ý khi upsampling từ 44,1 đến 48 kHz trong FastMixer).

  • BufferQueue của bạn phải có ít nhất 2 bộ đệm. (Yêu cầu này đã được thoải mái. Xem this commit bởi Glenn Kasten. Tôi không chắc chắn trong đó phiên bản Android này lần đầu tiên xuất hiện, nhưng một đoán sẽ là 4.4).

  • Bạn không thể sử dụng các hiệu ứng nhất định (ví dụ: Reverb, Tăng âm trầm, Cân bằng, Ảo hóa, ...).

Lớp SoundPool cũng sẽ cố gắng tận dụng nhanh AudioTrack s trong nội bộ khi có thể (các tiêu chuẩn tương tự như trên được áp dụng, ngoại trừ các phần BufferQueue).

2

Những người trong số các bạn liên lạc nhiều hơn được giới thiệu trong Android 10 Millisecond, tức là âm thanh độ trễ thấp trên Android. Chúng tôi ở Superpowered đã tạo Trình giải thích thời gian chờ cho âm thanh trên Android. Xin vui lòng xem ở đây:

http://superpowered.com/androidaudiopathlatency/#axzz3fDHsEe56

+1

Đây là giải thích tốt, nhưng không được cập nhật 100%. Bộ đệm AudioFlinger đã giảm trong L, loại bỏ tổng cộng hai bộ đệm từ đường dẫn. Hiện tại có một bộ đệm hiệu quả của độ trễ giữa ứng dụng và HAL (có vẻ như nhiều hơn, nhưng một số mã là đồng bộ - nhiều memcpys không phải lúc nào cũng có độ trễ cao hơn.) Ngoài ra, không chắc chắn về độ trễ bus 6ms " hình ảnh đến từ. Điều đó có vẻ quá cao. –

+0

Hi Ian, Hy vọng bạn là tốt. Chúng tôi có phiên bản cập nhật mới hơn tại đây: http://superpowered.com/android-marshmallow-latency –

+1

Điều đó có vẻ chính xác. Một điều còn thiếu là Nexus 9 DSP - nó được gọi là AHUB trong biểu dữ liệu Tegra K1. Tôi đoán rằng FIFO có kế toán trễ hơn phần mềm sau so với xe buýt. Tôi nghĩ rằng bạn cũng có thể được xem xét thực tế là các cuộc gọi viết HAL đang chặn. Cuộc gọi không quay trở lại cho đến khi đám cháy ngắt tiếp theo, do đó toàn bộ động cơ được lên lịch dựa trên ngắt âm thanh, chứ không phải trên bộ lập lịch biểu đơn tốc. Có một số vấn đề nghiêm trọng với điều này, nhiều trong số đó là duy nhất đối với các hệ điều hành dựa trên Linux, nhưng tôi không nghĩ rằng một mô hình "đẩy" là một trong số đó. –

Các vấn đề liên quan