forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow, unrecommended, but may provide data from otherwise-unusuable files
768009
function Analyze() {
		$info = &$this->getid3->info;

		$initialOffset = $info['avdataoffset'];

		if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) {
			if ($this->allow_bruteforce) {
				$info['error'][] = 'Rescanning file in BruteForce mode';
				$this->getOnlyMPEGaudioInfoBruteForce($this->getid3->fp, $info);
			}
		}


		if (isset($info['mpeg']['audio']['bitrate_mode'])) {
			$info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
		}

		if (((isset($info['id3v2']['headerlength']) && ($info['avdataoffset'] > $info['id3v2']['headerlength'])) || (!isset($info['id3v2']) && ($info['avdataoffset'] > 0) && ($info['avdataoffset'] != $initialOffset)))) {

			$synchoffsetwarning = 'Unknown data before synch ';
			if (isset($info['id3v2']['headerlength'])) {
				$synchoffsetwarning .= '(ID3v2 header ends at '.$info['id3v2']['headerlength'].', then '.($info['avdataoffset'] - $info['id3v2']['headerlength']).' bytes garbage, ';
			} elseif ($initialOffset > 0) {
				$synchoffsetwarning .= '(should be at '.$initialOffset.', ';
			} else {
				$synchoffsetwarning .= '(should be at beginning of file, ';
			}
			$synchoffsetwarning .= 'synch detected at '.$info['avdataoffset'].')';
			if (isset($info['audio']['bitrate_mode']) && ($info['audio']['bitrate_mode'] == 'cbr')) {

				if (!empty($info['id3v2']['headerlength']) && (($info['avdataoffset'] - $info['id3v2']['headerlength']) == $info['mpeg']['audio']['framelength'])) {

					$synchoffsetwarning .= '. This is a known problem with some versions of LAME (3.90-3.92) DLL in CBR mode.';
					$info['audio']['codec'] = 'LAME';
					$CurrentDataLAMEversionString = 'LAME3.';

				} elseif (empty($info['id3v2']['headerlength']) && ($info['avdataoffset'] == $info['mpeg']['audio']['framelength'])) {

					$synchoffsetwarning .= '. This is a known problem with some versions of LAME (3.90 - 3.92) DLL in CBR mode.';
					$info['audio']['codec'] = 'LAME';
					$CurrentDataLAMEversionString = 'LAME3.';

				}

			}
			$info['warning'][] = $synchoffsetwarning;

		}

		if (isset($info['mpeg']['audio']['LAME'])) {
			$info['audio']['codec'] = 'LAME';
			if (!empty($info['mpeg']['audio']['LAME']['long_version'])) {
				$info['audio']['encoder'] = rtrim($info['mpeg']['audio']['LAME']['long_version'], "\x00");
			} elseif (!empty($info['mpeg']['audio']['LAME']['short_version'])) {
				$info['audio']['encoder'] = rtrim($info['mpeg']['audio']['LAME']['short_version'], "\x00");
			}
		}

		$CurrentDataLAMEversionString = (!empty($CurrentDataLAMEversionString) ? $CurrentDataLAMEversionString : (isset($info['audio']['encoder']) ? $info['audio']['encoder'] : ''));
		if (!empty($CurrentDataLAMEversionString) && (substr($CurrentDataLAMEversionString, 0, 6) == 'LAME3.') && !preg_match('[0-9\)]', substr($CurrentDataLAMEversionString, -1))) {
			// a version number of LAME that does not end with a number like "LAME3.92"
			// or with a closing parenthesis like "LAME3.88 (alpha)"
			// or a version of LAME with the LAMEtag-not-filled-in-DLL-mode bug (3.90-3.92)

			// not sure what the actual last frame length will be, but will be less than or equal to 1441
			$PossiblyLongerLAMEversion_FrameLength = 1441;

			// Not sure what version of LAME this is - look in padding of last frame for longer version string
			$PossibleLAMEversionStringOffset = $info['avdataend'] - $PossiblyLongerLAMEversion_FrameLength;
			fseek($this->getid3->fp, $PossibleLAMEversionStringOffset);
			$PossiblyLongerLAMEversion_Data = fread($this->getid3->fp, $PossiblyLongerLAMEversion_FrameLength);
			switch (substr($CurrentDataLAMEversionString, -1)) {
				case 'a':
				case 'b':
					// "LAME3.94a" will have a longer version string of "LAME3.94 (alpha)" for example
					// need to trim off "a" to match longer string
					$CurrentDataLAMEversionString = substr($CurrentDataLAMEversionString, 0, -1);
					break;
			}
			if (($PossiblyLongerLAMEversion_String = strstr($PossiblyLongerLAMEversion_Data, $CurrentDataLAMEversionString)) !== false) {
				if (substr($PossiblyLongerLAMEversion_String, 0, strlen($CurrentDataLAMEversionString)) == $CurrentDataLAMEversionString) {
					$PossiblyLongerLAMEversion_NewString = substr($PossiblyLongerLAMEversion_String, 0, strspn($PossiblyLongerLAMEversion_String, 'LAME0123456789., (abcdefghijklmnopqrstuvwxyzJFSOND)')); //"LAME3.90.3"  "LAME3.87 (beta 1, Sep 27 2000)" "LAME3.88 (beta)"
					if (empty($info['audio']['encoder']) || (strlen($PossiblyLongerLAMEversion_NewString) > strlen($info['audio']['encoder']))) {
						$info['audio']['encoder'] = $PossiblyLongerLAMEversion_NewString;
					}
				}
			}
		}
		if (!empty($info['audio']['encoder'])) {
			$info['audio']['encoder'] = rtrim($info['audio']['encoder'], "\x00 ");
		}

		switch (isset($info['mpeg']['audio']['layer']) ? $info['mpeg']['audio']['layer'] : '') {
			case 1:
			case 2:
				$info['audio']['dataformat'] = 'mp'.$info['mpeg']['audio']['layer'];
				break;
		}
		if (isset($info['fileformat']) && ($info['fileformat'] == 'mp3')) {
			switch ($info['audio']['dataformat']) {
				case 'mp1':
				case 'mp2':
				case 'mp3':
					$info['fileformat'] = $info['audio']['dataformat'];
					break;

				default:
					$info['warning'][] = 'Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"';
					break;
			}
		}

		if (empty($info['fileformat'])) {
			unset($info['fileformat']);
			unset($info['audio']['bitrate_mode']);
			unset($info['avdataoffset']);
			unset($info['avdataend']);
			return false;
		}

		$info['mime_type']         = 'audio/mpeg';
		$info['audio']['lossless'] = false;

		// Calculate playtime
		if (!isset($info['playtime_seconds']) && isset($info['audio']['bitrate']) && ($info['audio']['bitrate'] > 0)) {
			$info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) * 8 / $info['audio']['bitrate'];
		}

		$info['audio']['encoder_options'] = $this->GuessEncoderOptions();

		return true;
	}
