2013-11-10 3 views
2

Я использую JLayer для декодирования MP3 и сохраняю его как данные PCM. Однако, независимо от того, какой файл MP3 я использую, я всегда получаю исключение ArrayIndexOutOfBoudnsException с индексом 443. Я слышал, что это происходит только с некоторыми MP3-файлами, но это происходит в каждом кадре с каждым воспроизведением MP3. Вот мой код:JLayer всегда выбрасывает ArrayIndexOutOfBounds Exception

private short[] getPCM(Header frameHeader, Bitstream bs) { 
    short[] pcm = null; 
    try { 
     Decoder d = new Decoder(); 
     SampleBuffer buffer = (SampleBuffer) d.decodeFrame(frameHeader, bs); 
     pcm = buffer.getBuffer(); 
    } catch (ArrayIndexOutOfBoundsException | DecoderException e) { 
     System.err.println("JLayer, stap it"); 
    } 
    return pcm; 
} 

И метод вызывается с этим кодом:

while ((frameHeader = bs.readFrame()) != null) { 
    short[] pcm = getPCM(frameHeader, bs); 

    for(short i : pcm){ 
     try { 
      os.write(i); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    }  
} 

трассировки стека:

java.lang.ArrayIndexOutOfBoundsException: 433 
at javazoom.jl.decoder.Bitstream.get_bits(Unknown Source) 
at javazoom.jl.decoder.LayerIIIDecoder.decode(Unknown Source) 
at javazoom.jl.decoder.LayerIIIDecoder.decodeFrame(Unknown Source) 
at javazoom.jl.decoder.Decoder.decodeFrame(Unknown Source) 
at com.dentonposs.Canvas.getPCM(Canvas.java:70) 
at com.dentonposs.Canvas.paintComponent(Canvas.java:48) 
at javax.swing.JComponent.paint(Unknown Source) 
at javax.swing.JComponent.paintChildren(Unknown Source) 
at javax.swing.JComponent.paint(Unknown Source) 
at javax.swing.JLayeredPane.paint(Unknown Source) 
at javax.swing.JComponent.paintChildren(Unknown Source) 
at javax.swing.JComponent.paintToOffscreen(Unknown Source) 
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source) 
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source) 
at javax.swing.RepaintManager.paint(Unknown Source) 
at javax.swing.JComponent.paint(Unknown Source) 
at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source) 
at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source) 
at sun.awt.SunGraphicsCallback.runComponents(Unknown Source) 
at java.awt.Container.paint(Unknown Source) 
at java.awt.Window.paint(Unknown Source) 
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source) 
at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source) 
at javax.swing.RepaintManager.access$700(Unknown Source) 
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source) 
at java.awt.event.InvocationEvent.dispatch(Unknown Source) 
at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
at java.awt.EventQueue.access$000(Unknown Source) 
at java.awt.EventQueue$3.run(Unknown Source) 
at java.awt.EventQueue$3.run(Unknown Source) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
at java.awt.EventQueue.dispatchEvent(Unknown Source) 
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
at java.awt.EventDispatchThread.run(Unknown Source) 
+0

Сообщение трассировки стека, и указать, какую линию исключение бросил из. – chrylis

+1

Ваш код в вашем блоке catch не будет очень описательным или полезным для вас. Лучше было бы иметь 'e.printStackTrace();' внутри блока catch. ** Редактировать **: @chrylis: с его текущим кодом, как написано, он никогда не увидит * стек. Надеюсь, он сможет и может опубликовать его, если он внесет изменения, которые я рекомендовал. –

+0

У меня там была трассировка стека, я не знаю почему я удалил ее, когда скопировал код. – gameboyprinter

ответ

1

Вам необходимо позвонить Bitstream.closeFrame() между каждым вызовом readFrame() - так

while ((frameHeader = bs.readFrame()) != null) { 
    short[] pcm = getPCM(frameHeader, bs); 

    bs.closeFrame(); 

    .. more .. 
+0

Это исправлено, спасибо тонну! – gameboyprinter

1

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

Для каждого кадра необходимо вызывать decodeFrame() только один раз.

Редактировать: Ваш стек не показывает, где вы действительно читаете данные. Поскольку исключение находится внутри метода компоновки компонентов, я предполагаю, что вы читаете кадр в другом потоке или в другом месте.

Также, глядя на ваш метод getPCM(): Этот код будет никогда работы. Вы не можете создать новый экземпляр декодера для каждого кадра - это просто не сработает, потому что декодер имеет много внутреннего состояния, которое необходимо и зависит от предыдущего кадра (кадров). Вы должны создать декодер только один раз и повторно использовать его для всех кадров.

Посмотрите на источник javazoom.jl.player.Player - он показывает правильный игровой цикл в методе воспроизведения (int) (его несколько строк длиной, но вы должны придерживаться порядка вызова, показанного там , иначе вы уничтожите правильное состояние с декодером и объектами, удерживаемыми декодером).

+0

Но я только вызываю decodeFrame один раз. Не следует '(frameHeader = bs.readFrame())' читать следующий кадр? – gameboyprinter

+0

@ blendmaster345 Сложно сказать, что вы называете в каком порядке, так как четко не указано, где в стеке вызовов выполняются фрагменты кода (вы, вероятно, считаете это очевидным, но мы можем видеть только то, что вы здесь показываете). См. Мое редактирование для некоторых дополнительных указателей. Придерживайтесь порядка вызова, показанного в примере кода, предоставленного jlayer, и ваши проблемы должны исчезнуть. – Durandal

+0

Это не исправить проблему, но это помогло с другой, которая пришла, поэтому спасибо. – gameboyprinter

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