From 8b00d67febf133e89f6a0bfabc41feed555dc4a9 Mon Sep 17 00:00:00 2001 From: chai Date: Sat, 12 Jan 2019 21:48:33 +0800 Subject: =?UTF-8?q?*=E5=8E=BB=E6=8E=89=E6=96=87=E4=BB=B6=E5=89=8D=E7=BC=80?= =?UTF-8?q?je=5F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libjin/audio/SDL/sdl_audio.cpp | 146 +++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 src/libjin/audio/SDL/sdl_audio.cpp (limited to 'src/libjin/audio/SDL/sdl_audio.cpp') diff --git a/src/libjin/audio/SDL/sdl_audio.cpp b/src/libjin/audio/SDL/sdl_audio.cpp new file mode 100644 index 0000000..4c4bcc2 --- /dev/null +++ b/src/libjin/audio/SDL/sdl_audio.cpp @@ -0,0 +1,146 @@ +#include "../../core/configuration.h" +#if defined(jin_audio) && (jin_audio == jin_audio_sdl) + +#include + +#include "../../math/math.h" +#include "../../utils/log.h" + +#include "sdl_audio.h" +#include "sdl_source.h" + +using namespace JinEngine::Math; + +namespace JinEngine +{ + namespace Audio + { + namespace SDL + { + + /* 注意callback是在音频线程调用 */ + static void defaultCallback(void *userdata, Uint8 *stream, int size) + { + static SDLAudio* audio = static_cast(userdata); + if (!audio->goOnProcess()) + return; + audio->lock(); + audio->processCommands(); + audio->processSources(stream, size); + audio->processBuffer(stream, size); + audio->unlock(); + } + + /*call only once*/ bool SDLAudio::startSystem(const SettingBase* s) + { + jin_log_info("Initialize audio system."); + + if (SDL_Init(SDL_INIT_AUDIO) < 0) + return false; + + SDL_AudioSpec spec; + Setting* setting = (Setting*)s; + if (setting == nullptr) + return false; + + unsigned int samplerate = setting->samplerate; + unsigned int samples = clamp(setting->samples, 1, setting->samplerate); + + spec.freq = samplerate; // 每秒采样的sample数,常用的有 11025, 22050, 44100 and 48000 Hz. + spec.format = AUDIO_S16SYS; // signed 16-bit samples in native byte order + spec.channels = SDLAUDIO_CHANNELS; // 立体声 + spec.samples = samples; // 每次采样时都一次性填充好,如果=setting->samplerate则每秒只调用1次 + spec.userdata = this; + spec.callback = defaultCallback; + + audioDevice = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0); + if (audioDevice == 0) + return false; + /* start audio */ + SDL_PauseAudioDevice(audioDevice, 0); + return true; + } + + /*call only once*/ void SDLAudio::quitSystem() + { + jin_log_info("Quit audio system."); + SDL_CloseAudio(); + } + + void SDLAudio::lock() + { + SDL_LockAudioDevice(audioDevice); + } + + void SDLAudio::unlock() + { + SDL_UnlockAudioDevice(audioDevice); + } + + bool SDLAudio::goOnProcess() + { + if (state == SDLAudio::State::STOP) + { + SDLSourceManager::get()->removeAllSource(); + pause(); + return false; + } + else if (state == SDLAudio::State::PAUSE) + return false; + else + return true; + } + + void SDLAudio::processCommands() + { + SDLSourceManager::get()->processCommands(); + } + + void SDLAudio::processSources(void* buffer, size_t len) + { + SDLSourceManager::get()->processSources(buffer, len); + } + + void SDLAudio::processBuffer(void* buff, size_t len) + { + short* buffer = (short*)buff; + int samples = (len / SDLAUDIO_BYTEDEPTH) >> 1; // 双声道 + const char L = 0, R = 1; + for (int i = 0; i < samples; ++i) + { + short* clip = buffer + (i << 1); + clip[L] *= volume; + clip[R] *= volume; + } + } + + void SDLAudio::play() + { + state = State::PLAY; + } + + void SDLAudio::stop() + { + state = State::STOP; + } + + void SDLAudio::pause() + { + state = State::PAUSE; + } + + void SDLAudio::resume() + { + state = State::PLAY; + } + + void SDLAudio::setVolume(float volume) + { + this->volume = clamp(volume, 0.0f, 1.0f); + } + + } // namespace SDL + } // namespace Audio +} // namespace JinEngine + +#endif // (jin_audio) && (jin_audio == jin_audio_sdl) \ No newline at end of file -- cgit v1.1-26-g67d0