612674
function getById(hypemId, callback) {
        var options = {
            method: 'HEAD',
            url: HYPEM_GO_URL + hypemId,
            followRedirect: false,
            timeout: FIVE_SECONDS_IN_MILLIS
        };

        request(options, function (error, response) {
            if (error || response.statusCode !== 302) {
                callback(error, null);
                return;
            }
            var songUrl = response.headers.location;
            if (isSoundcloudUrl(songUrl)) {
                var soundcloudUrl = getNormalizedSoundcloudUrl(songUrl);
                callback(null, soundcloudUrl);
            } else {
                requestHypemKey(hypemId, function (error, hypemKey) {
                    if (error) {
                        callback(error, null);
                        return;
                    }
                    requestMp3Url(hypemId, hypemKey, callback);
                });
            }
        });
    }
278163
def _get_info(self):
        
        out_parts = []
        while True:
            line = self.proc.stderr.readline()
            if not line:
                # EOF and data not found.
                raise CommunicationError("stream info not found")

            # In Python 3, result of reading from stderr is bytes.
            if isinstance(line, bytes):
                line = line.decode('utf8', 'ignore')

            line = line.strip().lower()

            if 'no such file' in line:
                raise IOError('file not found')
            elif 'invalid data found' in line:
                raise UnsupportedError()
            elif 'duration:' in line:
                out_parts.append(line)
            elif 'audio:' in line:
                out_parts.append(line)
                self._parse_info(''.join(out_parts))
                break
