Path: blob/main/src/lwjgl/java/javazoom/mp3spi/DecodedMpegAudioInputStream.java
8644 views
/*1* DecodedMpegAudioInputStream.2*3* JavaZOOM : [email protected]4* http://www.javazoom.net5*6* Copyright (c) 2012 by fireandfuel from Cuina Team (http://www.cuina.byethost12.com/)7*8*-----------------------------------------------------------------------------9* This program is free software; you can redistribute it and/or modify10* it under the terms of the GNU Library General Public License as published11* by the Free Software Foundation; either version 2 of the License, or12* (at your option) any later version.13*14* This program is distributed in the hope that it will be useful,15* but WITHOUT ANY WARRANTY; without even the implied warranty of16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the17* GNU Library General Public License for more details.18*19* You should have received a copy of the GNU Library General Public20* License along with this program; if not, write to the Free Software21* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.22*------------------------------------------------------------------------23*/2425package javazoom.mp3spi;2627import java.io.IOException;28import java.io.InputStream;29import javax.sound.sampled.AudioFormat;30import javax.sound.sampled.AudioInputStream;3132import tritonus.TAsynchronousFilteredAudioInputStream;3334import javazoom.jl.decoder.Bitstream;35import javazoom.jl.decoder.BitstreamException;36import javazoom.jl.decoder.Decoder;37import javazoom.jl.decoder.DecoderException;38import javazoom.jl.decoder.Header;39import javazoom.jl.decoder.Obuffer;4041/**42* Main decoder.43*/44public class DecodedMpegAudioInputStream extends TAsynchronousFilteredAudioInputStream45{46private InputStream m_encodedStream;47private Bitstream m_bitstream;48private Decoder m_decoder;49private Header m_header;50private DMAISObuffer m_oBuffer;5152// Bytes info.53private long byteslength = -1;54private long currentByte = 0;55// Frame info.56private int frameslength = -1;57private long currentFrame = 0;58private int currentFramesize = 0;5960public DecodedMpegAudioInputStream(AudioFormat outputFormat,61AudioInputStream bufferedInputStream)62{63super(outputFormat, -1);6465try66{67// Try to find out inputstream length to allow skip.68byteslength = bufferedInputStream.available();69} catch (IOException e)70{71byteslength = -1;72}73m_encodedStream = bufferedInputStream;74m_bitstream = new Bitstream(bufferedInputStream);75m_decoder = new Decoder(null);76// m_equalizer = new Equalizer();77// m_equalizer_values = new float[32];78// for (int b=0;b<m_equalizer.getBandCount();b++)79// {80// m_equalizer_values[b] = m_equalizer.getBand(b);81// }82// m_decoder.setEqualizer(m_equalizer);83m_oBuffer = new DMAISObuffer(outputFormat.getChannels());84m_decoder.setOutputBuffer(m_oBuffer);85try86{87m_header = m_bitstream.readFrame();88if((m_header != null) && (frameslength == -1) && (byteslength > 0))89frameslength = m_header.max_number_of_frames((int) byteslength);90} catch (BitstreamException e)91{9293byteslength = -1;94}95}9697public void execute()// if( reverseBytes )98// reverseBytes( smallBuffer, 0, bytesRead );99{100101try102{103// Following line hangs when FrameSize is available in AudioFormat.104Header header = null;105if(m_header == null)106header = m_bitstream.readFrame();107else header = m_header;108109if(header == null)110{111112getCircularBuffer().close();113return;114}115currentFrame++;116currentFramesize = header.calculate_framesize();117currentByte = currentByte + currentFramesize;118// Obuffer decoderOutput =119m_decoder.decodeFrame(header, m_bitstream);120m_bitstream.closeFrame();121getCircularBuffer().write(m_oBuffer.getBuffer(), 0, m_oBuffer.getCurrentBufferSize());122m_oBuffer.reset();123if(m_header != null)124m_header = null;125} catch (BitstreamException e)126{127128} catch (DecoderException e)129{130131}132133}134135public long skip(long bytes)136{137if((byteslength > 0) && (frameslength > 0))138{139float ratio = bytes * 1.0f / byteslength * 1.0f;140long bytesread = skipFrames((long) (ratio * frameslength));141currentByte = currentByte + bytesread;142m_header = null;143return bytesread;144} else return -1;145}146147/**148* Skip frames. You don't need to call it severals times, it will exactly149* skip given frames number.150*151* @param frames152* @return bytes length skipped matching to frames skipped.153*/154public long skipFrames(long frames)155{156157int framesRead = 0;158int bytesReads = 0;159try160{161for(int i = 0; i < frames; i++)162{163Header header = m_bitstream.readFrame();164if(header != null)165{166int fsize = header.calculate_framesize();167bytesReads = bytesReads + fsize;168}169m_bitstream.closeFrame();170framesRead++;171}172} catch (BitstreamException e)173{174175}176177currentFrame = currentFrame + framesRead;178return bytesReads;179}180181private boolean isBigEndian()182{183return getFormat().isBigEndian();184}185186public void close() throws IOException187{188super.close();189m_encodedStream.close();190}191192private class DMAISObuffer extends Obuffer193{194private int m_nChannels;195private byte[] m_abBuffer;196private int[] m_anBufferPointers;197private boolean m_bIsBigEndian;198199public DMAISObuffer(int nChannels)200{201m_nChannels = nChannels;202m_abBuffer = new byte[OBUFFERSIZE * nChannels];203m_anBufferPointers = new int[nChannels];204reset();205m_bIsBigEndian = DecodedMpegAudioInputStream.this.isBigEndian();206}207208public void append(int nChannel, short sValue)209{210byte bFirstByte;211byte bSecondByte;212if(m_bIsBigEndian)213{214bFirstByte = (byte) ((sValue >>> 8) & 0xFF);215bSecondByte = (byte) (sValue & 0xFF);216} else217// little endian218{219bFirstByte = (byte) (sValue & 0xFF);220bSecondByte = (byte) ((sValue >>> 8) & 0xFF);221}222m_abBuffer[m_anBufferPointers[nChannel]] = bFirstByte;223m_abBuffer[m_anBufferPointers[nChannel] + 1] = bSecondByte;224m_anBufferPointers[nChannel] += m_nChannels * 2;225}226227public void set_stop_flag()228{229}230231public void close()232{233}234235public void write_buffer(int nValue)236{237}238239public void clear_buffer()240{241}242243public byte[] getBuffer()244{245return m_abBuffer;246}247248public int getCurrentBufferSize()249{250return m_anBufferPointers[0];251}252253public void reset()254{255for(int i = 0; i < m_nChannels; i++)256{257/*258* Points to byte location, implicitely assuming 16 bit samples.259*/260m_anBufferPointers[i] = i * 2;261}262}263}264}265266267