private void packFlac() throws IOException {
        // get output file
        File outFile = getOutputFile();
        if (outFile == null) return;
        BitOutputStream os = null;
        FileOutputStream fos;
        try {
            fos = new FileOutputStream(outFile);
            os = new BitOutputStream(fos);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
            return;
        }
        
        // get seek table
        SeekTable seekTable = makeSeekTable();
        if (masterStreamInfo == null) return;
        
        // write FLAC marker
        os.writeByteBlock(Constants.STREAM_SYNC_STRING, Constants.STREAM_SYNC_STRING.length);
        
        // output StreamInfo
        masterStreamInfo.write(os, false);
        
        // output SeekTable
        seekTable.write(os, true);
        
        // generate output file
        for (int i = 0; i < albumFiles.size(); i++) {
            PackerFile aFile = (PackerFile)albumFiles.get(i);
            appendMsg("Process file " + i + ": " + aFile.file);
            try {
                RandomAccessFile raf = new RandomAccessFile(aFile.file, "r");
                raf.seek(aFile.firstFrameOffset);
                for (int bytes = raf.read(buffer); bytes > 0; bytes = raf.read(buffer)) {
                    fos.write(buffer, 0, bytes);
                }
                fos.flush();
            } catch (FileNotFoundException e) {
                appendMsg("File " + aFile.file + ": " + e);
            } catch (EOFException e) {
                appendMsg("File " + aFile.file + ": Done!");
            } catch (IOException e) {
                appendMsg("File " + aFile.file + ": " + e);
            }
        }
    }