1097846
async def read_frame(self, stream_id: int) -> bytes:
        
        stream = self._get_stream(stream_id)
        frame = await stream.read_frame()
        if frame.flow_controlled_length > 0:
            self._acknowledge_data(frame.flow_controlled_length, stream_id)
        return frame.data
9828
async def read_data(self, stream_id: int) -> bytes:
        
        frames = [f async for f in self.stream_frames(stream_id)]
        return b''.join(frames)
1261692
def ccid_xfr_block(self, data, timeout=0.1):
        
        frame = struct.pack("<BI5B", 0x6F, len(data), 0, 0, 0, 0, 0) + data
        self.transport.write(bytearray(frame))
        frame = self.transport.read(int(timeout * 1000))
        if not frame or len(frame) < 10:
            log.error("insufficient data for decoding ccid response")
            raise IOError(errno.EIO, os.strerror(errno.EIO))
        if frame[0] != 0x80:
            log.error("expected a RDR_to_PC_DataBlock")
            raise IOError(errno.EIO, os.strerror(errno.EIO))
        # if len(frame) != 10 + struct.unpack("<I", buffer(frame, 1, 4))[0]:
        if len(frame) != 10 + struct.unpack("<I", frame[1:5])[0]:
            log.error("RDR_to_PC_DataBlock length mismatch")
            raise IOError(errno.EIO, os.strerror(errno.EIO))
        return frame[10:]
140226
public byte[] getFrameData(String id)
	{
		if (frames.containsKey(id))
		{
			return ((ID3v2Frame) frames.get(id)).getFrameData();
		}

		return null;
	}
1085189
private boolean checkDefaultFileAlterDiscard()
	{
		return	id.equals(ID3v2Frames.AUDIO_SEEK_POINT_INDEX) || 
				id.equals(ID3v2Frames.AUDIO_ENCRYPTION) || 
				id.equals(ID3v2Frames.EVENT_TIMING_CODES) || 
				id.equals(ID3v2Frames.EQUALISATION) || 
				id.equals(ID3v2Frames.MPEG_LOCATION_LOOKUP_TABLE) || 
				id.equals(ID3v2Frames.POSITION_SYNCHRONISATION_FRAME) || 
				id.equals(ID3v2Frames.SEEK_FRAME) || 
				id.equals(ID3v2Frames.SYNCHRONISED_LYRIC) || 
				id.equals(ID3v2Frames.SYNCHRONISED_TEMPO_CODES) || 
				id.equals(ID3v2Frames.RELATIVE_VOLUME_ADJUSTMENT) || 
				id.equals(ID3v2Frames.ENCODED_BY) || 
				id.equals(ID3v2Frames.LENGTH);
	}
86273
function getSourceId(callback, audioPlusTab) {
        if (!callback) throw '"callback" parameter is mandatory.';
        if (sourceId) {
            callback(sourceId);
            sourceId = null;
            return;
        }

        screenCallback = callback;

        if (!!audioPlusTab) {
            window.postMessage('audio-plus-tab', '*');
            return;
        }
        window.postMessage('get-sourceId', '*');
    }
224190
public static void encodeHeaderByte(IoBuffer out, byte headerSize, int channelId) {
        if (channelId <= 63) {
            out.put((byte) ((headerSize << 6) + channelId));
        } else if (channelId <= 319) {
            out.put((byte) (headerSize << 6));
            out.put((byte) (channelId - 64));
        } else {
            out.put((byte) ((headerSize << 6) | 1));
            channelId -= 64;
            out.put((byte) (channelId & 0xff));
            out.put((byte) (channelId >> 8));
        }
    }
1072875
private FileStatus methodBasedGetFileInfo(String src) throws IOException {
    if (namenodeProtocolProxy.isMethodSupported(
        "getHdfsFileInfo", String.class)) {
      return HdfsFileStatus.toFileStatus(namenode.getHdfsFileInfo(src), src);
    } else {
      return namenode.getFileInfo(src);
    }
  }
