diff -upr -X /usr/src/dontdiff libfishsound.orig/config.h.in libfishsound/config.h.in
--- libfishsound.orig/config.h.in	2004-10-19 23:00:55.000000000 +0200
+++ libfishsound/config.h.in	2004-10-16 20:19:02.000000000 +0200
@@ -15,6 +15,9 @@
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
 
+/* Define to 1 if you have libOggFLAC */
+#undef HAVE_FLAC
+
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
diff -upr -X /usr/src/dontdiff libfishsound.orig/configure.ac libfishsound/configure.ac
--- libfishsound.orig/configure.ac	2004-10-19 23:00:56.000000000 +0200
+++ libfishsound/configure.ac	2004-10-12 02:23:37.000000000 +0200
@@ -305,6 +305,37 @@ fi
 AM_CONDITIONAL(HAVE_SPEEX, [test "x$HAVE_SPEEX" = "xyes"])
 
 dnl
+dnl  Detect flac
+dnl
+
+HAVE_FLAC=no
+FLAC_SUPPORT=no
+
+ac_enable_flac=yes
+AC_ARG_ENABLE(flac,
+     [  --disable-flac        enable building of Flac codec support ],
+     [ ac_enable_flac=no ], [ ac_enable_flac=yes] )
+
+if test "x${ac_enable_flac}" = xyes ; then
+  AC_CHECK_LIB(OggFLAC, FLAC__file_decoder_init, HAVE_FLAC="maybe", , [-lm -logg])
+  if test "x$HAVE_FLAC" = xmaybe; then
+    AC_CHECK_HEADER(FLAC/all.h, HAVE_FLAC="yes", HAVE_FLAC="no")
+  fi
+  if test "x$HAVE_FLAC" = xyes ; then
+    AC_DEFINE(HAVE_FLAC, [1], [Define to 1 if you have libOggFLAC])
+    FLAC_LIBS="-lFLAC -logg -lm"
+    AC_SUBST(FLAC_LIBS)
+    FLAC_SUPPORT="yes"
+  else
+    AC_DEFINE(HAVE_FLAC, [0], [Define to 1 if you have libOggFLAC])
+  fi
+else
+  AC_DEFINE(HAVE_FLAC, [0], [Define to 1 if you have libOggFLAC])
+  FLAC_SUPPORT="disabled"
+fi
+AM_CONDITIONAL(HAVE_FLAC, [test "x$HAVE_FLAC" = "xyes"])
+
+dnl
 dnl  Check codec disabling sanity
 dnl
 if test "x${ac_enable_vorbis}" = xno && test "x${ac_enable_speex}" = xno ; then
@@ -442,6 +473,17 @@ if test "x$HAVE_SPEEX" = xmaybe ; then
 ])
 fi
 
