Задержки при воспроизведении 2 звуков одновременно по таймеру

У меня есть небольшое приложение, которое устанавливает таймер и воспроизводит наборы из 2 звуков один за другим.

Я пробовал 2 таймера, потому что хотел, чтобы оба звука каждый раз начинались точно в одно и то же время. Я дал приложению 500 мс для установки обоих таймеров до их запуска.

    Calendar cal = Calendar.getInstance();
    Date start = new Date(cal.getTime().getTime() + 500);

    timerTask1 = new TimerTask() { //1st timer
      @Override
      public void run() {
          soundManager.playSound(1);
      }
    };
    timer1 = new Timer();
    timer1.schedule(timerTask1, start, 550);


    timerTask2 = new TimerTask() { //2nd timer
      @Override
      public void run() {
          soundManager.playSound(2);
      }
    };
    timer2 = new Timer();
    timer2.schedule(timerTask2, start, 550);
}

soundManager — это объект SoundManager, основанный на этом руководстве. . Единственным изменением, которое я сделал, было уменьшение количества доступных потоков с 20 до 2, так как я воспроизводил только 2 звука одновременно.

Теперь проблема. Он не воспроизводится с одинаковой скоростью ни на моем Motorola RAZR, ни на эмуляторе. Приложение иногда тормозит, из-за чего тормозит дольше, чем хотелось бы. Я не могу этого допустить. Что здесь может быть не так?

Я использую очень короткие звуки в формате OGG.

РЕДАКТИРОВАТЬ: я провел некоторое исследование. Использовал 2 подхода. Я измерял миллисекунды расстояния между звуком. Частота обновления составляла 500 мс.

  • Первым подходом был TimerTask - это большой провал. Он начался с 300 мс, затем постоянно рос и через некоторое время (2 минуты) стабилизировался на 497 мс, что было бы просто отлично, если бы оно началось так.
  • 2-й подход был циклом while на AsyncTask - он давал мне результаты от 475 до 500 мс, что лучше, чем TimerTask, но все же неточно.

В конце ни один из подходов не играл гладко. Всегда были задержки


person Jacek Kwiecień    schedule 17.08.2012    source источник
comment
Во-первых, TimerTask не гарантируется в реальном времени, поэтому я вполне могу себе представить, что что-то прерывает ваш процесс в течение 50 миллисекунд между каждым звуком. Во-вторых, кажется, что вызов soundManager.playSound(1);, а затем soundManager.playSound(2); будет воспроизводиться последовательно.   -  person Ken Y-N    schedule 20.08.2012
comment
обратите внимание, что оба звука воспроизводятся из отдельных потоков, поэтому я надеялся, что они начнутся в одно и то же время, поскольку они имеют одинаковое время начала. Что тогда было бы эквивалентно задаче таймера?   -  person Jacek Kwiecień    schedule 20.08.2012
comment
Каков размер каждого файла ogg   -  person Sherif elKhatib    schedule 24.08.2012


Ответы (2)


Я знаю, что это может быть слишком много, но вы можете попробовать другую реализацию SoundPool:

public class Sound {
    SoundPool soundPool;
    int soundID;

    public Sound(SoundPool soundPool, int soundID) {
        this.soundPool = soundPool;
        this.soundID = soundID;
    }

    public void play(float volume) {
        soundPool.play(soundID, volume, volume, 0, 0, 1);
    }

    public void dispose() {
        soundPool.unload(soundID);
    }
}

Чтобы использовать его, вы можете сделать что-то вроде этого:

SoundPool soundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
AssetFileDescriptor assetFileDescriptor = activity.getAssets().openFd(fileName);
int soundID = soundPool.load(assetFileDescriptor, 0);

Sound sound = new Sound(soundPool, soundID);

А потом играть:

sound.play(volume);

P.S. Если проблема сохраняется даже с этим кодом, оставьте комментарий, и я свяжусь с вами.

person dragostis    schedule 26.08.2012
comment
Я думаю, что проблема может быть где-то еще, чем в SoundPool. Согласно этой статье masterex.github.com/archive/ 2012/05/28/ TimerTask не может гарантировать мне выполнение в нужное время... - person Jacek Kwiecień; 26.08.2012
comment
Тогда попробуйте использовать AudioTrack. Возможно, SoundPool недостаточно эффективен. В этом случае AudioTrack будет лучшим выбором: Документация для разработчиков Android Реализация может быть похожа на класс Sound, только для этого нужно немного больше информации. Если у вас есть проблемы с реализацией, я могу помочь. Просто прокомментируйте или PM мне. - person dragostis; 26.08.2012
comment
martinhoeller.net/2012/01 /13/ нашел этот хороший туториал, сделал все как там написано. В основном все те же лаги. Я думаю, дело не в диспетчере звука, а в цикле. Я не знаю, как это исправить. Я добавил примечания в вопрос - person Jacek Kwiecień; 27.08.2012
comment
Возможно, вам следует попробовать Fork/Join из Java 7: Java Docs - person dragostis; 27.08.2012
comment
Наконец попробовал подход, который вы опубликовали, но результат тот же. Разветвить/присоединиться к Java7? Я не думаю, что Android 2.1 имеет это ...? - person Jacek Kwiecień; 29.08.2012
comment
Если у вас Java 7, если вы будете использовать библиотеки из Java 7, значит, их можно использовать. Просто посмотри. Я дал вам ссылку. Поищите в Google дополнительную информацию о Fork/Join. - person dragostis; 29.08.2012
comment
Я не думаю, что использование другой системы потоков поможет. Цикл, который я создал, довольно точен. Запаздывает сам звук. В образце метронома его разработчик создал постоянный AudioTrack из звука и правильного времени тишины.. Я думаю, что это может быть единственный способ... однако я не уверен, что это выполнимо для набора из 5 звуков. - person Jacek Kwiecień; 29.08.2012

Вы используете Саундпул? Это быстрее, чем MediaPlayer. Лучший шанс собрать два звука вместе — это воспроизвести их в одном потоке.

person Sameer    schedule 24.08.2012
comment
Да, я использую саундпул. я выложил по ссылке - person Jacek Kwiecień; 24.08.2012