780296
public void readHeader(FileChannel channel,String forceEncoding) throws IOException {
        if(forceEncoding != null) {
            fileEncoding = forceEncoding;
        }
		// we'll read in chunks of 1K
		ReadBufferManager in = new ReadBufferManager(channel);
		// do this or GO CRAZY
		// ByteBuffers come preset to BIG_ENDIAN !
		in.order(ByteOrder.LITTLE_ENDIAN);

		// type of file.
		byte magic = in.get();
		if (magic != MAGIC) {
			log.warn("Unsupported DBF file Type "
                    + Integer.toHexString(magic));
		}

		// parse the update date information.
		int tempUpdateYear = in.get();
		int tempUpdateMonth = in.get();
		int tempUpdateDay = in.get();
		// ouch Y2K uncompliant
		if (tempUpdateYear > 90) {
			tempUpdateYear += 1900;
		} else {
			tempUpdateYear += 2000;
		}
		Calendar c = Calendar.getInstance();
		c.set(Calendar.YEAR, tempUpdateYear);
		c.set(Calendar.MONTH, tempUpdateMonth - 1);
		c.set(Calendar.DATE, tempUpdateDay);
		date = c.getTime();

		// read the number of records.
		recordCnt = in.getInt();

		// read the length of the header structure.
		// ahhh.. unsigned little-endian shorts
		// mask out the byte and or it with shifted 2nd byte
		headerLength = (in.get() & 0xff) | ((in.get() & 0xff) << 8);

		// read the length of a record
		// ahhh.. unsigned little-endian shorts
		recordLength = (in.get() & 0xff) | ((in.get() & 0xff) << 8);

		// skip / skip thesreserved bytes in the header.
		in.skip(17);
        // read Language driver
        byte lngDriver = in.get();
        String encoding = CODE_PAGE_ENCODING.get(lngDriver);
        if(encoding!=null && forceEncoding == null) {
            this.fileEncoding = encoding;
        }
        // skip reserved
        in.skip(2);

		// calculate the number of Fields in the header
		fieldCnt = (headerLength - FILE_DESCRIPTOR_SIZE - 1)
				/ FILE_DESCRIPTOR_SIZE;

		// read all of the header records
		List<DbaseField> lfields = new ArrayList<DbaseField>();
		for (int i = 0; i < fieldCnt; i++) {
			DbaseField field = new DbaseField();

			// read the field name
			byte[] buffer = new byte[11];
			in.get(buffer);
			String name = new String(buffer, fileEncoding);
			int nullPoint = name.indexOf(0);
			if (nullPoint != -1) {
				name = name.substring(0, nullPoint);
			}
			field.fieldName = name.trim();

			// read the field type
			field.fieldType = (char) in.get();

			// read the field data address, offset from the start of the record.
			field.fieldDataAddress = in.getInt();

			// read the field length in bytes
			int length = (int) in.get();
			if (length < 0) {
				length += 256;
			}
			field.fieldLength = length;

			if (length > largestFieldSize) {
				largestFieldSize = length;
			}

			// read the field decimal count in bytes
			field.decimalCount = (int) in.get();

			// rreservedvededved bytes.
			// in.skipBytes(14);
			in.skip(14);

			// some broken shapefiles have 0-length attributes. The reference
			// implementation
			// (ArcExplorer 2.0, built with MapObjects) just ignores them.
			if (field.fieldLength > 0) {
				lfields.add(field);
			}
		}

		// Last byte is a marker for the end of the field definitions.
		// in.skipBytes(1);
		in.skip(1);


		fields = new DbaseField[lfields.size()];
		fields = lfields.toArray(fields);
	}
162613
function Analyze() {
		$info = &$this->getid3->info;

		// http://flac.sourceforge.net/format.html

		$this->fseek($info['avdataoffset'], SEEK_SET);
		$StreamMarker = $this->fread(4);
		$magic = 'fLaC';
		if ($StreamMarker != $magic) {
			$info['error'][] = 'Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($StreamMarker).'"';
			return false;
		}
		$info['fileformat']            = 'flac';
		$info['audio']['dataformat']   = 'flac';
		$info['audio']['bitrate_mode'] = 'vbr';
		$info['audio']['lossless']     = true;

		return $this->FLACparseMETAdata();
	}
