2013-07-16 6 views
1

MediaPlayer을 사용하여 오디오 파일을 동기화하고 YoutubePlayer을 사용하여 YouTube에서 스트리밍 오디오를 동기화해야합니다.Android에서 오디오를 동기화하는 방법은 무엇입니까?

MediaPlayer으로 시작하는 중에 오류가 발생했습니다. 약간의 지연 후에 시작되고 오디오 트랙이 동기화되지 않습니다. 오디오 파일이 무거 우므로 SoundPool을 사용하면 좋지 않습니다.

MediaPlayer의 시작을 관리하거나 오디오를 미리 버퍼링 (오디오를 PCM으로 디코딩하고 재생할 수 있습니까?) 할 수 있습니까?

미리 감사드립니다.

답변

1

저는 YoutubePlayer에 익숙하지 않지만 오디오 파일을 시작할 때 대기 시간을 줄이면 AudioTrack을 사용하는 것이 더 낫습니다 (또는 openSL에 익숙한 사용자는 video을 확인하십시오).

오디오를 괜찮은 결과로 동기화하는 데 사용한 간단한 해결 방법은 AudioTrack을 설정하고 오디오 파일의 PCM 데이터를 바이트 배열로 읽는 것입니다. 그런 다음 AudioTrack 플레이로 스레드를 만들고 내부에 명령을 작성하십시오. 오디오 파일 재생을 시작할 준비가되면 스레드에서 start를 호출하십시오. 샘플링 속도, 채널 및 형식은 스트리밍하는 오디오 파일에 따라 다릅니다.

int minBufferSize = AudioTrack.getMinBufferSize(441000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); 
at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM); 
filepath = Environment.getExternalStorageDirectory().getPath() + File.separator + "audiofile.wav"; 
fp = new File(Environment.getExternalStorageDirectory().getPath() + File.separator + "audiofile.wav"); 

     count = 0; 
     data = new byte[(int) fp.length()]; 
     try { 
      fis = new FileInputStream(filepath); 
      dis = new DataInputStream(fis); 
      while((count = dis.read(data, 0, (int) fp.length())) > -1){} 
      data = null; 
      dis.close(); 
      fis.close(); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     atThread = new Thread(new Runnable() { 
      public void run() { 
        at.play(); 
        at.write(data, 0, (int) fp.length()); 
        data = null; at.stop(); at.flush(); at.release(); 

      } 
      }); 

희망이 있습니다.

편집 : 도움을 @WilliamMorrison에

BIG 감사합니다! @ inazaruk의 대답 here을 수정 한 후 전체 파일을 메모리에 쓰지 않고도 별도의 웨이브 파일을 재생할 수있었습니다. 휴!

AudioTrack song_1, song_2; 
boolean stop = false; 
Button start_btn, stop_btn; 
DataInputStream dis_1, dis_2; 
File file_1 = new File(Environment.getExternalStorageDirectory().toString() + "/song_1.wav"); 
File file_2 = new File(Environment.getExternalStorageDirectory().toString() + "/song_2.wav"); 
FileInputStream fis_1, fis_2; 
int minBufferSize; 
Thread thread_1, thread_2; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    start_btn = (Button)findViewById(R.id.start); 
    start_btn.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      start(); 
     } 
    }); 

    stop_btn = (Button)findViewById(R.id.stop); 
    stop_btn.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      stop(); 
     } 
    });  
} 

Runnable read_song1 = new Runnable() {  
    public void run() { 

     Thread.currentThread().setPriority(Thread.MIN_PRIORITY); 
     byte [] audio_data = new byte[minBufferSize]; 
     try { 
      while(!stop) {  
       dis_1.read(audio_data, 0, minBufferSize); 
       song_1.write(audio_data, 0, audio_data.length); 
      } 
     } 
     catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
}; 

Runnable read_song2 = new Runnable() 
{  
    public void run() { 
     Thread.currentThread().setPriority(Thread.MIN_PRIORITY); 
     byte [] audio_data = new byte[minBufferSize]; 
     try { 
      while(!stop) {  
       dis_2.read(audio_data, 0, minBufferSize); 
       song_2.write(audio_data, 0, audio_data.length); 
      } 
     } 
     catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
}; 

void start() { 

    try { 
     fis_1 = new FileInputStream(file_1); fis_2 = new FileInputStream(file_2); 
     dis_1 = new DataInputStream(fis_1); dis_2 = new DataInputStream(fis_2); 

     stop = false; 

     minBufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT); 

     song_1 = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);    
     song_2 = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM); 

     song_1.play(); song_2.play();   
     thread_1 = new Thread(read_song1); thread_2 = new Thread(read_song2); 
     thread_1.start(); thread_2.start(); 
    } 
    catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } 
} 

void stop() { 

    stop = true;   
    song_1.stop(); song_2.stop(); 
    song_1.flush(); song_2.flush(); 
    song_1.release(); song_2.release(); 

    try { 
     dis_1.close(); dis_2.close(); 
     fis_1.close(); fis_2.close(); 
    } 
    catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 
+1

좋은 예입니다. 독자는이 코드가 PCM 오디오 파일 전체를 메모리로 읽는 것을 알고 있습니다. 이는 짧은 파일에는 적합하지만 긴 파일에는 적합하지 않음을 의미합니다. –

+0

아, 좋은 지적이야! 윌리엄에게 감사드립니다. – jch000

+0

@WilliamMorrison는 한 번에 메모리에 PCM 오디오 파일의 일부를 작성하는 방법에 대한 조언을해야합니까? 아마 뭔가 명백한 것을 놓치고 있지만 적절한 방법을 찾을 수없는 것 같습니다. 어떤 방향이라도 대단히 감사 할 것입니다! =] – jch000

관련 문제