@Test public void testGetTimeUsAtFirstAudioFrame() { assertThat(seeker.getTimeUs(XING_FRAME_POSITION + xingFrameSize)).isEqualTo(0); assertThat(seekerWithInputLength.getTimeUs(XING_FRAME_POSITION + xingFrameSize)).isEqualTo(0); }
@Override public long getTimeUs(long position) { long positionOffset = position - dataStartPosition; if (!isSeekable() || positionOffset <= xingFrameSize) { return 0L; } long[] tableOfContents = Assertions.checkNotNull(this.tableOfContents); double scaledPosition = (positionOffset * 256d) / dataSize; int prevTableIndex = Util.binarySearchFloor(tableOfContents, (long) scaledPosition, true, true); long prevTimeUs = getTimeUsForTableIndex(prevTableIndex); long prevScaledPosition = tableOfContents[prevTableIndex]; long nextTimeUs = getTimeUsForTableIndex(prevTableIndex + 1); long nextScaledPosition = prevTableIndex == 99 ? 256 : tableOfContents[prevTableIndex + 1]; double interpolateFraction = prevScaledPosition == nextScaledPosition ? 0 : ((scaledPosition - prevScaledPosition) / (nextScaledPosition - prevScaledPosition)); return prevTimeUs + Math.round(interpolateFraction * (nextTimeUs - prevTimeUs)); }
XingSeeker implements Mp3Extractor.Seeker { @Override public long getTimeUs(long position) { long positionOffset = position - dataStartPosition; if (!isSeekable() || positionOffset <= xingFrameSize) { return 0L; } long[] tableOfContents = Assertions.checkNotNull(this.tableOfContents); double scaledPosition = (positionOffset * 256d) / dataSize; int prevTableIndex = Util.binarySearchFloor(tableOfContents, (long) scaledPosition, true, true); long prevTimeUs = getTimeUsForTableIndex(prevTableIndex); long prevScaledPosition = tableOfContents[prevTableIndex]; long nextTimeUs = getTimeUsForTableIndex(prevTableIndex + 1); long nextScaledPosition = prevTableIndex == 99 ? 256 : tableOfContents[prevTableIndex + 1]; double interpolateFraction = prevScaledPosition == nextScaledPosition ? 0 : ((scaledPosition - prevScaledPosition) / (nextScaledPosition - prevScaledPosition)); return prevTimeUs + Math.round(interpolateFraction * (nextTimeUs - prevTimeUs)); } }
XingSeeker implements Mp3Extractor.Seeker { @Override public long getTimeUs(long position) { long positionOffset = position - dataStartPosition; if (!isSeekable() || positionOffset <= xingFrameSize) { return 0L; } long[] tableOfContents = Assertions.checkNotNull(this.tableOfContents); double scaledPosition = (positionOffset * 256d) / dataSize; int prevTableIndex = Util.binarySearchFloor(tableOfContents, (long) scaledPosition, true, true); long prevTimeUs = getTimeUsForTableIndex(prevTableIndex); long prevScaledPosition = tableOfContents[prevTableIndex]; long nextTimeUs = getTimeUsForTableIndex(prevTableIndex + 1); long nextScaledPosition = prevTableIndex == 99 ? 256 : tableOfContents[prevTableIndex + 1]; double interpolateFraction = prevScaledPosition == nextScaledPosition ? 0 : ((scaledPosition - prevScaledPosition) / (nextScaledPosition - prevScaledPosition)); return prevTimeUs + Math.round(interpolateFraction * (nextTimeUs - prevTimeUs)); } private  XingSeeker(long dataStartPosition, int xingFrameSize, long durationUs); private  XingSeeker(
      long dataStartPosition,
      int xingFrameSize,
      long durationUs,
      long dataSize,
      @Nullable long[] tableOfContents); }
XingSeeker implements Mp3Extractor.Seeker { @Override public long getTimeUs(long position) { long positionOffset = position - dataStartPosition; if (!isSeekable() || positionOffset <= xingFrameSize) { return 0L; } long[] tableOfContents = Assertions.checkNotNull(this.tableOfContents); double scaledPosition = (positionOffset * 256d) / dataSize; int prevTableIndex = Util.binarySearchFloor(tableOfContents, (long) scaledPosition, true, true); long prevTimeUs = getTimeUsForTableIndex(prevTableIndex); long prevScaledPosition = tableOfContents[prevTableIndex]; long nextTimeUs = getTimeUsForTableIndex(prevTableIndex + 1); long nextScaledPosition = prevTableIndex == 99 ? 256 : tableOfContents[prevTableIndex + 1]; double interpolateFraction = prevScaledPosition == nextScaledPosition ? 0 : ((scaledPosition - prevScaledPosition) / (nextScaledPosition - prevScaledPosition)); return prevTimeUs + Math.round(interpolateFraction * (nextTimeUs - prevTimeUs)); } private  XingSeeker(long dataStartPosition, int xingFrameSize, long durationUs); private  XingSeeker(
      long dataStartPosition,
      int xingFrameSize,
      long durationUs,
      long dataSize,
      @Nullable long[] tableOfContents); static @Nullable XingSeeker create(
      long inputLength, long position, MpegAudioHeader mpegAudioHeader, ParsableByteArray frame); @Override boolean isSeekable(); @Override SeekPoints getSeekPoints(long timeUs); @Override long getTimeUs(long position); @Override long getDurationUs(); @Override long getDataEndPosition(); }
XingSeeker implements Mp3Extractor.Seeker { @Override public long getTimeUs(long position) { long positionOffset = position - dataStartPosition; if (!isSeekable() || positionOffset <= xingFrameSize) { return 0L; } long[] tableOfContents = Assertions.checkNotNull(this.tableOfContents); double scaledPosition = (positionOffset * 256d) / dataSize; int prevTableIndex = Util.binarySearchFloor(tableOfContents, (long) scaledPosition, true, true); long prevTimeUs = getTimeUsForTableIndex(prevTableIndex); long prevScaledPosition = tableOfContents[prevTableIndex]; long nextTimeUs = getTimeUsForTableIndex(prevTableIndex + 1); long nextScaledPosition = prevTableIndex == 99 ? 256 : tableOfContents[prevTableIndex + 1]; double interpolateFraction = prevScaledPosition == nextScaledPosition ? 0 : ((scaledPosition - prevScaledPosition) / (nextScaledPosition - prevScaledPosition)); return prevTimeUs + Math.round(interpolateFraction * (nextTimeUs - prevTimeUs)); } private  XingSeeker(long dataStartPosition, int xingFrameSize, long durationUs); private  XingSeeker(
      long dataStartPosition,
      int xingFrameSize,
      long durationUs,
      long dataSize,
      @Nullable long[] tableOfContents); static @Nullable XingSeeker create(
      long inputLength, long position, MpegAudioHeader mpegAudioHeader, ParsableByteArray frame); @Override boolean isSeekable(); @Override SeekPoints getSeekPoints(long timeUs); @Override long getTimeUs(long position); @Override long getDurationUs(); @Override long getDataEndPosition();  }