+if test "x$HAVE_FLAC" != xyes ; then
+    AC_MSG_RESULT(
+[*** libOggFLAC, available from  http://flac.sourceforge.net/])
+fi
+if test "x$HAVE_FLAC" = xmaybe ; then
+    AC_MSG_RESULT(
+[      Development files missing: The libOggFLAC library binary seems to be
+      installed, but building of a test program failed.
+])
+fi
+
 AC_MSG_RESULT(
 [*** If you install the required libraries from source, you
 *** need to inform the dynamic linker of their location. If
@@ -516,6 +558,7 @@ AC_MSG_RESULT([
 
     Vorbis support: .............. $VORBIS_SUPPORT
     Speex support: ............... $SPEEX_SUPPORT
+    Flac support: ................ $FLAC_SUPPORT
 
   Example programs (./src/examples):
 
diff -upr -X /usr/src/dontdiff libfishsound.orig/include/fishsound/constants.h libfishsound/include/fishsound/constants.h
--- libfishsound.orig/include/fishsound/constants.h	2004-10-19 23:00:52.000000000 +0200
+++ libfishsound/include/fishsound/constants.h	2004-10-04 13:07:50.000000000 +0200
@@ -55,7 +55,10 @@ typedef enum _FishSoundCodecID {
   FISH_SOUND_VORBIS  = 0x01,
 
   /** Speex */
-  FISH_SOUND_SPEEX   = 0x02
+  FISH_SOUND_SPEEX   = 0x02,
+
+  /** Flac */
+  FISH_SOUND_FLAC    = 0x03
 } FishSoundCodecID;
 
 /** Command codes */
diff -upr -X /usr/src/dontdiff libfishsound.orig/src/examples/fishsound-decenc.c libfishsound/src/examples/fishsound-decenc.c
--- libfishsound.orig/src/examples/fishsound-decenc.c	2004-10-19 23:00:55.000000000 +0200
+++ libfishsound/src/examples/fishsound-decenc.c	2004-10-15 01:14:22.000000000 +0200
@@ -66,6 +66,7 @@ usage (char * progname)
   printf ("Options:\n");
   printf ("  --vorbis                  Use Vorbis as the output codec\n");
   printf ("  --speex                   Use Speex as the output codec\n");
+  printf ("  --flac                    Use Flac as the output codec\n");
   printf ("  --interleave              Use interleaved PCM internally\n");
   exit (1);
 }
@@ -224,6 +225,8 @@ main (int argc, char ** argv)
       format = FISH_SOUND_VORBIS;
     } else if (!strcmp (argv[i], "--speex")) {
       format = FISH_SOUND_SPEEX;
+    } else if (!strcmp (argv[i], "--flac")) {
+      format = FISH_SOUND_FLAC;
     } else if (!strcmp (argv[i], "--interleave")) {
       interleave = 1;
     } else if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "-h")) {
@@ -255,6 +258,15 @@ main (int argc, char ** argv)
     }
   }
 
+  if (format == FISH_SOUND_FLAC) {
+    if (HAVE_FLAC) {
+      printf ("Using Flac as the output codec\n");
+    } else {
+      fprintf (stderr, "Error: Flac support disabled\n");
+      exit (1);
+    }
+  }
+
   ed = fs_encdec_new (infilename, outfilename, format, interleave, blocksize);
 
   while ((n = oggz_read (ed->oggz_in, 1024)) > 0)
diff -upr -X /usr/src/dontdiff libfishsound.orig/src/examples/fishsound-encode.c libfishsound/src/examples/fishsound-encode.c
--- libfishsound.orig/src/examples/fishsound-encode.c	2004-10-19 23:00:55.000000000 +0200
+++ libfishsound/src/examples/fishsound-encode.c	2004-10-15 15:14:02.000000000 +0200
@@ -118,6 +118,8 @@ main (int argc, char ** argv)
   ext = strrchr (outfilename, '.');
   if (ext && !strncasecmp (ext, ".spx", 4))
     format = FISH_SOUND_SPEEX;
+  else if (ext && !strncasecmp (ext, ".flc", 4))
+    format = FISH_SOUND_FLAC;   
   else
     format = FISH_SOUND_VORBIS;
 
diff -upr -X /usr/src/dontdiff libfishsound.orig/src/examples/fishsound-identify.c libfishsound/src/examples/fishsound-identify.c
--- libfishsound.orig/src/examples/fishsound-identify.c	2004-10-19 23:00:55.000000000 +0200
+++ libfishsound/src/examples/fishsound-identify.c	2004-10-11 17:04:14.000000000 +0200
@@ -52,6 +52,7 @@ dump_identity (unsigned char * buf, long
   switch (format) {
   case FISH_SOUND_VORBIS: printf ("Vorbis\n"); break;
   case FISH_SOUND_SPEEX: printf ("Speex\n"); break;
+  case FISH_SOUND_FLAC: printf ("Flac\n"); break;
   default: printf ("Unknown\n");
   }
 
diff -upr -X /usr/src/dontdiff libfishsound.orig/src/libfishsound/fishsound.c libfishsound/src/libfishsound/fishsound.c
--- libfishsound.orig/src/libfishsound/fishsound.c	2004-10-19 23:00:54.000000000 +0200
+++ libfishsound/src/libfishsound/fishsound.c	2004-10-11 17:40:25.000000000 +0200
@@ -48,6 +48,9 @@ fish_sound_identify (unsigned char * buf
   if (fish_sound_speex_identify (buf, bytes) != FISH_SOUND_UNKNOWN)
     return FISH_SOUND_SPEEX;
 
+  if (fish_sound_flac_identify (buf, bytes) != FISH_SOUND_UNKNOWN)
+    return FISH_SOUND_FLAC;
+
   return FISH_SOUND_UNKNOWN;
 }
 
@@ -58,7 +61,9 @@ fish_sound_set_format (FishSound * fsoun
     fsound->codec = fish_sound_vorbis_codec ();
   } else if (format == FISH_SOUND_SPEEX) {
     fsound->codec = fish_sound_speex_codec ();
-  } else {
+  } else if (format == FISH_SOUND_FLAC) {
+    fsound->codec = fish_sound_flac_codec ();
+   } else {
     return -1;
   }
 
@@ -89,6 +94,9 @@ fish_sound_new (int mode, FishSoundInfo 
       if (!HAVE_SPEEX) {
         if (fsinfo->format == FISH_SOUND_SPEEX) return NULL;
       }
+      if (!HAVE_FLAC) {
+        if (fsinfo->format == FISH_SOUND_FLAC) return NULL;
+      }
     }
   } else if (mode != FISH_SOUND_DECODE) {
     return NULL;
diff -upr -X /usr/src/dontdiff libfishsound.orig/src/libfishsound/flac.c libfishsound/src/libfishsound/flac.c
--- libfishsound.orig/src/libfishsound/flac.c	2004-10-19 23:13:08.000000000 +0200
+++ libfishsound/src/libfishsound/flac.c	2004-10-17 13:45:36.000000000 +0200
@@ -0,0 +1,561 @@
+#define DEBUG
+#include <stdio.h>
+
+#include "config.h"
+
+#include "private.h"
+#include "convert.h"
+
+#if HAVE_FLAC
+#include "FLAC/all.h"
+
+#define BITS_PER_SAMPLE 24
+
+typedef struct _FishSoundFlacInfo {
+  FLAC__StreamDecoder *fsd;
+  FLAC__StreamEncoder *fse;
+  unsigned char * buffer;
+  char header;
+  long bufferlength;
+  unsigned long packetno;
+  struct {
+    unsigned char major, minor;
+  } version;
+  unsigned short header_packets;
+  void* pcm;
+} FishSoundFlacInfo;
+
+#ifdef FS_DECODE
+FLAC__StreamDecoderReadStatus fs_flac_read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+{
+  FishSound* fsound = (FishSound*)client_data;
+  FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data;
+#ifdef DEBUG
+  fprintf(stderr, "fs_flac_read_callback\n");
+#endif
+  if (fi->bufferlength > *bytes) {
+#ifdef DEBUG
+    fprintf(stderr, "too much data\n");
+#endif
+    return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+  } else if (fi->bufferlength < 1) {
+#ifdef DEBUG
+    fprintf(stderr, "no data\n");
+#endif
+    return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+  }
+  memcpy(buffer, fi->buffer, fi->bufferlength);
+  *bytes = fi->bufferlength;
+  fi->bufferlength = 0;
+  return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+}
+
+FLAC__StreamDecoderWriteStatus fs_flac_write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+{
+  FishSound* fsound = (FishSound*)client_data;
+  FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data;
+  int i, j, offset;
+#ifdef DEBUG
+  fprintf(stderr, "fs_flac_write_callback\n");
+#endif
+  switch (fsound->pcm_type) {
+  case FISH_SOUND_PCM_SHORT:
+    if (fsound->callback.decoded_short) {
+      if (fsound->interleave) {
+	FishSoundDecoded_ShortIlv dsi;
+	short* retpcm;
+	int shift = 16 - frame->header.bits_per_sample;
+	fi->pcm = realloc(fi->pcm, sizeof(short)*frame->header.channels*frame->header.blocksize);
+	retpcm = (short*) fi->pcm;
+	if (shift < 0) {
+	  shift = abs(shift);
+	  for (i=0; i<frame->header.blocksize; i++) {
+	    offset = i*frame->header.channels;
+	    for (j=0; j<frame->header.channels; j++)
+	      retpcm[offset + j] = buffer[j][i] >> shift;
+	  }
+	} else {
+	  for (i=0; i<frame->header.blocksize; i++) {
+	    offset = i*frame->header.channels;
+	    for (j=0; j<frame->header.channels; j++)
+	      retpcm[offset + j] = buffer[j][i] << shift;
+	  }
+	}
+	dsi = (FishSoundDecoded_ShortIlv)fsound->callback.decoded_short_ilv;
+	dsi (fsound, (short **)retpcm, frame->header.blocksize, fsound->user_data);
+      } else {
+	FishSoundDecoded_Short ds;
+	short** retpcm, *p;
+	int shift = 16 - frame->header.bits_per_sample;
+	fi->pcm = realloc(fi->pcm, sizeof(short)*frame->header.channels*frame->header.blocksize);
+	retpcm = fi->pcm;
+	if (shift < 0) {
+	  shift = abs(shift);
+	  for (i=0; i<frame->header.blocksize; i++)
+	    for (j=0; j<frame->header.channels; j++) {
+	      p = retpcm[j];
+	      p[i] = buffer[j][i] >> shift;
+	    }
+	} else {
+	  for (i=0; i<frame->header.blocksize; i++)
+	    for (j=0; j<frame->header.channels; j++) {
+	      p = retpcm[j];
+	      p[i] = buffer[j][i] << shift;
+	    }
+	}
+      	ds = (FishSoundDecoded_Short)fsound->callback.decoded_short;
+	ds (fsound, retpcm, frame->header.blocksize, fsound->user_data);
+      }
+    }
+    break;
+  case FISH_SOUND_PCM_INT:
+    if (fsound->callback.decoded_int) {
+      if (fsound->interleave) {
+	FishSoundDecoded_IntIlv dii;
+	int* retpcm;
+	int shift = 32 - frame->header.bits_per_sample;
+	fi->pcm = realloc(fi->pcm, sizeof(int)*frame->header.channels*frame->header.blocksize);
+	retpcm = (int*) fi->pcm;
+	for (i=0; i<frame->header.blocksize; i++) {
+	  offset = i*frame->header.channels;
+	  for (j=0; j<frame->header.channels; j++)
+	    retpcm[offset + j] = buffer[j][i] << shift;
+	}
+	dii = (FishSoundDecoded_IntIlv)fsound->callback.decoded_int_ilv;
+	dii (fsound, (int **)retpcm, frame->header.blocksize, fsound->user_data);
+      } else {
+	FishSoundDecoded_Int di;
+	int** retpcm, *p;
+	int shift = 32 - frame->header.bits_per_sample;
+	fi->pcm = realloc(fi->pcm, sizeof(int)*frame->header.channels*frame->header.blocksize);
+	retpcm = fi->pcm;
+	for (i=0; i<frame->header.blocksize; i++)
+	  for (j=0; j<frame->header.channels; j++) {
+	    p = retpcm[j];
+	    p[i] = buffer[j][i] << shift;
+	  }
+      	di = (FishSoundDecoded_Int)fsound->callback.decoded_int;
+	di (fsound, retpcm, frame->header.blocksize, fsound->user_data);
+      }
+    }
+    break;
+  case FISH_SOUND_PCM_FLOAT:
+    if (fsound->callback.decoded_float) {
+      if (fsound->interleave) {
+	FishSoundDecoded_FloatIlv dfi;
+	float* retpcm, norm = 1.0 / (1 + (1 << (frame->header.bits_per_sample - 1)));
+	fi->pcm = realloc(fi->pcm, sizeof(float)*frame->header.channels*frame->header.blocksize);
+	retpcm = (float*) fi->pcm;
+	for (i=0; i<frame->header.blocksize; i++) {
+	  offset = i*frame->header.channels;
+	  for (j=0; j<frame->header.channels; j++)
+	    retpcm[offset + j] = buffer[j][i] * norm;
+	}
+	dfi = (FishSoundDecoded_FloatIlv)fsound->callback.decoded_float_ilv;
+	dfi (fsound, (float **)retpcm, frame->header.blocksize, fsound->user_data);
+      } else {
+	FishSoundDecoded_Float df;
+	float** retpcm, *p, norm = 1.0 / (1 + (1 << (frame->header.bits_per_sample - 1)));
+	fi->pcm = realloc(fi->pcm, sizeof(float)*frame->header.channels*frame->header.blocksize);
+	retpcm = fi->pcm;
+	for (i=0; i<frame->header.blocksize; i++)
+	  for (j=0; j<frame->header.channels; j++) {
+	    p = retpcm[j];
+	    p[i] = buffer[j][i] * norm;
+	  }
+      	df = (FishSoundDecoded_Float)fsound->callback.decoded_float;
+	df (fsound, retpcm, frame->header.blocksize, fsound->user_data);
+      }
+    }
+    break;
+  case FISH_SOUND_PCM_DOUBLE:
+    if (fsound->callback.decoded_double) {
+      if (fsound->interleave) {
+	FishSoundDecoded_DoubleIlv ddi;
+	double* retpcm, norm = 1.0 / (1 + (1 << (frame->header.bits_per_sample - 1)));
+	fi->pcm = realloc(fi->pcm, sizeof(double)*frame->header.channels*frame->header.blocksize);
+	retpcm = (double*) fi->pcm;
+	for (i=0; i<frame->header.blocksize; i++) {
+	  offset = i*frame->header.channels;
+	  for (j=0; j<frame->header.channels; j++)
+	    retpcm[offset + j] = buffer[j][i] * norm;
+	}
+	ddi = (FishSoundDecoded_DoubleIlv)fsound->callback.decoded_double_ilv;
+	ddi (fsound, (double **)retpcm, frame->header.blocksize, fsound->user_data);
+      } else {
+	FishSoundDecoded_Double dd;
+	double** retpcm, *p, norm = 1.0 / (1 + (1 << (frame->header.bits_per_sample - 1)));
+	fi->pcm = realloc(fi->pcm, sizeof(double)*frame->header.channels*frame->header.blocksize);
+	retpcm = fi->pcm;
+	for (i=0; i<frame->header.blocksize; i++)
+	  for (j=0; j<frame->header.channels; j++) {
+	    p = retpcm[j];
+	    p[i] = buffer[j][i] * norm;
+	  }
+      	dd = (FishSoundDecoded_Double)fsound->callback.decoded_double;
+	dd (fsound, retpcm, frame->header.blocksize, fsound->user_data);
+      }
+    }
+    break;
+  default:
+    return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+    break;
+  }
+  return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+void fs_flac_meta_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+{
+  FishSound* fsound = (FishSound*)client_data;
+  /*  FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data; */
+#ifdef DEBUG
+  fprintf(stderr, "fs_flac_meta_callback\n");
+#endif
+  switch (metadata->type) {
+  case FLAC__METADATA_TYPE_STREAMINFO:
+    fsound->info.channels = metadata->data.stream_info.channels;
+    fsound->info.samplerate = metadata->data.stream_info.sample_rate;
+    break;
+  default:
+#ifdef DEBUG
+    fprintf(stderr, "not yet implemented type\n");
+#endif
+    break;
+  }
+}
+
+void fs_flac_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+{
+#ifdef DEBUG
+  fprintf(stderr, "fs_flac_error_callback\n");
+#endif
+  fprintf(stderr, "ERROR: %s\n", FLAC__StreamDecoderErrorStatusString[status]);
+}
+#endif
+
+#ifdef FS_ENCODE
+FLAC__StreamEncoderWriteStatus fs_flac_enc_write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
+{
+  FishSound* fsound = (FishSound*)client_data;
+  FishSoundFlacInfo *fi = fsound->codec_data;
+#ifdef DEBUG
+  fprintf(stderr, "fs_flac_enc_write_callback\n");
+  printf("bytes: %d, samples: %d\n", bytes, samples);
+#endif DEBUG
+  if (fsound->callback.encoded) {
+    FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback.encoded;
+    if (fi->packetno == 0 && fi->header <= 1) {
+      printf("first: %x\n", buffer[0]);
+      if (fi->header == 0) {
+	fi->buffer = (unsigned char*)malloc(sizeof(unsigned char)*(bytes+9));
+	fi->buffer[0] = 0x7f;
+	fi->buffer[1] = 0x46;
+	fi->buffer[2] = 0x4c;
+	fi->buffer[3] = 0x41;
+	fi->buffer[4] = 0x43;
+	fi->buffer[5] = 1;
+	fi->buffer[6] = 0;
+	fi->buffer[7] = 0;
+	fi->buffer[8] = 2;
+	memcpy (fi->buffer+9, buffer, bytes);
+        fi->bufferlength = bytes+9;
+	fi->header++;
+      } else {
+	unsigned char* tmp = (unsigned char*)malloc(sizeof(unsigned char)*(bytes+fi->bufferlength));
+	memcpy (tmp, fi->buffer, fi->bufferlength);
+	memcpy (tmp+fi->bufferlength, buffer, bytes);
+	fs_free(fi->buffer);
+	fi->buffer = tmp;
+	fi->bufferlength += bytes;
+	fi->header++;
+	encoded (fsound, (unsigned char *)fi->buffer, (long)fi->bufferlength,
+		 fsound->user_data);
+      }
+    } else {
+      encoded (fsound, (unsigned char *)buffer, (long)bytes,
+	       fsound->user_data);
+    }
+  }
+  return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
+}
+
+void fs_flac_enc_meta_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
+{
+  FishSound* fsound = (FishSound*)client_data;
+  /*  FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data; */
+#ifdef DEBUG
+  fprintf(stderr, "fs_flac_meta_callback\n");
+#endif
+  switch (metadata->type) {
+  case FLAC__METADATA_TYPE_STREAMINFO:
+    printf("channels %d\n", metadata->data.stream_info.channels);
+    /*
+    fsound->info.channels = metadata->data.stream_info.channels;
+    fsound->info.samplerate = metadata->data.stream_info.sample_rate;
+    */
+    break;
+  default:
+#ifdef DEBUG
+    fprintf(stderr, "not yet implemented type\n");
+#endif
+    break;
+  }
+}
+#endif
+
+int
+fish_sound_flac_identify (unsigned char * buf, long bytes)
+{
+  if (buf[0] != 0x7f) return FISH_SOUND_UNKNOWN;
+  if (bytes < 8) return FISH_SOUND_UNKNOWN;
+  if (!strncmp ((char *)buf+1, "FLAC", 4)) {
+#ifdef DEBUG
+    fprintf(stderr, "flac found\n");
+#endif
+    /* if only a short buffer was passed, do a weak identify */
+    if (bytes == 8) return FISH_SOUND_FLAC;
+
+    /* otherwise, assume the buffer is an entire initial header and
+     * feed it to vorbis_synthesis_headerin() */
+    if (!strncmp ((char *)buf+9, "fLaC", 4)) {
+      return FISH_SOUND_FLAC;
+    }
+  }
+  return FISH_SOUND_UNKNOWN;
+}
+
+static int
+fs_flac_command (FishSound * fsound, int command, void * data,
+		   int datasize)
+{
+  return 0;
+}
+
+#if FS_ENCODE
+static FishSound *
+fs_flac_enc_headers (FishSound * fsound)
+{
+  FishSoundFlacInfo *fi = fsound->codec_data;
+  fi->fse = FLAC__stream_encoder_new();
+  FLAC__stream_encoder_set_channels(fi->fse, fsound->info.channels);
+  FLAC__stream_encoder_set_sample_rate(fi->fse, fsound->info.samplerate);
+  FLAC__stream_encoder_set_bits_per_sample(fi->fse, BITS_PER_SAMPLE);
+  FLAC__stream_encoder_set_write_callback(fi->fse, fs_flac_enc_write_callback);
+  FLAC__stream_encoder_set_metadata_callback(fi->fse, fs_flac_enc_meta_callback);
+  FLAC__stream_encoder_set_client_data(fi->fse, fsound);
+  //  FLAC__stream_encoder_set_total_samples_estimate(fi->fse, );
+  if (FLAC__stream_encoder_init(fi->fse) != FLAC__STREAM_ENCODER_OK) return NULL;
+  return fsound;
+}
+
+static long
+fs_flac_encode_i_ilv (FishSound * fsound, int ** pcm, long frames)
+{
+  FishSoundFlacInfo *fi = fsound->codec_data;
+  int i, *p = (int *)pcm;
+  printf("frames: %ld\n", frames);
+  if (fi->packetno == 0)
+    fs_flac_enc_headers (fsound);
+  //  FLAC__stream_encoder_process_interleaved(fi->fse, pcm, frames);
+  fi->packetno++;
+  return 0;
+}
+
+static long
+fs_flac_encode_f_ilv (FishSound * fsound, float ** pcm, long frames)
+{
+  FishSoundFlacInfo *fi = fsound->codec_data;
+  FLAC__int32 *buffer;
+  float * p = (float*)pcm, norm = (1 << (BITS_PER_SAMPLE - 1));
+  int i;
+  long length = frames * fsound->info.channels;
+#ifdef DEBUG
+  fprintf(stderr, "fs_flac_encode_f_ilv\n");
+#endif
+  fi->pcm = realloc(fi->pcm, sizeof(FLAC__int32)*fsound->info.channels*frames);
+  buffer = (FLAC__int32*) fi->pcm;
+  for (i=0; i<length; i++)
+    buffer[i] = p[i] * norm;
+
+  if (fi->packetno == 0)
+    fs_flac_enc_headers (fsound);
+  FLAC__stream_encoder_process_interleaved(fi->fse, buffer, frames);
+  fi->packetno++;
+  return 0;
+}
+#endif
+
+#if FS_DECODE
+static void*
+process_header(FishSound * fsound, unsigned char *buf, long bytes)
+{
+  FishSoundFlacInfo *fi = fsound->codec_data;
+  if (buf[0] != 0x7f) return NULL;
+  if (strncmp(buf+1, "FLAC", 4) != 0) return NULL;
+  fi->version.major = buf[5];
+  fi->version.minor = buf[6];
+#ifdef DEBUG
+  printf("Flac Version: %d.%d\n", fi->version.major, fi->version.minor);
+#endif
+  fi->header_packets = buf[7] << 8 | buf[8];
+#ifdef DEBUG
+  printf("Number of Header packets: %d\n", fi->header_packets);
+#endif
+
+  if ((fi->fsd = FLAC__stream_decoder_new()) == NULL) return NULL;
+  FLAC__stream_decoder_set_read_callback(fi->fsd, fs_flac_read_callback);
+  FLAC__stream_decoder_set_write_callback(fi->fsd, fs_flac_write_callback);
+  FLAC__stream_decoder_set_metadata_callback(fi->fsd, fs_flac_meta_callback);
+  FLAC__stream_decoder_set_error_callback(fi->fsd, fs_flac_error_callback);
+  FLAC__stream_decoder_set_client_data(fi->fsd, fsound);
+  if (FLAC__stream_decoder_init(fi->fsd) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
+    return NULL;
+
+  return fi->fsd;
+}
+
+static long
+fs_flac_decode (FishSound * fsound, unsigned char * buf, long bytes)
+{
+  FishSoundFlacInfo *fi = fsound->codec_data;
+#ifdef DEBUG
+  fprintf(stderr, "fs_flac_decode\n");
+#endif
+  if (fi->packetno == 0) {
+    if (process_header(fsound, buf, bytes) == NULL) {
+      fprintf(stderr, "EROROROROR\n");
+      return -1;
+    }
+    fi->buffer = fs_malloc(sizeof(unsigned char)*bytes);
+    memcpy(fi->buffer, buf+9, bytes-9);
+    fi->bufferlength = bytes-9;
+  }
+  else if (fi->packetno <= fi->header_packets){
+    unsigned char* tmp = fs_malloc(sizeof(unsigned char)*(fi->bufferlength+bytes));
+    /*    if (fi->packetno ==  1)    fish_sound_comments_decode (fsound, buf, bytes); */
+    memcpy(tmp, fi->buffer, fi->bufferlength);
+    memcpy(tmp+fi->bufferlength, buf, bytes);
+    fi->bufferlength += bytes;
+    fs_free(fi->buffer);
+    fi->buffer = tmp;
+    if (fi->packetno == fi->header_packets) {
+      FLAC__stream_decoder_process_until_end_of_metadata(fi->fsd);
+      fs_free(fi->buffer);
+    }
+    /*
+  if (fi->packetno == 0) {
+    if (process_header(fi, buf, bytes) == NULL) printf("EROROROROR\n");
+    buf[13] |= 0x80;
+    fi->buffer = buf+9;
+    fi->bufferlength = bytes-9;
+    FLAC__stream_decoder_process_until_end_of_metadata(fi->fsd);
+    //  } else if (fi->packetno == 1) {
+    //    fish_sound_comments_decode (fsound, buf, bytes);
+  } else if (fi->packetno <= fi->header_packets) {
+    buf[0] |= 0x80;
+    fi->buffer = buf;
+    fi->bufferlength = bytes;
+    FLAC__stream_decoder_process_until_end_of_metadata(fi->fsd);
+    */
+  } else {
+    fi->buffer = buf;
+    fi->bufferlength = bytes;
+    FLAC__stream_decoder_process_single(fi->fsd);
+  }
+  fi->packetno++;
+  return 0;
+}
+#else /* !FS_DECODE */
+
+#define fs_flac_decode NULL
+
+#endif
+
+static FishSound *
+fs_flac_delete (FishSound * fsound)
+{
+  FishSoundFlacInfo * fi = (FishSoundFlacInfo *)fsound->codec_data;
+
+  if (fsound->mode == FISH_SOUND_DECODE) {
+    FLAC__stream_decoder_finish(fi->fsd);
+    FLAC__stream_decoder_delete(fi->fsd);
+  } else if (fsound->mode == FISH_SOUND_ENCODE) {
+    FLAC__stream_encoder_finish(fi->fse);
+    FLAC__stream_encoder_delete(fi->fse);
+    if (fi->buffer) fs_free(fi->buffer);
+  }
+  if (fi->pcm) fs_free(fi->pcm);
+  fs_free (fi);
+  fsound->codec_data = NULL;
+
+  return fsound;
+}
+
+static int
+fs_flac_reset (FishSound * fsound)
+{
+  FishSoundFlacInfo * fi = (FishSoundFlacInfo *)fsound->codec_data;
+  if (fsound->mode == FISH_SOUND_DECODE) {
+    FLAC__stream_decoder_reset(fi->fsd);
+  } else if (fsound->mode == FISH_SOUND_ENCODE) {
+  }
+  return 0;
+}
+
+static FishSound *
+fs_flac_init (FishSound * fsound)
+{
+  FishSoundFlacInfo *fi;
+
+  fi = fs_malloc (sizeof (FishSoundFlacInfo));
+  if (fi == NULL) return NULL;
+  fi->packetno = 0;
+  fi->header = 0;
+  fi->pcm = NULL;
+  fi->header_packets = 0;
+  fi->fsd = NULL;
+  fi->fse = NULL;
+
+  fsound->codec_data = fi;
+
+#if FS_ENCODE
+  /*
+  if (fsound->mode == FISH_SOUND_ENCODE) {
+    fs_flac_enc_init (fsound);
+  }
+  */
+#endif /* FS_ENCODE */
+
+  return fsound;
+}
+
+FishSoundCodec *
+fish_sound_flac_codec (void)
+{
+  FishSoundCodec * codec;
+
+  codec = (FishSoundCodec *) fs_malloc (sizeof (FishSoundCodec));
+
+  codec->format.format = FISH_SOUND_FLAC;
+  codec->format.name = "Flac (Xiph.Org)";
+  codec->format.extension = "ogg";
+
+  codec->init = fs_flac_init;
+  codec->del = fs_flac_delete;
+  codec->reset = fs_flac_reset;
+  codec->command = fs_flac_command;
+  codec->decode = fs_flac_decode;
+  codec->encode_s = NULL;
+  codec->encode_s_ilv = NULL;
+  codec->encode_i = NULL;
+  codec->encode_i_ilv = fs_flac_encode_i_ilv;
+  codec->encode_f = NULL;
+  codec->encode_f_ilv = fs_flac_encode_f_ilv;
+  codec->encode_d = NULL;
+  codec->encode_d_ilv = NULL;
+  codec->flush = NULL;
+
+  return codec;
+}
+
+#endif
diff -upr -X /usr/src/dontdiff libfishsound.orig/src/libfishsound/Makefile.am libfishsound/src/libfishsound/Makefile.am
--- libfishsound.orig/src/libfishsound/Makefile.am	2004-10-19 23:00:55.000000000 +0200
+++ libfishsound/src/libfishsound/Makefile.am	2004-10-15 16:45:17.000000000 +0200
@@ -21,7 +21,8 @@ libfishsound_la_SOURCES = \
 	comments.c \
 	speex.c \
 	vorbis.c \
+	flac.c \
 	fs_vector.c
 
 libfishsound_la_LDFLAGS = -version-info @SHARED_VERSION_INFO@ @SHLIB_VERSION_ARG@
-libfishsound_la_LIBADD = $(VORBIS_LIBS) $(SPEEX_LIBS)
+libfishsound_la_LIBADD = $(VORBIS_LIBS) $(SPEEX_LIBS) $(FLAC_LIBS)
diff -upr -X /usr/src/dontdiff libfishsound.orig/src/libfishsound/private.h libfishsound/src/libfishsound/private.h
--- libfishsound.orig/src/libfishsound/private.h	2004-10-19 23:00:54.000000000 +0200
+++ libfishsound/src/libfishsound/private.h	2004-10-13 02:13:27.000000000 +0200
@@ -209,6 +209,9 @@ FishSoundCodec * fish_sound_vorbis_codec
 int fish_sound_speex_identify (unsigned char * buf, long bytes);
 FishSoundCodec * fish_sound_speex_codec (void);
 
+int fish_sound_flac_identify (unsigned char * buf, long bytes);
+FishSoundCodec * fish_sound_flac_codec (void);
+
 /* comments */
 int fish_sound_comments_init (FishSound * fsound);
 int fish_sound_comments_free (FishSound * fsound);
diff -upr -X /usr/src/dontdiff libfishsound.orig/src/tests/encdec-audio.c libfishsound/src/tests/encdec-audio.c
--- libfishsound.orig/src/tests/encdec-audio.c	2004-10-19 23:00:54.000000000 +0200
+++ libfishsound/src/tests/encdec-audio.c	2004-10-15 16:50:38.000000000 +0200
@@ -53,6 +53,7 @@ usage (char * progname)
   printf ("  --nasty                   Run with large test parameters\n");
   printf ("  --disable-vorbis          Disable testing of Vorbis codec\n");
   printf ("  --disable-speex           Disable testing of Speex codec\n");
+  printf ("  --disable-flac           Disable testing of Flac codec\n");
   printf ("  --disable-interleave      Disable testing of interleave\n");
   printf ("  --disable-non-interleave  Disable testing of non-interleave\n");
   exit (1);
@@ -88,7 +89,7 @@ static char * pcm_name[] = {
 /* For one-time tests, configure these by commandline args */
 static int * test_blocksizes, * test_samplerates, * test_channels;
 static int iter = DEFAULT_ITER;
-static int test_vorbis = HAVE_VORBIS, test_speex = HAVE_SPEEX;
+static int test_vorbis = HAVE_VORBIS, test_speex = HAVE_SPEEX, test_flac = HAVE_FLAC;
 static int test_interleave = 1, test_non_interleave = 1;
 
 static int nasty_blocksizes[] = {128, 256, 512, 1024, 2048, 4096, 0};
@@ -389,7 +390,7 @@ fs_encdec_test (FishSoundPCM pcm_type, i
   snprintf (msg, 128,
 	    "+ %2d channel %6d Hz %s %d frame %-6s (%s)",
 	    channels, samplerate,
-	    format == FISH_SOUND_VORBIS ? "Vorbis," : "Speex, ",
+	    format == FISH_SOUND_VORBIS ? "Vorbis," : (format == FISH_SOUND_FLAC ? "Flac," : "Speex, "),
 	    blocksize, pcm_name[pcm_type],
 	    interleave ? "interleave" : "non-interleave");
   INFO (msg);
@@ -435,6 +436,8 @@ parse_args (int argc, char * argv[])
       test_vorbis = 0;
     } else if (!strcmp (argv[i], "--disable-speex")) {
       test_speex = 0;
+    } else if (!strcmp (argv[i], "--disable-flac")) {
+      test_flac = 0;
     } else if (!strcmp (argv[i], "--disable-interleave")) {
       test_interleave = 0;
     } else if (!strcmp (argv[i], "--disable-non-interleave")) {
@@ -453,6 +456,7 @@ parse_args (int argc, char * argv[])
 
   if (!test_vorbis) INFO ("* DISABLED testing of Vorbis");
   if (!test_speex) INFO ("* DISABLED testing of Speex");
+  if (!test_flac) INFO ("* DISABLED testing of Flac");
   if (!test_interleave) INFO ("* DISABLED testing of INTERLEAVE");
   if (!test_non_interleave) INFO ("* DISABLED testing of NON-INTERLEAVE");
 }
@@ -489,6 +493,15 @@ main (int argc, char * argv[])
 	      
 	      }
 	    }
+
+	    /* Test FLAC */
+	    if (test_flac) {
+	      if (test_channels[c] <= 8) {
+		fs_encdec_test (pcm_type, test_samplerates[s], test_channels[c],
+				FISH_SOUND_FLAC, 0, test_blocksizes[b]);
+	      
+	      }
+	    }
 	  }
 
 	  if (test_interleave) {
@@ -506,6 +519,15 @@ main (int argc, char * argv[])
 	      
 	      }
 	    }
+
+	    /* Test FLAC */
+	    if (test_flac) {
+	      if (test_channels[c] <= 8) {
+		fs_encdec_test (pcm_type, test_samplerates[s], test_channels[c],
+				FISH_SOUND_FLAC, 1, test_blocksizes[b]);
+	      
+	      }
+	    }
 	  }
 	}
       }
