// Copyright 2014-2025 Jesper Larsson
//
// This file is part of Klipspringer, <https://klipspringer.avadeaux.net/>
//
// Klipspringer is free software: you can redistribute it and/or modify it under the terms of the
// GNU General Public License as published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// Klipspringer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with Klipspringer. If
// not, see <https://www.gnu.org/licenses/>.

import java.io.IOException;
import java.nio.ByteBuffer;
import net.avadeaux.klipspringer.codec.*;
import javax.sound.sampled.*;

/** Demonstration of Klipspringer FLAC decoding interface that seeks in the file. Compile and run
  * example:
  * <pre>
  *     javac -cp lib/klipcodec.jar examples/FlacSeekTest.java
  *     java -cp examples:lib/klipcodec.jar --enable-native-access=ALL-UNNAMED -Djava.library.path=lib FlacSeekTest some_audio_file.flac
  * </pre>
  */
public class FlacSeekTest {
    private static PcmFormat globalFormat;

    static class LimitedTarget implements FlacDecoder.Target {
        private final double seconds;
        private long writeLimit;
        private Device.Player player;

        LimitedTarget(double seconds) { this.seconds = seconds; }

        public synchronized void metadata(PcmFormat format, long totalSamples) throws IOException {
            try {
                SourceDataLine line = AudioSystem.getSourceDataLine(format);
                writeLimit =  (long) (seconds * format.rate() * format.fs());
                player = new LinePlayer(line, false);
                globalFormat = format;
            } catch (LineUnavailableException ex) {
                throw new IOException(ex);
            }
        }

        public synchronized boolean write(ByteBuffer data) throws IOException {
            if (writeLimit == 0) { return false; }
            int p = data.position();
            int q = data.limit();
            int n = (int) Math.min(q-p, writeLimit);
            data.limit(n);
            boolean ok = player.write(data) && data.position() == p+n;
            writeLimit -= data.position() - p;
            data.limit(q); // return to saved value
            return ok;
        }

        public void close() throws IOException {
            if (player != null) {
                player.drain();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        if (args.length != 1) {
            System.err.println("Expecting FLAC file argument");
            System.exit(1);
        }

        FlacDecoder decoder;

        System.out.println("Playing 2 seconds from the start of the file");
        decoder = new FlacDecoder(args[0], new LimitedTarget(2));
        decoder.decodeAll(0);
        decoder.close();

        System.out.println("Playing 4 seconds from the start of the file");
        decoder = new FlacDecoder(args[0], new LimitedTarget(4));
        decoder.decodeAll(0);
        decoder.close();

        System.out.println("Playing from 20 seconds into the file until the end");
        decoder = new FlacDecoder(args[0], new LimitedTarget(1000000));
        decoder.decodeAll(20 * globalFormat.rate());
        decoder.close();

        System.out.println("Playing the whole file again");
        decoder = new FlacDecoder(args[0], new LimitedTarget(1000000));
        decoder.decodeAll(0);
        decoder.close();

        decoder.close();
    }
}

Version: v4.3.2.2 (2026-05-16T17:03:34+02:00)
Raw file
Source code overview
Klipspringer home