From 4bf163ecfac27c3dd86dff96df6f4647f9afe021 Mon Sep 17 00:00:00 2001

From: =?UTF-8?q?Jaakko=20Ker=C3=A4nen?= jaakko.keranen@iki.fi

Date: Fri, 9 Oct 2020 14:19:40 +0300

Subject: [PATCH 1/1] Cleanup

Moved buffers out of player.c. Include MIME type with the data so the correct decoder can be chosen.

Added stb_vorbis: https://github.com/nothings/stb


CMakeLists.txt | 3 +

src/audio/buf.c | 107 +

src/audio/buf.h | 74 +

src/audio/player.c | 197 +-

src/audio/player.h | 4 +-

src/audio/stb_vorbis.c | 5563 ++++++++++++++++++++++++++++++++++++++++

src/media.c | 8 +-

7 files changed, 5802 insertions(+), 154 deletions(-)

create mode 100644 src/audio/buf.c

create mode 100644 src/audio/buf.h

create mode 100644 src/audio/stb_vorbis.c

diff --git a/CMakeLists.txt b/CMakeLists.txt

index 15ff9a0a..263942e3 100644

--- a/CMakeLists.txt

+++ b/CMakeLists.txt

@@ -106,8 +106,11 @@ set (SOURCES

 src/visited.c

 src/visited.h

 # Audio playback:

 src/audio/player.c

 src/audio/player.h

 # User interface:

 src/ui/color.c

 src/ui/color.h

diff --git a/src/audio/buf.c b/src/audio/buf.c

new file mode 100644

index 00000000..e61164d4

--- /dev/null

+++ b/src/audio/buf.c

@@ -0,0 +1,107 @@

+/* Copyright 2020 Jaakko Keränen jaakko.keranen@iki.fi

+Redistribution and use in source and binary forms, with or without

+modification, are permitted provided that the following conditions are met:

+1. Redistributions of source code must retain the above copyright notice, this

+2. Redistributions in binary form must reproduce the above copyright notice,

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */

+#include "buf.h"

+iDefineTypeConstruction(InputBuf)

+void init_InputBuf(iInputBuf *d) {

+}

+void deinit_InputBuf(iInputBuf *d) {

+}

+size_t size_InputBuf(const iInputBuf *d) {

+}

+/----------------------------------------------------------------------------------------------/

+iDefineTypeConstructionArgs(SampleBuf, (SDL_AudioFormat format, size_t numChannels, size_t count),

+void init_SampleBuf(iSampleBuf *d, SDL_AudioFormat format, size_t numChannels, size_t count) {

+}

+void deinit_SampleBuf(iSampleBuf *d) {

+}

+size_t size_SampleBuf(const iSampleBuf *d) {

+}

+size_t vacancy_SampleBuf(const iSampleBuf *d) {

+}

+iBool isFull_SampleBuf(const iSampleBuf *d) {

+}

+void write_SampleBuf(iSampleBuf *d, const void *samples, const size_t n) {

+}

+void read_SampleBuf(iSampleBuf *d, const size_t n, void *samples_out) {

+}

diff --git a/src/audio/buf.h b/src/audio/buf.h

new file mode 100644

index 00000000..de123481

--- /dev/null

+++ b/src/audio/buf.h

@@ -0,0 +1,74 @@

+/* Copyright 2020 Jaakko Keränen jaakko.keranen@iki.fi

+Redistribution and use in source and binary forms, with or without

+modification, are permitted provided that the following conditions are met:

+1. Redistributions of source code must retain the above copyright notice, this

+2. Redistributions in binary form must reproduce the above copyright notice,

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR

+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON

+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */

+#pragma once

+#include "the_Foundation/block.h"

+#include "the_Foundation/mutex.h"

+#include <SDL_audio.h>

+iDeclareType(InputBuf)

+iDeclareType(SampleBuf)

+#if !defined (AUDIO_S24LSB)

+# define AUDIO_S24LSB 0x8018 /* 24-bit integer samples */

+#endif

+#if !defined (AUDIO_F64LSB)

+# define AUDIO_F64LSB 0x8140 /* 64-bit floating point samples */

+#endif

+struct Impl_InputBuf {

+};

+iDeclareTypeConstruction(InputBuf)

+size_t size_InputBuf (const iInputBuf *);

+/----------------------------------------------------------------------------------------------/

+struct Impl_SampleBuf {

+};

+iDeclareTypeConstructionArgs(SampleBuf, SDL_AudioFormat format, size_t numChannels, size_t count)

+size_t size_SampleBuf (const iSampleBuf *);

+iBool isFull_SampleBuf (const iSampleBuf *);

+size_t vacancy_SampleBuf (const iSampleBuf *);

+iLocalDef void *ptr_SampleBuf_(iSampleBuf *d, size_t pos) {

+}

+void write_SampleBuf (iSampleBuf *, const void *samples, const size_t n);

+void read_SampleBuf (iSampleBuf *, const size_t n, void *samples_out);

diff --git a/src/audio/player.c b/src/audio/player.c

index 07f41f01..0825dabd 100644

--- a/src/audio/player.c

+++ b/src/audio/player.c

@@ -21,146 +21,38 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */

#include "player.h"

+#include "buf.h"

+#define STB_VORBIS_HEADER_ONLY

+#include "stb_vorbis.c"

#include <the_Foundation/buffer.h>

#include <the_Foundation/thread.h>

#include <SDL_audio.h>

-iDeclareType(InputBuf)

-#if !defined (AUDIO_S24LSB)

-# define AUDIO_S24LSB 0x8018 /* 24-bit integer samples */

-#endif

-#if !defined (AUDIO_F64LSB)

-# define AUDIO_F64LSB 0x8140 /* 64-bit floating point samples */

-#endif

-struct Impl_InputBuf {

-};

-void init_InputBuf(iInputBuf *d) {

-}

-void deinit_InputBuf(iInputBuf *d) {

-}

-size_t size_InputBuf(const iInputBuf *d) {

-}

-iDefineTypeConstruction(InputBuf)

-/----------------------------------------------------------------------------------------------/

-iDeclareType(SampleBuf)

-struct Impl_SampleBuf {

-};

-void init_SampleBuf(iSampleBuf *d, SDL_AudioFormat format, size_t numChannels, size_t count) {

-}

-void deinit_SampleBuf(iSampleBuf *d) {

-}

-size_t size_SampleBuf(const iSampleBuf *d) {

-}

-size_t vacancy_SampleBuf(const iSampleBuf *d) {

-}

-iBool isFull_SampleBuf(const iSampleBuf *d) {

-}

-iLocalDef void *ptr_SampleBuf_(iSampleBuf *d, size_t pos) {

-}

-void write_SampleBuf(iSampleBuf *d, const void *samples, const size_t n) {

-}

-void read_SampleBuf(iSampleBuf *d, const size_t n, void *samples_out) {

-}

/----------------------------------------------------------------------------------------------/

iDeclareType(ContentSpec)

-struct Impl_ContentSpec {

-};

-iDeclareType(Decoder)

enum iDecoderType {

 none_DecoderType,

 wav_DecoderType,

 vorbis_DecoderType,

 midi_DecoderType,

};

+struct Impl_ContentSpec {

+};

+iDeclareType(Decoder)

struct Impl_Decoder {

 enum iDecoderType type;

 float             gain;

@@ -176,12 +68,12 @@ struct Impl_Decoder {

 iRanges           wavData;

};

-enum iDecoderParseStatus {

+enum iDecoderStatus {

};

-static enum iDecoderParseStatus parseWav_Decoder_(iDecoder *d, iRanges inputRange) {

+static enum iDecoderStatus decodeWav_Decoder_(iDecoder *d, iRanges inputRange) {

 const uint8_t numChannels     = d->output.numChannels;

 const size_t  inputSampleSize = numChannels * SDL_AUDIO_BITSIZE(d->inputFormat) / 8;

 const size_t  vacancy         = vacancy_SampleBuf(&d->output);

@@ -189,11 +81,11 @@ static enum iDecoderParseStatus parseWav_Decoder_(iDecoder *d, iRanges inputRang

 const size_t  avail =

     iMin(inputRange.end - inputBytePos, d->wavData.end - inputBytePos) / inputSampleSize;

 if (avail == 0) {

 }

 const size_t n = iMin(vacancy, avail);

 if (n == 0) {

 }

 void *samples = malloc(inputSampleSize * n);

 /* Get a copy of the input for mixing. */ {

@@ -259,7 +151,7 @@ static enum iDecoderParseStatus parseWav_Decoder_(iDecoder *d, iRanges inputRang

 iGuardMutex(&d->outputMutex, write_SampleBuf(&d->output, samples, n));

 d->currentSample += n;

 free(samples);

}

static iThreadResult run_Decoder_(iThread *thread) {

@@ -273,17 +165,17 @@ static iThreadResult run_Decoder_(iThread *thread) {

     iAssert(inputRange.start <= inputRange.end);

     if (!d->type) break;

     /* Have data to work on and a place to save output? */

     if (!isEmpty_Range(&inputRange)) {

         switch (d->type) {

             case wav_DecoderType:

                 break;

             default:

                 break;

         }

     }

         lock_Mutex(&d->input->mtx);

         if (size_InputBuf(d->input) == inputSize) {

             wait_Condition(&d->input->changed, &d->input->mtx);

@@ -302,10 +194,10 @@ static iThreadResult run_Decoder_(iThread *thread) {

}

void init_Decoder(iDecoder *d, iInputBuf *input, const iContentSpec *spec) {

 d->gain        = 0.5f;

 d->input       = input;

 d->inputFormat = spec->inputFormat;

 d->totalInputSize = spec->totalInputSize;

 init_SampleBuf(&d->output,

@@ -330,16 +222,22 @@ void deinit_Decoder(iDecoder *d) {

 deinit_SampleBuf(&d->output);

}

+static void start_Decoder_(iDecoder *d) {

+}

iDefineTypeConstructionArgs(Decoder, (iInputBuf *input, const iContentSpec *spec),

                         input, spec)

/----------------------------------------------------------------------------------------------/

struct Impl_Player {

 SDL_AudioDeviceID device;

};

iDefineTypeConstruction(Player)

@@ -358,8 +256,8 @@ static iContentSpec contentSpec_Player_(const iPlayer *d) {

 const size_t dataSize = size_InputBuf(d->data);

 iBuffer *buf = iClob(new_Buffer());

 open_Buffer(buf, &d->data->data);

     /* Read the RIFF/WAVE header. */

     iStream *is = stream_Buffer(buf);

     char magic[4];

@@ -428,8 +326,8 @@ static iContentSpec contentSpec_Player_(const iPlayer *d) {

             }

         }

         else if (memcmp(magic, "data", 4) == 0) {

             break;

         }

         else {

@@ -462,6 +360,7 @@ static void writeOutputSamples_Player_(void *plr, Uint8 *stream, int len) {

void init_Player(iPlayer *d) {

 iZap(d->spec);

 d->device  = 0;

 d->decoder = NULL;

 d->data    = new_InputBuf();

@@ -470,6 +369,7 @@ void init_Player(iPlayer *d) {

void deinit_Player(iPlayer *d) {

 stop_Player(d);

 delete_InputBuf(d->data);

}

iBool isStarted_Player(const iPlayer *d) {

@@ -481,13 +381,14 @@ iBool isPaused_Player(const iPlayer *d) {

 return SDL_GetAudioDeviceStatus(d->device) == SDL_AUDIO_PAUSED;

}

-void setFormatHint_Player(iPlayer *d, const char *hint) {

-}

-void updateSourceData_Player(iPlayer *d, const iBlock *data, enum iPlayerUpdate update) {

+void updateSourceData_Player(iPlayer *d, const iString *mimeType, const iBlock *data,

 /* TODO: Add MIME as argument */

 iInputBuf *input = d->data;

 lock_Mutex(&input->mtx);

 switch (update) {

     case replace_PlayerUpdate:

         set_Block(&input->data, data);

@@ -515,7 +416,7 @@ iBool start_Player(iPlayer *d) {

 if (isStarted_Player(d)) {

     return iFalse;

 }

 content.output.callback = writeOutputSamples_Player_;

 content.output.userdata = d;

 d->device = SDL_OpenAudioDevice(NULL, SDL_FALSE /* playback */, &content.output, &d->spec, 0);

diff --git a/src/audio/player.h b/src/audio/player.h

index fe6717b0..720f2d78 100644

--- a/src/audio/player.h

+++ b/src/audio/player.h

@@ -33,8 +33,8 @@ enum iPlayerUpdate {

 complete_PlayerUpdate,

};

-void setFormatHint_Player (iPlayer *, const char *hint);

-void updateSourceData_Player (iPlayer *, const iBlock *data, enum iPlayerUpdate update);

+void updateSourceData_Player (iPlayer *, const iString *mimeType, const iBlock *data,

iBool start_Player (iPlayer *);

void setPaused_Player (iPlayer *, iBool isPaused);

diff --git a/src/audio/stb_vorbis.c b/src/audio/stb_vorbis.c

new file mode 100644

index 00000000..a8cbfa6c

--- /dev/null

+++ b/src/audio/stb_vorbis.c

@@ -0,0 +1,5563 @@

+// Ogg Vorbis audio decoder - v1.20 - public domain

+// http://nothings.org/stb_vorbis/

+//

+// Original version written by Sean Barrett in 2007.

+//

+// Originally sponsored by RAD Game Tools. Seeking implementation

+// sponsored by Phillip Bennefall, Marc Andersen, Aaron Baker,

+// Elias Software, Aras Pranckevicius, and Sean Barrett.

+//

+// LICENSE

+//

+// See end of file for license information.

+//

+// Limitations:

+//

+// - floor 0 not supported (used in old ogg vorbis files pre-2004)

+// - lossless sample-truncation at beginning ignored

+// - cannot concatenate multiple vorbis streams

+// - sample positions are 32-bit, limiting seekable 192Khz

+// files to around 6 hours (Ogg supports 64-bit)

+//

+// Feature contributors:

+// Dougall Johnson (sample-exact seeking)

+//

+// Bugfix/warning contributors:

+// Terje Mathisen Niklas Frykholm Andy Hill

+// Casey Muratori John Bolton Gargaj

+// Laurent Gomila Marc LeBlanc Ronny Chevalier

+// Bernhard Wodo Evan Balster github:alxprd

+// Tom Beaumont Ingo Leitgeb Nicolas Guillemot

+// Phillip Bennefall Rohit Thiago Goulart

+// github:manxorist saga musix github:infatum

+// Timur Gagiev Maxwell Koo Peter Waller

+// github:audinowho Dougall Johnson David Reid

+// github:Clownacy Pedro J. Estebanez Remi Verschelde

+//

+// Partial history:

+// 1.20 - 2020-07-11 - several small fixes

+// 1.19 - 2020-02-05 - warnings

+// 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc.

+// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure)

+// 1.16 - 2019-03-04 - fix warnings

+// 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found

+// 1.14 - 2018-02-11 - delete bogus dealloca usage

+// 1.13 - 2018-01-29 - fix truncation of last frame (hopefully)

+// 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files

+// 1.11 - 2017-07-23 - fix MinGW compilation

+// 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory

+// 1.09 - 2016-04-04 - back out 'truncation of last frame' fix from previous version

+// 1.08 - 2016-04-02 - warnings; setup memory leaks; truncation of last frame

+// 1.07 - 2015-01-16 - fixes for crashes on invalid files; warning fixes; const

+// 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson)

+// some crash fixes when out of memory or with corrupt files

+// fix some inappropriately signed shifts

+// 1.05 - 2015-04-19 - don't define __forceinline if it's redundant

+// 1.04 - 2014-08-27 - fix missing const-correct case in API

+// 1.03 - 2014-08-07 - warning fixes

+// 1.02 - 2014-07-09 - declare qsort comparison as explicitly _cdecl in Windows

+// 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float (interleaved was correct)

+// 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in >2-channel;

+// (API change) report sample rate for decode-full-file funcs

+//

+// See end of file for full version history.

+//////////////////////////////////////////////////////////////////////////////

+//

+// HEADER BEGINS HERE

+//

+#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H

+#define STB_VORBIS_INCLUDE_STB_VORBIS_H

+#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO)

+#define STB_VORBIS_NO_STDIO 1

+#endif

+#ifndef STB_VORBIS_NO_STDIO

+#include <stdio.h>

+#endif

+#ifdef __cplusplus

+extern "C" {

+#endif

+/////////// THREAD SAFETY

+// Individual stb_vorbis* handles are not thread-safe; you cannot decode from

+// them from multiple threads at the same time. However, you can have multiple

+// stb_vorbis* handles and decode from them independently in multiple thrads.

+/////////// MEMORY ALLOCATION

+// normally stb_vorbis uses malloc() to allocate memory at startup,

+// and alloca() to allocate temporary memory during a frame on the

+// stack. (Memory consumption will depend on the amount of setup

+// data in the file and how you set the compile flags for speed

+// vs. size. In my test files the maximal-size usage is ~150KB.)

+//

+// You can modify the wrapper functions in the source (setup_malloc,

+// setup_temp_malloc, temp_malloc) to change this behavior, or you

+// can use a simpler allocation model: you pass in a buffer from

+// which stb_vorbis will allocate all its memory (including the

+// temp memory). "open" may fail with a VORBIS_outofmem if you

+// do not pass in enough data; there is no way to determine how

+// much you do need except to succeed (at which point you can

+// query get_info to find the exact amount required. yes I know

+// this is lame).

+//

+// If you pass in a non-NULL buffer of the type below, allocation

+// will occur from it as described above. Otherwise just pass NULL

+// to use malloc()/alloca()

+typedef struct

+{

+} stb_vorbis_alloc;

+/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES

+typedef struct stb_vorbis stb_vorbis;

+typedef struct

+{

+} stb_vorbis_info;

+typedef struct

+{

+} stb_vorbis_comment;

+// get general information about the file

+extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f);

+// get ogg comments

+extern stb_vorbis_comment stb_vorbis_get_comment(stb_vorbis *f);

+// get the last error detected (clears it, too)

+extern int stb_vorbis_get_error(stb_vorbis *f);

+// close an ogg vorbis file and free all memory in use

+extern void stb_vorbis_close(stb_vorbis *f);

+// this function returns the offset (in samples) from the beginning of the

+// file that will be returned by the next decode, if it is known, or -1

+// otherwise. after a flush_pushdata() call, this may take a while before

+// it becomes valid again.

+// NOT WORKING YET after a seek with PULLDATA API

+extern int stb_vorbis_get_sample_offset(stb_vorbis *f);

+// returns the current seek point within the file, or offset from the beginning

+// of the memory buffer. In pushdata mode it returns 0.

+extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f);

+/////////// PUSHDATA API

+#ifndef STB_VORBIS_NO_PUSHDATA_API

+// this API allows you to get blocks of data from any source and hand

+// them to stb_vorbis. you have to buffer them; stb_vorbis will tell

+// you how much it used, and you have to give it the rest next time;

+// and stb_vorbis may not have enough data to work with and you will

+// need to give it the same data again PLUS more. Note that the Vorbis

+// specification does not bound the size of an individual frame.

+extern stb_vorbis *stb_vorbis_open_pushdata(

+// create a vorbis decoder by passing in the initial data block containing

+// the ogg&vorbis headers (you don't need to do parse them, just provide

+// the first N bytes of the file--you're told if it's not enough, see below)

+// on success, returns an stb_vorbis *, does not set error, returns the amount of

+// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes;

+// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed

+// if returns NULL and *error is VORBIS_need_more_data, then the input block was

+// incomplete and you need to pass in a larger block from the start of the file

+extern int stb_vorbis_decode_frame_pushdata(

+// decode a frame of audio sample data if possible from the passed-in data block

+//

+// return value: number of bytes we used from datablock

+//

+// possible cases:

+// 0 bytes used, 0 samples output (need more data)

+// N bytes used, 0 samples output (resynching the stream, keep going)

+// N bytes used, M samples output (one frame of data)

+// note that after opening a file, you will ALWAYS get one N-bytes,0-sample

+// frame, because Vorbis always "discards" the first frame.

+//

+// Note that on resynch, stb_vorbis will rarely consume all of the buffer,

+// instead only datablock_length_in_bytes-3 or less. This is because it wants

+// to avoid missing parts of a page header if they cross a datablock boundary,

+// without writing state-machiney code to record a partial detection.

+//

+// The number of channels returned are stored in *channels (which can be

+// NULL--it is always the same as the number of channels reported by

+// get_info). output will contain an array of float buffers, one per

+// channel. In other words, (*output)[0][0] contains the first sample from

+// the first channel, and (*output)[1][0] contains the first sample from

+// the second channel.

+extern void stb_vorbis_flush_pushdata(stb_vorbis *f);

+// inform stb_vorbis that your next datablock will not be contiguous with

+// previous ones (e.g. you've seeked in the data); future attempts to decode

+// frames will cause stb_vorbis to resynchronize (as noted above), and

+// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it

+// will begin decoding the next frame.

+//

+// if you want to seek using pushdata, you need to seek in your file, then

+// call stb_vorbis_flush_pushdata(), then start calling decoding, then once

+// decoding is returning you data, call stb_vorbis_get_sample_offset, and

+// if you don't like the result, seek your file again and repeat.

+#endif

+////////// PULLING INPUT API

+#ifndef STB_VORBIS_NO_PULLDATA_API

+// This API assumes stb_vorbis is allowed to pull data from a source--

+// either a block of memory containing the entire vorbis stream, or a

+// FILE * that you or it create, or possibly some other reading mechanism

+// if you go modify the source to replace the FILE * case with some kind

+// of callback to your code. (But if you don't support seeking, you may

+// just want to go ahead and use pushdata.)

+#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION)

+extern int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output);

+#endif

+#if !defined(STB_VORBIS_NO_INTEGER_CONVERSION)

+extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *channels, int *sample_rate, short **output);

+#endif

+// decode an entire file and output the data interleaved into a malloc()ed

+// buffer stored in *output. The return value is the number of samples

+// decoded, or -1 if the file could not be opened or was not an ogg vorbis file.

+// When you're done with it, just free() the pointer returned in *output.

+extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len,

+// create an ogg vorbis decoder from an ogg vorbis stream in memory (note

+// this must be the entire stream!). on failure, returns NULL and sets *error

+#ifndef STB_VORBIS_NO_STDIO

+extern stb_vorbis * stb_vorbis_open_filename(const char *filename,

+// create an ogg vorbis decoder from a filename via fopen(). on failure,

+// returns NULL and sets *error (possibly to VORBIS_file_open_failure).

+extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,

+// create an ogg vorbis decoder from an open FILE *, looking for a stream at

+// the current seek point (ftell). on failure, returns NULL and sets *error.

+// note that stb_vorbis must "own" this stream; if you seek it in between

+// calls to stb_vorbis, it will become confused. Moreover, if you attempt to

+// perform stb_vorbis_seek_*() operations on this file, it will assume it

+// owns the entire rest of the file after the start point. Use the next

+// function, stb_vorbis_open_file_section(), to limit it.

+extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close,

+// create an ogg vorbis decoder from an open FILE *, looking for a stream at

+// the current seek point (ftell); the stream will be of length 'len' bytes.

+// on failure, returns NULL and sets *error. note that stb_vorbis must "own"

+// this stream; if you seek it in between calls to stb_vorbis, it will become

+// confused.

+#endif

+extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number);

+extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);

+// these functions seek in the Vorbis file to (approximately) 'sample_number'.

+// after calling seek_frame(), the next call to get_frame_*() will include

+// the specified sample. after calling stb_vorbis_seek(), the next call to

+// stb_vorbis_get_samples_* will start with the specified sample. If you

+// do not need to seek to EXACTLY the target sample when using get_samples_*,

+// you can also use seek_frame().

+extern int stb_vorbis_seek_start(stb_vorbis *f);

+// this function is equivalent to stb_vorbis_seek(f,0)

+extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f);

+extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f);

+// these functions return the total length of the vorbis stream

+extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output);

+// decode the next frame and return the number of samples. the number of

+// channels returned are stored in *channels (which can be NULL--it is always

+// the same as the number of channels reported by get_info). *output will

+// contain an array of float* buffers, one per channel. These outputs will

+// be overwritten on the next call to stb_vorbis_get_frame_*.

+//

+// You generally should not intermix calls to stb_vorbis_get_frame_*()

+// and stb_vorbis_get_samples_*(), since the latter calls the former.

+#ifndef STB_VORBIS_NO_INTEGER_CONVERSION

+extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts);

+extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples);

+#endif

+// decode the next frame and return the number of samples per channel.

+// Note that for interleaved data, you pass in the number of shorts (the

+// size of your array), but the return value is the number of samples per

+// channel, not the total number of samples.

+//

+// The data is coerced to the number of channels you request according to the

+// channel coercion rules (see below). You must pass in the size of your

+// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.

+// The maximum buffer size needed can be gotten from get_info(); however,

+// the Vorbis I specification implies an absolute maximum of 4096 samples

+// per channel.

+// Channel coercion rules:

+// Let M be the number of channels requested, and N the number of channels present,

+// and Cn be the nth channel; let stereo L be the sum of all L and center channels,

+// and stereo R be the sum of all R and center channels (channel assignment from the

+// vorbis spec).

+// M N output

+// 1 k sum(Ck) for all k

+// 2 * stereo L, stereo R

+// k l k > l, the first l channels, then 0s

+// k l k <= l, the first k channels

+// Note that this is not good surround etc. mixing at all! It's just so

+// you get something useful.

+extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats);

+extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples);

+// gets num_samples samples, not necessarily on a frame boundary--this requires

+// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES.

+// Returns the number of samples stored per channel; it may be less than requested

+// at the end of the file. If there are no more samples in the file, returns 0.

+#ifndef STB_VORBIS_NO_INTEGER_CONVERSION

+extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts);

+extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples);

+#endif

+// gets num_samples samples, not necessarily on a frame boundary--this requires

+// buffering so you have to supply the buffers. Applies the coercion rules above

+// to produce 'channels' channels. Returns the number of samples stored per channel;

+// it may be less than requested at the end of the file. If there are no more

+// samples in the file, returns 0.

+#endif

+//////// ERROR CODES

+enum STBVorbisError

+{

+};

+#ifdef __cplusplus

+}

+#endif

+#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H

+//

+// HEADER ENDS HERE

+//

+//////////////////////////////////////////////////////////////////////////////

+#ifndef STB_VORBIS_HEADER_ONLY

+// global configuration settings (e.g. set these in the project/makefile),

+// or just set them in this file at the top (although ideally the first few

+// should be visible when the header file is compiled too, although it's not

+// crucial)

+// STB_VORBIS_NO_PUSHDATA_API

+// does not compile the code for the various stb_vorbis_*_pushdata()

+// functions

+// #define STB_VORBIS_NO_PUSHDATA_API

+// STB_VORBIS_NO_PULLDATA_API

+// does not compile the code for the non-pushdata APIs

+// #define STB_VORBIS_NO_PULLDATA_API

+// STB_VORBIS_NO_STDIO

+// does not compile the code for the APIs that use FILE *s internally

+// or externally (implied by STB_VORBIS_NO_PULLDATA_API)

+// #define STB_VORBIS_NO_STDIO

+// STB_VORBIS_NO_INTEGER_CONVERSION

+// does not compile the code for converting audio sample data from

+// float to integer (implied by STB_VORBIS_NO_PULLDATA_API)

+// #define STB_VORBIS_NO_INTEGER_CONVERSION

+// STB_VORBIS_NO_FAST_SCALED_FLOAT

+// does not use a fast float-to-int trick to accelerate float-to-int on

+// most platforms which requires endianness be defined correctly.

+//#define STB_VORBIS_NO_FAST_SCALED_FLOAT

+// STB_VORBIS_MAX_CHANNELS [number]

+// globally define this to the maximum number of channels you need.

+// The spec does not put a restriction on channels except that

+// the count is stored in a byte, so 255 is the hard limit.

+// Reducing this saves about 16 bytes per value, so using 16 saves

+// (255-16)*16 or around 4KB. Plus anything other memory usage

+// I forgot to account for. Can probably go as low as 8 (7.1 audio),

+// 6 (5.1 audio), or 2 (stereo only).

+#ifndef STB_VORBIS_MAX_CHANNELS

+#define STB_VORBIS_MAX_CHANNELS 16 // enough for anyone?

+#endif

+// STB_VORBIS_PUSHDATA_CRC_COUNT [number]

+// after a flush_pushdata(), stb_vorbis begins scanning for the

+// next valid page, without backtracking. when it finds something

+// that looks like a page, it streams through it and verifies its

+// CRC32. Should that validation fail, it keeps scanning. But it's

+// possible that while streaming through to check the CRC32 of

+// one candidate page, it sees another candidate page. This #define

+// determines how many "overlapping" candidate pages it can search

+// at once. Note that "real" pages are typically ~4KB to ~8KB, whereas

+// garbage pages could be as big as 64KB, but probably average ~16KB.

+// So don't hose ourselves by scanning an apparent 64KB page and

+// missing a ton of real ones in the interim; so minimum of 2

+#ifndef STB_VORBIS_PUSHDATA_CRC_COUNT

+#define STB_VORBIS_PUSHDATA_CRC_COUNT 4

+#endif

+// STB_VORBIS_FAST_HUFFMAN_LENGTH [number]

+// sets the log size of the huffman-acceleration table. Maximum

+// supported value is 24. with larger numbers, more decodings are O(1),

+// but the table size is larger so worse cache missing, so you'll have

+// to probe (and try multiple ogg vorbis files) to find the sweet spot.

+#ifndef STB_VORBIS_FAST_HUFFMAN_LENGTH

+#define STB_VORBIS_FAST_HUFFMAN_LENGTH 10

+#endif

+// STB_VORBIS_FAST_BINARY_LENGTH [number]

+// sets the log size of the binary-search acceleration table. this

+// is used in similar fashion to the fast-huffman size to set initial

+// parameters for the binary search

+// STB_VORBIS_FAST_HUFFMAN_INT

+// The fast huffman tables are much more efficient if they can be

+// stored as 16-bit results instead of 32-bit results. This restricts

+// the codebooks to having only 65535 possible outcomes, though.

+// (At least, accelerated by the huffman table.)

+#ifndef STB_VORBIS_FAST_HUFFMAN_INT

+#define STB_VORBIS_FAST_HUFFMAN_SHORT

+#endif

+// STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH

+// If the 'fast huffman' search doesn't succeed, then stb_vorbis falls

+// back on binary searching for the correct one. This requires storing

+// extra tables with the huffman codes in sorted order. Defining this

+// symbol trades off space for speed by forcing a linear search in the

+// non-fast case, except for "sparse" codebooks.

+// #define STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH

+// STB_VORBIS_DIVIDES_IN_RESIDUE

+// stb_vorbis precomputes the result of the scalar residue decoding

+// that would otherwise require a divide per chunk. you can trade off

+// space for time by defining this symbol.

+// #define STB_VORBIS_DIVIDES_IN_RESIDUE

+// STB_VORBIS_DIVIDES_IN_CODEBOOK

+// vorbis VQ codebooks can be encoded two ways: with every case explicitly

+// stored, or with all elements being chosen from a small range of values,

+// and all values possible in all elements. By default, stb_vorbis expands

+// this latter kind out to look like the former kind for ease of decoding,

+// because otherwise an integer divide-per-vector-element is required to

+// unpack the index. If you define STB_VORBIS_DIVIDES_IN_CODEBOOK, you can

+// trade off storage for speed.

+//#define STB_VORBIS_DIVIDES_IN_CODEBOOK

+#ifdef STB_VORBIS_CODEBOOK_SHORTS

+#error "STB_VORBIS_CODEBOOK_SHORTS is no longer supported as it produced incorrect results for some input formats"

+#endif

+// STB_VORBIS_DIVIDE_TABLE

+// this replaces small integer divides in the floor decode loop with

+// table lookups. made less than 1% difference, so disabled by default.

+// STB_VORBIS_NO_INLINE_DECODE

+// disables the inlining of the scalar codebook fast-huffman decode.

+// might save a little codespace; useful for debugging

+// #define STB_VORBIS_NO_INLINE_DECODE

+// STB_VORBIS_NO_DEFER_FLOOR

+// Normally we only decode the floor without synthesizing the actual

+// full curve. We can instead synthesize the curve immediately. This

+// requires more memory and is very likely slower, so I don't think

+// you'd ever want to do it except for debugging.

+// #define STB_VORBIS_NO_DEFER_FLOOR

+//////////////////////////////////////////////////////////////////////////////

+#ifdef STB_VORBIS_NO_PULLDATA_API

+#endif

+#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO)

+#endif

+#ifndef STB_VORBIS_NO_INTEGER_CONVERSION

+#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT

+#endif

+#endif

+#ifndef STB_VORBIS_NO_STDIO

+#include <stdio.h>

+#endif

+#ifndef STB_VORBIS_NO_CRT

+#else // STB_VORBIS_NO_CRT

+#endif // STB_VORBIS_NO_CRT

+#include <limits.h>

+#ifdef MINGW32

+#elif !defined(_MSC_VER)

+#endif

+#if STB_VORBIS_MAX_CHANNELS > 256

+#error "Value of STB_VORBIS_MAX_CHANNELS outside of allowed range"

+#endif

+#if STB_VORBIS_FAST_HUFFMAN_LENGTH > 24

+#error "Value of STB_VORBIS_FAST_HUFFMAN_LENGTH outside of allowed range"

+#endif

+#if 0

+#include <crtdbg.h>

+#define CHECK(f) _CrtIsValidHeapPointer(f->channel_buffers[1])

+#else

+#define CHECK(f) ((void) 0)

+#endif

+#define MAX_BLOCKSIZE_LOG 13 // from specification

+#define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG)

+typedef unsigned char uint8;

+typedef signed char int8;

+typedef unsigned short uint16;

+typedef signed short int16;

+typedef unsigned int uint32;

+typedef signed int int32;

+#ifndef TRUE

+#define TRUE 1

+#define FALSE 0

+#endif

+typedef float codetype;

+// @NOTE

+//

+// Some arrays below are tagged "//varies", which means it's actually

+// a variable-sized piece of data, but rather than malloc I assume it's

+// small enough it's better to just allocate it all together with the

+// main thing

+//

+// Most of the variables are specified with the smallest size I could pack

+// them into. It might give better performance to make them all full-sized

+// integers. It should be safe to freely rearrange the structures or change

+// the sizes larger--nothing relies on silently truncating etc., nor the

+// order of variables.

+#define FAST_HUFFMAN_TABLE_SIZE (1 << STB_VORBIS_FAST_HUFFMAN_LENGTH)

+#define FAST_HUFFMAN_TABLE_MASK (FAST_HUFFMAN_TABLE_SIZE - 1)

+typedef struct

+{

+} Codebook;

+typedef struct

+{

+} Floor0;

+typedef struct

+{

+} Floor1;

+typedef union

+{

+} Floor;

+typedef struct

+{

+} Residue;

+typedef struct

+{

+} MappingChannel;

+typedef struct

+{

+} Mapping;

+typedef struct

+{

+} Mode;

+typedef struct

+{

+} CRCscan;

+typedef struct

+{

+} ProbedPage;

+struct stb_vorbis

+{

+#ifndef STB_VORBIS_NO_STDIO

+#endif

+#ifndef STB_VORBIS_NO_PUSHDATA_API

+#endif

+};

+#if defined(STB_VORBIS_NO_PUSHDATA_API)

+#elif defined(STB_VORBIS_NO_PULLDATA_API)

+#else

+#endif

+typedef struct stb_vorbis vorb;

+static int error(vorb *f, enum STBVorbisError e)

+{

+}

+// these functions are used for allocating temporary memory

+// while decoding. if you can afford the stack space, use

+// alloca(); otherwise, provide a temp buffer and it will

+// allocate out of those.

+#define array_size_required(count,size) (count*(sizeof(void *)+(size)))

+#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size))

+#define temp_free(f,p) (void)0

+#define temp_alloc_save(f) ((f)->temp_offset)

+#define temp_alloc_restore(f,p) ((f)->temp_offset = (p))

+#define temp_block_array(f,count,size) make_block_array(temp_alloc(f,array_size_required(count,size)), count, size)

+// given a sufficiently large block of memory, make an array of pointers to subblocks of it

+static void *make_block_array(void *mem, int count, int size)

+{

+}

+static void *setup_malloc(vorb *f, int sz)

+{

+}

+static void setup_free(vorb *f, void *p)

+{

+}

+static void *setup_temp_malloc(vorb *f, int sz)

+{

+}

+static void setup_temp_free(vorb *f, void *p, int sz)

+{

+}

+#define CRC32_POLY 0x04c11db7 // from spec

+static uint32 crc_table[256];

+static void crc32_init(void)

+{

+}

+static __forceinline uint32 crc32_update(uint32 crc, uint8 byte)

+{

+}

+// used in setup, and for huffman that doesn't go fast path

+static unsigned int bit_reverse(unsigned int n)

+{

+}

+static float square(float x)

+{

+}

+// this is a weird definition of log2() for which log2(1) = 1, log2(2) = 2, log2(4) = 3

+// as required by the specification. fast(?) implementation from stb.h

+// @OPTIMIZE: called multiple times per-packet with "constants"; move to setup

+static int ilog(int32 n)

+{

+}

+#ifndef M_PI

+#endif

+// code length assigned to a value with no huffman encoding

+#define NO_CODE 255

+/////////////////////// LEAF SETUP FUNCTIONS //////////////////////////

+//

+// these functions are only called at setup, and only a few times

+// per file

+static float float32_unpack(uint32 x)

+{

+}

+// zlib & jpeg huffman tables assume that the output symbols

+// can either be arbitrarily arranged, or have monotonically

+// increasing frequencies--they rely on the lengths being sorted;

+// this makes for a very simple generation algorithm.

+// vorbis allows a huffman table with non-sorted lengths. This

+// requires a more sophisticated construction, since symbols in

+// order do not map to huffman codes "in order".

+static void add_entry(Codebook *c, uint32 huff_code, int symbol, int count, int len, uint32 *values)

+{

+}

+static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)

+{

+}

+// accelerated huffman table allows fast O(1) match of all symbols

+// of length <= STB_VORBIS_FAST_HUFFMAN_LENGTH

+static void compute_accelerated_huffman(Codebook *c)

+{

+}

+#ifdef _MSC_VER

+#define STBV_CDECL __cdecl

+#else

+#define STBV_CDECL

+#endif

+static int STBV_CDECL uint32_compare(const void *p, const void *q)

+{

+}

+static int include_in_sort(Codebook *c, uint8 len)

+{

+}

+// if the fast table above doesn't work, we want to binary

+// search them... need to reverse the bits

+static void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values)

+{

+}

+// only run while parsing the header (3 times)

+static int vorbis_validate(uint8 *data)

+{

+}

+// called from setup only, once per code book

+// (formula implied by specification)

+static int lookup1_values(int entries, int dim)

+{

+}

+// called twice per file

+static void compute_twiddle_factors(int n, float *A, float *B, float *C)

+{

+}

+static void compute_window(int n, float *window)

+{

+}

+static void compute_bitreverse(int n, uint16 *rev)

+{

+}

+static int init_blocksize(vorb *f, int b, int n)

+{

+}

+static void neighbors(uint16 *x, int n, int *plow, int *phigh)

+{

+}

+// this has been repurposed so y is now the original index instead of y

+typedef struct

+{

+} stbv__floor_ordering;

+static int STBV_CDECL point_compare(const void *p, const void *q)

+{

+}

+//

+/////////////////////// END LEAF SETUP FUNCTIONS //////////////////////////

+#if defined(STB_VORBIS_NO_STDIO)

+#else

+#endif

+static uint8 get8(vorb *z)

+{

+}

+static uint32 get32(vorb *f)

+{

+}

+static int getn(vorb *z, uint8 *data, int n)

+{

+}

+static void skip(vorb *z, int n)

+{

+}

+static int set_file_offset(stb_vorbis *f, unsigned int loc)

+{

+}

+static uint8 ogg_page_header[4] = { 0x4f, 0x67, 0x67, 0x53 };

+static int capture_pattern(vorb *f)

+{

+}

+#define PAGEFLAG_continued_packet 1

+#define PAGEFLAG_first_page 2

+#define PAGEFLAG_last_page 4

+static int start_page_no_capturepattern(vorb *f)

+{

+}

+static int start_page(vorb *f)

+{

+}

+static int start_packet(vorb *f)

+{

+}

+static int maybe_start_packet(vorb *f)

+{

+}

+static int next_segment(vorb *f)

+{

+}

+#define EOP (-1)

+#define INVALID_BITS (-1)

+static int get8_packet_raw(vorb *f)

+{

+}

+static int get8_packet(vorb *f)

+{

+}

+static int get32_packet(vorb *f)

+{

+}

+static void flush_packet(vorb *f)

+{

+}

+// @OPTIMIZE: this is the secondary bit decoder, so it's probably not as important

+// as the huffman decoder?

+static uint32 get_bits(vorb *f, int n)

+{

+}

+// @OPTIMIZE: primary accumulator for huffman

+// expand the buffer to as many bits as possible without reading off end of packet

+// it might be nice to allow f->valid_bits and f->acc to be stored in registers,

+// e.g. cache them locally and decode locally

+static __forceinline void prep_huffman(vorb *f)

+{

+}

+enum

+{

+};

+static int codebook_decode_scalar_raw(vorb *f, Codebook *c)

+{

+}

+#ifndef STB_VORBIS_NO_INLINE_DECODE

+#define DECODE_RAW(var, f,c) \

+#else

+static int codebook_decode_scalar(vorb *f, Codebook *c)

+{

+}

+#define DECODE_RAW(var,f,c) var = codebook_decode_scalar(f,c);

+#endif

+#define DECODE(var,f,c) \

+#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK

+#else

+#endif

+// CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case

+// where we avoid one addition

+#define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off])

+#define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off])

+#define CODEBOOK_ELEMENT_BASE(c) (0)

+static int codebook_decode_start(vorb *f, Codebook *c)

+{

+}

+static int codebook_decode(vorb *f, Codebook *c, float *output, int len)

+{

+#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK

+#endif

+}

+static int codebook_decode_step(vorb *f, Codebook *c, float *output, int len, int step)

+{

+#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK

+#endif

+}

+static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **outputs, int ch, int *c_inter_p, int *p_inter_p, int len, int total_decode)

+{

+}

+static int predict_point(int x, int x0, int x1, int y0, int y1)

+{

+}

+// the following table is block-copied from the specification

+static float inverse_db_table[256] =

+{

+};

+// @OPTIMIZE: if you want to replace this bresenham line-drawing routine,

+// note that you must produce bit-identical output to decode correctly;

+// this specific sequence of operations is specified in the spec (it's

+// drawing integer-quantized frequency-space lines that the encoder

+// expects to be exactly the same)

+// ... also, isn't the whole point of Bresenham's algorithm to NOT

+// have to divide in the setup? sigh.

+#ifndef STB_VORBIS_NO_DEFER_FLOOR

+#define LINE_OP(a,b) a *= b

+#else

+#define LINE_OP(a,b) a = b

+#endif

+#ifdef STB_VORBIS_DIVIDE_TABLE

+#define DIVTAB_NUMER 32

+#define DIVTAB_DENOM 64

+int8 integer_divide_table[DIVTAB_NUMER][DIVTAB_DENOM]; // 2KB

+#endif

+static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y1, int n)

+{

+#ifdef STB_VORBIS_DIVIDE_TABLE

+#else

+#endif

+}

+static int residue_decode(vorb *f, Codebook *book, float *target, int offset, int n, int rtype)

+{

+}

+// n is 1/2 of the blocksize --

+// specification: "Correct per-vector decode length is [n]/2"

+static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode)

+{

+}

+#if 0

+// slow way for debugging

+void inverse_mdct_slow(float *buffer, int n)

+{

+}

+#elif 0

+// same as above, but just barely able to run in real time on modern machines

+void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype)

+{

+}

+#elif 0

+// transform to use a slow dct-iv; this is STILL basically trivial,

+// but only requires half as many ops

+void dct_iv_slow(float *buffer, int n)

+{

+}

+void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype)

+{

+}

+#endif

+#ifndef LIBVORBIS_MDCT

+#define LIBVORBIS_MDCT 0

+#endif

+#if LIBVORBIS_MDCT

+// directly call the vorbis MDCT using an interface documented

+// by Jeff Roberts... useful for performance comparison

+typedef struct

+{

+} mdct_lookup;

+extern void mdct_init(mdct_lookup *lookup, int n);

+extern void mdct_clear(mdct_lookup *l);

+extern void mdct_backward(mdct_lookup *init, float *in, float *out);

+mdct_lookup M1,M2;

+void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)

+{

+}

+#endif

+// the following were split out into separate functions while optimizing;

+// they could be pushed back up but eh. __forceinline showed no change;

+// they're probably already being inlined.

+static void imdct_step3_iter0_loop(int n, float *e, int i_off, int k_off, float *A)

+{

+}

+static void imdct_step3_inner_r_loop(int lim, float *e, int d0, int k_off, float *A, int k1)

+{

+}

+static void imdct_step3_inner_s_loop(int n, float *e, int i_off, int k_off, float *A, int a_off, int k0)

+{

+}

+static __forceinline void iter_54(float *z)

+{

+}

+static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, int base_n)

+{

+}

+static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)

+{

+}

+#if 0

+// this is the original version of the above code, if you want to optimize it from scratch

+void inverse_mdct_naive(float *buffer, int n)

+{

+}

+#endif

+static float *get_window(vorb *f, int len)

+{

+}

+#ifndef STB_VORBIS_NO_DEFER_FLOOR

+typedef int16 YTYPE;

+#else

+typedef int YTYPE;

+#endif

+static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *finalY, uint8 *step2_flag)

