Java 运行线程时Android Studio应用程序崩溃

Java 运行线程时Android Studio应用程序崩溃,java,multithreading,android-studio,audio,audiotrack,Java,Multithreading,Android Studio,Audio,Audiotrack,首先,我要声明,我对Android Studio和Java脚本非常陌生,编程甚至不是我的专长。然而,我正在尝试开发一个音频合成器应用程序,虽然我可以让一切正常工作,但我无法让音频流。基本上,我可以在静态模式下使用AudioTrack播放计算出的声音波形长达10秒,但是,我不能动态播放多个按键(我在应用程序上设置了一个2倍频程25键键盘),我也不能长时间按住一个键。我有一个长度滑块,可以将播放的音符的持续时间从0.1秒调整到10秒。我希望能够一次按下多个键,同时长时间按住一个键,让应用程序连续输出

首先,我要声明,我对Android Studio和Java脚本非常陌生,编程甚至不是我的专长。然而,我正在尝试开发一个音频合成器应用程序,虽然我可以让一切正常工作,但我无法让音频流。基本上,我可以在静态模式下使用AudioTrack播放计算出的声音波形长达10秒,但是,我不能动态播放多个按键(我在应用程序上设置了一个2倍频程25键键盘),我也不能长时间按住一个键。我有一个长度滑块,可以将播放的音符的持续时间从0.1秒调整到10秒。我希望能够一次按下多个键,同时长时间按住一个键,让应用程序连续输出声音。我做了一些研究,似乎实现这一点的最佳方式是使用AudioTrack库的“流”模式,并使用线程?我对库、线程甚至语言都很不熟悉

我遵循提供的音频流教程,只是尝试了一种稍有不同的方法,我相信这种方法在我的情况下会更好。我已经在下面发布了我的测试代码(请注意,这不是我播放不同声音的全部代码,而是只有一个按键设置(c4)的最小值),我正试图让它持续播放声音。当我第一次按下键时,只要我一直按住键,它就会播放声音。但是,在我松开键并再次按下后,应用程序就会崩溃。我不太清楚为什么会发生这种情况。我尝试了不同的方法,例如调用“audioThread.start()”函数只有一次,或者尝试停止线程,但我没有成功。如果我只调用了“audioThread.start()”函数一次,当我再次按下该键时,应用程序不会崩溃,但它也不会播放声音。当它播放声音时,如果我再次按下该键,应用程序会崩溃

我也给出了我上面问题的全部范围,因为我也不确定使用线程是否是最好的方法。理想情况下,我希望这样我可以按下键盘上的25个键中的任何一个键,音频库将同时播放按下的键的声音,如果不按下任何键,则不会输出任何内容。我不喜欢运行25个不同线程的想法,因为我的音频缓冲区是在每个线程中设置的,如果我一次播放多个音符,我认为这会覆盖以前的缓冲区?如果你认为我在这里使用线程的目标应用程序的方向错了,请告诉我。我认为线程会更好,因为在流式传输音频之前,我确实需要做大量的计算(最多25 x 6 x 3=450次触发操作来计算我的一个波形样本),因此我认为以某种方式管道化计算会更好

不管是哪种方式,请让我知道为什么我在第二次按键时无法获得下面的测试设置来播放声音?如果这是相关信息,我也在使用Lenovo tabM10 FHD Plus。这也是我第一次使用stackOverflow,所以如果我在格式化我的帖子方面做得很糟糕,我深表歉意。如果你认为我应该编辑我的帖子以请更简洁/清楚地说明我的问题,请让我知道,我会解决它。对于给您带来的不便,我深表歉意

我的测试代码:

package com.example.ece496_simplesynth;
导入androidx.annotation.RequiresApi;
导入androidx.appcompat.app.appcompat活动;
导入androidx.core.view.MotionEventCompat;
导入android.graphics.Color;
导入android.media.AudioFormat;
导入android.media.AudioManager;
导入android.media.AudioTrack;
导入android.os.Build;
导入android.os.Bundle;
导入android.view.MotionEvent;
导入android.view.view;
公共类MainActivity扩展了AppCompatActivity{
私人音轨;
私有int-intBufferSize;
私人短[]短音频数据;
private boolean isActive=false;
私有线程;
私有布尔键压=false;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
最终视图c4=(视图)findViewById(R.id.c4);
c4.setOnTouchListener(新视图.OnTouchListener(){
@凌驾
公共布尔onTouch(视图、运动事件、运动事件){
int action=motionEvent.getAction();/.getActionMasked(motionEvent);
if(action==MotionEvent.action\u DOWN){
c4.setBackgroundColor(Color.parseColor(#ed1b24”);/“#81DAF5”
按键=真;
audioThread.start();
}
else if(action==MotionEvent.action\u UP){
c4.设置背景颜色(Color.parseColor(#FFFFFF”);
keyPress=false;
//audioThread.stop();
}
返回true;
}
});
audioThread=新线程(新可运行(){
@RequiresApi(api=Build.VERSION\u code.LOLLIPOP)
@凌驾
公开募捐{
threadLoop();
}
});
}
@RequiresApi(api=Build.VERSION\u code.LOLLIPOP)
私有void threadLoop(){
int intSampleRate=AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
intBufferSize=AudioTrack.getMinBufferSize(intSampleRate,AudioFormat.CHANNEL\u OUT\u MONO,AudioFormat.ENCODING\u PCM\u 16位);
shortAudioData=新的short[intBufferSize];
audioTrack=新的audioTrack(AudioManager.STREAM_MUSIC,
邀请,
AudioFormat.CHANNEL\u OUT\u MONO,
AudioFormat.ENCODING_PCM_16位,
intBufferSize,
音频跟踪模式(音频流);