2014-09-01 7 views
0

내 응용 프로그램의 경우 심장 박동 모니터의 경고음을 복제해야합니다. 즉, 1 분마다 N 번 소리를냅니다. 문제는 약 5ms 지연되는 것 같습니다. OS 및 기타 오버 헤드에서 컨텍스트 전환으로 인해 실시간 성능을 기대할 수 없다는 것을 알고 있습니다.Android : 심박수 BPM 사운드 재생

mBeepThread = new Thread(new Runnable() { 

     @Override 
     public void run() { 
      ArrayList<Long> beepTimes = new ArrayList<Long>(5000); 
      try { 
       AssetFileDescriptor afd; 
       afd = getAssets().openFd("audio/heart_beep.ogg"); 
       SoundPool sp = new SoundPool(10,AudioManager.STREAM_MUSIC,0); 

       int soundId = sp.load(afd, 1); 
       MediaPlayer mp = new MediaPlayer(); 
       mp.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength()); 
       long duration = mp.getDuration(); 
       long waitTime = (60000/bpmVal) - duration; 
       mp.release(); 
       Log.i(TAG,"Beeping every "+waitTime+"ms"); 
       while(true) { 
        beepTimes.add(SystemClock.elapsedRealtime()); 
        sp.play(soundId,1,1,1,0,1); 
        Thread.sleep(waitTime); 
       } 
      } catch (IllegalStateException | IOException | InterruptedException e) { 
       Log.e(TAG,e.getMessage(),e); 
       Iterator<Long> it = beepTimes.iterator(); 
       int count = 0; 
       Long oldTime = it.next(); 
       while(it.hasNext()) { 
        long newTime = it.next(); 
        long diff = newTime - oldTime; 
        oldTime = newTime; 
        Log.i(TAG,String.format("Beep %d: %d",count++,diff)); 
       } 
       return; 
      } 
     } 
    }); 
    mBeepThread.start(); 

나는 그것을 재생하기 위해 할 수 있나요 : 여기

MainActivity: Beeping every 946ms 

MainActivity: java.lang.InterruptedException 

MainActivity: Beep 0: 951 
MainActivity: Beep 1: 951 
MainActivity: Beep 2: 951 
MainActivity: Beep 3: 951 
MainActivity: Beep 4: 951 
MainActivity: Beep 5: 951 
MainActivity: Beep 6: 952 
MainActivity: Beep 7: 951 
MainActivity: Beep 8: 954 
MainActivity: Beep 9: 951 
MainActivity: Beep 10: 953 
MainActivity: Beep 11: 952 
MainActivity: Beep 12: 951 
MainActivity: Beep 13: 951 

나는 비프 음을 재생하는 데 사용하는 내 Thread입니다 : 80의 BPM으로, 나는 다음과 같은 로그 출력을 얻을 설정된 BPM에 사실인가, 아니면 실제로 946ms마다 재생 되는가? 그리고 다른 5 개가 사운드 재생 및 로깅을 만드는 오버 헤드 일 뿐인가?

나는 waitTime에서 5ms를 벗어날 수 있지만, 실제 문제를 푸는 것과 같은 느낌입니다.

+0

재생을 호출하는 데 약간의 오버 헤드가있을 수 있지만 큰 문제는 'Thread.sleep'에 실시간 보장이 없다는 것입니다. 그것은 스케줄러의 변덕에 지배를받습니다. – jaket

+0

@ jaket 그럼 어떻게하면 당신은 다음 번에 삐 소리를 낼 수 있습니까? –

+0

글쎄, 나라면 시스템 클럭보다는 오히려 오디오 클럭에 동기화하고 싶다. 제 말은, 드럼 머신이나 DAW가 Thread.sleeps를 가진 곳이라고 상상할 수 있습니까? 불행히도 정확한 방법은 정확한 샘플을 재생할 때까지 출력에 0 번을 출력하는 것입니다. – jaket

답변

0

이 질문은 이전에 메트로놈의 구현과 관련하여 질문 한 많은 질문과 비슷합니다.

정확하게 이것을 달성하는 유일한 방법은 자신의 PCM 스트림을 렌더링하는 것입니다. 시스템 (벽) 클록은 오디오 클록과 동기가 없으므로 안정적으로 주기적 이벤트를 삽입 할 수는 없습니다 (예 : 타이머를 사용하는 전용 스레드 절전). 혼잡하지 않도록 정확한 스케줄링 및/또는 런 루프에 의존한다.

대신 N 개의 샘플이 PCM 스트림으로 렌더링 된 후에 이벤트를 삽입합니다. 여기서 N은 마침표 및 샘플 속도의 함수입니다.

+0

달성 방법에 대한 코드 예제를 제공 할 수 있습니까? 다른 질문을 읽고 아무도 코드를 제공하지 않았거나 링크 된 방법이 없습니다. 이 작업을 수행. –

+0

죄송합니다. Android 용으로 준비하지 않았습니다. 비록 내가하는 곳의 iOS조차도, 그것은 꽤 많은 코드입니다. – marko