2012-09-11 3 views
0

메신저에서 사용자가 디스플레이에 표시된 가상 피아노에서 재생할 수있는 피아노 앱을 구현하려고합니다. 지연 시간이 짧기 때문에 AudioTrack 클래스를 사용하려고하는데 많은 문제가 있습니다. 내 문제는 소리를 빠르게 재생하는 것입니다. 지금은 버튼을 사용하여 테스트하고 있습니다. 버튼을 빨리 누르면 예외가 발생합니다.피아노 소리를 재생하기위한 Android AudioTrack 클래스

09-11 15:06:19.089: E/AudioTrack(3729): AudioFlinger could not create track, status: -12 
09-11 15:06:19.097: E/AudioTrack-JNI(3729): Error initializing AudioTrack 
09-11 15:06:19.097: E/AudioTrack-Java(3729): [ android.media.AudioTrack ] Error code -20 when initializing AudioTrack. 
09-11 15:06:19.097: D/AndroidRuntime(3729): Shutting down VM 
09-11 15:06:19.097: W/dalvikvm(3729): threadid=1: thread exiting with uncaught exception (group=0x4001d888) 
09-11 15:06:19.097: E/AndroidRuntime(3729): FATAL EXCEPTION: main 
09-11 15:06:19.097: E/AndroidRuntime(3729): java.lang.IllegalStateException: play() called on uninitialized AudioTrack. 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at android.media.AudioTrack.play(AudioTrack.java:764) 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at com.example.audiotrackvssoundpoollayer.MainActivity.onClick(MainActivity.java:216) 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at android.view.View.performClick(View.java:2461) 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at android.view.View$PerformClick.run(View.java:8890) 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at android.os.Handler.handleCallback(Handler.java:587) 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at android.os.Handler.dispatchMessage(Handler.java:92) 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at android.os.Looper.loop(Looper.java:123) 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at android.app.ActivityThread.main(ActivityThread.java:4632) 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at java.lang.reflect.Method.invokeNative(Native Method) 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at java.lang.reflect.Method.invoke(Method.java:521) 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858) 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
09-11 15:06:19.097: E/AndroidRuntime(3729):  at dalvik.system.NativeStart.main(Native Method) 

정적 모드에서 AudioTrack을 사용하고 있습니다. 사운드를 재생할 때마다 새 AudioTrack (...)을 사용하여 새 AudioTrack 객체를 만들고 다음 (...) 및 재생 (...)을 작성해야합니다.

나는 그것이 가능하지 않다고 생각합니다. 여기

코드의 ... 충분히 빨리 따라서 예외 인스턴스화 : 소리가 다른 비동기 작업 클래스의 해시 맵에 저장됩니다

public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_main); 

      Button buttonA1 = (Button) findViewById(R.id.buttonA1); 
      buttonA1.setOnClickListener(this); 
      Button buttonA2 = (Button) findViewById(R.id.buttonA2); 
      buttonA2.setOnClickListener(this); 
      Button buttonA3 = (Button) findViewById(R.id.buttonA3); 
      buttonA3.setOnClickListener(this); 
      Button buttonA4 = (Button) findViewById(R.id.buttonA4); 
      buttonA4.setOnClickListener(this); 
      Button buttonA5 = (Button) findViewById(R.id.buttonA5); 
      buttonA5.setOnClickListener(this); 
      Button buttonA6 = (Button) findViewById(R.id.buttonA6); 
      buttonA6.setOnClickListener(this); 
      Button buttonA7 = (Button) findViewById(R.id.buttonA7); 
      buttonA7.setOnClickListener(this); 
      Button buttonA8 = (Button) findViewById(R.id.buttonA8); 
      buttonA8.setOnClickListener(this); 

      //***AudioTrack*** 
      AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE); 
      float actualVolume = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); 
      float maxVolume = (float) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 
      volume = actualVolume/maxVolume; 
      minBufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
          AudioFormat.ENCODING_PCM_16BIT); 

      assetManager = getResources().getAssets(); 



     } 

