2010-06-21 2 views
2

Я вижу странное поведение с экземплярами Clip на Java.Захват аудиозахвата

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

  • Сортировать по воспроизводимый в настоящее время клипы взвешенной суммы PAN и framePosition.
  • Выберите клип с максимальным значением, которое будет остановлено и перезапущено.
  • Повторно запустить клип (следующий метод):

void restart(Clip clip, float gain, float pan) { 
    clip.stop(); 
    clip.flush(); 
    pan = Math.max(-1f, Math.min(pan, 1f)); 
    ((FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN)) 
         .setValue(gain); 
    ((FloatControl) clip.getControl(FloatControl.Type.PAN)) 
         .setValue(pan); 
    clip.setFramePosition(0); 
    clip.start(); 
} 

Странное поведение имеет место, если этот метод вызывается много раз в быстрой последовательности (например, 20 раз в течение 1 мс):

  • Клип играет
  • Зажигает событие START, чтобы сообщить, что он начал играть
  • Клип никогда не запускает событие STOP.
  • Последующие вызовы stop и start не имеют никакого эффекта (но не бросать исключения.)
  • getFramePosition всегда возвращает 0, даже когда клип слышно (в последний раз.)

Любая идея может быть причиной этого?

Я не думаю, что это проблема многопоточности (по крайней мере, не в моем коде.) Только один поток вызывает публичные методы моего класса (и все они synchronized так или иначе)


Может быть связанные с this bug.

+0

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

+0

@mdma, я попробую это, но я был бы удивлен, если бы это имело значение. 'restart' вызывается только из другого метода' synchronized'. – finnw

ответ

1

Вызовы DataLine.start и DataLine.stop являются уже синхронизированы на смесителе DataLine «s внутри AbstractDataLine.

Я сильно подозреваю, что somewehere вниз в стеке вызовов (ниже implStart()/implStop() из любой DataLine воплощение вы получили, скорее всего, в родной nStart/nstop) по меньшей мере, одного асинхронного вызова производится, таким образом, в результате чего в условиях гонки вы наблюдаете.

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

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

Для того, чтобы выполнить вышеупомянутое более глубокое исследование, нужно было бы знать, на какой платформе вы находитесь, а также подтверждение фактических (реализации) имен классов ваших и Mixer экземпляров.

UPDATE

Параллельно, пожалуйста, используйте самоанализа, чтобы установить com.sun.media.sound.Printer.trace = true (или обеспечить свою собственную реализацию com.sun.media.sound.Printer в CLASSPATH.)

По существу DirectClip.open() spawnsthread, который получает доступ к нескольким volatile variables (из особого интереса существа doIO) небезопасным образом, что может привести к зависанию основного витка воспроизведения.

Вы можете подтвердить (или немощных) это (в сочетании с Printer следов), заставляя thread dump в момент кажущегося откосе, и осматривая воспроизведение состояние потока/трассировки стека (или использовать отладчик.)

Если doIO и т. Д. Доступ получается не, чтобы быть проблемой, а затем продолжать копать в собственных реализациях, это все еще нужно; если doIO и т. д. доступ делает, то это проблема, опять же, нет легкого исправления (вы можете попытаться использовать интроспекцию, чтобы захватить DirectClip.thread и периодически сигнализировать об этом в случае, если она заглохнет из-за doIO - снова, будет подтверждено .)

+0

Микшер - это 'com.sun.media.sound.DirectAudioDevice', а клип -' com.sun.media.sound.DirectAudioDevice.DirectClip'. – finnw

+0

... и платформа ...? :) – vladr

+0

Romascanul, Первоначально на Windows XP. Воспроизводится на Vista (но это происходит реже в Vista, чем на XP). Не удалось воспроизвести на Ubuntu, но это было запущено на нетбуке с одним ядром процессора (что может замаскировать проблему, если это проблема с потоками в библиотеке.) – finnw

Смежные вопросы