2011-03-13 25 views
10

मैं फ़ाइल लोड करके और बाइट्स को AudioTrack.write() में FileInputStream> BufferedInputStream> DataInputStream विधि के माध्यम से अपने एंड्रॉइड फोन पर WAV खेल रहा हूं। ऑडियो ठीक खेलता है और जब यह होता है, तो मैं अच्छे प्रदर्शन के साथ फ्लाई पर नमूना दर, वॉल्यूम इत्यादि को आसानी से समायोजित कर सकता हूं। हालांकि, खेल शुरू करने के लिए ट्रैक के लिए लगभग दो पूर्ण सेकंड लग रहे हैं। मुझे पता है कि ऑडियोट्रैक में एक अपरिहार्य देरी है, लेकिन यह हास्यास्पद है। हर बार जब मैं एक ट्रैक चलाने, मैं इस मिल:ऑडियोट्रैक अंतराल: प्राप्त बफर का समय

03-13 14:55:57.100: WARN/AudioTrack(3454): obtainBuffer timed out (is the CPU pegged?) 0x2e9348 user=00000960,  server=00000000 
03-13 14:55:57.340: WARN/AudioFlinger(72): write blocked for 233 msecs, 9 delayed writes, thread 0xba28 

मैंने देखा है कि एक की देरी लिखने की संख्या बढ़ जाती हर बार जब मैं एक ट्रैक खेलने - यहां तक ​​कि कई सत्रों की - समय फोन है से चालू कर दिया गया ब्लॉक समय हमेशा 230 - 240 मिमी होता है, जो इस डिवाइस पर 9600 के न्यूनतम बफर आकार (9600/44100) पर विचार करने में समझ में आता है। मैंने इस संदेश को इंटरनेट पर अनगिनत खोजों में देखा है, लेकिन आमतौर पर यह ऑडियो बजाने या ऑडियो छोड़ने से संबंधित नहीं लगता है। मेरे मामले में, यह सिर्फ देरी शुरू हो गया है।

मैं अपने सभी कोड को उच्च प्राथमिकता धागे में चला रहा हूं। मैं जो कर रहा हूं उसका एक संक्षिप्त-अभी-कार्यात्मक संस्करण यहां दिया गया है। यह मेरी प्लेबैक कक्षा में थ्रेड कॉलबैक है। दोबारा, यह काम करता है (केवल 16-बिट, 44.1kHz, स्टीरियो फाइलें अभी खेल रहा है), यह हमेशा शुरू करने के लिए हमेशा के लिए लेता है और यह प्राप्त होता है कि हर बार बफर/देरी लिखने वाला संदेश होता है।

public void run() { 

    // Load file 
    FileInputStream mFileInputStream; 
    try { 
     // mFile is instance of custom file class -- this is correct, 
     // so don't sweat this line 
     mFileInputStream = new FileInputStream(mFile.path()); 
    } catch (FileNotFoundException e) { 
     // log 
    } 

    BufferedInputStream mBufferedInputStream = new BufferedInputStream(mFileInputStream, mBufferLength); 
    DataInputStream mDataInputStream = new DataInputStream(mBufferedInputStream); 

    // Skip header 
    try { 
     if (mDataInputStream.available() > 44) { 
      mDataInputStream.skipBytes(44); 
     } 
    } catch (IOException e) { 
     // log 
    } 

    // Initialize device 
    mAudioTrack = new AudioTrack(
     AudioManager.STREAM_MUSIC, 
     ConfigManager.SAMPLE_RATE, 
     AudioFormat.CHANNEL_CONFIGURATION_STEREO, 
     AudioFormat.ENCODING_PCM_16BIT, 
     ConfigManager.AUDIO_BUFFER_LENGTH, 
     AudioTrack.MODE_STREAM 
    ); 
    mAudioTrack.play(); 

    // Initialize buffer 
    byte[] mByteArray = new byte[mBufferLength]; 
    int mBytesToWrite = 0; 
    int mBytesWritten = 0; 

    // Loop to keep thread running 
    while (mRun) { 

     // This flag is turned on when the user presses "play" 
     while (mPlaying) { 

      try { 
       // Check if data is available 
       if (mDataInputStream.available() > 0) { 

        // Read data from file and write to audio device 
        mBytesToWrite = mDataInputStream.read(mByteArray, 0, mBufferLength); 
        mBytesWritten += mAudioTrack.write(mByteArray, 0, mBytesToWrite); 

       } 
      } 
      catch (IOException e){ 
       // log 
      }     
     } 
    } 
} 

