2014-10-07 7 views
7

में ऑडियो रिकॉर्ड रिकॉर्ड करता है मैं पीसीएम 16LE प्रारूप, 8000Hz, 1channel में ऑडियो रिकॉर्ड के साथ ध्वनि रिकॉर्ड कर रहा हूं। यह एंड्रॉइड संस्करण 2.3.3-4.4.4 में ठीक है, लेकिन एंड्रॉइड एल (5.0) डेवलपर पूर्वावलोकन (नेक्सस 5, नेक्सस 7 और एमुलेटर पर) में अजीब अंतःक्रियात्मक ध्वनि रिकॉर्ड करता है।ऑडियो रिकॉर्डर एंड्रॉइड एल डेवलपर पूर्वावलोकन

यहाँ दर्ज की ध्वनि (- रिकॉर्डिंग, दूसरी छमाही - पहली छमाही प्लेबैक) का नमूना है: https://www.dropbox.com/s/3wcgufua5pphwtt/android_l_sound_record_error.m4a?dl=0

मैं दर्ज की गई ध्वनि चलाने के लिए अलग नमूना दर (4000, 16000) और उपयोग करने की कोशिश के रूप में 8 बिट लेकिन ध्वनि अस्थायी रहती है। इस ध्वनि के साथ समस्या क्या हो सकती है?

मैं इनपुट आरंभ के लिए getAudioRecord() द्वारा ऑडियो रिकार्ड करने के लिए इस AudioRecordTask उपयोग कर रहा हूँ (कोई त्रुटि आपरेशन के दौरान लौट आए, ऑडियो मात्रा प्राप्त आकार उतना ही internalBufferSize मूल्य के लिए):

public final int SAMPLING_RATE = 8000; 

private AudioRecord getAudioRecord() { 
    int internalBufferSize = AudioRecord.getMinBufferSize(SAMPLING_RATE, 
      AudioFormat.CHANNEL_IN_MONO, 
      AudioFormat.ENCODING_PCM_16BIT); //returns 640 

    internalBufferSize = 8000; //also tried returned value (640) and values 2560, 30000 - no changes 

    final int SOURCE; 
    if (Build.VERSION.SDK_INT < 11) { 
     SOURCE = MediaRecorder.AudioSource.MIC; 
    } else { 
     SOURCE = MediaRecorder.AudioSource.VOICE_COMMUNICATION; 
    } 

    AudioRecord record = new AudioRecord(SOURCE, 
      SAMPLING_RATE, 
      AudioFormat.CHANNEL_IN_MONO, 
      AudioFormat.ENCODING_PCM_16BIT, 
      internalBufferSize); 

    int state = record.getState(); 
    if (state != AudioRecord.STATE_INITIALIZED) { 
     try { 
      record.release(); 
     } catch (Exception e) { 
     } 
     return null; 
    } 

    if (record.getState() == android.media.AudioRecord.STATE_INITIALIZED) { 
     record.startRecording(); 
    } else { 
     record.release(); 
     return null; 
    } 
    return record; 
} 

private class AudioRecordTask extends AsyncTask<Void, Void, Void> { 
    final int PARTIAL_BUFFER_SIZE = SAMPLING_RATE; 
    final int NECESSARY_BUFFER_SIZE = 15 * PARTIAL_BUFFER_SIZE * Short.SIZE/8; 
    final int FULL_BUFFER_SIZE = NECESSARY_BUFFER_SIZE * 2; //XXX: * 2 for the case when system returns more data than needed 
    short[] mBuffer; 
    int mTotalSize; 
    int mTotalSizeInBytes; 
    boolean mResult; 
    private Object mLock = new Object(); 

    @Override 
    protected void onPreExecute() 
    { 
     mIsRecording = true; 

     mBuffer = new short[FULL_BUFFER_SIZE]; 
     mTotalSize = 0; 
     mTotalSizeInBytes = 0; 
     mResult = false; 
    } 

    @Override 
    protected Void doInBackground(Void... arg0) { 
     synchronized (mLock) { 
      android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); 
      AudioRecord record = getAudioRecord(); 
      if (record == null) { 
       mResult = false; 
       return null; 
      } 

      for (int i = 0; i < 15 * 100; i++) { //XXX: * 100 to record enough data (system can return lesser than needed) 
       int datalen = record.read(mBuffer, mTotalSize, PARTIAL_BUFFER_SIZE); 
       if (datalen > 0) { 
        mTotalSize += datalen; 
        mTotalSizeInBytes = mTotalSize*2; 
       } else { 
        Log.w("", "error " + datalen + " in AudioRecord.read"); 
       } 
       if (isCancelled() || mTotalSizeInBytes > NECESSARY_BUFFER_SIZE) { 
        break; 
       } 
      } 
      if (record.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) { 
       record.stop(); 
      } 

      record.release(); 
      mResult = true; 
      return null; 
     } 
    } 

    @Override 
    protected void onPostExecute(Void r) { 
     synchronized (mLock) { 
      mIsRecording = false; 
      fin(); 
     } 
    } 

    @Override 
    protected void onCancelled() { 
     //XXX: on old Androids (e.g. 2.3.3) onCancelled being called while doInBackground is still running 
     synchronized (mLock) { 
      mIsRecording = false; 
      if (mAbort) { 
       return; 
      } 
      fin(); 
     } 
    } 

    private void fin() { 
     if (mResult && mTotalSizeInBytes > 0) { 
      sendRecordedAudioToServer(mBuffer, mTotalSize, mTotalSizeInBytes); 
     } else { 
      showError(null); 
     } 
    } 
} 

उत्तर

4

यह एंड्रॉयड एल में एक बग है डेवलपर पूर्वावलोकन: https://code.google.com/p/android-developer-preview/issues/detail?id=1492

लघु [] बफर तर्क के लिए AudioRecord.read शॉर्ट्स में मूल्य के बजाय बाइट्स में मान देता है।

वर्कअराउंड के रूप में byte [] बफर के साथ AudioRecord.read का उपयोग करें।

+0

यह जारी 5.0 में तय किया गया प्रतीत होता है, हालांकि एक संबंधित समस्या है जहां ऑफसेट पैरामीटर गलती से दोगुना हो जाता है - प्रयास करते समय https://code.google.com/p/android/issues/detail?id=80866 देखें एक पैच जमा करने के लिए मुझे बताया गया था कि आंतरिक रूप से भी तय किया गया है, हालांकि कोई रिलीज में यह कब प्रकट होगा। –

+0

मैंने 5.0.2 में इस (मुझे लगता है) में अभी दुर्घटनाग्रस्त हो गया है। क्या इसका मतलब यह है कि अगर बाइट [] बफर पढ़ा जाता है तो यह ऑफसेट पैरामीटर सहित सही काम करता है, या फिर भी यह दोगुना हो गया है? – nmw01223

+0

बाइट [] बफर का उपयोग करते समय सभी ऑफसेट सहित ठीक है (यह 5.0 और 5.0.1 पर था, अभी तक 5.0.2 पर परीक्षण नहीं किया गया है) –

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