Я пытаюсь написать приложение для Android, которое будет служить, помимо прочего, метроном. Это требует способности периодически воспроизводить различные звуки с точным временем, но на данный момент я работаю над тем, чтобы заставить их работать. Обученный слушатель легко обнаружил ошибку более 2-3 мс. Вот моя воспроизводящая нить:Воспроизведение периодического звука на Android
protected void onCreate(Bundle savedInstanceState) {
// stuff
int minBufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
}
public void startThread(View view){
mThread = new Thread (new Runnable() {
public void run(){
Log.d(TAG, "Starting met at tempo: " + mTempo + " Interval: " + (60000/mTempo));
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
InputStream in = getResources().openRawResource(R.raw.chirp);
byte [] output = getBytesFromStream(in);
Log.d(TAG, "Output length: " + output.length);
mAudioTrack.play();
while (mRunning) {
mAudioTrack.write(output, 0, output.length);
try {
Thread.sleep(60000/mTempo);
} catch (InterruptedException e) {
}
}
mAudioTrack.release();
}
});
mThread.start();
}
R.raw.chirp - синусоидальная структура, генерируемая в Audacity. 1000 Гц, отобранных на 44100 Гц в течение 100 мс, поэтому это должно быть около 4410 образцов. Тестирование этого на Nexus 4 с темпом, установленным на 200bpm (т. Е. Чирп должен воспроизводиться каждые 300 мс), звук оказался хорошим, но для хорошей оценки я записал вывод в Audacity через линейный вход. Я заметил две странности:
1) Чирп, казалось, играл в периоды между 298-299 мс. Это было по большей части последовательным, но что 1-2 мс изменяет темп до 201bpm, что достаточно, чтобы выбить его из синхронизации с эталонным метрономом.
2) Вторая странность не была последовательно повторяемой, но после кажущегося случайного числа чириков был бы один чирп, задерживаемый полными 20 мс.
Второй вопрос, который я мог бы, по-видимому, объяснить; возможно, проблема с потоком/приоритетом? Однако первый вопрос меня озадачивает. Я бы подумал, что если что-нибудь, чириканье должно опоздать, а не рано. Я считаю, что эти проблемы связаны, и я также начинаю думать, что не понимаю, что происходит, и делаю что-то очень простое (это мой первый раз, когда я работаю со звуковым кодом любого типа.)
помощь будет высоко оценена.
Спасибо. Это, в конечном счете, то, что я думал, что мне придется делать, но я хотел посмотреть, что будет с этим делать. Я полагал, что это не сработает, но это особый способ, которым это не работает, что меня смущает. Я предположил, что будет какая-то задержка между записью данных и их прослушиванием, благодаря асинхронному характеру функции.Это не объясняет, почему большая часть ударов выходила последовательно раньше, чем ожидалось. – sigmabeta