+{

+}

+// The meaning of "left" and "right"

+//

+// For a given frame:

+// we compute samples from 0..n

+// window_center is n/2

+// we'll window and mix the samples from left_start to left_end with data from the previous frame

+// all of the samples from left_end to right_start can be output without mixing; however,

+// this interval is 0-length except when transitioning between short and long frames

+// all of the samples from right_start to right_end need to be mixed with the next frame,

+// which we don't have, so those get saved in a buffer

+// frame N's right_end-right_start, the number of samples to mix with the next frame,

+// has to be the same as frame N+1's left_end-left_start (which they are by

+// construction)

+static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode)

+{

+// WINDOWING

+}

+static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, int left_end, int right_start, int right_end, int *p_left)

+{

+// WINDOWING

+// FLOORS

+#ifdef STB_VORBIS_NO_DEFER_FLOOR

+#else

+#endif

+// RESIDUE DECODE

+// INVERSE COUPLING

+#ifndef STB_VORBIS_NO_DEFER_FLOOR

+#else

+#endif

+// INVERSE MDCT

+}

+static int vorbis_decode_packet(vorb *f, int *len, int *p_left, int *p_right)

+{

+}

+static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right)

+{

+}

+static int vorbis_pump_first_frame(stb_vorbis *f)

+{

+}

