我的Android操作系统是Android M. Nexus 6。
我将AndroidSpeakerWriter
实现为
public class AndroidSpeakerWriter {
private final static String TAG= "AndroidSpeakerWriter";
private AudioTrack audioTrack;
short[] buffer;
public AndroidSpeakerWriter() {
buffer = new short[1024];
}
public void init(int sampleRateInHZ){
int minBufferSize = AudioTrack.getMinBufferSize(sampleRateInHZ,
AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHZ,
AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize,
AudioTrack.MODE_STREAM); // 0-static 1-stream
}
public void fillBuffer(short[] samples) {
if (buffer.length<samples.length) {
buffer = new short[samples.length];
}
System.arraycopy(samples, 0, buffer, 0, samples.length);
}
public void writeSamples(short[] samples) {
fillBuffer(samples);
audioTrack.write(buffer, 0, samples.length);
}
public void stop() {
audioTrack.stop();
}
public void play() {
audioTrack.play();
}
}
然后我点击按钮时发送样本
public void play(final short[] signal) {
if (signal == null){
Log.d(TAG, "play: a null signal");
return;
}
Thread t = new Thread(new Runnable() {
@Override
public void run() {
android.os.Process
.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
androidSpeakerWriter.play();
androidSpeakerWriter.writeSamples(signal);
androidSpeakerWriter.stop();
}
});
t.start();
}
问题是每次单击按钮时设备都不会发出蜂鸣声。 有时候它有效,有时则不然。 当我在旧的nexus galaxy手机安卓4.3上运行时没有这样的问题。有人遇到过类似的问题吗?提前感谢您的帮助。
有一点是,目前我的嘟嘟声非常短(256个样本),甚至不接近minBufferSize
。
静态模式的bufferSizeInBytes
构造函数中的AudioTrack
应该是您根据模糊document想要播放的音频样本长度。
那么即使对于静态模式,它仍然对缓冲区有最小的大小约束吗?为什么nexus galaxy可以在静态模式下播放256个样本音频而nexus 6不能播放。
我使用AudioManager
来获取本机缓冲区大小/采样率
nexus galaxy:144/44100 nexus 6:192/48000
我找到了那些相关的:
答案 0 :(得分:0)
我认为这是由线程之间的不正确同步引起的。您的androidSpeakerWriter
实例分别在不同的线程调用play()
,writeSamples()
,stop()
中不断运行。单击按钮将触发创建具有相同androidSpeakerWriter
实例的新线程。
因此,当线程A正在执行androidSpeakerWriter.play()
时,线程B可能正在执行androidSpeakerWriter.writeSamples()
,这可能会覆盖正在播放的当前音频数据。
尝试
synchronized(androidSpeakerWriter) {
androidSpeakerWriter.play();
androidSpeakerWriter.writeSamples(signal);
androidSpeakerWriter.stop();
}
如果您必须播放不适合内存的长音频数据,则使用 MODE_STREAM
。如果您需要播放短音频文件,如哔声,则可以在创建AudioTrack时使用MODE_STATIC
。然后更改播放代码,如下所示:
synchronized(androidSpeakerWriter) {
androidSpeakerWriter.writeSamples(signal);
androidSpeakerWriter.play();
}