2015-08-05 3 views
3

Я пытаюсь создать приложение для аудиозаписей для Android Wear. Прямо сейчас, я могу захватить звук на часах, передать его на телефон и сохранить его в файле. Однако в аудиофайле присутствуют промежутки или обрезанные части.Android Wear Audio Recorder с использованием ChannelAPI

Я нашел это заданные вопросы, связанные с моей проблемой link1, link2, но они не могли мне помочь.


Вот мой код:

Во-первых, на стороне часов, я создаю канал, используя channelAPI и успешно отправить аудио захватывается на часы на смартфоне.

//here are the variables values that I used 

//44100Hz is currently the only rate that is guaranteed to work on all devices 
//but other rates such as 22050, 16000, and 11025 may work on some devices. 

private static final int RECORDER_SAMPLE_RATE = 44100; 
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO; 
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT; 
int BufferElements2Rec = 1024; 
int BytesPerElement = 2; 

//start the process of recording audio 
private void startRecording() { 

    recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 
      RECORDER_SAMPLE_RATE, RECORDER_CHANNELS, 
      RECORDER_AUDIO_ENCODING, BufferElements2Rec * BytesPerElement); 

    recorder.startRecording(); 
    isRecording = true; 
    recordingThread = new Thread(new Runnable() { 
     public void run() { 
      writeAudioDataToPhone(); 
     } 
    }, "AudioRecorder Thread"); 
    recordingThread.start(); 
} 

private void writeAudioDataToPhone(){ 

    short sData[] = new short[BufferElements2Rec]; 
    ChannelApi.OpenChannelResult result = Wearable.ChannelApi.openChannel(googleClient, nodeId, "/mypath").await(); 
    channel = result.getChannel(); 

    Channel.GetOutputStreamResult getOutputStreamResult = channel.getOutputStream(googleClient).await(); 
    OutputStream outputStream = getOutputStreamResult.getOutputStream(); 

    while (isRecording) { 
     // gets the voice output from microphone to byte format 

     recorder.read(sData, 0, BufferElements2Rec); 
     try { 
      byte bData[] = short2byte(sData); 
      outputStream.write(bData); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
    try { 
     outputStream.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

Затем со стороны смартфона я получаю аудиоданные с канала и записываю их в файл PCM.

public void onChannelOpened(Channel channel) { 
    if (channel.getPath().equals("/mypath")) { 
     Channel.GetInputStreamResult getInputStreamResult = channel.getInputStream(mGoogleApiClient).await(); 
     inputStream = getInputStreamResult.getInputStream(); 

     writePCMToFile(inputStream); 

     MainActivity.this.runOnUiThread(new Runnable() { 
      public void run() { 
       Toast.makeText(MainActivity.this, "Audio file received!", Toast.LENGTH_SHORT).show(); 
      } 
     }); 
    } 
} 

public void writePCMToFile(InputStream inputStream) { 
    OutputStream outputStream = null; 

    try { 
     // write the inputStream to a FileOutputStream 
     outputStream = new FileOutputStream(new File("/sdcard/wearRecord.pcm")); 

     int read = 0; 
     byte[] bytes = new byte[1024]; 

     while ((read = inputStream.read(bytes)) != -1) { 
      outputStream.write(bytes, 0, read); 
     } 

     System.out.println("Done writing PCM to file!"); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     if (inputStream != null) { 
      try { 
       inputStream.close(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     if (outputStream != null) { 
      try { 
       // outputStream.flush(); 
       outputStream.close(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

     } 
    } 
} 

Что я делаю неправильно или что ваши предложения, чтобы достичь идеального беспрерывного аудиофайла на смартфоне? Заранее спасибо.

+0

Вы пробовали сделать гораздо больший буфер? 1024 байта очень малы, и было бы легко задержать на телефоне, чтобы вы пропустили какой-то звук. –

+0

Да. Я также попытался использовать в десять раз значение, возвращаемое функцией AudioRecord.getMinBufferSize, но результат был тот же. –

ответ

1

Я заметил в вашем коде, что вы все читаете в короткий [] массив, а затем преобразовываете его в массив byte [] для отправляемого API канала. Ваш код также создает новый массив byte [] через каждую итерацию цикла, что создаст много работы для сборщика мусора. В общем, вы хотите избежать выделения внутри циклов.

Я бы выделил один байт [] массив вверху и пусть класс AudioRecord хранит его непосредственно в массиве byte [] (просто убедитесь, что вы выделяете в два раза больше байтов, чем вы делали шорты), с кодом, подобным этому :

mAudioTemp = new byte[bufferSize]; 

int result; 
while ((result = mAudioRecord.read(mAudioTemp, 0, mAudioTemp.length)) > 0) { 
    try { 
    mAudioStream.write(mAudioTemp, 0, result); 
    } catch (IOException e) { 
    Log.e(Const.TAG, "Write to audio channel failed: " + e); 
    } 
} 

Я также проверил это с 1-секундным звуковым буфером, используя такой код, и он работал красиво. Я не уверен, каков минимальный размер буфера до того, как у него возникнут проблемы:

int bufferSize = Math.max(
    AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT), 
    44100 * 2); 
+0

Спасибо за ответ! Итак, на карманной стороне я бы использовал тот же bufferSize, что и носимая сторона, а не 1024, верно? –

+0

После примерно 20 секунд записи звук снова начинает обрезку ... –

Смежные вопросы