+#ifndef STB_VORBIS_NO_PUSHDATA_API

+static int is_whole_packet_present(stb_vorbis *f)

+{

+}

+#endif // !STB_VORBIS_NO_PUSHDATA_API

+static int start_decoder(vorb *f)

+{

+#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK

+#endif

+#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK

+#endif

+#ifdef STB_VORBIS_DIVIDE_TABLE

+#endif

+}

+static void vorbis_deinit(stb_vorbis *p)

+{

+}

+void stb_vorbis_close(stb_vorbis *p)

+{

+}

+static void vorbis_init(stb_vorbis *p, const stb_vorbis_alloc *z)

+{

+}

+int stb_vorbis_get_sample_offset(stb_vorbis *f)

+{

+}

+stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f)

+{

+}

+stb_vorbis_comment stb_vorbis_get_comment(stb_vorbis *f)

+{

+}

+int stb_vorbis_get_error(stb_vorbis *f)

+{

+}

+static stb_vorbis * vorbis_alloc(stb_vorbis *f)

+{

+}

+#ifndef STB_VORBIS_NO_PUSHDATA_API

+void stb_vorbis_flush_pushdata(stb_vorbis *f)

+{

+}

+static int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len)

+{

+}

+// return value: number of bytes we used

+int stb_vorbis_decode_frame_pushdata(

+{

+}

+stb_vorbis *stb_vorbis_open_pushdata(

+{

+}

+#endif // STB_VORBIS_NO_PUSHDATA_API

+unsigned int stb_vorbis_get_file_offset(stb_vorbis *f)

+{

+}

+#ifndef STB_VORBIS_NO_PULLDATA_API

+//

+// DATA-PULLING API

+//

+static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last)

+{

+}

+#define SAMPLE_unknown 0xffffffff

+// seeking is implemented with a binary search, which narrows down the range to

+// 64K, before using a linear search (because finding the synchronization

+// pattern can be expensive, and the chance we'd find the end page again is

+// relatively high for small ranges)

+//

+// two initial interpolation-style probes are used at the start of the search

+// to try to bound either side of the binary search sensibly, while still

+// working in O(log n) time if they fail.

+static int get_seek_page_info(stb_vorbis *f, ProbedPage *z)

+{

+}

+// rarely used function to seek back to the preceding page while finding the

+// start of a packet

+static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset)