मैं कृत्रिम रूप से लंबे अंतराल अतीत मिल सकता है, मैं आसानी से इनहेरिट विलंबता के साथ एक बाद, उम्मीद के मुताबिक स्थिति में मेरी लिखने शुरू करने से सौदा कर सकते हैं (यानी, पिछले न्यूनतम बफर लंबाई छोड़ जब मैं एक फ़ाइल को चलाते समय शुरू)।

+1

कुछ करना चाहता हूँ चाहते हैं। क्या आपको कोई समाधान मिला? – sunside

+1

दुर्भाग्य से अभी तक नहीं। :/ – BTR

उत्तर

2

मैं एक समान समस्या में भाग गया, हालांकि मैं पीसीएम डेटा पढ़ने के लिए, BufferedInputStream के बजाय, RandomAccessFile का उपयोग कर रहा था। मुद्दा यह था कि फ़ाइल I/O बहुत धीमी थी। मुझे संदेह है कि आपको बफर्ड स्ट्रीम के साथ भी यह समस्या होगी, क्योंकि आई/ओ अभी भी ऑडियो प्रोसेसिंग के समान थ्रेड पर हो रहा है।

समाधान दो धागे हैं: एक थ्रेड जो फ़ाइल से बफर पढ़ता है और उन्हें स्मृति में कतार देता है, और एक अन्य थ्रेड जो इस कतार से पढ़ता है और ऑडियो हार्डवेयर को लिखता है। मैंने इसे पूरा करने के लिए एक ConcurrentLinkedQueue का उपयोग किया।

मैंने ऑडियो रिकॉर्डॉर्ड का उपयोग करके रिकॉर्डिंग के लिए एक ही तकनीक का उपयोग किया, लेकिन विपरीत दिशा में। कुंजी I/O को अलग थ्रेड पर रखना है।

+0

धन्यवाद! यह परियोजना समाधान के लिए इंतजार कर रही है। मैं इसे आज़माउंगा। – BTR

1

पार्टी के जवाब में थोड़ा देर हो चुकी है, लेकिन अगर यह भविष्य में किसी की भी मदद करता है - तो मैं कोड में कोड के समान कोड के साथ इस सटीक समस्या में भाग गया, जहां ऑडियोट्रैक बनाया गया है और खेलने के लिए सेट है, लेकिन तुरंत लिखा नहीं है।

मैंने पाया कि लिखने शुरू करने से पहले ऑडियोट्रैक बनाने के तुरंत बाद देरी हो गई। किसी कारण से ऑडियोट्रैक एक खाली बफर के साथ बैठना पसंद नहीं करता है।

ऊपर कोड के संदर्भ में, आप मुझे इस समय एक ऐसी ही समस्या है की तरह

mAudioTrack=null; 
while (mRun) 
{ 

    // This flag is turned on when the user presses "play" 
    while (mPlaying) 
    { 

     try 
     { 
      if (mAudioTrack==null) { 
       mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, ConfigManager.SAMPLE_RATE,AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_16BIT,ConfigManager.AUDIO_BUFFER_LENGTH,AudioTrack.MODE_STREAM); 
       mAudioTrack.play(); 
      } 
      // Rest of the playback code here 
     } 
    } 
    mAudioTrack=null; 
}