From 3a1b55d2f77765d2cd6f771d2c275c620a0622ad Mon Sep 17 00:00:00 2001
From: johns <>
Date: Fri, 26 Jul 2002 23:53:20 +0000
Subject: [PATCH] Mp3 now works again, but still no stream support.

---
 src/sound/mad.cpp | 259 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 257 insertions(+), 2 deletions(-)

diff --git a/src/sound/mad.cpp b/src/sound/mad.cpp
index 3c4a0fc38..b770ba235 100644
--- a/src/sound/mad.cpp
+++ b/src/sound/mad.cpp
@@ -178,6 +178,245 @@ local enum mad_flow MAD_error(void *user __attribute__((unused)),
     return MAD_FLOW_BREAK;
 }
 
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+#if 0
+
+/**
+**	Type member function to read from the ogg file
+**
+**	@param sample	    Sample reading from
+**	@param buf	    Buffer to write data to
+**	@param len	    Length of the buffer
+**
+**	@return		    Number of bytes read
+*/
+local int Mp3ReadStream(Sample* sample, void* buf, int len)
+{
+    Mp3Data* data;
+    int i;
+    int n;
+    int bitstream;
+
+    data = (Mp3Data*) sample->User;
+
+    // see if we have enough read already
+    if (data->PointerInBuffer + len - sample->Data > sample->Length) {
+	// not enough in buffer, read more
+	n = sample->Length - (data->PointerInBuffer - sample->Data);
+	memcpy(sample->Data, data->PointerInBuffer, n);
+	sample->Length = n;
+	data->PointerInBuffer = sample->Data;
+
+	n = OGG_BUFFER_SIZE - n;
+	for (;;) {
+	    i = ov_read(data->VorbisFile,
+		    data->PointerInBuffer + sample->Length, n, 0, 2, 1,
+		    &bitstream);
+	    if (i <= 0) {
+		break;
+	    }
+	    sample->Length += i;
+	    n -= i;
+	    if (n < 4096) {
+		break;
+	    }
+	}
+	if (sample->Length < len) {
+	    len = sample->Length;
+	}
+    }
+
+    memcpy(buf, data->PointerInBuffer, len);
+    data->PointerInBuffer += len;
+    return len;
+}
+
+/**
+**	Type member function to free an ogg file
+**
+**	@param sample	    Sample to free
+*/
+local void Mp3FreeStream(Sample* sample)
+{
+    Mp3Data* data;
+
+    IfDebug( AllocatedSoundMemory -= sizeof(*sample) + OGG_BUFFER_SIZE);
+
+    data = (Mp3Data*)sample->User;
+    ov_clear(data->VorbisFile);
+    free(data);
+    free(sample);
+}
+
+/**
+**	Mp3 object type structure.
+*/
+local const SampleType Mp3StreamSampleType = {
+    Mp3ReadStream,
+    Mp3FreeStream,
+};
+#endif
+
+/**
+**	Type member function to read from the ogg file
+**
+**	@param sample	    Sample reading from
+**	@param buf	    Buffer to write data to
+**	@param len	    Length of the buffer
+**
+**	@return		    Number of bytes read
+*/
+local int Mp3Read(Sample* sample, void* buf, int len)
+{
+    unsigned pos;
+
+    pos = (unsigned)sample->User;
+    if (pos + len > sample->Length) {		// Not enough data?
+	len = sample->Length - pos;
+    }
+    memcpy(buf, sample->Data + pos, len);
+
+    sample->User = (void*)(pos + len);
+
+    return len;
+}
+
+/**
+**	Type member function to free an ogg file
+**
+**	@param sample	    Sample to free
+*/
+local void Mp3Free(Sample* sample)
+{
+    IfDebug( AllocatedSoundMemory -= sample->Length; );
+
+    free(sample);
+}
+
+/**
+**	Mp3 object type structure.
+*/
+local const SampleType Mp3SampleType = {
+    Mp3Read,
+    Mp3Free,
+};
+
+/**
+**	Test code.
+*/
+static int run_sync(struct mad_decoder *decoder)
+{
+    enum mad_flow (*error_func) (void *, struct mad_stream *,
+	struct mad_frame *);
+    void *error_data;
+    int bad_last_frame = 0;
+    struct mad_stream *stream;
+    struct mad_frame *frame;
+    struct mad_synth *synth;
+    int result = 0;
+
+    error_func = decoder->error_func;
+    error_data = decoder->cb_data;
+
+    stream = &decoder->sync->stream;
+    frame = &decoder->sync->frame;
+    synth = &decoder->sync->synth;
+
+    mad_stream_init(stream);
+    mad_frame_init(frame);
+    mad_synth_init(synth);
+
+    mad_stream_options(stream, decoder->options);
+
+    do {
+	switch (decoder->input_func(decoder->cb_data, stream)) {
+	    case MAD_FLOW_STOP:
+		goto done;
+	    case MAD_FLOW_BREAK:
+		goto fail;
+	    case MAD_FLOW_IGNORE:
+		continue;
+	    case MAD_FLOW_CONTINUE:
+		break;
+	}
+
+	while (1) {
+	    if (decoder->header_func) {
+		if (mad_header_decode(&frame->header, stream) == -1) {
+		    if (!MAD_RECOVERABLE(stream->error))
+			break;
+
+		    switch (error_func(error_data, stream, frame)) {
+			case MAD_FLOW_STOP:
+			    goto done;
+			case MAD_FLOW_BREAK:
+			    goto fail;
+			case MAD_FLOW_IGNORE:
+			case MAD_FLOW_CONTINUE:
+			default:
+			    continue;
+		    }
+		}
+
+		switch (decoder->header_func(decoder->cb_data, &frame->header)) {
+		    case MAD_FLOW_STOP:
+			goto done;
+		    case MAD_FLOW_BREAK:
+			goto fail;
+		    case MAD_FLOW_IGNORE:
+			continue;
+		    case MAD_FLOW_CONTINUE:
+			break;
+		}
+	    }
+
+	    if (mad_frame_decode(frame, stream) == -1) {
+		if (!MAD_RECOVERABLE(stream->error))
+		    break;
+
+		switch (error_func(error_data, stream, frame)) {
+		    case MAD_FLOW_STOP:
+			goto done;
+		    case MAD_FLOW_BREAK:
+			goto fail;
+		    case MAD_FLOW_IGNORE:
+			break;
+		    case MAD_FLOW_CONTINUE:
+		    default:
+			continue;
+		}
+	    } else
+		bad_last_frame = 0;
+
+	    mad_synth_frame(synth, frame);
+
+	    if (decoder->output_func) {
+		switch (decoder->output_func(decoder->cb_data, &frame->header,
+			&synth->pcm)) {
+		    case MAD_FLOW_STOP:
+			goto done;
+		    case MAD_FLOW_BREAK:
+			goto fail;
+		    case MAD_FLOW_IGNORE:
+		    case MAD_FLOW_CONTINUE:
+			break;
+		}
+	    }
+	}
+    } while (stream->error == MAD_ERROR_BUFLEN);
+
+fail:
+    result = -1;
+
+done:
+    mad_synth_finish(synth);
+    mad_frame_finish(frame);
+    mad_stream_finish(stream);
+
+    return result;
+}
+
 /**
 **	Load mp3.
 **
@@ -229,15 +468,31 @@ global Sample *LoadMp3(const char* name, int flags __attribute__((unused)))
 	MAD_error, 0 /* message */);
 
     // start decoding
+    // mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
 
-    mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
+    decoder.sync = malloc(sizeof(*decoder.sync));
+    if (!decoder.sync) {
+	mad_decoder_finish(&decoder);
+	CLclose(f);
+	return NULL;
+    }
+
+    run_sync(&decoder);
+
+    free(decoder.sync);
+    decoder.sync = 0;
 
     // release the decoder
 
     mad_decoder_finish(&decoder);
-
     CLclose(f);
 
+    user.Sample->Type = &Mp3SampleType;
+    user.Sample->User = 0;
+
+    DebugLevel0Fn(" %d\n" _C_ user.Sample->Length);
+    IfDebug( AllocatedSoundMemory += user.Sample->Length; );
+
     return user.Sample;
 }