+{

+}

+// implements the search logic for finding a page and starting decoding. if

+// the function succeeds, current_loc_valid will be true and current_loc will

+// be less than or equal to the provided sample number (the closer the

+// better).

+static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)

+{

+error:

+}

+// the same as vorbis_decode_initial, but without advancing

+static int peek_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode)

+{

+}

+int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number)

+{

+}

+int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number)

+{

+}

+int stb_vorbis_seek_start(stb_vorbis *f)

+{

+}

+unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f)

+{

+}

+float stb_vorbis_stream_length_in_seconds(stb_vorbis *f)

+{

+}

+int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output)

+{

+}

+#ifndef STB_VORBIS_NO_STDIO

+stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc, unsigned int length)

+{

+}

+stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc)

+{

+}

+stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc)

+{

+#if defined(_WIN32) && defined(STDC_WANT_SECURE_LIB)

+#else

+#endif

+}

+#endif // STB_VORBIS_NO_STDIO

+stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc)

+{

+}

+#ifndef STB_VORBIS_NO_INTEGER_CONVERSION

+#define PLAYBACK_MONO 1

+#define PLAYBACK_LEFT 2

+#define PLAYBACK_RIGHT 4

+#define L (PLAYBACK_LEFT | PLAYBACK_MONO)

+#define C (PLAYBACK_LEFT | PLAYBACK_RIGHT | PLAYBACK_MONO)

+#define R (PLAYBACK_RIGHT | PLAYBACK_MONO)

+static int8 channel_position[7][6] =

+{

+};

+#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT

+#else

+#endif

+static void copy_samples(short *dest, float *src, int len)

+{

+}

+static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len)

+{

+}

+static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len)

+{

+}

+static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples)

+{

+}

+int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples)

+{

+}

+static void convert_channels_short_interleaved(int buf_c, short *buffer, int data_c, float **data, int d_offset, int len)

+{

+}

+int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts)

+{

+}

+int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts)

+{

+}

+int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int len)

+{

+}

+#ifndef STB_VORBIS_NO_STDIO

+int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output)

+{

+}

+#endif // NO_STDIO

+int stb_vorbis_decode_memory(const uint8 *mem, int len, int *channels, int *sample_rate, short **output)

+{

+}

+#endif // STB_VORBIS_NO_INTEGER_CONVERSION

+int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats)

+{

+}

+int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples)

+{

+}

+#endif // STB_VORBIS_NO_PULLDATA_API

+/* Version history

+*/

+#endif // STB_VORBIS_HEADER_ONLY

+/*

+------------------------------------------------------------------------------

+This software is available under 2 licenses -- choose whichever you prefer.

+------------------------------------------------------------------------------

+ALTERNATIVE A - MIT License

+Copyright (c) 2017 Sean Barrett

+Permission is hereby granted, free of charge, to any person obtaining a copy of

+this software and associated documentation files (the "Software"), to deal in

+the Software without restriction, including without limitation the rights to

+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies

+of the Software, and to permit persons to whom the Software is furnished to do

+so, subject to the following conditions:

+The above copyright notice and this permission notice shall be included in all

+copies or substantial portions of the Software.

+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE

+SOFTWARE.

+------------------------------------------------------------------------------

+ALTERNATIVE B - Public Domain (www.unlicense.org)

+This is free and unencumbered software released into the public domain.

+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this

+software, either in source code form or as a compiled binary, for any purpose,

+commercial or non-commercial, and by any means.

+In jurisdictions that recognize copyright laws, the author or authors of this

+software dedicate any and all copyright interest in the software to the public

+domain. We make this dedication for the benefit of the public at large and to

+the detriment of our heirs and successors. We intend this dedication to be an

+overt act of relinquishment in perpetuity of all present and future rights to

+this software under copyright law.

+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN

+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION

+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+------------------------------------------------------------------------------

+*/

