2010-05-08 6 views
1

есть приложение, которое обрабатывает данные в реальном времени и должно звучать, когда происходит определенное событие. Событие триггера может происходить несколько раз в секунду, и если звуковой сигнал уже воспроизводится, когда другое событие запускает код, он просто должен игнорировать его (в отличие от прерывания текущего звукового сигнала и запуска нового). Вот основной код:Мне нужно закрыть аудиоклип?

Clip clickClip 

public void prepareProcess() { 
    super.prepareProcess(); 

    clickClip = null; 

    try { 
     clipFile = new File("C:/WINDOWS/Media/CHIMES.wav"); 
     ais = AudioSystem.getAudioInputStream(clipFile); 
     clickClip = AudioSystem.getClip(); 
     clickClip.open(ais); 

     fileIsLoaded = true; 

    } catch (Exception ex) { 
     clickClip = null; 
     fileIsLoaded = false; 
    } 
} 

public void playSound() { 

    if (fileIsLoaded) { 

     if ((clickClip==null) || (!clickClip.isRunning())) { 

      try { 
       clickClip.setFramePosition(0); 
       clickClip.start(); 
      } catch (Exception ex) { 
       System.out.println("Cannot play click noise"); 
       ex.printStackTrace(); 
      } 
     } 
    } 

Метод prepareProcess получает запустить один раз в самом начале, и метод PlaySound вызывается каждый раз, когда происходит событие запуска. Мой вопрос: мне нужно закрыть объект clickClip? Я знаю, что могу добавить actionListener для мониторинга события Stop, но так как событие происходит так часто, я беспокоюсь о том, что дополнительная обработка замедлит сбор данных в режиме реального времени.

Код, кажется, работает нормально, но мое беспокойство - утечка памяти. Вышеприведенный код основан на примере, который я нашел при поиске в сети, но в примере использовался actionListener для закрытия Clip специально «для устранения утечек памяти, которые могут возникнуть, когда метод остановки не был реализован». Моя программа предназначена для работы в течение нескольких часов, поэтому любые утечки памяти, которые у меня возникают, вызовут проблемы.

Я буду честен: я понятия не имею, как проверить, есть ли у меня проблема. Я использую Netbeans, и запуск профилировщика памяти просто дал мне огромный список вещей, которые я не знаю, как читать. Это должно быть простой частью программы, и я трачу на нее часы. Любая помощь будет принята с благодарностью!

Майкл

ответ

0

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

В вашем коде ничего похожего не происходит. Поскольку prepareProcess() работает только один раз, это не очень подозрительно. Это оставляет playSound(), который вообще не содержит каких-либо объектов, а тем более недействительный цикл исключения ссылок.

Предостережение в том, что я не уверен, что происходит за кулисами в объекте звукового клипа, и его трудно проверить, потому что majuscule-C Clip - это только интерфейс. Однако, если вы используете сторонний код, я был бы очень удивлен, обнаружив там утечку.

Короткий рассказ, Я бы не стал беспокоиться об этом, пока и пока вы не увидите что-то вроде OutOfMemoryError.

+0

Большое спасибо за ответ. Я согласен с вами в том, что, основываясь на коде, который я даю, это не кажется проблемой. Но (как вы говорите) я не знаю, что происходит за кулисами объекта Clip.Обманывая больше с помощью профилировщика памяти Netbeans, кажется, что каждый новый объект выделяется каждый раз при воспроизведении звука. Тем не менее, колонка «Живой объект» никогда не увеличивается, поэтому я предполагаю, что это означает, что сбор мусора позаботится об этом немедленно. Странное поведение, но я обязательно буду следить за ним во время тестирования, чтобы убедиться, что все в порядке. Еще раз спасибо. Michael – Michael

4

да, закрытие необходимо

myClip.addLineListener(new LineListener() { 
    public void update(LineEvent myLineEvent) { 
     if (myLineEvent.getType() == LineEvent.Type.STOP) 
     myClip.close(); 
    } 
    }); 

или

if (!myClip.isRunning()) 
    myClip.close(); 

В моем приложении (написано до появления util.concurrent), это механизм закрытия зажима.

public static final Vector<Clip> vector = new Vector<Clip>(); 
    static final int vector_size = 5; 

    // typically called before calling play() 
    static synchronized void consolidate() { 
    while (vector_size < vector.size()) { 
     Clip myClip = vector.get(0); 
     if (myClip.isRunning()) 
     break; 
     myClip.close(); 
     vector.remove(0); 
    } 
    if (vector_size * 2 < vector.size()) 
     System.out.println("warning: audio consolidation lagging"); 
    } 

    public static void play(final File myFile) { 
    try { 
     AudioInputStream myAudioInputStream = AudioSystem.getAudioInputStream(myFile); 
     final Clip myClip = AudioSystem.getClip(); 
     vector.add(myClip); 
     myClip.open(myAudioInputStream); 
     myClip.start(); 
    } catch (Exception myException) { 
     myException.printStackTrace(); 
    } 
    } 

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

+1

В чем причина вашего ответа? почему это необходимо? Каковы преимущества? – pstanton

+0

Если вы не закрываете клипы, все будет хорошо, пока ваша программа не выйдет из-за нехватки памяти. это приложение, в котором я столкнулся с этой проблемой: [link] (http://www.youtube.com/watch?v=3F06TdnnOjQ) – datahaki

+0

интересный. Я обнаружил, что закрывающие клипы будут дорогими, и когда это делается во время активного воспроизведения (с использованием другого клипа), происходит задержка. я должен будет проверить сборку мусора теории re, и, возможно, закрыть клипы навалом, если все аудиовоспроизведение бездействует. вы заметили задержки при закрытии и как вы преодолели это? – pstanton

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