2011-03-14 21 views
10

पर ध्वनि बजाना ध्वनि मेरे पास मेरे एप्लिकेशन में एक ऑडियोट्रैक है, जो स्ट्रीम मोड पर सेट है। मैं ऑडियो लिखना चाहता हूं जो मुझे वायरलेस कनेक्शन पर प्राप्त होता है। Audiotrack इस तरह घोषित किया जाता है:ऑडियोट्रैक: वाईफाई

mPlayer = new AudioTrack(STREAM_TYPE, 
         FREQUENCY, 
         CHANNEL_CONFIG_OUT, 
         AUDIO_ENCODING, 
         PLAYER_CAPACITY, 
         PLAY_MODE); 

कहाँ मानकों की तरह परिभाषित कर रहे हैं:

private static final int FREQUENCY = 8000, 
         CHANNEL_CONFIG_OUT = AudioFormat.CHANNEL_OUT_MONO, 
         AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT, 
         PLAYER_CAPACITY = 2048, 
         STREAM_TYPE = AudioManager.STREAM_MUSIC, 
         PLAY_MODE = AudioTrack.MODE_STREAM; 

हालांकि, जब मैं लिखने() के साथ audiotrack के लिए डेटा लिखने, यह अस्थिर खेलेंगे ... कॉल

byte[] audio = packet.getData(); 
mPlayer.write(audio, 0, audio.length); 

नेटवर्क कनेक्शन पर जब भी एक पैकेट प्राप्त होता है तो कॉल किया जाता है। क्या किसी के पास कोई विचार है कि यह चटनी क्यों लगता है? शायद यह वाईफाई कनेक्शन के साथ कुछ करने के लिए है? मुझे ऐसा नहीं लगता है, क्योंकि जब मैं एंड्रॉइड फोन से डेटा यूडीपी पर दूसरे स्रोत पर भेजता हूं, तो ध्वनि दूसरी तरफ भयानक नहीं लगता है। ध्वनि तब पूरी तरह से लगता है और चतुर नहीं है ... तो क्या किसी के पास यह विचार है कि यह क्यों हो रहा है?

+0

क्या आपने 'PLAYER_CAPACITY' के साथ खेलने का प्रयास किया है? मेरा मानना ​​है कि आपको उचित मूल्य प्राप्त करने के लिए 'getMinBufferSize() 'का उपयोग करना चाहिए, जैसा कि यहां दिखाया गया है: http://developer.android.com/reference/android/media/AudioTrack.html – gary

+0

मैंने कोशिश की है ... लेकिन नेटवर्क से प्राप्त डेटा आमतौर पर 4096 I (वर्तमान में) से कम है, इस डिवाइस पर getMinBufferSize से मिलता है। इसे बफरसाइज़ करने के लिए सेट करना <प्राप्त बाइट्स के परिणामस्वरूप कोई भी ऑडियो नहीं खेला जा रहा है ... मुझे प्राप्त बाइट्स की मात्रा 900 से 2048 तक (स्रोत, अन्य मोबाइल डिवाइस या पीसी के आधार पर) प्राप्त होती है। – ThaMe90

+0

मेरे पास इस पर दूसरा नजरिया था, मेरे मामले में, चटनी पैकेट गायब/पुनः प्रेषण की महत्वपूर्ण मात्रा के कारण है। एंड्रॉइड जैसी कुछ संसाधन-सीमित प्रणाली में, प्रोग्राम को प्रत्येक व्यक्तिगत यूडीपी पैकेट को पर्याप्त रूप से पैकेट को रोकने के लिए पर्याप्त प्रक्रिया को संसाधित करना होगा। – yorkw

उत्तर

5

मैंने mPlayer.write(audio, 0, audio.length); को अपने Thread में आंशिक रूप से हल किया है। यह चॉकलेट-नेस में से कुछ लेता है (इस तथ्य के कारण कि लिखना एक अवरुद्ध कॉल है), लेकिन यह अभी भी एक अच्छा दूसरा या 2 के बाद चटनी लगता है। इसमें अभी भी 2-3 सेकंड की महत्वपूर्ण देरी है।

