add vorbis
This commit is contained in:
parent
f69a8b3132
commit
feb686e155
14 changed files with 5882 additions and 26 deletions
|
|
@ -78,7 +78,7 @@ int main(int argc, char** argv){
|
|||
|
||||
GSClientToggleSkybox(GSEngineGetClient(engine), GSTrue);
|
||||
|
||||
if((sound = GSSoundOpen(GSClientGetSoundEngine(GSEngineGetClient(engine)), "game:/shanghai.mp3")) != NULL){
|
||||
if((sound = GSSoundOpen(GSClientGetSoundEngine(GSEngineGetClient(engine)), "game:/shanghai.ogg")) != NULL){
|
||||
GSSoundToggleLoop(sound, 1);
|
||||
GSSoundStart(sound);
|
||||
}
|
||||
|
|
|
|||
5584
engine/external/stb/stb_vorbis.c
generated
vendored
Normal file
5584
engine/external/stb/stb_vorbis.c
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
4
engine/external/stb/stb_vorbis.h
generated
vendored
Normal file
4
engine/external/stb/stb_vorbis.h
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef STB_VORBIS_IMPLEMENTATION
|
||||
#define STB_VORBIS_HEADER_ONLY
|
||||
#endif
|
||||
#include "stb_vorbis.c"
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* sound.c */
|
||||
/* src/sound/sound.c */
|
||||
GSDECL GSSound GSSoundNew(GSSoundEngine sengine);
|
||||
GSDECL GSSound GSSoundOpen(GSSoundEngine sengine, const char* path);
|
||||
GSDECL void GSSoundClose(GSSound sound);
|
||||
|
|
@ -19,11 +19,13 @@ GSDECL void GSSoundPause(GSSound audio);
|
|||
GSDECL void GSSoundLock(GSSound sound);
|
||||
GSDECL void GSSoundUnlock(GSSound sound);
|
||||
|
||||
/* snd_xm.c */
|
||||
/* you can guess where they are */
|
||||
GSDECL GSSound GSSoundOpenXM(GSSoundEngine sengine, GSFile file);
|
||||
|
||||
/* snd_mod.c */
|
||||
GSDECL GSSound GSSoundOpenMOD(GSSoundEngine sengine, GSFile file);
|
||||
GSDECL GSSound GSSoundOpenMP3(GSSoundEngine sengine, GSFile file);
|
||||
GSDECL GSSound GSSoundOpenFLAC(GSSoundEngine sengine, GSFile file);
|
||||
GSDECL GSSound GSSoundOpenVorbis(GSSoundEngine sengine, GSFile file);
|
||||
GSDECL GSSound GSSoundOpenWAV(GSSoundEngine sengine, GSFile file);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,8 +179,11 @@ struct _GSSound {
|
|||
|
||||
GSFile file;
|
||||
|
||||
void* opaque1;
|
||||
void* opaque2;
|
||||
void* opaque1;
|
||||
void* opaque2;
|
||||
int from_samplerate;
|
||||
ma_resampler_config resampler_config;
|
||||
ma_resampler resampler;
|
||||
|
||||
GSSoundResetCallback reset;
|
||||
GSSoundReadCallback read;
|
||||
|
|
|
|||
2
engine/src/external/stb_vorbis.c
vendored
Normal file
2
engine/src/external/stb_vorbis.c
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#define STB_VORBIS_IMPLEMENTATION
|
||||
#include <stb_vorbis.h>
|
||||
50
engine/src/sound/snd_flac.c
Normal file
50
engine/src/sound/snd_flac.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include <GearSrc/Sound.h>
|
||||
|
||||
#include <GearSrc/SoundDriver.h>
|
||||
#include <GearSrc/File.h>
|
||||
|
||||
#include <dr_flac.h>
|
||||
|
||||
static void snd_reset(GSSound sound) {
|
||||
drflac_seek_to_pcm_frame(sound->opaque1, 0);
|
||||
}
|
||||
|
||||
static int snd_read(GSSound sound, GSI16* out, int frame) {
|
||||
return drflac_read_pcm_frames_s16(sound->opaque1, frame, out);
|
||||
}
|
||||
|
||||
static void snd_close(GSSound sound) {
|
||||
if(sound->opaque1 != NULL) {
|
||||
drflac_free(sound->opaque1, NULL);
|
||||
}
|
||||
free(sound->opaque2);
|
||||
}
|
||||
|
||||
GSSound GSSoundOpenFLAC(GSSoundEngine sengine, GSFile file) {
|
||||
GSSound sound = GSSoundNew(sengine);
|
||||
int size;
|
||||
|
||||
size = GSFileSize(file);
|
||||
sound->opaque2 = malloc(size);
|
||||
GSFileRead(file, sound->opaque2, size);
|
||||
|
||||
sound->reset = snd_reset;
|
||||
sound->read = snd_read;
|
||||
sound->close = snd_close;
|
||||
|
||||
if(size < 4 || memcmp(sound->opaque2, "fLaC", 4) != 0) {
|
||||
GSSoundClose(sound);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if((sound->opaque1 = drflac_open_memory(sound->opaque2, size, NULL)) == NULL) {
|
||||
GSSoundClose(sound);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sound->from_samplerate = ((drflac*)sound->opaque1)->sampleRate;
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
|
@ -42,8 +42,6 @@ GSSound GSSoundOpenMOD(GSSoundEngine sengine, GSFile file) {
|
|||
GSSound sound = GSSoundNew(sengine);
|
||||
int size;
|
||||
|
||||
GSFileSeek(file, 0);
|
||||
|
||||
size = GSFileSize(file);
|
||||
sound->opaque2 = malloc(size);
|
||||
GSFileRead(file, sound->opaque2, size);
|
||||
|
|
|
|||
59
engine/src/sound/snd_mp3.c
Normal file
59
engine/src/sound/snd_mp3.c
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#include <GearSrc/Sound.h>
|
||||
|
||||
#include <GearSrc/SoundDriver.h>
|
||||
#include <GearSrc/File.h>
|
||||
|
||||
#include <dr_mp3.h>
|
||||
|
||||
static void snd_reset(GSSound sound) {
|
||||
drmp3_seek_to_pcm_frame(sound->opaque1, 0);
|
||||
}
|
||||
|
||||
static int snd_read(GSSound sound, GSI16* out, int frame) {
|
||||
return drmp3_read_pcm_frames_s16(sound->opaque1, frame, out);
|
||||
}
|
||||
|
||||
static void snd_close(GSSound sound) {
|
||||
if(sound->opaque1 != NULL) {
|
||||
drmp3_uninit(sound->opaque1);
|
||||
free(sound->opaque1);
|
||||
}
|
||||
free(sound->opaque2);
|
||||
}
|
||||
|
||||
GSSound GSSoundOpenMP3(GSSoundEngine sengine, GSFile file) {
|
||||
GSSound sound = GSSoundNew(sengine);
|
||||
int size;
|
||||
unsigned char* buf;
|
||||
|
||||
size = GSFileSize(file);
|
||||
sound->opaque2 = malloc(size);
|
||||
GSFileRead(file, sound->opaque2, size);
|
||||
|
||||
sound->reset = snd_reset;
|
||||
sound->read = snd_read;
|
||||
sound->close = snd_close;
|
||||
|
||||
buf = sound->opaque2;
|
||||
if(size > 2 && buf[0] == 0xff && (buf[1] == 0xfb || buf[1] == 0xf3 || buf[2] == 0xf2)) {
|
||||
} else if(size > 3 && memcmp(buf, "ID3", 3) == 0) {
|
||||
} else {
|
||||
GSSoundClose(sound);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sound->opaque1 = malloc(sizeof(drmp3));
|
||||
if(!drmp3_init_memory(sound->opaque1, sound->opaque2, size, NULL)) {
|
||||
free(sound->opaque1);
|
||||
sound->opaque1 = NULL;
|
||||
|
||||
GSSoundClose(sound);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sound->from_samplerate = ((drmp3*)sound->opaque1)->sampleRate;
|
||||
|
||||
return sound;
|
||||
}
|
||||
48
engine/src/sound/snd_vorbis.c
Normal file
48
engine/src/sound/snd_vorbis.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#include <GearSrc/Sound.h>
|
||||
|
||||
#include <GearSrc/SoundDriver.h>
|
||||
#include <GearSrc/File.h>
|
||||
|
||||
#include <stb_vorbis.h>
|
||||
|
||||
static void snd_reset(GSSound sound) {
|
||||
stb_vorbis_seek_frame(sound->opaque1, 0);
|
||||
}
|
||||
|
||||
static int snd_read(GSSound sound, GSI16* out, int frame) {
|
||||
return stb_vorbis_get_samples_short_interleaved(sound->opaque1, 2, out, frame * 2);
|
||||
}
|
||||
|
||||
static void snd_close(GSSound sound) {
|
||||
if(sound->opaque1 != NULL) {
|
||||
stb_vorbis_close(sound->opaque1);
|
||||
}
|
||||
free(sound->opaque2);
|
||||
}
|
||||
|
||||
GSSound GSSoundOpenVorbis(GSSoundEngine sengine, GSFile file) {
|
||||
GSSound sound = GSSoundNew(sengine);
|
||||
int size;
|
||||
stb_vorbis_info info;
|
||||
int err;
|
||||
|
||||
size = GSFileSize(file);
|
||||
sound->opaque2 = malloc(size);
|
||||
GSFileRead(file, sound->opaque2, size);
|
||||
|
||||
sound->reset = snd_reset;
|
||||
sound->read = snd_read;
|
||||
sound->close = snd_close;
|
||||
|
||||
if((sound->opaque1 = stb_vorbis_open_memory(sound->opaque2, size, &err, NULL)) == NULL) {
|
||||
GSSoundClose(sound);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info = stb_vorbis_get_info(sound->opaque1);
|
||||
|
||||
sound->from_samplerate = info.sample_rate;
|
||||
|
||||
return sound;
|
||||
}
|
||||
55
engine/src/sound/snd_wav.c
Normal file
55
engine/src/sound/snd_wav.c
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#include <GearSrc/Sound.h>
|
||||
|
||||
#include <GearSrc/SoundDriver.h>
|
||||
#include <GearSrc/File.h>
|
||||
|
||||
#include <dr_wav.h>
|
||||
|
||||
static void snd_reset(GSSound sound) {
|
||||
drwav_seek_to_pcm_frame(sound->opaque1, 0);
|
||||
}
|
||||
|
||||
static int snd_read(GSSound sound, GSI16* out, int frame) {
|
||||
return drwav_read_pcm_frames_s16(sound->opaque1, frame, out);
|
||||
}
|
||||
|
||||
static void snd_close(GSSound sound) {
|
||||
if(sound->opaque1 != NULL) {
|
||||
drwav_uninit(sound->opaque1);
|
||||
free(sound->opaque1);
|
||||
}
|
||||
free(sound->opaque2);
|
||||
}
|
||||
|
||||
GSSound GSSoundOpenWAV(GSSoundEngine sengine, GSFile file) {
|
||||
GSSound sound = GSSoundNew(sengine);
|
||||
int size;
|
||||
|
||||
size = GSFileSize(file);
|
||||
sound->opaque2 = malloc(size);
|
||||
GSFileRead(file, sound->opaque2, size);
|
||||
|
||||
sound->reset = snd_reset;
|
||||
sound->read = snd_read;
|
||||
sound->close = snd_close;
|
||||
|
||||
if(size < 4 || memcmp(sound->opaque2, "RIFF", 4) != 0) {
|
||||
GSSoundClose(sound);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sound->opaque1 = malloc(sizeof(drwav));
|
||||
if(!drwav_init_memory(sound->opaque1, sound->opaque2, size, NULL)) {
|
||||
free(sound->opaque1);
|
||||
sound->opaque1 = NULL;
|
||||
|
||||
GSSoundClose(sound);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sound->from_samplerate = ((drwav*)sound->opaque1)->sampleRate;
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
|
@ -28,8 +28,6 @@ GSSound GSSoundOpenXM(GSSoundEngine sengine, GSFile file) {
|
|||
GSSound sound = GSSoundNew(sengine);
|
||||
int size;
|
||||
|
||||
GSFileSeek(file, 0);
|
||||
|
||||
size = GSFileSize(file);
|
||||
sound->opaque2 = malloc(size);
|
||||
GSFileRead(file, sound->opaque2, size);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <GearSrc/Sound.h>
|
||||
|
||||
#include <GearSrc/File.h>
|
||||
#include <GearSrc/SoundDriver.h>
|
||||
#include <GearSrc/SoundEngine.h>
|
||||
#include <GearSrc/Sound.h>
|
||||
#include <GearSrc/Log.h>
|
||||
|
|
@ -18,6 +19,8 @@ GSSound GSSoundNew(GSSoundEngine sengine) {
|
|||
sound->paused = 1;
|
||||
sound->loop = 0;
|
||||
|
||||
sound->from_samplerate = 0;
|
||||
|
||||
ma_mutex_init(&sound->mutex);
|
||||
|
||||
GSSoundEngineLock(sengine);
|
||||
|
|
@ -27,21 +30,44 @@ GSSound GSSoundNew(GSSoundEngine sengine) {
|
|||
return sound;
|
||||
}
|
||||
|
||||
static void after(GSSound s) {
|
||||
GSSoundLock(s);
|
||||
if(s->from_samplerate > 0) {
|
||||
s->resampler_config = ma_resampler_config_init(ma_format_s16, 2, s->from_samplerate, GSSoundDriverRate, ma_resample_algorithm_linear);
|
||||
ma_resampler_init(&s->resampler_config, NULL, &s->resampler);
|
||||
}
|
||||
GSSoundUnlock(s);
|
||||
}
|
||||
|
||||
typedef struct pair {
|
||||
const char* name;
|
||||
GSSound (*callback)(GSSoundEngine sengine, GSFile file);
|
||||
} pair_t;
|
||||
|
||||
GSSound GSSoundOpen(GSSoundEngine sengine, const char* path) {
|
||||
GSSound s;
|
||||
GSFile f;
|
||||
int i;
|
||||
pair_t formats[] = {
|
||||
{"XM", GSSoundOpenXM}, /**/
|
||||
{"MOD", GSSoundOpenMOD}, /**/
|
||||
{"MP3", GSSoundOpenMP3}, /**/
|
||||
{"FLAC", GSSoundOpenFLAC}, /**/
|
||||
{"Vorbis", GSSoundOpenVorbis}, /**/
|
||||
{"WAV", GSSoundOpenWAV} /**/
|
||||
};
|
||||
|
||||
if((f = GSFileOpen(sengine->engine, path)) == NULL) return NULL;
|
||||
if((s = GSSoundOpenXM(sengine, f)) != NULL) {
|
||||
s->file = f;
|
||||
GSLog(sengine->engine, GSLogInfo, "%s: Opened as XM", path);
|
||||
return s;
|
||||
}
|
||||
|
||||
if((s = GSSoundOpenMOD(sengine, f)) != NULL) {
|
||||
s->file = f;
|
||||
GSLog(sengine->engine, GSLogInfo, "%s: Opened as MOD", path);
|
||||
return s;
|
||||
for(i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) {
|
||||
GSFileSeek(f, 0);
|
||||
|
||||
if((s = formats[i].callback(sengine, f)) != NULL) {
|
||||
s->file = f;
|
||||
GSLog(sengine->engine, GSLogInfo, "%s: Opened as %s", path, formats[i].name);
|
||||
after(s);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
GSLog(sengine->engine, GSLogError, "%s: Unrecognized format", path);
|
||||
|
|
@ -70,6 +96,8 @@ void GSSoundClose(GSSound sound) {
|
|||
|
||||
if(sound->file != NULL) GSFileClose(sound->file);
|
||||
|
||||
if(sound->from_samplerate > 0) ma_resampler_uninit(&sound->resampler, NULL);
|
||||
|
||||
free(sound);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,13 +11,14 @@ static void read_callback(void* opaque, GSI16* out, int frame) {
|
|||
GSSoundEngine sengine = opaque;
|
||||
int i;
|
||||
GSNumber* buffer = malloc(sizeof(*buffer) * frame * 2);
|
||||
GSI16* result = malloc(sizeof(*result) * frame * 2);
|
||||
|
||||
for(i = 0; i < frame * 2; i++) buffer[i] = 0;
|
||||
|
||||
GSSoundEngineLock(sengine);
|
||||
for(i = 0; i < arrlen(sengine->sound); i++) {
|
||||
int s;
|
||||
int s, f;
|
||||
GSI16* result;
|
||||
GSI16* result2;
|
||||
|
||||
GSSoundLock(sengine->sound[i]);
|
||||
if(sengine->sound[i]->paused || sengine->sound[i]->read == NULL) {
|
||||
|
|
@ -25,23 +26,47 @@ static void read_callback(void* opaque, GSI16* out, int frame) {
|
|||
continue;
|
||||
}
|
||||
|
||||
memset(result, 0, sizeof(*result) * frame * 2);
|
||||
s = sengine->sound[i]->read(sengine->sound[i], result, frame);
|
||||
if(sengine->sound[i]->from_samplerate > 0) {
|
||||
f = frame * sengine->sound[i]->from_samplerate / GSSoundDriverRate;
|
||||
} else {
|
||||
f = frame;
|
||||
}
|
||||
|
||||
result = malloc(sizeof(*result) * f * 2);
|
||||
memset(result, 0, sizeof(*result) * f * 2);
|
||||
s = sengine->sound[i]->read(sengine->sound[i], result, f);
|
||||
if(s > 0) {
|
||||
int j;
|
||||
for(j = 0; j < s * 2; j++) buffer[j] += (GSNumber)result[j] / 32767;
|
||||
|
||||
if(sengine->sound[i]->from_samplerate > 0) {
|
||||
ma_uint64 fin = f;
|
||||
ma_uint64 fout = frame;
|
||||
|
||||
result2 = malloc(sizeof(*result2) * frame * 2);
|
||||
memset(result2, 0, sizeof(*result2) * frame * 2);
|
||||
|
||||
ma_resampler_process_pcm_frames(&sengine->sound[i]->resampler, result, &fin, result2, &fout);
|
||||
|
||||
s = s * GSSoundDriverRate / sengine->sound[i]->from_samplerate;
|
||||
} else {
|
||||
result2 = result;
|
||||
}
|
||||
|
||||
for(j = 0; j < s * 2; j++) buffer[j] += (GSNumber)result2[j] / 32767;
|
||||
|
||||
if(result2 != result) free(result2);
|
||||
} else if(sengine->sound[i]->loop && sengine->sound[i]->reset != NULL) {
|
||||
sengine->sound[i]->reset(sengine->sound[i]);
|
||||
} else {
|
||||
sengine->sound[i]->paused = GSTrue;
|
||||
}
|
||||
free(result);
|
||||
GSSoundUnlock(sengine->sound[i]);
|
||||
}
|
||||
GSSoundEngineUnlock(sengine);
|
||||
|
||||
for(i = 0; i < frame * 2; i++) out[i] = buffer[i] * 32767;
|
||||
|
||||
free(result);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue