format
This commit is contained in:
parent
6c1a07cb68
commit
a74bd0b3e7
4 changed files with 139 additions and 141 deletions
|
|
@ -4,46 +4,45 @@
|
|||
#define DR_MP3_IMPLEMENTATION
|
||||
#include <dr_mp3.h>
|
||||
|
||||
static MDESoundContext mp3_open(const char* path){
|
||||
static MDESoundContext mp3_open(const char* path) {
|
||||
MDESoundContext ctx = malloc(sizeof(*ctx));
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
ctx->title = MDEID3GetString(path, "TIT2");
|
||||
ctx->title = MDEID3GetString(path, "TIT2");
|
||||
ctx->artist = MDEID3GetString(path, "TPE1");
|
||||
ctx->album = MDEID3GetString(path, "TALB");
|
||||
ctx->genre = MDEID3GetString(path, "TCON");
|
||||
ctx->album = MDEID3GetString(path, "TALB");
|
||||
ctx->genre = MDEID3GetString(path, "TCON");
|
||||
|
||||
ctx->opaque = malloc(sizeof(drmp3));
|
||||
if(!drmp3_init_file(ctx->opaque, path, NULL)){
|
||||
if(!drmp3_init_file(ctx->opaque, path, NULL)) {
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->channels = ((drmp3*)ctx->opaque)->channels;
|
||||
ctx->channels = ((drmp3*)ctx->opaque)->channels;
|
||||
ctx->sample_rate = ((drmp3*)ctx->opaque)->sampleRate;
|
||||
ctx->frames = drmp3_get_pcm_frame_count(ctx->opaque);
|
||||
ctx->frames = drmp3_get_pcm_frame_count(ctx->opaque);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void mp3_close(MDESoundContext ctx){
|
||||
static void mp3_close(MDESoundContext ctx) {
|
||||
drmp3_uninit(ctx->opaque);
|
||||
free(ctx->opaque);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static int mp3_read(MDESoundContext ctx, short* out, int frames){
|
||||
static int mp3_read(MDESoundContext ctx, short* out, int frames) {
|
||||
return drmp3_read_pcm_frames_s16(ctx->opaque, frames, out);
|
||||
}
|
||||
|
||||
static void mp3_seek(MDESoundContext ctx, int frames){
|
||||
static void mp3_seek(MDESoundContext ctx, int frames) {
|
||||
drmp3_seek_to_pcm_frame(ctx->opaque, frames);
|
||||
}
|
||||
|
||||
static MDESoundDriverRec rec = {
|
||||
mp3_open,
|
||||
mp3_close,
|
||||
mp3_read,
|
||||
mp3_seek
|
||||
};
|
||||
mp3_open,
|
||||
mp3_close,
|
||||
mp3_read,
|
||||
mp3_seek};
|
||||
MDESoundDriver MDESoundDriverMP3 = &rec;
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
#include <vorbis/vorbisfile.h>
|
||||
|
||||
static MDESoundContext vorbis_open(const char* path){
|
||||
static MDESoundContext vorbis_open(const char* path) {
|
||||
MDESoundContext ctx;
|
||||
FILE* f = fopen(path, "rb");
|
||||
FILE* f = fopen(path, "rb");
|
||||
vorbis_comment* comments;
|
||||
if(f == NULL) return NULL;
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ static MDESoundContext vorbis_open(const char* path){
|
|||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
ctx->opaque = malloc(sizeof(OggVorbis_File));
|
||||
if(ov_open_callbacks(f, ctx->opaque, NULL, 0, OV_CALLBACKS_DEFAULT) < 0){
|
||||
if(ov_open_callbacks(f, ctx->opaque, NULL, 0, OV_CALLBACKS_DEFAULT) < 0) {
|
||||
free(ctx->opaque);
|
||||
free(ctx);
|
||||
fclose(f);
|
||||
|
|
@ -21,54 +21,53 @@ static MDESoundContext vorbis_open(const char* path){
|
|||
}
|
||||
|
||||
comments = ov_comment(ctx->opaque, -1);
|
||||
if(comments != NULL){
|
||||
if(comments != NULL) {
|
||||
int i;
|
||||
for(i = 0; i < comments->comments; i++){
|
||||
for(i = 0; i < comments->comments; i++) {
|
||||
char* s = MDEStringDuplicate(comments->user_comments[i]);
|
||||
char* p = strchr(s, '=');
|
||||
if(p != NULL){
|
||||
if(p != NULL) {
|
||||
p[0] = 0;
|
||||
if(strcasecmp(s, "TITLE") == 0){
|
||||
if(strcasecmp(s, "TITLE") == 0) {
|
||||
ctx->title = MDEStringDuplicate(p + 1);
|
||||
}else if(strcasecmp(s, "ALBUM") == 0){
|
||||
} else if(strcasecmp(s, "ALBUM") == 0) {
|
||||
ctx->album = MDEStringDuplicate(p + 1);
|
||||
}else if(strcasecmp(s, "ARTIST") == 0){
|
||||
} else if(strcasecmp(s, "ARTIST") == 0) {
|
||||
ctx->artist = MDEStringDuplicate(p + 1);
|
||||
}else if(strcasecmp(s, "GENRE") == 0){
|
||||
} else if(strcasecmp(s, "GENRE") == 0) {
|
||||
ctx->genre = MDEStringDuplicate(p + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
|
||||
ctx->channels = ov_info(ctx->opaque, -1)->channels;
|
||||
ctx->channels = ov_info(ctx->opaque, -1)->channels;
|
||||
ctx->sample_rate = ov_info(ctx->opaque, -1)->rate;
|
||||
ctx->frames = ov_pcm_total(ctx->opaque, -1);
|
||||
ctx->frames = ov_pcm_total(ctx->opaque, -1);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void vorbis_close(MDESoundContext ctx){
|
||||
static void vorbis_close(MDESoundContext ctx) {
|
||||
ov_clear(ctx->opaque);
|
||||
free(ctx->opaque);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static int vorbis_read(MDESoundContext ctx, short* out, int frames){
|
||||
static int vorbis_read(MDESoundContext ctx, short* out, int frames) {
|
||||
int n;
|
||||
return ov_read(ctx->opaque, (char*)out, frames * 2 * ctx->channels, 0, 2, 1, &n) / 2 / ctx->channels;
|
||||
}
|
||||
|
||||
static void vorbis_seek(MDESoundContext ctx, int frames){
|
||||
static void vorbis_seek(MDESoundContext ctx, int frames) {
|
||||
ov_pcm_seek(ctx->opaque, frames);
|
||||
}
|
||||
|
||||
static MDESoundDriverRec rec = {
|
||||
vorbis_open,
|
||||
vorbis_close,
|
||||
vorbis_read,
|
||||
vorbis_seek
|
||||
};
|
||||
vorbis_open,
|
||||
vorbis_close,
|
||||
vorbis_read,
|
||||
vorbis_seek};
|
||||
MDESoundDriver MDESoundDriverVorbis = &rec;
|
||||
|
|
|
|||
144
sound/id3.c
144
sound/id3.c
|
|
@ -2,93 +2,93 @@
|
|||
#include <MDE/Core/String.h>
|
||||
|
||||
static unsigned int syncsafe(FILE* f) {
|
||||
unsigned char d[4];
|
||||
unsigned int r = 0;
|
||||
int i;
|
||||
fread(d, 4, 1, f);
|
||||
unsigned char d[4];
|
||||
unsigned int r = 0;
|
||||
int i;
|
||||
fread(d, 4, 1, f);
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
r = r << 7;
|
||||
r = r | (d[i] & 127);
|
||||
}
|
||||
for(i = 0; i < 4; i++) {
|
||||
r = r << 7;
|
||||
r = r | (d[i] & 127);
|
||||
}
|
||||
|
||||
return r;
|
||||
return r;
|
||||
}
|
||||
|
||||
static unsigned int big(FILE* f) {
|
||||
unsigned char d[4];
|
||||
unsigned int r = 0;
|
||||
int i;
|
||||
fread(d, 4, 1, f);
|
||||
unsigned char d[4];
|
||||
unsigned int r = 0;
|
||||
int i;
|
||||
fread(d, 4, 1, f);
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
r = r << 8;
|
||||
r = r | d[i];
|
||||
}
|
||||
for(i = 0; i < 4; i++) {
|
||||
r = r << 8;
|
||||
r = r | d[i];
|
||||
}
|
||||
|
||||
return r;
|
||||
return r;
|
||||
}
|
||||
|
||||
char* MDEID3GetTag(const char* path, const char* name, size_t* size){
|
||||
FILE* f = fopen(path, "rb");
|
||||
unsigned char* d = NULL;
|
||||
char sig[3];
|
||||
unsigned char ver[2];
|
||||
unsigned char flag;
|
||||
unsigned char frame[4];
|
||||
unsigned int dsz = 0;
|
||||
if(f == NULL) return NULL;
|
||||
char* MDEID3GetTag(const char* path, const char* name, size_t* size) {
|
||||
FILE* f = fopen(path, "rb");
|
||||
unsigned char* d = NULL;
|
||||
char sig[3];
|
||||
unsigned char ver[2];
|
||||
unsigned char flag;
|
||||
unsigned char frame[4];
|
||||
unsigned int dsz = 0;
|
||||
if(f == NULL) return NULL;
|
||||
|
||||
fread(sig, 3, 1, f);
|
||||
if(memcmp(sig, "ID3", 3) != 0) return NULL;
|
||||
fread(sig, 3, 1, f);
|
||||
if(memcmp(sig, "ID3", 3) != 0) return NULL;
|
||||
|
||||
fread(ver, 2, 1, f);
|
||||
if(memcmp(ver, "\x04\x00", 2) != 0 && memcmp(ver, "\x03\x00", 2) != 0) return NULL;
|
||||
fread(ver, 2, 1, f);
|
||||
if(memcmp(ver, "\x04\x00", 2) != 0 && memcmp(ver, "\x03\x00", 2) != 0) return NULL;
|
||||
|
||||
fread(&flag, 1, 1, f);
|
||||
if(flag & (1 << 6)) return NULL; /* FIXME */
|
||||
if(flag & (1 << 7)) return NULL; /* what even is this??? */
|
||||
fread(&flag, 1, 1, f);
|
||||
if(flag & (1 << 6)) return NULL; /* FIXME */
|
||||
if(flag & (1 << 7)) return NULL; /* what even is this??? */
|
||||
|
||||
dsz = syncsafe(f);
|
||||
dsz = syncsafe(f);
|
||||
|
||||
while(dsz > 0) {
|
||||
unsigned int fsz;
|
||||
while(dsz > 0) {
|
||||
unsigned int fsz;
|
||||
|
||||
fread(frame, 4, 1, f);
|
||||
if(frame[0] == 0) break; /* XXX: Is this ok? */
|
||||
fread(frame, 4, 1, f);
|
||||
if(frame[0] == 0) break; /* XXX: Is this ok? */
|
||||
|
||||
if(memcmp(ver, "\x04\x00", 2) == 0) {
|
||||
fsz = syncsafe(f);
|
||||
} else {
|
||||
fsz = big(f);
|
||||
}
|
||||
if(memcmp(ver, "\x04\x00", 2) == 0) {
|
||||
fsz = syncsafe(f);
|
||||
} else {
|
||||
fsz = big(f);
|
||||
}
|
||||
|
||||
fseek(f, 2, SEEK_CUR);
|
||||
if(memcmp(frame, name, strlen(name)) == 0) {
|
||||
fseek(f, 2, SEEK_CUR);
|
||||
if(memcmp(frame, name, strlen(name)) == 0) {
|
||||
d = malloc(fsz);
|
||||
fread(d, fsz, 1, f);
|
||||
|
||||
*size = fsz;
|
||||
break;
|
||||
} else {
|
||||
fseek(f, fsz, SEEK_CUR);
|
||||
}
|
||||
} else {
|
||||
fseek(f, fsz, SEEK_CUR);
|
||||
}
|
||||
|
||||
dsz -= 4 + 4 + 2 + fsz;
|
||||
}
|
||||
dsz -= 4 + 4 + 2 + fsz;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
fclose(f);
|
||||
|
||||
return d;
|
||||
return d;
|
||||
}
|
||||
|
||||
char* MDEID3GetString(const char* path, const char* name){
|
||||
size_t sz;
|
||||
char* MDEID3GetString(const char* path, const char* name) {
|
||||
size_t sz;
|
||||
unsigned char* d = MDEID3GetTag(path, name, &sz);
|
||||
char* s;
|
||||
int i;
|
||||
char* s;
|
||||
int i;
|
||||
if(d == NULL) return NULL;
|
||||
if(d[0] == 2){
|
||||
if(d[0] == 2) {
|
||||
free(d);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -96,24 +96,24 @@ char* MDEID3GetString(const char* path, const char* name){
|
|||
s = malloc(sz - 1 + 1);
|
||||
memcpy(s, d + 1, sz - 1);
|
||||
s[sz - 1] = 0;
|
||||
if(d[0] == 1){
|
||||
if(d[0] == 1) {
|
||||
unsigned short bom = *(unsigned short*)&s[0];
|
||||
|
||||
for(i = 1; i < sz - 1; i++){
|
||||
if(bom == 0xfffe){
|
||||
for(i = 1; i < sz - 1; i++) {
|
||||
if(bom == 0xfffe) {
|
||||
unsigned short n = 0;
|
||||
n = n << 8;
|
||||
n = n | s[2 * i + 0];
|
||||
n = n << 8;
|
||||
n = n | s[2 * i + 1];
|
||||
s[i - 1] = n & 0x7f;
|
||||
}else if(bom == 0xfeff){
|
||||
n = n << 8;
|
||||
n = n | s[2 * i + 0];
|
||||
n = n << 8;
|
||||
n = n | s[2 * i + 1];
|
||||
s[i - 1] = n & 0x7f;
|
||||
} else if(bom == 0xfeff) {
|
||||
unsigned short n = 0;
|
||||
n = n << 8;
|
||||
n = n | s[2 * i + 1];
|
||||
n = n << 8;
|
||||
n = n | s[2 * i + 0];
|
||||
s[i - 1] = n & 0x7f;
|
||||
n = n << 8;
|
||||
n = n | s[2 * i + 1];
|
||||
n = n << 8;
|
||||
n = n | s[2 * i + 0];
|
||||
s[i - 1] = n & 0x7f;
|
||||
}
|
||||
}
|
||||
s[i - 1] = 0;
|
||||
|
|
|
|||
|
|
@ -3,25 +3,25 @@
|
|||
#include <stb_ds.h>
|
||||
|
||||
#define TRY_DRIVER(name) \
|
||||
if(sound->context == NULL){ \
|
||||
sound->driver = MDESoundDriver ## name; \
|
||||
sound->context = MDESoundDriver ## name->open(path); \
|
||||
if(sound->context == NULL) { \
|
||||
sound->driver = MDESoundDriver##name; \
|
||||
sound->context = MDESoundDriver##name->open(path); \
|
||||
}
|
||||
|
||||
MDESound MDESoundOpen(const char* path){
|
||||
MDESound MDESoundOpen(const char* path) {
|
||||
MDESound sound = malloc(sizeof(*sound));
|
||||
sound->context = NULL;
|
||||
sound->buffer = NULL;
|
||||
sound->buffer = NULL;
|
||||
|
||||
TRY_DRIVER(MP3);
|
||||
TRY_DRIVER(Vorbis);
|
||||
|
||||
if(sound->context == NULL){
|
||||
if(sound->context == NULL) {
|
||||
free(sound);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(sound->context->channels != 2 && sound->context->channels != 1){
|
||||
if(sound->context->channels != 2 && sound->context->channels != 1) {
|
||||
MDESoundClose(sound);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -29,18 +29,18 @@ MDESound MDESoundOpen(const char* path){
|
|||
return sound;
|
||||
}
|
||||
|
||||
int MDESoundRead(MDESound sound, short* out, int frames){
|
||||
int MDESoundRead(MDESound sound, short* out, int frames) {
|
||||
int total = frames;
|
||||
int seek = 0;
|
||||
int seek = 0;
|
||||
|
||||
while(arrlen(sound->buffer) > 0 && total > 0){
|
||||
while(arrlen(sound->buffer) > 0 && total > 0) {
|
||||
int fr = (sound->buffer[0].frames - sound->buffer[0].seek);
|
||||
if(fr > total) fr = total;
|
||||
|
||||
memcpy(out + seek * 2, sound->buffer[0].data + sound->buffer[0].seek * 2, 2 * 2 * fr);
|
||||
|
||||
sound->buffer[0].seek += fr;
|
||||
if(sound->buffer[0].seek == sound->buffer[0].frames){
|
||||
if(sound->buffer[0].seek == sound->buffer[0].frames) {
|
||||
free(sound->buffer[0].data);
|
||||
arrdel(sound->buffer, 0);
|
||||
}
|
||||
|
|
@ -48,35 +48,35 @@ int MDESoundRead(MDESound sound, short* out, int frames){
|
|||
seek += fr;
|
||||
}
|
||||
|
||||
while(total > 0){
|
||||
int i;
|
||||
while(total > 0) {
|
||||
int i;
|
||||
short* buf = malloc(sizeof(*buf) * 2 * frames);
|
||||
short* f = malloc(sizeof(*f) * sound->context->channels * frames);
|
||||
int r = sound->driver->read(sound->context, f, frames);
|
||||
if(sound->context->channels == 2){
|
||||
for(i = 0; i < r * 2; i++){
|
||||
short* f = malloc(sizeof(*f) * sound->context->channels * frames);
|
||||
int r = sound->driver->read(sound->context, f, frames);
|
||||
if(sound->context->channels == 2) {
|
||||
for(i = 0; i < r * 2; i++) {
|
||||
buf[i] = f[i];
|
||||
}
|
||||
}else if(sound->context->channels == 1){
|
||||
for(i = 0; i < r; i++){
|
||||
} else if(sound->context->channels == 1) {
|
||||
for(i = 0; i < r; i++) {
|
||||
buf[i * 2 + 0] = f[i];
|
||||
buf[i * 2 + 1] = f[i];
|
||||
}
|
||||
}
|
||||
free(f);
|
||||
|
||||
if(r == 0){
|
||||
if(r == 0) {
|
||||
free(buf);
|
||||
break;
|
||||
}else if(total >= r){
|
||||
} else if(total >= r) {
|
||||
memcpy(out + seek * 2, buf, r * 2 * 2);
|
||||
seek += r;
|
||||
total -= r;
|
||||
free(buf);
|
||||
}else if(total < r){
|
||||
} else if(total < r) {
|
||||
MDESoundBuffer buffer;
|
||||
buffer.data = buf;
|
||||
buffer.seek = total;
|
||||
buffer.data = buf;
|
||||
buffer.seek = total;
|
||||
buffer.frames = r;
|
||||
arrput(sound->buffer, buffer);
|
||||
|
||||
|
|
@ -89,12 +89,12 @@ int MDESoundRead(MDESound sound, short* out, int frames){
|
|||
return seek;
|
||||
}
|
||||
|
||||
int MDESoundReadFloat(MDESound sound, float* out, int frames){
|
||||
int MDESoundReadFloat(MDESound sound, float* out, int frames) {
|
||||
short* f = malloc(sizeof(*f) * 2 * frames);
|
||||
int i;
|
||||
int r = MDESoundRead(sound, f, frames);
|
||||
int i;
|
||||
int r = MDESoundRead(sound, f, frames);
|
||||
|
||||
for(i = 0; i < r * 2; i++){
|
||||
for(i = 0; i < r * 2; i++) {
|
||||
out[i] = f[i] / 32767.0;
|
||||
}
|
||||
|
||||
|
|
@ -103,11 +103,11 @@ int MDESoundReadFloat(MDESound sound, float* out, int frames){
|
|||
return r;
|
||||
}
|
||||
|
||||
void MDESoundSeek(MDESound sound, int frames){
|
||||
void MDESoundSeek(MDESound sound, int frames) {
|
||||
sound->driver->seek(sound->context, frames);
|
||||
}
|
||||
|
||||
void MDESoundClose(MDESound sound){
|
||||
void MDESoundClose(MDESound sound) {
|
||||
int i;
|
||||
if(sound->context->title != NULL) free(sound->context->title);
|
||||
if(sound->context->artist != NULL) free(sound->context->artist);
|
||||
|
|
@ -116,7 +116,7 @@ void MDESoundClose(MDESound sound){
|
|||
|
||||
sound->driver->close(sound->context);
|
||||
|
||||
for(i = 0; i < arrlen(sound->buffer); i++){
|
||||
for(i = 0; i < arrlen(sound->buffer); i++) {
|
||||
free(sound->buffer[i].data);
|
||||
}
|
||||
arrfree(sound->buffer);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue