Skip to content

Instantly share code, notes, and snippets.

@AliceLR
Last active November 23, 2021 03:03
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/58fadf18f2248e163faed113baa0a25d to your computer and use it in GitHub Desktop.
Save AliceLR/58fadf18f2248e163faed113baa0a25d to your computer and use it in GitHub Desktop.
#if 0
clang++ $CXXFLAGS -fno-pie mem.cpp -omem src/depackers/vorbis.lo -lxmp
exit
#endif
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <memory>
#include <xmp.h>
#include "src/depackers/vorbis.h"
int main(int argc, char *argv[])
{
xmp_context opaque;
struct xmp_test_info info;
struct stat st;
unsigned int status_count[256]{};
unsigned int status_unkn = 0;
unsigned int total = 0;
int ret;
int i;
if(argc < 2)
return -1;
opaque = xmp_create_context();
for(i = 1; i < argc; i++)
{
fprintf(stderr, "Loading '%s'... ", argv[i]);
fflush(stderr);
FILE *f = fopen(argv[i], "rb");
if(!f)
{
fprintf(stderr, "fopen error\n");
continue;
}
// Workaround for broken MSan instrumentation of *stat().
memset(&st, 0, sizeof(struct stat));
ret = fstat(fileno(f), &st);
if(ret)
{
fprintf(stderr, "fstat error\n");
fclose(f);
continue;
}
size_t len = st.st_size;
std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
if(!buf)
{
fprintf(stderr, "malloc error\n");
fclose(f);
continue;
}
ret = fread(buf.get(), 1, len, f);
if(ret != len)
{
fprintf(stderr, "fread error\n");
fclose(f);
continue;
}
fclose(f);
/* Special case: Ogg signature? Invoke stb-vorbis directly. */
if(len >= 4 && buf[0] == 'O' && buf[1] == 'g' && buf[2] == 'g' && buf[3] == 'S')
{
int16_t *pcm16 = NULL;
int ch, rate;
int ret = stb_vorbis_decode_memory(buf.get(), len, &ch, &rate, &pcm16);
if(pcm16)
free(pcm16);
fprintf(stderr, "vorbis:%d\n", ret);
continue;
}
/* Try memory-mapped IO first. */
int ret = xmp_load_module_from_memory(opaque, buf.get(), len);
fprintf(stderr, "mem:%d", ret);
if(ret == -XMP_ERROR_FORMAT)
{
/* Might packed--try a full load. */
ret = xmp_load_module(opaque, argv[i]);
fprintf(stderr, " file:%d", ret);
}
else
{
/* Might also be packed--test the depackers. */
FILE *tmpf = fmemopen(buf.get(), len, "rb");
int ret2 = xmp_test_module_from_file(tmpf, &info);
fclose(tmpf);
fprintf(stderr, " file(test):%d", ret2);
}
if(ret == 0)
{
/* Attempt to play part of the module. */
struct xmp_module_info minfo;
xmp_get_module_info(opaque, &minfo);
/* Derive these from the MD5 for now :( */
int interp = minfo.md5[7] * 3U / 256;
int mono = (minfo.md5[3] & 1) ^ (minfo.md5[14] >> 7);
switch(interp)
{
case 0:
interp = XMP_INTERP_NEAREST;
break;
case 1:
interp = XMP_INTERP_LINEAR;
break;
default:
interp = XMP_INTERP_SPLINE;
break;
}
xmp_start_player(opaque, XMP_MIN_SRATE, mono ? XMP_FORMAT_MONO : 0);
xmp_set_player(opaque, XMP_PLAYER_INTERP, interp);
int ret2 = 0;
for(int i = 0; i < 64; i++)
{
ret2 = xmp_play_frame(opaque);
if(ret2)
break;
}
fprintf(stderr, " play:%d", ret2);
}
fprintf(stderr, "\n");
total++;
if(ret <= 0 && ret > -256)
status_count[-ret]++;
else
status_unkn++;
}
fflush(stderr);
if(total > 1)
{
if(status_unkn)
fprintf(stderr, "status ?: %u\n", status_unkn);
for(i = 0; i < 256; i++)
{
if(status_count[i])
fprintf(stderr, "status %4d: %u\n", -i, status_count[i]);
}
fflush(stderr);
}
xmp_free_context(opaque);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment