2012-06-07 3 views
2

У меня есть приложение на рынке, которое записывает аудио с использованием класса AudioRecord и сохраняет его на SD-карте. Пользователи с новой серией телефонов HTC One не могут записать.AudioRecord с новыми телефонами Android One One One

При запуске записи он сохраняет файл 1 КБ на SD-карту и останавливается там. Обычно он, по крайней мере, создает заголовок 44 КБ, поэтому я считаю, что он останавливается где-то в функции prepare(). У меня нет HTC, чтобы проверить это, так что я ошеломлен. Я подключил класс, который я использую для записи, и записываю несжатый звук. В моей звукозаписывающей деятельности я инициализировать объект extAudioRecorder с consturctor следующим образом:

extAudioRecorder = new ExtAudioRecorder(true, 
AudioSource.MIC, 
44100, 
AudioFormat.CHANNEL_IN_MONO, 
AudioFormat.ENCODING_PCM_16BIT); 

Я чувствую, что это должно работать на более новом телефоне.

Любая помощь будет оценена по достоинству. Вот полный источник класса, который я использую для записи. Он также может делать то же самое с телефонами LG Optimus One.

public class ExtAudioRecorder implements Runnable 
{ 
private final static int[] sampleRates = {44100, 22050, 11025, 8000}; 
private static final String AUDIO_RECORDER_FOLDER = "FOLDER"; 
String sdPath = Environment.getExternalStorageDirectory().getPath(); 
File file = new File(sdPath,AUDIO_RECORDER_FOLDER); 
String FullFilePath; 
String fileName; 
static int sampleRate; 
private volatile boolean recording = false; 
double RecordReadDelayInSeconds = 0; 
double RecordDelayInSeconds = 0; 


private MediaPlayer mPlayer; 
private static String mp3Path = Environment.getExternalStorageDirectory() + "/FOLDER/tmp/tmp.mp3"; 


double beatDelayInSeconds = 0; 

public ExtAudioRecorder getInstanse(Boolean recordingCompressed) 
{ 
    ExtAudioRecorder result = null; 

    if(recordingCompressed) 
    { 
     result = new ExtAudioRecorder( false, 
             AudioSource.MIC, 
             sampleRates[3], 
             AudioFormat.CHANNEL_IN_MONO, 
             AudioFormat.ENCODING_PCM_16BIT); 
    } 
    else 
    { 
     int i=0; 
     do 
     { 
      result = new ExtAudioRecorder( true, 
              AudioSource.MIC, 
              sampleRates[i], 
              AudioFormat.CHANNEL_IN_MONO, 
              AudioFormat.ENCODING_PCM_16BIT); 
      sampleRate = sampleRates[i]; 

     } while((++i<sampleRates.length) & !(result.getState() == ExtAudioRecorder.State.INITIALIZING)); 
    } 
    return result; 
} 

/** 
* INITIALIZING : recorder is initializing; 
* READY : recorder has been initialized, recorder not yet started 
* RECORDING : recording 
* ERROR : reconstruction needed 
* STOPPED: reset needed 
*/ 
public enum State {INITIALIZING, READY, RECORDING, ERROR, STOPPED}; 

public static final boolean RECORDING_UNCOMPRESSED = true; 
public static final boolean RECORDING_COMPRESSED = false; 

// The interval in which the recorded samples are output to the file 
// Used only in uncompressed mode 
private static final int TIMER_INTERVAL = 120; 

// Toggles uncompressed recording on/off; RECORDING_UNCOMPRESSED/RECORDING_COMPRESSED 
private boolean   rUncompressed; 

// Recorder used for uncompressed recording 
private AudioRecord  audioRecorder = null; 

// Recorder used for compressed recording 
private MediaRecorder mediaRecorder = null; 

// Stores current amplitude (only in uncompressed mode) 
private int    cAmplitude= 0; 

// Output file path 
private String   filePath = null; 

// Recorder state; see State 
private State   state; 

// File writer (only in uncompressed mode) 
private RandomAccessFile randomAccessWriter; 

// Number of channels, sample rate, sample size(size in bits), buffer size, audio source, sample size(see AudioFormat) 
private short     nChannels; 
private int      sRate; 
private short     bSamples; 
private int      bufferSize; 
private int      aSource; 
private int      aFormat; 

// Number of frames written to file on each output(only in uncompressed mode) 
private int      framePeriod; 

// Buffer for output(only in uncompressed mode) 
private byte[]     buffer; 

// Number of bytes written to file after header(only in uncompressed mode) 
// after stop() is called, this size is written to the header/data chunk in the wave file 
private int      payloadSize; 

/** 
* 
* Returns the state of the recorder in a RehearsalAudioRecord.State typed object. 
* Useful, as no exceptions are thrown. 
* 
* @return recorder state 
*/ 
public State getState() 
{ 
    return state; 
} 

/* 
* 
* Method used for recording. 
* 
*/ 
private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener() 
{ 
    @Override 
    public void onPeriodicNotification(AudioRecord recorder) 
    { 
     if (state != State.STOPPED) 
     { 
     audioRecorder.read(buffer, 0, buffer.length); // Fill buffer 
     try 
     { 
      randomAccessWriter.write(buffer); // Write buffer to file 
      payloadSize += buffer.length; 
      if (bSamples == 16) 
      { 
       for (int i=0; i<buffer.length/2; i++) 
       { // 16bit sample size 
        short curSample = getShort(buffer[i*2], buffer[i*2+1]); 
        if (curSample > cAmplitude) 
        { // Check amplitude 
         cAmplitude = curSample; 
        } 
       } 
      } 
      else  
      { // 8bit sample size 
       for (int i=0; i<buffer.length; i++) 
       { 
        if (buffer[i] > cAmplitude) 
        { // Check amplitude 
         cAmplitude = buffer[i]; 
        } 
       } 
      } 
     } 
     catch (IOException e) 
     { 
      Log.e(ExtAudioRecorder.class.getName(), "Error occured in updateListener, recording is aborted"); 
      stop(); 
     } 
     } 
    } 

    @Override 
    public void onMarkerReached(AudioRecord recorder) 
    { 
     // NOT USED 
    } 
}; 
/** 
* 
* 
* Default constructor 
* 
* Instantiates a new recorder, in case of compressed recording the parameters can be left as 0. 
* In case of errors, no exception is thrown, but the state is set to ERROR 
* 
*/ 
public ExtAudioRecorder(boolean uncompressed, int audioSource, int sampleRate, int channelConfig, int audioFormat) 
{ 
    try 
    { 
     rUncompressed = uncompressed; 
     if (rUncompressed) 
     { // RECORDING_UNCOMPRESSED 
      if (audioFormat == AudioFormat.ENCODING_PCM_16BIT) 
      { 
       bSamples = 16; 
      } 
      else 
      { 
       bSamples = 8; 
      } 

      if (channelConfig == AudioFormat.CHANNEL_IN_MONO) 
      { 
       nChannels = 1; 
      } 
      else 
      { 
       nChannels = 2; 
      } 

      aSource = audioSource; 
      sRate = sampleRate; 
      aFormat = audioFormat; 

      framePeriod = sampleRate * TIMER_INTERVAL/1000; 
      bufferSize = framePeriod * 2 * bSamples * nChannels/8; 
      if (bufferSize < AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat)) 
      { // Check to make sure buffer size is not smaller than the smallest allowed one 
       bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); 
       // Set frame period and timer interval accordingly 
       framePeriod = bufferSize/(2 * bSamples * nChannels/8); 
       Log.w(ExtAudioRecorder.class.getName(), "Increasing buffer size to " + Integer.toString(bufferSize)); 
      } 

      audioRecorder = new AudioRecord(audioSource, sampleRate, channelConfig, audioFormat, bufferSize); 

      if (audioRecorder.getState() != AudioRecord.STATE_INITIALIZED) 
       throw new Exception("AudioRecord initialization failed"); 
      audioRecorder.setRecordPositionUpdateListener(updateListener); 
      audioRecorder.setPositionNotificationPeriod(framePeriod); 
     } else 
     { // RECORDING_COMPRESSED 
      mediaRecorder = new MediaRecorder(); 
      mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
      mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
      mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);    
     } 
     cAmplitude = 0; 
     filePath = null; 
     state = State.INITIALIZING; 
    } catch (Exception e) 
    { 
     if (e.getMessage() != null) 
     { 
      Log.e(ExtAudioRecorder.class.getName(), e.getMessage()); 
     } 
     else 
     { 
      Log.e(ExtAudioRecorder.class.getName(), "Unknown error occured while initializing recording"); 
     } 
     state = State.ERROR; 
    } 
} 

/** 
* Sets output file path, call directly after construction/reset. 
* 
* @param output file path 
* 
*/ 
public void setOutputFile(String argPath) 
{ 

    try 
    { 
     if (state == State.INITIALIZING) 
     { 
      filePath = argPath; 
      if (!rUncompressed) 
      { 
       mediaRecorder.setOutputFile(sdPath + "/FOLDER/" + filePath);      
      } 
     } 
    } 
    catch (Exception e) 
    { 
     if (e.getMessage() != null) 
     { 
      Log.e(ExtAudioRecorder.class.getName(), e.getMessage()); 
     } 
     else 
     { 
      Log.e(ExtAudioRecorder.class.getName(), "Unknown error occured while setting output path"); 
     } 
     state = State.ERROR; 
    } 
} 

/** 
* 
* Returns the largest amplitude sampled since the last call to this method. 
* 
* @return returns the largest amplitude since the last call, or 0 when not in recording state. 
* 
*/ 
public int getMaxAmplitude() 
{ 
    if (state == State.RECORDING) 
    { 
     if (rUncompressed) 
     { 
      int result = cAmplitude; 
      cAmplitude = 0; 
      return result; 
     } 
     else 
     { 
      try 
      { 
       return mediaRecorder.getMaxAmplitude(); 
      } 
      catch (IllegalStateException e) 
      { 
       return 0; 
      } 
     } 
    } 
    else 
    { 
     return 0; 
    } 
} 