public void onClick(View button) { 


     switch(button.getId()) { 

     case R.id.buttonA1: 
      audioTrack1 = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
        AudioFormat.ENCODING_PCM_16BIT, minBufferSize * 65, AudioTrack.MODE_STATIC); 
      audioTrack1.write(soundMap.get(3), 0, minBufferSize * 65); 
      audioTrack1.play(); 
      break; 
     case R.id.buttonA2: 
      audioTrack2 = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
        AudioFormat.ENCODING_PCM_16BIT, minBufferSize * 65, AudioTrack.MODE_STATIC); 
      audioTrack2.write(soundMap.get(3), 0, minBufferSize * 65); 
      audioTrack2.play(); 
      break; 
     case R.id.buttonA3: 
      audioTrack3 = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
        AudioFormat.ENCODING_PCM_16BIT, minBufferSize * 65, AudioTrack.MODE_STATIC); 
      audioTrack3.write(soundMap.get(3), 0, minBufferSize * 65); 
      audioTrack3.play(); 
      break;  
     case R.id.buttonA4: 
      audioTrack4 = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
        AudioFormat.ENCODING_PCM_16BIT, minBufferSize * 65, AudioTrack.MODE_STATIC); 
      audioTrack4.write(soundMap.get(3), 0, minBufferSize * 65); 
      audioTrack4.play(); 
      break; 
     case R.id.buttonA5: 
      audioTrack5 = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
        AudioFormat.ENCODING_PCM_16BIT, minBufferSize * 65, AudioTrack.MODE_STATIC); 
      audioTrack5.write(soundMap.get(4), 0, minBufferSize * 65); 
      audioTrack5.play(); 
      break; 
     case R.id.buttonA6: 
      audioTrack6 = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
        AudioFormat.ENCODING_PCM_16BIT, minBufferSize * 65, AudioTrack.MODE_STATIC); 
      audioTrack6.write(soundMap.get(5), 0, minBufferSize * 65); 
      audioTrack6.play(); 
      break; 
     case R.id.buttonA7: 
      audioTrack7 = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
        AudioFormat.ENCODING_PCM_16BIT, minBufferSize * 65, AudioTrack.MODE_STATIC); 
      audioTrack7.write(soundMap.get(6), 0, minBufferSize * 65); 
      audioTrack7.play(); 
      break; 
     case R.id.buttonA8: 
      audioTrack8 = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
        AudioFormat.ENCODING_PCM_16BIT, minBufferSize * 65, AudioTrack.MODE_STATIC); 
      audioTrack8.write(soundMap.get(7), 0, minBufferSize * 65); 
      audioTrack8.play(); 
      break; 
    } 
} 

누군가가이 문제를 해결하는 데 도움이 할 수 있다면 좋을 것 , 어쩌면 사운드가 사전 처리되거나 빈 바이트 버퍼가 audiotrack에 쓰여지고 버튼 클릭시 해시 맵 사운드가 오디오로 스트리밍되는 정적 모드 대신 스트림 모드를 사용합니다 선로.

답변

1

나는 SoundPool을보고 사용해야한다고 생각합니다. 그것은 당신이하고 싶은 일을하도록 특별히 설계된 것 같습니다. 그것은 동적으로 생성 된 소리와 함께 작동하지 않지만 피아노를 연주하고 있기 때문에 어쨌든 샘플을 WAV 파일로 가정합니다.

재생 속도를 사용하면 피치를 변경할 수 있습니다 : 배속 = 1 옥타브 위로 재생, 절반 속도 = 1 옥타브 아래로 재생. 나중에 더 세련된 방법을 사용하는 것이 좋습니다.

+0

안녕하세요, 답장을 보내 주셔서 감사합니다. 그러나 나는 또한 기관을위한 루프 기능이 필요합니다. 그리고 사운드 풀의 루프 기능은 각 루프 시작 사이의 틈 때문에 찾고자하는 것이 아닙니다. 따라서 나는 audiotrack 또는 ndk와 같은 하위 수준의 클래스를 사용해야합니다. audiotrack (클릭 소리)에서 재생 속도를 설정할 때도 안드로이드 틱에 문제가 발생했습니다. 아직도 다른 도서관을 찾고있는 Im ... – sNore