647460
def wr_dat_file(file_name, fmt, d_signal, byte_offset, expanded=False,
                e_d_signal=None, samps_per_frame=None, write_dir=''):
    
    # Combine list of arrays into single array
    if expanded:
        n_sig = len(e_d_signal)
        sig_len = int(len(e_d_signal[0])/samps_per_frame[0])
        # Effectively create MxN signal, with extra frame samples acting
        # like extra channels
        d_signal = np.zeros((sig_len, sum(samps_per_frame)), dtype = 'int64')
        # Counter for channel number
        expand_ch = 0
        for ch in range(n_sig):
            spf = samps_per_frame[ch]
            for framenum in range(spf):
                d_signal[:, expand_ch] = e_d_signal[ch][framenum::spf]
                expand_ch = expand_ch + 1

    # This n_sig is used for making list items.
    # Does not necessarily represent number of signals (ie. for expanded=True)
    n_sig = d_signal.shape[1]

    if fmt == '80':
        # convert to 8 bit offset binary form
        d_signal = d_signal + 128
        # Concatenate into 1D
        d_signal = d_signal.reshape(-1)
        # Convert to un_signed 8 bit dtype to write
        b_write = d_signal.astype('uint8')

    elif fmt == '212':
        # Each sample is represented by a 12 bit two's complement
        # amplitude. The first sample is obtained from the 12 least
        # significant bits of the first byte pair (stored least
        # significant byte first). The second sample is formed from the
        # 4 remaining bits of the first byte pair (which are the 4 high
        # bits of the 12-bit sample) and the next byte (which contains
        # the remaining 8 bits of the second sample). The process is
        # repeated for each successive pair of samples.

        # convert to 12 bit two's complement
        d_signal[d_signal<0] = d_signal[d_signal<0] + 4096

        # Concatenate into 1D
        d_signal = d_signal.reshape(-1)

        n_samp = len(d_signal)
        # use this for byte processing
        processn_samp = n_samp

        # Odd numbered number of samples. Fill in extra blank for
        # following byte calculation.
        if processn_samp % 2:
            d_signal = np.concatenate([d_signal, np.array([0])])
            processn_samp +=1

        # The individual bytes to write
        b_write = np.zeros([int(1.5*processn_samp)], dtype = 'uint8')

        # Fill in the byte triplets

        # Triplet 1 from lowest 8 bits of sample 1
        b_write[0::3] = d_signal[0::2] & 255
        # Triplet 2 from highest 4 bits of samples 1 (lower) and 2 (upper)
        b_write[1::3] = ((d_signal[0::2] & 3840) >> 8) + ((d_signal[1::2] & 3840) >> 4)
        # Triplet 3 from lowest 8 bits of sample 2
        b_write[2::3] = d_signal[1::2] & 255

        # If we added an extra sample for byte calculation, remove the last byte (don't write)
        if n_samp % 2:
            b_write = b_write[:-1]

    elif fmt == '16':
        # convert to 16 bit two's complement
        d_signal[d_signal<0] = d_signal[d_signal<0] + 65536
        # Split samples into separate bytes using binary masks
        b1 = d_signal & [255]*n_sig
        b2 = ( d_signal & [65280]*n_sig ) >> 8
        # Interweave the bytes so that the same samples' bytes are consecutive
        b1 = b1.reshape((-1, 1))
        b2 = b2.reshape((-1, 1))
        b_write = np.concatenate((b1, b2), axis=1)
        b_write = b_write.reshape((1,-1))[0]
        # Convert to un_signed 8 bit dtype to write
        b_write = b_write.astype('uint8')
    elif fmt == '24':
        # convert to 24 bit two's complement
        d_signal[d_signal<0] = d_signal[d_signal<0] + 16777216
        # Split samples into separate bytes using binary masks
        b1 = d_signal & [255]*n_sig
        b2 = ( d_signal & [65280]*n_sig ) >> 8
        b3 = ( d_signal & [16711680]*n_sig ) >> 16
        # Interweave the bytes so that the same samples' bytes are consecutive
        b1 = b1.reshape((-1, 1))
        b2 = b2.reshape((-1, 1))
        b3 = b3.reshape((-1, 1))
        b_write = np.concatenate((b1, b2, b3), axis=1)
        b_write = b_write.reshape((1,-1))[0]
        # Convert to un_signed 8 bit dtype to write
        b_write = b_write.astype('uint8')

    elif fmt == '32':
        # convert to 32 bit two's complement
        d_signal[d_signal<0] = d_signal[d_signal<0] + 4294967296
        # Split samples into separate bytes using binary masks
        b1 = d_signal & [255]*n_sig
        b2 = ( d_signal & [65280]*n_sig ) >> 8
        b3 = ( d_signal & [16711680]*n_sig ) >> 16
        b4 = ( d_signal & [4278190080]*n_sig ) >> 24
        # Interweave the bytes so that the same samples' bytes are consecutive
        b1 = b1.reshape((-1, 1))
        b2 = b2.reshape((-1, 1))
        b3 = b3.reshape((-1, 1))
        b4 = b4.reshape((-1, 1))
        b_write = np.concatenate((b1, b2, b3, b4), axis=1)
        b_write = b_write.reshape((1,-1))[0]
        # Convert to un_signed 8 bit dtype to write
        b_write = b_write.astype('uint8')
    else:
        raise ValueError('This library currently only supports writing the following formats: 80, 16, 24, 32')

    # Byte offset in the file
    if byte_offset is not None and byte_offset>0:
        print('Writing file '+file_name+' with '+str(byte_offset)+' empty leading bytes')
        b_write = np.append(np.zeros(byte_offset, dtype = 'uint8'), b_write)

    # Write the bytes to the file
    with open(os.path.join(write_dir, file_name),'wb') as f:
        b_write.tofile(f)