new Thread(){ 
    public void run(){ 
     byte[] audio = packet.getData(); 
     mPlayer.write(audio, 0, audio.length); 
    } 
}.start(); 

बस एक छोटे से गुमनाम Thread कि लेखन अब है ...

किसी इस समस्या को हल करने के लिए पर एक विचार है?


संपादित करें:

कुछ आगे की जाँच के और डिबगिंग के बाद, मैंने देखा है कि इस obtainBuffer साथ एक मुद्दा है। मैंने java code of the AudioTrack और C++ code of AudioTrack पर देखा है और मैंने देखा है कि यह केवल C++ कोड में दिखाई दे सकता है।

if (__builtin_expect(result!=NO_ERROR, false)) { 
    LOGW( "obtainBuffer timed out (is the CPU pegged?) " 
      "user=%08x, server=%08x", u, s); 
    mAudioTrack->start(); // FIXME: Wake up audioflinger 
    timeout = 1; 
} 

मैंने देखा है कि कोड के इस टुकड़े में FIXME है। : < लेकिन वैसे भी, क्या कोई यह समझा सकता है कि यह सी ++ कोड कैसे काम करता है? मैं इसके साथ कुछ अनुभव प्राप्त हुआ है, लेकिन यह इस रूप में के रूप में जटिल नहीं था ...


संपादित करें 2:

मैं अब कुछ अलग की कोशिश की है, अंतर किया जा रहा है कि मैं डेटा बफ़र मुझे मिलता है, और फिर जब बफर कुछ डेटा से भरा होता है, तो यह खिलाड़ी को लिखा जा रहा है। हालांकि, खिलाड़ी कुछ चक्रों के लिए उपभोग करने के साथ रहता है, तो obtainBuffer timed out (is the CPU pegged?) चेतावनी में शामिल होता है, और खिलाड़ी को लिखे जाने पर कोई भी डेटा नहीं होता है जब तक कि यह जीवन वापस शुरू नहीं हो जाता ... उसके बाद, यह लगातार डेटा प्राप्त करेगा जब तक बफर खाली नहीं होता तब तक इसे लिखा जाता है।

एक और मामूली अंतर यह है कि मैं अब प्लेयर को एक फाइल स्ट्रीम करता हूं। यही है, इसे टुकड़ों में पढ़ना, उन हिस्सों को बफर में लिखना। यह वाईफाई पर प्राप्त होने वाले पैकेजों को अनुकरण करता है ...

मुझे आश्चर्य है कि यह सिर्फ एक ओएस मुद्दा है जो एंड्रॉइड है, और ऐसा कुछ नहीं है जिसे मैं अपने आप हल कर सकता हूं ... किसी को भी कोई विचार है उस पर?


संपादित करें 3:

मैं और अधिक परीक्षण किया है, लेकिन यह मेरे लिए किसी भी आगे मदद नहीं करता है। यह परीक्षण मुझे दिखाता है कि जब मैं पहली बार ऑडियोट्रैक को लिखने की कोशिश करता हूं तो मुझे केवल अंतराल मिलता है। इसे पूरा होने में कुछ और 3 सेकंड के बीच लगता है। मैं निम्न कोड बिट का उपयोग करके ऐसा किया:

long beforeTime = Utilities.getCurrentTimeMillis(), afterTime = 0; 
mPlayer.write(data, 0, data.length); 
afterTime = Utilities.getCurrentTimeMillis(); 
Log.e("WriteToPlayerThread", "Writing a package took " + (afterTime - beforeTime) + " milliseconds"); 

हालांकि, मैं निम्नलिखित परिणाम प्राप्त: Logcat Image http://img810.imageshack.us/img810/3453/logcatimage.png

