2012-09-11 48 views
0

即时尝试实现钢琴应用程序,用户可以在显示器上显示的虚拟钢琴上播放。由于尝试使用AudioTrack Class的低延迟,这会造成很大的麻烦。我的问题是快速播放声音。目前我使用按钮来测试它。如果我按下按钮快,我得到这个例外:用于播放钢琴声音的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(....),然后写(...)和播放(...)

我认为它不能实例化速度不够快,因此例外...

下面的代码:这些声音都存储在一个HashMap在不同的异步任务类

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,然后在按钮上单击hashmap声音流式传输到音频跟踪。

回答

1

我想你应该看看SoundPool并使用它。它似乎专门设计用来完成你想要做的事情。它不适用于动态生成的声音,但是因为您正在弹钢琴,所以我假设您将样本作为SDCard上的WAV文件进行处理。

使用播放速度,您可以更改音高:以倍速播放= 1倍频程,半速度= 1倍八度音程。您可能希望稍后使用更精细的方法:)

+0

嗨,感谢您的回复。但我也需要一个器官的循环功能。而且由于每个循环开始之间的差距,soundpool中的循环函数并不是我正在寻找的。因此我不得不使用像audiotrack或ndk这样的较低级别的类。在audiotrack中设置回放速度时,我还遇到了android ics的问题(点击噪音)。我仍然在寻找其他图书馆...... – sNore