public void calculate() throws IOException {
        OggStreamAudioData data;

        // Calculate the headers sizing
        OggAudioInfoHeader info = headers.getInfo();
        handleHeader(info);
        handleHeader(headers.getTags());
        handleHeader(headers.getSetup());

        // Have each audio packet handled, tracking at least granules
        while ((data = audio.getNextAudioPacket()) != null) {
            handleAudioData(data);
        }

        // Calculate the duration from the granules, if found
        if (lastGranule > 0) {
            long samples = lastGranule - info.getPreSkip();
            double sampleRate = info.getSampleRate();
            if (info instanceof OpusInfo) {
                // Opus is a special case - granule *always* runs at 48kHz
                sampleRate = OpusAudioData.OPUS_GRANULE_RATE;
            }
            durationSeconds = samples / sampleRate;
        }
    }