/** * Creates a bit field for the MPEG frame header. * * @return the bit field * @throws IOException if an error occurs */ private HeaderBitField createHeaderField() throws IOException { HeaderBitField field = new HeaderBitField(); field.add(nextByte()); field.add(nextByte()); field.add(nextByte()); return field; }
/** * Searches for the next MPEG frame header from the current stream position on. This method * advances the underlying input stream until it finds a valid frame header or the end of the * stream is reached. In the former case a corresponding {@code AudioFrame} object is created. In * the latter case there are no more headers, so the end of the stream is probably reached. * * @return the next {@code AudioFrame} or <b>null</b> * @throws IOException if an IO error occurs */ public AudioFrame nextFrame() throws IOException { AudioFrame frame = null; while (!endOfStream && frame == null) { findFrameSyncByte(); if (!endOfStream) { HeaderBitField headerField = createHeaderField(); if (!endOfStream) { frame = createHeader(headerField); if (frame == null) { pushBack(headerField); } else { System.arraycopy(headerField.toArray(), 0, header, 0, 3); } } } } currentHeader = frame; return frame; }
/** * Creates an {@code AudioFrame} object based on the given header field. If the header field * contains invalid values, result is <b>null</b>. * * @param bits the header bit field * @return the {@code AudioFrame} */ private static AudioFrame createHeader(HeaderBitField bits) { if (bits.get(21, 23) != 7) { return null; } int mpegVer = bits.get(19, 20); int layer = bits.get(17, 18); int bitRateCode = bits.get(12, 15); int sampleRateCode = bits.get(10, 11); int padding = bits.get(9); if (mpegVer == 1 || layer == 0 || bitRateCode == 0 || bitRateCode == 15 || sampleRateCode == 3) { // invalid header values return null; } int bitRate = calculateBitRate(mpegVer, layer, bitRateCode); int sampleRate = calculateSampleRate(mpegVer, sampleRateCode); int length = calculateFrameLength(layer, bitRate, sampleRate, padding); float duration = calculateDuration(layer, sampleRate); int channels = calculateChannels(bits.get(6, 7)); return new AudioFrame(mpegVer, layer, bitRate, sampleRate, channels, length, duration); }
/** * Pushes the given header field back in the stream so that the bytes are read again. This method * is called if an invalid header was detected. Then search has to continue at the next byte after * the frame sync byte. * * @param field the header bit field with the invalid frame header * @throws IOException if an error occurs */ private void pushBack(HeaderBitField field) throws IOException { unread(field.toArray()); }