Воспроизведение звука каждые N миллисекунд - PullRequest
12 голосов
/ 16 мая 2011

Я разрабатываю приложение метронома. Пользователь может выбрать во время выполнения bpm, и мое приложение будет воспроизводить звук «тика» соответственно. «Тик» - это одиночный метрономный «выстрел» (mp3). Я пытался реализовать его с помощью Handler и MediaPlayer, но метроном не совсем точен. Поэтому я подумал об изменении всего подхода: когда пользователь выбирает новое значение ударов в минуту, я синтезирую новый звук, повторяя тиковый звук X раз каждые N миллисекунд, а затем циклически повторяя созданный во время выполнения звук. Это действительная альтернатива? Как это можно реализовать в Android?

Ответы [ 3 ]

6 голосов
/ 22 мая 2013

Альтернатива зацикливания синтезированного звука, кажется, на данный момент является лучшим выбором.В Google I / O 2013 состоялся замечательный сеанс аудио, который называется High Performance Audio , и я бы посоветовал посмотреть, чтобы глубже понять, как работает система и какие проблемы возникают у разработчиковбудет сталкиваться при работе с задержкой звука.Примерно в 17:00 видео показывает график, показывающий джиттер в сравнении с обратными вызовами.В идеальном мире, который не существует (о, правда?), Дрожание будет равно нулю для всех запланированных обратных вызовов.Но это не так, поскольку дрожание достигает 35 миллисекунд или даже больше, поскольку данные на графике были получены с использованием неуказанного устройства ICS, и сценарии, безусловно, хуже, чем это.

Итак,поскольку метроном является точным инструментом, а эти дрожания совсем не хороши, подход к воспроизведению по расписанию следует оставить в стороне.Я даже сделал вполне реальную работу метронома с синтезированным звуком, используя AudioTrack.

Надеюсь, это поможет ^^

1 голос
/ 16 мая 2011

Вы можете попробовать использовать TimerTask , запланированный для с фиксированной скоростью выполнение на Таймер .

Timer и TimerTask являются частью Android SDK (и Java SE). Выполнения не задерживаются из-за времени выполнения предыдущего события.

Timer timer = new Timer("MetronomeTimer", true);
TimerTask tone = new TimerTask(){
     @Override
     public void run(){
         //Play sound
     }
};
timer.scheduleAtFixedRate(tone, 500, 500); //120 BPM. Executes every 500 ms.

Затем вы можете отменить TimerTask, когда вам нужно изменить BPM.

tone.cancel();
tone = new TimerTask(){...}
timer.scheduleAtFixedRate(tone, 1000, 1000); //60 BPM. Executes every 1000 ms.

Еще одна возможность, которая может удовлетворить ваши требования (из ваших комментариев), - это вращать поток и проверять System.nanoTime () и спать с шагом, но вращаться, когда вы приближаетесь к пробуждению.

long delayNanos = 500000000;
long wakeup = System.nanoTime() + delayNanos; //Half second from right now
long now;

while(!done){
     now = System.nanoTime();

     //If we are less than 50 milliseconds from wake up. Spin away. 
     if(now <= wakeup - 50000000){
          //Sleep in very small increments, so we don't spin unrestricted.

          Thread.sleep(10); 
     }
     if(now >= wakeup){
           //Play sound
           wakeup += delayNanos;
     }
}
0 голосов
/ 07 января 2016

Когда этот звук воспроизведения называется

mSoundManager.playSound(1);

Android ждет завершения вызова, а затем вы звоните

mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200);

однако, если вы отмените эти вызовы, вы можете обнаружить, что время более точное.

mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200);
mSoundManager.playSound(1);

Вы не можете рассчитывать на то, что ваш звук занимает ровно столько же времени для воспроизведения, поэтому лучше сказать обработчику публиковать сообщение первым. Однако все еще не идеал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...