1238901
@Override
    public KeyFrameMeta analyzeKeyFrames() {
        if (keyframeMeta != null) {
            return keyframeMeta;
        }
        try {
            lock.lockInterruptibly();
            // check for cached keyframe informations
            if (keyframeCache != null) {
                keyframeMeta = keyframeCache.loadKeyFrameMeta(file);
                if (keyframeMeta != null) {
                    // Keyframe data loaded, create other mappings
                    duration = keyframeMeta.duration;
                    posTimeMap = new HashMap<>();
                    for (int i = 0; i < keyframeMeta.positions.length; i++) {
                        posTimeMap.put(keyframeMeta.positions[i], (long) keyframeMeta.timestamps[i]);
                    }
                    return keyframeMeta;
                }
            }
            // create a holder for the metadata
            keyframeMeta = new KeyFrameMeta();
            // Lists of video positions and timestamps
            List<Long> positionList = new ArrayList<>();
            List<Integer> timestampList = new ArrayList<>();
            // Lists of audio positions and timestamps
            List<Long> audioPositionList = new ArrayList<>();
            List<Integer> audioTimestampList = new ArrayList<>();
            long origPos = getCurrentPosition();
            // point to the first tag
            setCurrentPosition(9);
            // number of tags read
            int totalValidTags = 0;
            // start off as audio only
            boolean audioOnly = true;
            while (hasMoreTags()) {
                long pos = getCurrentPosition();
                // read tag header and duration
                ITag tmpTag = null;
                try {
                    tmpTag = readTagHeader();
                } catch (UnsupportedDataTypeException e) {
                    log.warn("analyzeKeyFrames", e);
                }
                if (tmpTag != null) {
                    totalValidTags++;
                } else {
                    break;
                }
                duration = tmpTag.getTimestamp();
                if (tmpTag.getDataType() == IoConstants.TYPE_VIDEO) {
                    if (audioOnly) {
                        audioOnly = false;
                        audioPositionList.clear();
                        audioTimestampList.clear();
                    }
                    if (firstVideoTag == -1) {
                        firstVideoTag = pos;
                    }
                    // Grab Frame type
                    fillBuffer(1);
                    int frametype = in.get();
                    if (keyframeMeta.videoCodecId == -1) {
                        keyframeMeta.videoCodecId = frametype & MASK_VIDEO_CODEC;
                    }
                    if (((frametype & MASK_VIDEO_FRAMETYPE) >> 4) == FLAG_FRAMETYPE_KEYFRAME) {
                        positionList.add(pos);
                        timestampList.add(tmpTag.getTimestamp());
                    }
                } else if (tmpTag.getDataType() == IoConstants.TYPE_AUDIO) {
                    if (firstAudioTag == -1) {
                        firstAudioTag = pos;
                    }
                    // Grab Frame type
                    fillBuffer(1);
                    int frametype = in.get() & 0xff;
                    if (keyframeMeta.audioCodecId == -1) {
                        keyframeMeta.audioCodecId = (frametype & MASK_SOUND_FORMAT) >> 4;
                    }
                    if (audioOnly) {
                        audioPositionList.add(pos);
                        audioTimestampList.add(tmpTag.getTimestamp());
                    }
                }
                // XXX Paul: this 'properly' handles damaged FLV files - as far as duration/size is concerned
                long newPosition = pos + tmpTag.getBodySize() + 15;
                // log.debug("---->" + in.remaining() + " limit=" + in.limit() + "
                // new pos=" + newPosition);
                if (newPosition >= getTotalBytes()) {
                    log.error("New position exceeds limit");
                    if (log.isDebugEnabled()) {
                        log.debug("-----\nKeyframe analysis\n\tdata type={} bodysize={}\n\tremaining={} limit={}\n\tnew pos={} pos={}\n-----", 
                                new Object[] { tmpTag.getDataType(), tmpTag.getBodySize(), getRemainingBytes(), getTotalBytes(), newPosition, pos });
                    }
                    //XXX Paul: A runtime exception is probably not needed here
                    log.info("New position {} exceeds limit {}", newPosition, getTotalBytes());
                    //just break from the loop
                    break;
                } else {
                    setCurrentPosition(newPosition);
                }
            }
            // restore the pos
            setCurrentPosition(origPos);
            log.debug("Total valid tags found: {}", totalValidTags);
            keyframeMeta.duration = duration;
            posTimeMap = new HashMap<Long, Long>();
            if (audioOnly) {
                // The flv only contains audio tags, use their lists
                // to support pause and seeking
                positionList = audioPositionList;
                timestampList = audioTimestampList;
            }
            keyframeMeta.audioOnly = audioOnly;
            keyframeMeta.positions = new long[positionList.size()];
            keyframeMeta.timestamps = new int[timestampList.size()];
            for (int i = 0; i < keyframeMeta.positions.length; i++) {
                keyframeMeta.positions[i] = positionList.get(i);
                keyframeMeta.timestamps[i] = timestampList.get(i);
                posTimeMap.put((long) positionList.get(i), (long) timestampList.get(i));
            }
            if (keyframeCache != null) {
                keyframeCache.saveKeyFrameMeta(file, keyframeMeta);
            }
        } catch (InterruptedException e) {
            log.warn("Exception acquiring lock", e);
        } finally {
            if (lock.isLocked()) {
                lock.unlock();
            }
        }
        return keyframeMeta;
    }
312187
def is_wav(origin, filepath, fileobj, *args, **kwargs):
    
    # pylint: disable=unused-argument
    if origin == 'read' and fileobj is not None:
        loc = fileobj.tell()
        fileobj.seek(0)
        try:
            riff, _, fmt = struct.unpack('<4sI4s', fileobj.read(12))
            if isinstance(riff, bytes):
                riff = riff.decode('utf-8')
                fmt = fmt.decode('utf-8')
            return riff == WAV_SIGNATURE[0] and fmt == WAV_SIGNATURE[1]
        except (UnicodeDecodeError, struct.error):
            return False
        finally:
            fileobj.seek(loc)
    elif filepath is not None:
        return filepath.endswith(('.wav', '.wave'))
    else:
        try:
            wave.open(args[0])
        except (wave.Error, AttributeError):
            return False
        else:
            return True
399701
def getSoundFileDuration(fn):
    '''
    
    '''
    audiofile = wave.open(fn, "r")
    
    params = audiofile.getparams()
    framerate = params[2]
    nframes = params[3]
    
    duration = float(nframes) / framerate
    return duration