Я получил отстранение от всех входов и выходов из работы с Clips
, так как они имеют много раздражающих аспектов.
Но да, как уже упоминалось в комментариях, вы должны инициализировать (открывать) каждый Clip
один раз и только один раз в начале вашей программы. Затем перезапускайте Clip
каждый раз, когда вам это нужно. API покажет вам точные команды для сброса Clip
в начальный кадр и его воспроизведения.
Управление потоками утомительно. Если я правильно понимаю, Clip
запускает поток демона для реального аудио выхода. Потоки демона умирают, когда родительский поток завершается. Следовательно, вы решили добавить команду Thread.sleep () и LineListener
, чтобы сохранить поток живым в течение всего SFX, чтобы его демон не зависал при завершении родительского потока.
Хотя я беспокоюсь, что если вы используете этот подход, вызывающий поток (код, запускаемый нажатием кнопки) не сможет делать что-либо еще в течение периода "сна". Если код кнопки только выполняет воспроизведение, то все будет в порядке. Но что, если позже вы решите, чтобы что-то еще было запущено с помощью того же нажатия кнопки (как анимация зуммера)? Может возникнуть необходимость добавить еще один слой усложнения, например, обернуть клип в еще один поток, единственной обязанностью которого является воспроизведение клипа. Тогда ваше нажатие кнопки может запустить эту оболочку и делать другие вещи, не подвергаясь самому решению Thread.sleep ().
Теперь должно быть возможно избежать всего этого! Допустим, вы сделали Clip
с именем buzzer и открыли его в начале своей программы, удерживая его в переменной экземпляра (как предложил Эндрю). Затем, скажем, вы вызываете buzzer.start () из потока, который остается в живых до бесконечности, такого как классический игровой цикл. Я думаю, что в этом клипе start () запустит поток демона и будет играть до тех пор, пока этот цикл игрового цикла продолжает существовать. Таким образом, вы сможете обойтись без сна и прослушивания линии. Но я не уверен на 100%, не написав пример и не попробовав его сам.
(Как нить кнопки сообщает нити игрового цикла о воспроизведении звука? Возможно, нить кнопки устанавливает флаг, а нить игрового цикла проверяет этот флаг как часть своего обычного цикла «обновления». Хм. Возможно Мне действительно нужно попробовать написать код, прежде чем предлагать его в качестве совета.)
В качестве альтернативы не стесняйтесь изучать код и, возможно, использовать AudioCue . Это похоже на Clip
при загрузке и воспроизведении, но под ним используется SourceDataLine
для вывода вместо Clip
. Если вы посмотрите на код, вы увидите, что SourceDataLine
поддерживается в своем собственном потоке (который остается живым как часть открываемого AudioCue
). Это устраняет много осложнений.
Приятным преимуществом этого подхода является то, что он позволяет обеспечить одновременное воспроизведение, например, если вы хотите запустить второй экземпляр зуммера, пока первый еще воспроизводится. AudioCue
также позволяет вам выполнять такие вещи, как воспроизведение зуммера на разных скоростях, что может быть полезно для того, чтобы ваш SFX звучал как несколько сигналов. Я сделал все возможное, чтобы предоставить документацию и примеры. Лицензия позволяет вам вырезать и вставить код, как лучше всего подходит для ваших конкретных потребностей.