Skip to content

Instantly share code, notes, and snippets.

@AliceLR
Created April 11, 2022 10:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AliceLR/6c64ebb0efafbd12ee2682eaf1b99f3a to your computer and use it in GitHub Desktop.
Save AliceLR/6c64ebb0efafbd12ee2682eaf1b99f3a to your computer and use it in GitHub Desktop.
/* Extended Module Player
* Copyright (C) 1996-2022 Claudio Matsuoka and Hipolito Carraro Jr
*
* 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.
*/
#include "loader.h"
#define HAVE_LIBVORBIS
#include <limits.h>
#ifdef HAVE_LIBVORBIS
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
#ifdef WORDS_BIGENDIAN
#define OV_ENDIAN 1
#else
#define OV_ENDIAN 0
#endif
#define OV_READ_PARAMS(bsp) OV_ENDIAN, 2, 1, (bsp)
#define EXTERNAL_VORBIS
#endif
#ifdef HAVE_TREMOR
#include <tremor/ivorbiscodec.h>
#include <tremor/ivorbisfile.h>
#define OV_READ_PARAMS(bsp) (bsp)
#define EXTERNAL_VORBIS
#endif
#ifdef EXTERNAL_VORBIS
static size_t read_cb(void *dest, size_t len, size_t num, void *handle)
{
return mread(dest, len, num, (MFILE *)handle);
}
static int seek_cb(void *handle, ogg_int64_t off, int whence)
{
if(off > LONG_MAX)
return -1;
return mseek((MFILE *)handle, off, whence);
}
static long tell_cb(void *handle)
{
return mtell((MFILE *)handle);
}
static ov_callbacks cb = { read_cb, seek_cb, NULL, tell_cb };
int libxmp_vorbis_decode(const uint8 *data, int len, int *ch, int *rate, int16 **dest)
{
OggVorbis_File vf;
vorbis_info *vi;
MFILE *m;
int16 *pcm16;
ogg_int64_t pcm16_len;
int pos = 0;
int n, s;
if ((m = mopen(data, len, 0)) == NULL)
return -1;
if (ov_open_callbacks(m, &vf, NULL, 0, cb) < 0)
goto err;
vi = ov_info(&vf, -1);
pcm16_len = ov_pcm_total(&vf, -1);
if (vi == NULL || vi->channels > 2 || pcm16_len < 0 || pcm16_len > MAX_SAMPLE_SIZE)
goto err_close;
*ch = vi->channels;
*rate = vi->bitrate_nominal;
pcm16_len *= vi->channels * 2;
if ((pcm16 = (int16 *)calloc(1, pcm16_len)) == NULL)
goto err_close;
while (pcm16_len > 0) {
n = ov_read(&vf, (char *)pcm16 + pos, pcm16_len, OV_READ_PARAMS(&s));
if (n <= 0)
break;
pcm16_len -= n;
pos += n;
}
ov_clear(&vf);
mclose(m);
if (n < 0) {
free(pcm16);
return -1;
}
*dest = pcm16;
return pos / (*ch * 2);
err_close:
ov_clear(&vf);
err:
mclose(m);
return -1;
}
#elif !defined(LIBXMP_DISABLE_VORBIS) /* stb_vorbis */
#include "vorbis.h"
int libxmp_vorbis_decode(const uint8 *data, int len, int *ch, int *rate, int16 **dest)
{
return stb_vorbis_decode_memory(data, len, ch, rate, dest);
}
#else /* vorbis disabled */
int libxmp_vorbis_decode(const uint8 *data, int len, int *ch, int *rate, int16 **dest)
{
return -1;
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment