Вот представление связанного кода, адаптированного для API уровня 23+, с добавленным параметром для длительности тона:
short generatedSnd[];
int sampleRate = 44100;
float freqOfTone = 1000; //Hz
float amplitude = 10000; //0..32767 (0x7FFF)
float lengthSeconds = 1.0f;
private void genTone(){
int numSamples = (int) (sampleRate * lengthSeconds);
generatedSnd = new short[numSamples];
// fill out the array
for (int i = 0; i < numSamples; ++i) {
generatedSnd[i] = (short) (Math.sin(2 * Math.PI * i / (sampleRate/freqOfTone)) * amplitude);
}
}
private void playSound(){
AudioTrack audioTrack = new AudioTrack.Builder()
.setAudioFormat(
new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setSampleRate(sampleRate)
.setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
.build()
)
.setTransferMode(AudioTrack.MODE_STATIC)
.setBufferSizeInBytes(generatedSnd.length * 2) //2 bytes-per-sample
.build();
audioTrack.write(generatedSnd, 0, generatedSnd.length);
audioTrack.play();
}
Этот код был протестирован до 50 с в эмуляторе, но он может зависнуть при большем времени воспроизведения из-за размера, передаваемого на setBufferSize()
. Обратите внимание, что он не включает другие расширенные функции, помогающие вам обрабатывать произвольно длительное время воспроизведения, например 1.) потоковое воспроизведение или 2.) фазовая коррекция из-за float
ошибок квантования при значениях, далеких от 0.
Однако он должен нормально работать в течение менее 10 секунд.
Также не указан код очистки AudioTrack (stop()
/ release()
).