android - Android AudioTrack类,用于播放钢琴声音

标签 android audio stream audiotrack

我正在尝试实现一个钢琴应用程序,在该应用程序中用户可以在显示屏上显示的虚拟钢琴上弹奏。由于等待时间短,我试图使用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;
    }
}

如果有人可以帮助解决此问题,那就太好了,例如使用流模式而不是静态模式,在这种模式下,声音会被预处理,或者将空字节缓冲区写入音轨,然后单击按钮,将哈希图声音流式传输到音轨。

最佳答案

我认为您应该看看SoundPool并使用它。它似乎是专门为执行您想做的事情而设计的。它不适用于动态生成的声音,但是由于您正在弹钢琴,因此我假设您还是将样本作为WAV文件保存在SDCard上。

使用播放速度,您可以更改音调:以两倍的速度= 1个 Octave 向上播放,以一半的速度= 1个 Octave 向下播放。您稍后可能要使用更精致的方法:)

关于android - Android AudioTrack类,用于播放钢琴声音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12373143/

相关文章:

java - 如何将下面显示的结果转换为 ListView?

android - 我想播放我的 Assets 或原始文件夹中的视频

ios - 将数据传递到我的自定义NSObject?

c - c中的匿名流

flutter - 如何从Firestore制作父/子对象流

Android开发,如何获取大概坐标?

java - Android Activity 生命周期 --- 如何在重新启动 Activity 时重置变量?

ios - 从服务器流式传输 .caf 音频文件

c - 噪音消除设置 - 智能地组合麦克风的信号

node.js - NodeJS 和 Node-webkit 文件上传有进度