diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libjin/audio/sdl/audio.cpp | 34 | ||||
-rw-r--r-- | src/libjin/audio/sdl/audio.h | 15 | ||||
-rw-r--r-- | src/libjin/audio/sdl/source.cpp | 76 | ||||
-rw-r--r-- | src/libjin/audio/sdl/source.h | 4 | ||||
-rw-r--r-- | src/libjin/math/math.h | 6 | ||||
-rw-r--r-- | src/libjin/utils/unittest.cpp | 7 |
6 files changed, 68 insertions, 74 deletions
diff --git a/src/libjin/audio/sdl/audio.cpp b/src/libjin/audio/sdl/audio.cpp index 5277a3d..a26ea1a 100644 --- a/src/libjin/audio/sdl/audio.cpp +++ b/src/libjin/audio/sdl/audio.cpp @@ -1,3 +1,4 @@ +#include <iostream> #include "audio.h" #include "source.h" @@ -6,35 +7,32 @@ namespace jin namespace audio { - void SDLAudio::defaultCallback(void *userdata, Uint8 *stream, int size) + /* עcallbackƵ̵߳ */ + void defaultCallback(void *userdata, Uint8 *stream, int size) { SDLAudio* audio = (SDLAudio*)userdata; - SDL_LockAudioDevice(audio->audioDevice); + audio->lock(); audio->processCommands(); audio->processSources(stream, size); - SDL_UnlockAudioDevice(audio->audioDevice); + audio->unlock(); } onlyonce bool SDLAudio::_init(const SettingBase* s) { if (SDL_Init(SDL_INIT_AUDIO) < 0) return false; - SDLAudioSetting* setting = (SDLAudioSetting*)s; SDL_AudioSpec spec; - zero(spec); - spec.freq = 44100; - spec.format = AUDIO_S16SYS; - spec.channels = 1; - spec.samples = 2048; + spec.freq = 44100; // 44100 Hz + spec.format = AUDIO_S16SYS; // signed 16bits + spec.channels = 2; // + spec.samples = 1 << 15; // Uin16Χ2 spec.userdata = this; spec.callback = defaultCallback; audioDevice = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0); if (audioDevice == 0) - { return false; - } - // start audio + /* start audio */ SDL_PauseAudioDevice(audioDevice, 0); return true; } @@ -45,12 +43,22 @@ namespace audio delete audio; } + void SDLAudio::lock() + { + SDL_LockAudioDevice(audioDevice); + } + + void SDLAudio::unlock() + { + SDL_UnlockAudioDevice(audioDevice); + } + void SDLAudio::processCommands() { SDLSourceManager::get()->processCommands(); } - void SDLAudio::processSources(Uint8* buffer, int len) + void SDLAudio::processSources(void* buffer, size_t len) { SDLSourceManager::get()->processSources(buffer, len); } diff --git a/src/libjin/audio/sdl/audio.h b/src/libjin/audio/sdl/audio.h index a0e63da..528fa7d 100644 --- a/src/libjin/audio/sdl/audio.h +++ b/src/libjin/audio/sdl/audio.h @@ -14,16 +14,6 @@ namespace audio public: - /* - struct Setting : SettingBase - { - int rate; // - int resolution; // ֱ - char channels; // - int samples; // ȡ - }; - */ - static inline Audio* get() { return audio != NULL ? audio : (audio = new SDLAudio()); @@ -42,9 +32,10 @@ namespace audio /* process functions*/ void processCommands(); - void processSources(Uint8* buffer, int len); + void processSources(void* buffer, size_t len); - static void defaultCallback(void *userdata, Uint8 *stream, int size); + void lock(); + void unlock(); private: diff --git a/src/libjin/audio/sdl/source.cpp b/src/libjin/audio/sdl/source.cpp index e8490f5..3686a92 100644 --- a/src/libjin/audio/sdl/source.cpp +++ b/src/libjin/audio/sdl/source.cpp @@ -38,6 +38,12 @@ namespace audio SDLSource* source; }; + typedef enum CHANNEL + { + MONO = 1, // + STEREO = 2, // + }; + typedef MASK enum STATUS { PLAYING = 1, @@ -122,7 +128,7 @@ namespace audio raw.rate = wav.samplerate; raw.bitdepth = wav.bitdepth; raw.samples = raw.size / (wav.bitdepth / 8.f); - raw.channel = wav.channels; + raw.channel = clamp(wav.channels, CHANNEL::MONO, CHANNEL::STEREO); raw.silence = 0; } else @@ -132,6 +138,7 @@ namespace audio void SDLSource::loadOGG(void* mem, int size) { raw.samples = stb_vorbis_decode_memory((unsigned char*)mem, size, (int*)&raw.channel, &raw.rate, (short**)&raw.data) << 1; + raw.channel = clamp(raw.channel, CHANNEL::MONO, CHANNEL::STEREO); raw.size = raw.samples << 1; // 2 bytes each sample raw.bitdepth = 16; raw.end = (char*)raw.data + raw.size; @@ -275,56 +282,45 @@ Manager::get()->pushCommand(cmd); \ } } - shared void Manager::processSources(Uint8* buffer, int len) + /* AUDIO_S16SYS[size>>1] buffer */ + shared void Manager::processSources(void* buf, size_t size) { - memset(buffer, 0, len); - int16_t* buf16 = (int16_t*)buffer; - int samples = len >> 1; + Sint16* buffer = (Sint16*)buf; + unsigned int samples = size >> 1; + memset(buffer, 0, size); + SDLSource* src = nullptr; std::vector<SDLSource*>::iterator it = sources.begin(); - SDLSource* source = nullptr; for (; it != sources.end();) { - source = *it; - int16_t* data16 = (int16_t*)source->raw.data; - if (source->is(STOPPED)) - removeSource(source); - else if (source->is(PAUSED)) - continue; - else if (source->is(PLAYING)) + src = *it; + if (src == nullptr) + goto next; + src->status.pos; + Sint16* source = (Sint16*)((char*)src->raw.data + src->status.pos); + unsigned int remain = src->raw.samples - (src->status.pos >> 1); + for (int i = 0; i < min(remain, samples); ++i) { - int16_t* src16 = (int16_t*)((char*)source->raw.data + source->status.pos); - int remainsample = (source->raw.size - source->status.pos) >> 1; - int bound = min(samples, remainsample); - for (int i = 0; i < bound; ++i) - { - buf16[i] += src16[i]; // mix sources - } - source->status.pos += (bound << 1); - if (remainsample < samples) + buffer[i] += (src->raw.channel == CHANNEL::STEREO ? source[i] : source[(i % 2) * 2]); + } + if (remain < samples) + { + if (!src->status.loop) { - if (source->status.loop) - { - int j = 0; - for (int i = bound; i < samples; ++i) - { - int val = data16[j]; - buf16[i] += val; - ++j; - } - source->status.pos = (j << 1); - break; - } - else - { - it = sources.erase(it); - continue; - } + it = sources.erase(it); + continue; } + int j = 0; + for (int i = samples - remain; i < samples; ++i, ++j) + buffer[i] += (src->raw.channel == CHANNEL::STEREO ? source[j] : source[j % 2 * 2]); + src->status.pos = (j << 1); + continue; } + src->status.pos += (samples << 1); + next: ++it; } } - + shared void Manager::removeSource(SDLSource* source) { std::vector<SDLSource*>::iterator it = sources.begin(); diff --git a/src/libjin/audio/sdl/source.h b/src/libjin/audio/sdl/source.h index 743d4f0..2f9acb5 100644 --- a/src/libjin/audio/sdl/source.h +++ b/src/libjin/audio/sdl/source.h @@ -58,7 +58,7 @@ namespace audio int rate; // Ƶ unsigned char bitdepth; // ÿsampleıس int samples; // sample = size / (bitdepth / 8) - unsigned char channel; // channel12 + unsigned char channel; // channel1(mono)2(stereo) char silence; // 0 } raw; @@ -83,7 +83,7 @@ namespace audio /* Process function */ static void processCommands(); - static void processSources(Uint8* buffer, int len); + static void processSources(void* buffer, size_t size); private: diff --git a/src/libjin/math/math.h b/src/libjin/math/math.h index f6a299e..849f74b 100644 --- a/src/libjin/math/math.h +++ b/src/libjin/math/math.h @@ -7,9 +7,9 @@ #include "matrix.h" #include "quad.h" -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#define clamp(a, mi,ma) min(max(a,mi),ma) +#define min(a,b) (a < b ? a : b) +#define max(a,b) (a > b ? a : b) +#define clamp(a, mi,ma) (min(max(a,mi),ma)) #define within(a,min,max) (a >= min && a <= max) #define without(a,min,max) (a < min || a > max) diff --git a/src/libjin/utils/unittest.cpp b/src/libjin/utils/unittest.cpp index 062604e..ce72173 100644 --- a/src/libjin/utils/unittest.cpp +++ b/src/libjin/utils/unittest.cpp @@ -16,11 +16,10 @@ int main(int argc, char* argv[]) audio->init(0); SDLSource* source = SDLSource::createSource("a.ogg"); SDLSource* source2 = SDLSource::createSource("a.wav"); - source->play(); - //source2->play(); - source2->setLoop(true); //source->play(); - //source->setLoop(true); + source2->play(); + source->setLoop(true); + source2->setLoop(true); int i = 0; while (true) { |