SoundManager2 имеет нерегулярную задержку - PullRequest
4 голосов
/ 16 марта 2010

Я играю несколько нот на регулярной основе. Каждый из них задерживается на случайное количество миллисекунд, создавая резкий нерегулярный эффект. Как мне это исправить?

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

Ответы типа «реализовать собственную небольшую замену SoundManager2, оптимизированную для воспроизведения, чувствительного к времени», в порядке, если вы знаете, как это сделать :), но сейчас я стараюсь не переписывать все мое приложение во Flash.

Пример приложения с нулевой слышимой задержкой см. На основе флэш-памяти ToneMatrix .

TestCase ( посмотрите здесь в прямом эфире или получите в виде почтового индекса ):

<head>
<title></title>
<script type="text/javascript" 
src="http://www.schillmania.com/projects/soundmanager2/script/soundmanager2.js">
</script>
<script type="text/javascript">
soundManager.url = '.'
soundManager.flashVersion = 9
soundManager.useHighPerformance = true
soundManager.useFastPolling = true
soundManager.autoLoad = true

function recur(func, delay) {
    window.setTimeout(function() { recur(func, delay); func(); }, delay)
}

soundManager.onload = function() {
    var sound = soundManager.createSound("test", "test.mp3")
    recur(function() { sound.play() }, 300)
}
</script>
</head>
<body>
</body>
</html>

Ответы [ 4 ]

10 голосов
/ 28 мая 2010

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

Для всех, кто сказал: "У меня это работает нормально!" попробуйте изменить размер или переместить окно браузера, когда демонстрация плаката закончится. Вы услышите больше, чем просто небольшую задержку. Это наиболее заметно в Firefox и IE, но даже Chrome это почувствует.

Что еще хуже, если вы нажмете и будете удерживать мышь в поле закрытия окна браузера, звук полностью остановится, пока вы не отпустите кнопку мыши (вы можете отпустить ее за пределами окна закрытия и фактически не закрывать окно, к вашему сведению ).

Что здесь происходит?

Оказывается, что когда вы начинаете изменять размер или перемещаться по окну браузера, браузер пытается выполнить несколько задач, связанных с изменением свойств окна, с тем, чтобы не отставать от сценария JavaScript, происходящего в окне. Он сокращает окно, когда это необходимо.

Когда вы удерживаете мышь над окном закрытия в окне браузера, время полностью останавливается. Это то, что происходит с меньшими приращениями, когда вы изменяете размер или перемещаете окно: время в мире javascript стоит на месте небольшими, единичными частями (или большими частями, в зависимости от того, насколько медленна ваша машина).

Теперь вы можете сказать: «Конечно, изменение размера браузера или удерживание кнопки закрытия приводит к приостановке работы браузера, но обычно этого не происходит». К сожалению, вы были бы не правы.

Это происходит постоянно, на самом деле. Я запустил тесты, и оказалось, что даже если оставить окно браузера полностью неподвижным, не касаясь мыши и не касаясь клавиатуры, фоновые процессы на компьютере могут все еще вызывать «икоты», что означает, что в течение коротких периодов времени (возможно, всего несколько миллисекунд) время в браузере «стоит на месте» с совершенно случайными интервалами вне вашего контроля.

Что я подразумеваю под "стоять на месте"? Допустим, у вас есть вызов setInterval () (это относится и к setTimeout), который выполняется каждые 33 миллисекунды (около 30 кадров в секунду). Теперь вы ожидаете, что через каждые 33 миллисекунды "реального мира" будет вызываться ваша функция. И в большинстве случаев это правда.

Но когда начинают происходить «икоты», ваш вызов setInterval может произойти за 43 миллисекунды. Что произошло за 10 мс? Ничего такого. Время остановилось. В браузере ничего не обновлялось. Если у вас воспроизводился звук, он продолжит воспроизведение, но никакие НОВЫЕ звуковые вызовы не начнут воспроизводиться, потому что JavaScript вообще не выполняется. Если бы у вас было 5 запущенных функций setInterval (), все они были бы приостановлены на 10 мсек в какой-то момент.

Единственный способ сказать, что «время остановилось» - это опросить реальное время в ваших обратных вызовах функции setInterval. Вы сможете увидеть, что браузер пытается поддерживать большую часть времени, но когда вы начнете изменять размер окна или делать что-то стрессовое, интервалы будут длиннее, чем обычно, но весь ваш код останется синхронизированным (Я создаю игры, используя эту технику, так что вы увидите, что все ваши обновления игр происходят синхронно, но только слегка заикаются).

Обычно я должен отметить, что эти заикания совершенно незаметны, и если вы не напишите функцию для записи реального времени во время setInterval (как я делал в моем собственном тестировании), вы даже не узнаете об этом. Но это становится проблемой, если вы пытаетесь создать некоторый тип повторяющегося звука (например, звуковой сигнал на фоне Астериодов), используя повторяющиеся вызовы play ().

Мое предложение? Если у вас есть звук, который, как вы знаете, будет зацикливаться, дайте ему большую длительность, может быть, 10 секунд, и вы с меньшей вероятностью заметите икоту (теперь графика на экране все еще может сбиваться, но вы облажались) ).

Если вы пишете игру и у главного героя стреляют из пулемета, не делайте 10 быстрых вызовов последовательности к playSound ('singleShot'), не делайте один вызов playSound ('machineGunFire10Rounds') или что-то вдоль этих линий.