/** 
* 
* Prepares the recorder for recording, in case the recorder is not in the INITIALIZING state and the file path was not set 
* the recorder is set to the ERROR state, which makes a reconstruction necessary. 
* In case uncompressed recording is toggled, the header of the wave file is written. 
* In case of an exception, the state is changed to ERROR 
*  
*/ 
public void prepare() 
{ 
    try 
    { 
     if (state == State.INITIALIZING) 
     { 
      if (rUncompressed) 
      { 
       if ((audioRecorder.getState() == AudioRecord.STATE_INITIALIZED) & (filePath != null)) 
       { 
        // write file header 

         if(!file.exists()) 
          file.mkdirs(); 

        fileName = filePath; 
        FullFilePath = file.getAbsoluteFile() + "/" + fileName; 
        randomAccessWriter = new RandomAccessFile(FullFilePath, "rw"); 

        randomAccessWriter.setLength(0); // Set file length to 0, to prevent unexpected behavior in case the file already existed 
        randomAccessWriter.writeBytes("RIFF"); 
        randomAccessWriter.writeInt(0); // Final file size not known yet, write 0 
        randomAccessWriter.writeBytes("WAVE"); 
        randomAccessWriter.writeBytes("fmt "); 
        randomAccessWriter.writeInt(Integer.reverseBytes(16)); // Sub-chunk size, 16 for PCM 
        randomAccessWriter.writeShort(Short.reverseBytes((short) 1)); // AudioFormat, 1 for PCM 
        randomAccessWriter.writeShort(Short.reverseBytes(nChannels));// Number of channels, 1 for mono, 2 for stereo 
        randomAccessWriter.writeInt(Integer.reverseBytes(sRate)); // Sample rate 
        randomAccessWriter.writeInt(Integer.reverseBytes(sRate*bSamples*nChannels/8)); // Byte rate, SampleRate*NumberOfChannels*BitsPerSample/8 
        randomAccessWriter.writeShort(Short.reverseBytes((short)(nChannels*bSamples/8))); // Block align, NumberOfChannels*BitsPerSample/8 
        randomAccessWriter.writeShort(Short.reverseBytes(bSamples)); // Bits per sample 
        randomAccessWriter.writeBytes("data"); 
        randomAccessWriter.writeInt(0); // Data chunk size not known yet, write 0 

        buffer = new byte[framePeriod*bSamples/8*nChannels]; 
        state = State.READY; 
       } 
       else 
       { 
        Log.e(ExtAudioRecorder.class.getName(), "prepare() method called on uninitialized recorder"); 
        state = State.ERROR; 
       } 
      } 
      else 
      { 
       mediaRecorder.prepare(); 
       state = State.READY; 
      } 
     } 
     else 
     { 
      Log.e(ExtAudioRecorder.class.getName(), "prepare() method called on illegal state"); 
      release(); 
      state = State.ERROR; 
     } 
    } 
    catch(Exception e) 
    { 
     if (e.getMessage() != null) 
     { 
      Log.e(ExtAudioRecorder.class.getName(), e.getMessage()); 
     } 
     else 
     { 
      Log.e(ExtAudioRecorder.class.getName(), "Unknown error occured in prepare()"); 
     } 
     state = State.ERROR; 
    } 
} 