ये पता चलता है कि अंतराल शुरू में, शुरुआत में होता है जिसके बाद audiotrack हो रही डेटा रखता है लगातार ... मुझे वास्तव में यह तय करने की ज़रूरत है ...

+0

__builtin_expect एक अनुकूलन संकेत है। तर्क "अगर त्रुटि है, तो लॉग इन करने के लिए wite, audiotrack पर कॉल शुरू करें(), और टाइमआउट ध्वज सेट करें।" 'परिणाम' पिछली पंक्ति में सेट किया जा रहा है,' परिणाम = cblk-> cv.waitRelative (cblk-> ताला, सेकंड (1)); ', जो एक शर्त चर पर प्रतीक्षा करता है। तो ऐसा लगता है कि थ्रेड-सफी योजना के साथ कुछ गड़बड़ है। – AShelly

+0

इस कोड में थ्रेड-सेफ्टी बग का और सबूत बाद में एक ही फ़ंक्शन में है: 'LOGW_IF (टाइमआउट, "*** गंभीर चेतावनी *** प्राप्तबफर() का समय समाप्त हो गया लेकिन उसे लॉक करने की आवश्यकता नहीं थी। हमने पुनर्प्राप्त किया, लेकिन ऐसा नहीं होना चाहिए (उपयोगकर्ता =% 08x, सर्वर =% 08x) ", यू, एस);' – AShelly

+0

हाँ, लेकिन मुझे यह चेतावनी कभी नहीं मिली ... केवल "नियमित" एक ... – ThaMe90

7

क्या आप जानते हैं कि प्रति सेकेंड कितने बाइट्स आप प्राप्त कर रहे हैं, पैकेट की तुलना में औसत समय, और पैकेट के बीच अधिकतम समय? यदि नहीं, तो क्या आप इसकी गणना करने के लिए कोड जोड़ सकते हैं?

स्ट्रीम को भरने के लिए आपको 8000 नमूने/सेकेंड * 2 बाइट्स/नमूना = 16,000 बाइट प्रति सेकंड औसत करने की आवश्यकता है।

आने वाले पैकेट के बीच 2048 बाइट्स/(16000 बाइट्स/सेकंड) = 128 मिलीसेकंड का एक अंतर आपके स्ट्रीम को सूखने और ऑडियो को स्टटर करने का कारण बन जाएगा।

इसे रोकने के लिए एक तरीका बफर आकार (PLAYER_CAPACITY) बढ़ाएं। आने वाला पैकेट आकार और दर में भिन्नता को संभालने में एक बड़ा बफर अधिक सक्षम होगा। जब आप बफर को प्रारंभ में भरने की प्रतीक्षा करते हैं तो अतिरिक्त स्थिरता की लागत प्लेबैक शुरू करने में बड़ी देरी होती है।

+0

किसी न किसी अनुमान पर मुझे प्रति सेकेंड 67,200 बाइट मिलते हैं। 960 बाइट्स के लायक 70 पैकेजों के बारे में (मोटे तौर पर)। मैं मोटे तौर पर कहता हूं क्योंकि यह वायर्ड कनेक्शन के माध्यम से है। जब मैं वायरलेस से गुजरता हूं, तो मुझे लगता है कि मुझे लगभग 50 मिलेंगे (शायद थोड़ा और शायद थोड़ा कम) पैकेज एक सेकंड, मुझे प्रति सेकंड 48,000 बाइट दे रहा है। मैं कहूंगा कि इसे भरने के लिए पर्याप्त है। : o – ThaMe90

+0

कुछ डीबगिंग और कई लॉगकैट्स को देखने के बाद, मुझे यह पता चला है कि यह एक "प्राप्त बफर टाइम आउट" बग है ... मैं अभी भी इसे ठीक करने की कोशिश कर रहा हूं ... – ThaMe90

+0

क्या आपने कभी इस समस्या को हल किया है?कृपया अपडेट पोस्ट करें। मुझे भी एक ही समस्या है .... धन्यवाद !!! – aProgrammer

संबंधित मुद्दे