Чтобы обойти это, вам придется проделать некоторую хитрость, но в большинстве случаев все будет в порядке.

Похоже, что апплеты Flash выполняются в процессе, который как-то менее подвержен влиянию всего этого «замораживания времени», происходящего в обычной среде браузера / javascript, но я все еще могу добиться этого даже по вашей ссылке на ToneMatrix Например, изменив размер или переместив окно браузера.

Но Flash все еще выглядит намного лучше, чем javascript. Когда я оставлю браузер в покое, я буду готов поспорить, что Flash не зависает в течение какого-то времени и интервалы всегда работают вовремя.

ТЛ; др:

  • вы ввернуты в то, что вы надеетесь достичь
  • попробуйте разобраться с этим, используя некоторые обходные пути
  • переписать ваш проект на чистом flash (без JavaScript)
  • ждите, пока браузеры станут лучше (Firefox 4 получает новый движок javascript под названием JaegerMonkey , который будет интересно посмотреть)
  • откуда мне все это знать? Я провел много тестов и логов с аудио-вызовами javascript, setInterval и soundManager / html5
1 голос
/ 25 марта 2010

В своем комментарии к вашему вопросу я упомянул, что не слышу неровностей при воспроизведении вашего семпла. Это означает, что я либо «глухой к ритму», либо в вашей настройке может быть что-то, что мешает хорошей производительности в реальном времени. Вы не упоминаете какие-либо подробности своей среды, но на вашем компьютере могут быть запущены другие процессы, которые загружают циклы ЦП, или более старая версия Flash, которая может не справляться с задержками звука. Я сам использую последнюю версию Flash (10. что-то), тогда как ваши параметры требуют Flash 9. Но, возможно, я должен предположить, что если вы достаточно умны, чтобы использовать SoundManager2 и StackOverflow, то вы бы устранили эти проблемы.

Итак, вот некоторые возможные способы устранения неполадок и комментарии, которые приходят на ум:

1) На сайте SoundManager есть несколько демонстраций, включая JS-DOM "painting" + Sound, V2 . Вы слышите нерегулярные задержки и задержки? Если нет, возможно, вы можете сравнить, что они там делают, с тем, что вы делаете. Если да, то, возможно, посмотрите на вашу машинную среду. Когда я запускаю эту демонстрацию, она очень отзывчива. ( РЕДАКТИРОВАТЬ: Однако при более внимательном рассмотрении вы можете наблюдать, как изменяется размер штампов кисти во время обводки. Поскольку он изменяется в зависимости от временного интервала между событиями мыши (при условии, что вы удерживаете постоянную мышь) скорость), вы можете визуально увидеть любые неровности в шаблоне событий мыши. Я вижу случайные изменения в размерах штампов, которые указывают на то, что события мыши не приходят в обычное время. Что приводит нас к событиям Javascript.)

2) Javascript setTimeout() и setInterval() не очень надежны в отношении времени. По большей части они возвращаются на каком-то приблизительном интервале запрошенного вами интервала, но могут быть большие вариации, обычно задержки, которые делают их ненадежными. Я обнаружил, что то же самое верно при использовании ActionScript внутри Flash. Возможно, вы захотите распечатать время выполнения вашего вызова sound.play (), чтобы увидеть, связаны ли эти ошибки с нарушениями в setTimeout/setInterval(). Если это так, вы можете попытаться сократить интервал, а затем опрашивать системное время, чтобы приблизиться к желаемому интервалу в 300 мс. Вы можете опросить системное время, используя new Date().getTime(), и это, похоже, имеет мс точность. Опрос - это, конечно, отвратительный хак, который засасывает циклы, когда их можно использовать для чего-то другого, и я не рекомендую его вообще, но вы можете попробовать его, чтобы посмотреть, поможет ли это. EDIT: Вот запись Джона Резига об обработке событий ввода и таймера в js .

3) Когда флеш воспроизводит звуки, обычно возникает задержка, просто чтобы игрок мог «нарастить напор» и убедиться, что в буфере достаточно материала для воспроизведения до того, как будет заполнен следующий запрос буфера. , Существует компромисс между этой задержкой и надежностью непрерывного воспроизведения. Это может быть ограничением, с которым вы ничего не можете сделать, за исключением «внедрения [вашей] небольшой замены SoundManager2», что, я знаю, вы не хотите делать.

Надеюсь, это поможет. Недавно я написал звуковой эксперимент для AS3, который познакомил меня с некоторыми основами, и я буду наблюдать за этим пространством, чтобы увидеть, какие другие предложения приходят людям.

0 голосов
/ 31 мая 2013

Как объяснено в другом ответе, вы никак не можете этого избежать. Но ...

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

Взгляните на источник на прототипе демо, и (если возможно) сделайте выстрел с низкой задержкой. Это хорошо сработало для меня.

Удачи!

0 голосов
/ 23 марта 2010

Вы используете интервал javascript, который не может быть гарантированно сработал в точное время. Я уверен, что внутренняя синхронизация с Flash более надежна.

Но это может помочь, огонь возобновится ПОСЛЕ того, как вы запустили воспроизведение звука.

window.setTimeout(function() { func(); recur(func, delay); }, delay);
...