/** 
* 
* 
* Releases the resources associated with this class, and removes the unnecessary files, when necessary 
* 
*/ 
public void release() 
{ 
    if (state == State.RECORDING) 
    { 
     stop(); 
    } 
    else 
    { 
     if ((state == State.READY) & (rUncompressed)) 
     { 
      try 
      { 
       randomAccessWriter.close(); // Remove prepared file 
      } 
      catch (IOException e) 
      { 
       Log.e(ExtAudioRecorder.class.getName(), "I/O exception occured while closing output file"); 
      } 
      //delete file 
      //(new File(filePath)).delete(); 
     } 
    } 

    if (rUncompressed) 
    { 
     if (audioRecorder != null) 
     { 
      audioRecorder.release(); 
     } 
    } 
    else 
    { 
     if (mediaRecorder != null) 
     { 
      mediaRecorder.release(); 
     } 
    } 
} 

/** 
* 
* 
* Resets the recorder to the INITIALIZING state, as if it was just created. 
* In case the class was in RECORDING state, the recording is stopped. 
* In case of exceptions the class is set to the ERROR state. 
* 
*/ 
public void reset() 
{ 
    try 
    { 
     if (state != State.ERROR) 
     { 
      release(); 
      filePath = null; // Reset file path 
      cAmplitude = 0; // Reset amplitude 
      if (rUncompressed) 
      { 
       audioRecorder = new AudioRecord(aSource, sRate, nChannels+1, aFormat, bufferSize); 
      } 
      else 
      { 
       mediaRecorder = new MediaRecorder(); 
       mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
       mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
       mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
      } 
      state = State.INITIALIZING; 
     } 
    } 
    catch (Exception e) 
    { 
     Log.e(ExtAudioRecorder.class.getName(), e.getMessage()); 
     state = State.ERROR; 
    } 
} 