diff --git a/src/media.c b/src/media.c

index c447704b..c0d6d3de 100644

--- a/src/media.c

+++ b/src/media.c

@@ -182,13 +182,13 @@ void setData_Media(iMedia *d, iGmLinkId linkId, const iString *mime, const iBloc

     else {

         audio = at_PtrArray(&d->audio, existing - 1);

         iAssert(equal_String(&audio->props.mime, mime)); /* MIME cannot change */

         if (!isStarted_Player(audio->player)) {

             /* Maybe the previous updates didn't have enough data. */

             start_Player(audio->player);

         }

         if (!isPartial) {

         }

     }

 }

@@ -209,9 +209,9 @@ void setData_Media(iMedia *d, iGmLinkId linkId, const iString *mime, const iBloc

         audio->props.linkId = linkId; /* TODO: use a hash? */

         audio->props.isPermanent = !allowHide;

         set_String(&audio->props.mime, mime);

         if (!isPartial) {

         }

         pushBack_PtrArray(&d->audio, audio);

         /* TEST: Start playing right away. */

--

2.25.1

Proxy Information
Original URL
gemini://git.skyjake.fi/lagrange/release/patch/4bf163ecfac27c3dd86dff96df6f4647f9afe021.patch
Status Code
Success (20)
Meta
text/plain
Capsule Response Time
44.701886 milliseconds
Gemini-to-HTML Time
71.872074 milliseconds

This content has been proxied by September (ba2dc).