/** 
* 
* 
* Starts the recording, and sets the state to RECORDING. 
* Call after prepare(). 
* 
*/ 
public void start() 
{ 
    if (state == State.READY) 
    { 
     if (rUncompressed) 
     { 
      payloadSize = 0; 
      RecordReadDelayInSeconds = 0; 
      RecordDelayInSeconds = 0; 

      mPlayer = new MediaPlayer(); 
      try { 
       mPlayer.setDataSource(mp3Path); 
       mPlayer.prepare(); 
      } catch (IllegalArgumentException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (SecurityException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (IllegalStateException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

      long recordstarted = System.nanoTime(); 
      audioRecorder.startRecording(); 
      long recordstopped = System.nanoTime(); 
      long recordDelay = recordstopped - recordstarted; 

      double RecordDelayInSeconds = recordDelay/1000000.0; 

      Log.i("StartRecording() Delay in seconds", String.valueOf(RecordDelayInSeconds)); 

      long recordreadstarted = System.nanoTime(); 
      audioRecorder.read(buffer, 0, buffer.length); 
      long recordreadstopped = System.nanoTime(); 
      long recordreadDelay = recordreadstopped - recordreadstarted; 
      RecordReadDelayInSeconds = recordreadDelay/1000000.0; 
      Log.i("Record read() Delay in seconds", String.valueOf(RecordReadDelayInSeconds)); 


      long mediastarted = System.nanoTime(); 
      mPlayer.start(); 
      long mediastopped = System.nanoTime(); 
      long beatDelay = mediastopped - mediastarted; 

      beatDelayInSeconds = 0; 
      beatDelayInSeconds = (beatDelay)/1000000000.0; 
      Log.i("Beat Delay in seconds", String.valueOf(beatDelayInSeconds)); 




     } 
     else 
     { 
      mediaRecorder.start(); 
     } 
     state = State.RECORDING; 
    } 
    else 
    { 
     Log.e(ExtAudioRecorder.class.getName(), "start() called on illegal state"); 
     state = State.ERROR; 
    } 
} 

/** 
* 
* 
* Stops the recording, and sets the state to STOPPED. 
* In case of further usage, a reset is needed. 
* Also finalizes the wave file in case of uncompressed recording. 
* 
*/ 
public void stop() 
{ 
    if (state == State.RECORDING) 
    { 
     if (rUncompressed) 
     { 
      audioRecorder.stop(); 

      try 
      { 
       randomAccessWriter.seek(4); // Write size to RIFF header 
       randomAccessWriter.writeInt(Integer.reverseBytes(36+payloadSize)); 

       randomAccessWriter.seek(40); // Write size to Subchunk2Size field 
       randomAccessWriter.writeInt(Integer.reverseBytes(payloadSize)); 

       randomAccessWriter.close(); 

       //mPlayer.stop(); 
      } 
      catch(IOException e) 
      { 
       Log.e(ExtAudioRecorder.class.getName(), "I/O exception occured while closing output file"); 
       state = State.ERROR; 
      } 
     } 
     else 
     { 
      mediaRecorder.stop(); 
     } 
     state = State.STOPPED; 
    } 
    else 
    { 
     Log.e(ExtAudioRecorder.class.getName(), "stop() called on illegal state"); 
     state = State.ERROR; 
    } 
} 

/* 
* 
* Converts a byte[2] to a short, in LITTLE_ENDIAN format 
* 
*/ 
private short getShort(byte argB1, byte argB2) 
{ 
    return (short)(argB1 | (argB2 << 8)); 
} 

public String[] GetFileProperties() 
{ 
    String[] fileProperties = new String[3]; 
    fileProperties[0] = FullFilePath; 
    fileProperties[1] = fileName; 
    fileProperties[2] = Integer.toString(sampleRate); 

    return fileProperties; 
} 

@Override 
public void run() { 
    android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); 
    start(); 

} 

public void StopMediaPlayer() 
{ 

    try { 
     mPlayer.stop(); 
    } catch (IllegalStateException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

public boolean isRecording() { 
    return recording; 
} 

public int GetSampleRate() 
{ 
    return sampleRate; 
} 

public double GetBeatDelay() 
{ 
    return beatDelayInSeconds; 
} 

public int GetRecordDelay() 
{ 
    return (int)(RecordReadDelayInSeconds +RecordDelayInSeconds); 

} 

}

ответ

1

Я был в состоянии получить эти ценности работы:
AudioSource.MIC
+44100
AudioFormat.CHANNEL_IN_MONO
AudioFormat.ENCODING_PCM_16BIT

Используя этот код, чтобы попробовать все значения :
https://github.com/lnanek/Misc/tree/master/TestOneXAudioRecord

Он выводит эту запись в журнале на One X (AT & T), один X (Европа), и один S (T-Mobile):
Д/TestOneXAudioRecordActivity (10500): Попытка скорости 44100Hz, биты : 2, канал: 16
Д/TestOneXAudioRecordActivity (10500): AudioRecord.getState = AudioRecord.STATE_INITIALIZED
I/TestOneXAudioRecordActivity (10500): инициализирован AudioRecord = [email protected] f0

В какой-то момент программа не могла инициализировать AudioRecord, но я перезагрузил устройство и начал работать. Я думаю, что другая программа использовала микрофон или одна из моих предыдущих попыток не выпустила AudioRecord, то есть аппаратное обеспечение было занято. Поэтому убедитесь, что вы попробуете перезапустить телефон и не собираетесь запускать какие-либо другие приложения для записи.

+0

Я думаю, что это все! Я даже пошел и купил HTC One, и он отлично работал: [. Если он перезагрузит телефон. Спасибо! – nawlrus