diff options
Diffstat (limited to 'src/libjin/Audio/SDL')
-rw-r--r-- | src/libjin/Audio/SDL/SDLAudio.cpp | 246 | ||||
-rw-r--r-- | src/libjin/Audio/SDL/SDLAudio.h | 90 | ||||
-rw-r--r-- | src/libjin/Audio/SDL/SDLSource.cpp | 756 | ||||
-rw-r--r-- | src/libjin/Audio/SDL/SDLSource.h | 154 |
4 files changed, 623 insertions, 623 deletions
diff --git a/src/libjin/Audio/SDL/SDLAudio.cpp b/src/libjin/Audio/SDL/SDLAudio.cpp index 9a256b1..e06979c 100644 --- a/src/libjin/Audio/SDL/SDLAudio.cpp +++ b/src/libjin/Audio/SDL/SDLAudio.cpp @@ -9,133 +9,133 @@ namespace jin { -namespace audio -{ - - using namespace jin::math; - - /* עcallbackƵ̵߳ */ - static void defaultCallback(void *userdata, Uint8 *stream, int size) - { - static SDLAudio* audio = static_cast<SDLAudio*>(userdata); - if (!audio->goOnProcess()) - return; - audio->lock(); - audio->processCommands(); - audio->processSources(stream, size); - audio->processBuffer(stream, size); - audio->unlock(); - } - - /*call only once*/ bool SDLAudio::initSystem(const SettingBase* s) - { -#if LIBJIN_DEBUG - Loghelper::log(Loglevel::LV_INFO, "Init Audio System"); -#endif - - 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<int>(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() - { - 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; - } + namespace audio + { + + using namespace jin::math; + + /* עcallbackƵ̵߳ */ + static void defaultCallback(void *userdata, Uint8 *stream, int size) + { + static SDLAudio* audio = static_cast<SDLAudio*>(userdata); + if (!audio->goOnProcess()) + return; + audio->lock(); + audio->processCommands(); + audio->processSources(stream, size); + audio->processBuffer(stream, size); + audio->unlock(); + } + + /*call only once*/ bool SDLAudio::initSystem(const SettingBase* s) + { + #if LIBJIN_DEBUG + Loghelper::log(Loglevel::LV_INFO, "Init Audio System"); + #endif + + 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<int>(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() + { + 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::stop() + { + state = State::STOP; + } - void SDLAudio::pause() - { - state = State::PAUSE; - } - - void SDLAudio::resume() - { - state = State::PLAY; - } + 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); - } + void SDLAudio::setVolume(float volume) + { + this->volume = clamp(volume, 0.0f, 1.0f); + } -} // audio + } // audio } // jin #endif // LIBJIN_MODULES_AUDIO && LIBJIN_AUDIO_SDLAUDIO diff --git a/src/libjin/Audio/SDL/SDLAudio.h b/src/libjin/Audio/SDL/SDLAudio.h index db232b7..32519d2 100644 --- a/src/libjin/Audio/SDL/SDLAudio.h +++ b/src/libjin/Audio/SDL/SDLAudio.h @@ -9,51 +9,51 @@ namespace jin { -namespace audio -{ - -#define SDLAUDIO_BITDEPTH 16 -#define SDLAUDIO_BYTEDEPTH (SDLAUDIO_BITDEPTH >> 3) -#define SDLAUDIO_CHANNELS 2 - - class SDLAudio : public Audio<SDLAudio> - { - public: - struct Setting : SettingBase - { - public: - int samplerate; // Ƶ - int samples; // sample<=samplerate - }; - - /* IAudio interface */ - void play() override; - void stop() override; - void pause() override; - void resume() override; - void setVolume(float volume) override; - /* process functions*/ - void processCommands(); - void processSources(void* buffer, size_t len); - void processBuffer(void* buffer, size_t len); - bool goOnProcess(); - /* thread-safe */ - void lock(); - void unlock(); - - private: - SINGLETON(SDLAudio); - SDLAudio() {}; - ~SDLAudio() {}; - /* subsystem interface */ - bool initSystem(const SettingBase* setting) override; - void quitSystem() override; - - unsigned int audioDevice; - - }; - -} // audio + namespace audio + { + + #define SDLAUDIO_BITDEPTH 16 + #define SDLAUDIO_BYTEDEPTH (SDLAUDIO_BITDEPTH >> 3) + #define SDLAUDIO_CHANNELS 2 + + class SDLAudio : public Audio<SDLAudio> + { + public: + struct Setting : SettingBase + { + public: + int samplerate; // Ƶ + int samples; // sample<=samplerate + }; + + /* IAudio interface */ + void play() override; + void stop() override; + void pause() override; + void resume() override; + void setVolume(float volume) override; + /* process functions*/ + void processCommands(); + void processSources(void* buffer, size_t len); + void processBuffer(void* buffer, size_t len); + bool goOnProcess(); + /* thread-safe */ + void lock(); + void unlock(); + + private: + SINGLETON(SDLAudio); + SDLAudio() {}; + ~SDLAudio() {}; + /* subsystem interface */ + bool initSystem(const SettingBase* setting) override; + void quitSystem() override; + + unsigned int audioDevice; + + }; + + } // audio } // jin #endif // LIBJIN_MODULES_AUDIO && LIBJIN_AUDIO_SDLAUDIO diff --git a/src/libjin/Audio/SDL/SDLSource.cpp b/src/libjin/Audio/SDL/SDLSource.cpp index 9f4f2fb..12ffb9b 100644 --- a/src/libjin/Audio/SDL/SDLSource.cpp +++ b/src/libjin/Audio/SDL/SDLSource.cpp @@ -14,386 +14,386 @@ namespace jin { -namespace audio -{ - - using namespace jin::math; - -#define BITS 8 - - typedef struct SDLSourceCommand - { - typedef enum Action - { - Nothing = 0, - Play, - Stop, - Pause, - Resume, - Rewind, - SetVolume, - SetLoop, - SetRate, - }; - Action action; - union { - int _integer; - float _float; - bool _boolean; - const char* _string; - } parameter; - - SDLSource* source; - }; - - typedef enum CHANNEL - { - MONO = 1, // - STEREO = 2, // - }; - - typedef /*mask*/ enum STATUS - { - PLAYING = 1, - PAUSED = 2, - STOPPED = 4 - }; - -#define Command SDLSourceCommand -#define Action Command::Action -#define Manager SDLSourceManager - - ///*class member*/ std::queue<Command*> Manager::commands; - ///*class member*/ std::stack<Command*> Manager::commandsPool; - ///*class member*/ std::vector<SDLSource*> Manager::sources; - /*class member*/ Manager* Manager::manager = nullptr; - - SDLSource* SDLSource::createSource(const char* file) - { - std::ifstream fs; - fs.open(file, std::ios::binary); - if (!fs.is_open()) - { - fs.close(); - return nullptr; - } - fs.seekg(0,std::ios::end); - int size = fs.tellg(); - fs.seekg(0, std::ios::beg); - char* buffer = (char*)malloc(size); - memset(buffer, 0, size); - fs.read(buffer, size); - fs.close(); - SDLSource* source = createSource(buffer, size); - free(buffer); - return source; - } - - SDLSource* SDLSource::createSource(void* mem, size_t size) - { - if (mem == nullptr) - return nullptr; - SDLSource* source = new SDLSource(); - try - { - SourceType format = getType(mem, size); - switch (format) - { - case OGG: source->decode_ogg(mem, size); break; - case WAV: source->decode_wav(mem, size); break; - } - } - catch (SourceException& exp) - { - delete source; - return nullptr; - }; - return source; - } - - SDLSource::SDLSource() - { - memset(&status, 0, sizeof(status)); - memset(&raw, 0, sizeof(raw)); - status.volume = 1; - } - - SDLSource::~SDLSource() - { - delete raw.data; - raw.end = 0; - raw.data = 0; - } - - void SDLSource::decode_wav(void* mem, int size) - { - wav_t wav; - if (wav_read(&wav, mem, size) == 0) - { - raw.data = wav.data; - raw.length = wav.length * wav.channels * wav.bitdepth / 8; - raw.channels = clamp<int>(wav.channels, CHANNEL::MONO, CHANNEL::STEREO); - raw.end = (char*)raw.data + raw.length; - raw.samplerate = wav.samplerate; - raw.bitdepth = wav.bitdepth; - raw.samples = wav.length; - } - else - throw SourceException(); - } - - void SDLSource::decode_ogg(void* _mem, int size) - { - unsigned char* mem = (unsigned char*)_mem; - int channels; - int samplerate; - short* data = (short*)raw.data; - int samples = stb_vorbis_decode_memory( - mem, - size, - &channels, - &samplerate, - &data - ); - const int bitdepth = sizeof(short) * BITS; - raw.channels = channels; - raw.samplerate = samplerate; - raw.data = data; - raw.samples = samples; // һsample - raw.length = samples * channels * sizeof(short); // һsample - raw.bitdepth = bitdepth; - raw.end = (char*)data + raw.length; - } - -#define ActionNone(T)\ -do{\ -Command* cmd = Manager::get()->getCommand();\ -cmd->action = Action::T; \ -cmd->source = this; \ -Manager::get()->pushCommand(cmd); \ -} while (0) - -#define ActionArg(T, ARGT, ARG)\ -do{\ -Command* cmd = Manager::get()->getCommand();\ -cmd->action = Action::T; \ -cmd->parameter.ARGT = ARG; \ -cmd->source = this; \ -Manager::get()->pushCommand(cmd); \ -}while(0) - -#define ActionInt(T, INT) ActionArg(T, _integer, INT) -#define ActionFloat(T, FLT) ActionArg(T, _float, FLT) -#define ActionString(T, STR) ActionArg(T, _string, STR) -#define ActionBool(T, BOL) ActionArg(T, _boolean, BOL) - - void SDLSource::play() - { - ActionNone(Play); - } - - void SDLSource::stop() - { - ActionNone(Stop); - } - - void SDLSource::pause() - { - ActionNone(Pause); - } - - void SDLSource::resume() - { - ActionNone(Resume); - } + namespace audio + { + + using namespace jin::math; + + #define BITS 8 + + typedef struct SDLSourceCommand + { + typedef enum Action + { + Nothing = 0, + Play, + Stop, + Pause, + Resume, + Rewind, + SetVolume, + SetLoop, + SetRate, + }; + Action action; + union { + int _integer; + float _float; + bool _boolean; + const char* _string; + } parameter; + + SDLSource* source; + }; + + typedef enum CHANNEL + { + MONO = 1, // + STEREO = 2, // + }; + + typedef /*mask*/ enum STATUS + { + PLAYING = 1, + PAUSED = 2, + STOPPED = 4 + }; + + #define Command SDLSourceCommand + #define Action Command::Action + #define Manager SDLSourceManager + + ///*class member*/ std::queue<Command*> Manager::commands; + ///*class member*/ std::stack<Command*> Manager::commandsPool; + ///*class member*/ std::vector<SDLSource*> Manager::sources; + /*class member*/ Manager* Manager::manager = nullptr; + + SDLSource* SDLSource::createSource(const char* file) + { + std::ifstream fs; + fs.open(file, std::ios::binary); + if (!fs.is_open()) + { + fs.close(); + return nullptr; + } + fs.seekg(0,std::ios::end); + int size = fs.tellg(); + fs.seekg(0, std::ios::beg); + char* buffer = (char*)malloc(size); + memset(buffer, 0, size); + fs.read(buffer, size); + fs.close(); + SDLSource* source = createSource(buffer, size); + free(buffer); + return source; + } + + SDLSource* SDLSource::createSource(void* mem, size_t size) + { + if (mem == nullptr) + return nullptr; + SDLSource* source = new SDLSource(); + try + { + SourceType format = getType(mem, size); + switch (format) + { + case OGG: source->decode_ogg(mem, size); break; + case WAV: source->decode_wav(mem, size); break; + } + } + catch (SourceException& exp) + { + delete source; + return nullptr; + }; + return source; + } + + SDLSource::SDLSource() + { + memset(&status, 0, sizeof(status)); + memset(&raw, 0, sizeof(raw)); + status.volume = 1; + } + + SDLSource::~SDLSource() + { + delete raw.data; + raw.end = 0; + raw.data = 0; + } + + void SDLSource::decode_wav(void* mem, int size) + { + wav_t wav; + if (wav_read(&wav, mem, size) == 0) + { + raw.data = wav.data; + raw.length = wav.length * wav.channels * wav.bitdepth / 8; + raw.channels = clamp<int>(wav.channels, CHANNEL::MONO, CHANNEL::STEREO); + raw.end = (char*)raw.data + raw.length; + raw.samplerate = wav.samplerate; + raw.bitdepth = wav.bitdepth; + raw.samples = wav.length; + } + else + throw SourceException(); + } + + void SDLSource::decode_ogg(void* _mem, int size) + { + unsigned char* mem = (unsigned char*)_mem; + int channels; + int samplerate; + short* data = (short*)raw.data; + int samples = stb_vorbis_decode_memory( + mem, + size, + &channels, + &samplerate, + &data + ); + const int bitdepth = sizeof(short) * BITS; + raw.channels = channels; + raw.samplerate = samplerate; + raw.data = data; + raw.samples = samples; // һsample + raw.length = samples * channels * sizeof(short); // һsample + raw.bitdepth = bitdepth; + raw.end = (char*)data + raw.length; + } + + #define ActionNone(T)\ + do{\ + Command* cmd = Manager::get()->getCommand();\ + cmd->action = Action::T; \ + cmd->source = this; \ + Manager::get()->pushCommand(cmd); \ + } while (0) + + #define ActionArg(T, ARGT, ARG)\ + do{\ + Command* cmd = Manager::get()->getCommand();\ + cmd->action = Action::T; \ + cmd->parameter.ARGT = ARG; \ + cmd->source = this; \ + Manager::get()->pushCommand(cmd); \ + }while(0) + + #define ActionInt(T, INT) ActionArg(T, _integer, INT) + #define ActionFloat(T, FLT) ActionArg(T, _float, FLT) + #define ActionString(T, STR) ActionArg(T, _string, STR) + #define ActionBool(T, BOL) ActionArg(T, _boolean, BOL) + + void SDLSource::play() + { + ActionNone(Play); + } + + void SDLSource::stop() + { + ActionNone(Stop); + } + + void SDLSource::pause() + { + ActionNone(Pause); + } + + void SDLSource::resume() + { + ActionNone(Resume); + } - void SDLSource::rewind() - { - ActionNone(Rewind); - } - - inline bool SDLSource::isStopped() const - { - return is(STOPPED); - } - - bool SDLSource::isPaused() const - { - return is(PAUSED); - } - - void SDLSource::setPitch(float pitch) - { - } - - void SDLSource::setVolume(float volume) - { - ActionFloat(SetVolume, clamp(volume, 0.0f, 1.0f)); - } - - bool SDLSource::setLoop(bool loop) - { - ActionBool(SetLoop, loop); - return false; - } - - void SDLSource::setRate(float rate) - { - ActionFloat(SetRate, rate); - } - - inline void SDLSource::handle( - SDLSourceManager* manager, - SDLSourceCommand* cmd - ) - { - switch (cmd->action) - { - case Command::Action::Play: - manager->removeSource(this); - manager->pushSource(this); - status.state = PLAYING; - status.pos = 0; // rewind - break; - case Command::Action::Stop: - manager->removeSource(this); - status.state = STOPPED; - status.pos = 0; // rewind - break; - case Command::Action::Pause: - manager->removeSource(this); - status.state = PAUSED; - break; - case Command::Action::Resume: - manager->removeSource(this); - manager->pushSource(this); - status.state = PLAYING; - break; - case Command::Action::Rewind: - status.state = PLAYING; - status.pos = 0; - break; - case Command::Action::SetVolume: - status.volume = cmd->parameter._float; - break; - case Command::Action::SetLoop: - status.loop = cmd->parameter._boolean; - break; - } - } + void SDLSource::rewind() + { + ActionNone(Rewind); + } + + inline bool SDLSource::isStopped() const + { + return is(STOPPED); + } + + bool SDLSource::isPaused() const + { + return is(PAUSED); + } + + void SDLSource::setPitch(float pitch) + { + } + + void SDLSource::setVolume(float volume) + { + ActionFloat(SetVolume, clamp(volume, 0.0f, 1.0f)); + } + + bool SDLSource::setLoop(bool loop) + { + ActionBool(SetLoop, loop); + return false; + } + + void SDLSource::setRate(float rate) + { + ActionFloat(SetRate, rate); + } + + inline void SDLSource::handle( + SDLSourceManager* manager, + SDLSourceCommand* cmd + ) + { + switch (cmd->action) + { + case Command::Action::Play: + manager->removeSource(this); + manager->pushSource(this); + status.state = PLAYING; + status.pos = 0; // rewind + break; + case Command::Action::Stop: + manager->removeSource(this); + status.state = STOPPED; + status.pos = 0; // rewind + break; + case Command::Action::Pause: + manager->removeSource(this); + status.state = PAUSED; + break; + case Command::Action::Resume: + manager->removeSource(this); + manager->pushSource(this); + status.state = PLAYING; + break; + case Command::Action::Rewind: + status.state = PLAYING; + status.pos = 0; + break; + case Command::Action::SetVolume: + status.volume = cmd->parameter._float; + break; + case Command::Action::SetLoop: + status.loop = cmd->parameter._boolean; + break; + } + } - inline void SDLSource::process(void* buf, size_t size) - { - short* buffer = (short*)buf; // AUDIO_S16SYS - int samples = (size / SDLAUDIO_BYTEDEPTH) >> 1; // ˫ - const char L = 0, R = 1; - for (int i = 0; i < samples; ++i) - { - char* source = (char*)raw.data + status.pos * (raw.bitdepth / 8) * raw.channels; - short l = 0; - short r = 0; - if (raw.bitdepth == 16) - { - l = ((short*)source)[L] * status.volume; - r = ((short*)source)[L + raw.channels - 1] * status.volume; - } - else if (raw.bitdepth == 8) - { - l = source[L] << 8; // << 8 Ŵ16bits - r = source[L + raw.channels - 1] << 8; - } - short* sample = buffer + (i << 1); - sample[L] = clamp(sample[L] + l, SHRT_MIN, SHRT_MAX); // - sample[R] = clamp(sample[R] + r, SHRT_MIN, SHRT_MAX); // - ++status.pos; - if (status.pos > raw.samples && status.loop) - status.pos = 0; // rewind - else if (status.pos > raw.samples && !status.loop) - break; - } - } - - Manager* Manager::get() - { - return (manager == nullptr ? manager = new Manager() : manager); - } - - void Manager::processCommands() - { - Command* cmd = nullptr; - SDLSource* source = nullptr; - while (!commands.empty()) - { - cmd = commands.front(); - if (cmd != nullptr) - { - source = cmd->source; - if (source != nullptr) - source->handle(manager, cmd); - } - commands.pop(); - } - } - - /* AUDIO_S16SYS[size>>1] buffer */ - void Manager::processSources(void* buf, size_t size) - { - /* clear render buffer */ - memset(buf, 0, size); - SDLSource* src = nullptr; - std::vector<SDLSource*>::iterator it = sources.begin(); - for (; it != sources.end();) - { - src = *it; - if (src != nullptr) - src->process(buf, size); - ++it; - } - } - - void Manager::removeSource(SDLSource* source) - { - std::vector<SDLSource*>::iterator it = sources.begin(); - for (it = sources.begin(); it != sources.end(); ) - { - if (*it == source) - { - it = sources.erase(it); - return; - } - ++it; - } - } - - void Manager::removeAllSource() - { - sources.clear(); - } - - void Manager::pushSource(SDLSource* source) - { - if(source != nullptr) - sources.push_back(source); - } - - void Manager::pushCommand(SDLSourceCommand* cmd) - { - commands.push(cmd); - } - - Command* Manager::getCommand() - { - if (!commandsPool.empty()) - { - Command* cmd = commandsPool.top(); - commandsPool.pop(); - return cmd; - } - return new Command(); - } - - -} // audio + inline void SDLSource::process(void* buf, size_t size) + { + short* buffer = (short*)buf; // AUDIO_S16SYS + int samples = (size / SDLAUDIO_BYTEDEPTH) >> 1; // ˫ + const char L = 0, R = 1; + for (int i = 0; i < samples; ++i) + { + char* source = (char*)raw.data + status.pos * (raw.bitdepth / 8) * raw.channels; + short l = 0; + short r = 0; + if (raw.bitdepth == 16) + { + l = ((short*)source)[L] * status.volume; + r = ((short*)source)[L + raw.channels - 1] * status.volume; + } + else if (raw.bitdepth == 8) + { + l = source[L] << 8; // << 8 Ŵ16bits + r = source[L + raw.channels - 1] << 8; + } + short* sample = buffer + (i << 1); + sample[L] = clamp(sample[L] + l, SHRT_MIN, SHRT_MAX); // + sample[R] = clamp(sample[R] + r, SHRT_MIN, SHRT_MAX); // + ++status.pos; + if (status.pos > raw.samples && status.loop) + status.pos = 0; // rewind + else if (status.pos > raw.samples && !status.loop) + break; + } + } + + Manager* Manager::get() + { + return (manager == nullptr ? manager = new Manager() : manager); + } + + void Manager::processCommands() + { + Command* cmd = nullptr; + SDLSource* source = nullptr; + while (!commands.empty()) + { + cmd = commands.front(); + if (cmd != nullptr) + { + source = cmd->source; + if (source != nullptr) + source->handle(manager, cmd); + } + commands.pop(); + } + } + + /* AUDIO_S16SYS[size>>1] buffer */ + void Manager::processSources(void* buf, size_t size) + { + /* clear render buffer */ + memset(buf, 0, size); + SDLSource* src = nullptr; + std::vector<SDLSource*>::iterator it = sources.begin(); + for (; it != sources.end();) + { + src = *it; + if (src != nullptr) + src->process(buf, size); + ++it; + } + } + + void Manager::removeSource(SDLSource* source) + { + std::vector<SDLSource*>::iterator it = sources.begin(); + for (it = sources.begin(); it != sources.end(); ) + { + if (*it == source) + { + it = sources.erase(it); + return; + } + ++it; + } + } + + void Manager::removeAllSource() + { + sources.clear(); + } + + void Manager::pushSource(SDLSource* source) + { + if(source != nullptr) + sources.push_back(source); + } + + void Manager::pushCommand(SDLSourceCommand* cmd) + { + commands.push(cmd); + } + + Command* Manager::getCommand() + { + if (!commandsPool.empty()) + { + Command* cmd = commandsPool.top(); + commandsPool.pop(); + return cmd; + } + return new Command(); + } + + + } // audio } // jin #endif // LIBJIN_MODULES_AUDIO && LIBJIN_AUDIO_SDLAUDIO diff --git a/src/libjin/Audio/SDL/SDLSource.h b/src/libjin/Audio/SDL/SDLSource.h index 3feef9f..d9059cb 100644 --- a/src/libjin/Audio/SDL/SDLSource.h +++ b/src/libjin/Audio/SDL/SDLSource.h @@ -12,95 +12,95 @@ namespace jin { -namespace audio -{ + namespace audio + { - typedef struct SDLSourceCommand; - class SDLSourceManager; + typedef struct SDLSourceCommand; + class SDLSourceManager; - class SDLSource : public Source - { - public: - static SDLSource* createSource(const char* file); - static SDLSource* createSource(void* mem, size_t size); + class SDLSource : public Source + { + public: + static SDLSource* createSource(const char* file); + static SDLSource* createSource(void* mem, size_t size); - ~SDLSource(); - /* ISource interface */ - void play() override; - void stop() override; - void pause() override; - void resume() override; - void rewind() override; - bool isStopped() const override; - bool isPaused() const override; - void setPitch(float pitch) override; - void setVolume(float volume) override; - bool setLoop(bool loop) override; - void setRate(float rate) override; - /* handle and process anduio clip */ - inline void handle(SDLSourceManager* manager, SDLSourceCommand* cmd); - inline void process(void* buffer, size_t size); + ~SDLSource(); + /* ISource interface */ + void play() override; + void stop() override; + void pause() override; + void resume() override; + void rewind() override; + bool isStopped() const override; + bool isPaused() const override; + void setPitch(float pitch) override; + void setVolume(float volume) override; + bool setLoop(bool loop) override; + void setRate(float rate) override; + /* handle and process anduio clip */ + inline void handle(SDLSourceManager* manager, SDLSourceCommand* cmd); + inline void process(void* buffer, size_t size); - protected: - SDLSource(); - /* decode raw audio data */ - void decode_wav(void* mem, int size); - void decode_ogg(void* mem, int size); - /* check state */ - inline bool is(int state) const { return (status.state & state) == state; } + protected: + SDLSource(); + /* decode raw audio data */ + void decode_wav(void* mem, int size); + void decode_ogg(void* mem, int size); + /* check state */ + inline bool is(int state) const { return (status.state & state) == state; } - struct{ - const void* data; // Ƶ - int length; // dataֽڳ - const void* end; // dataβ = (unsigned char*)data + size - int samplerate; // Ƶ - unsigned char bitdepth; // ÿsampleıس - int samples; // sample = size / (bitdepth / 8) - unsigned char channels; // channel1(mono)2(stereo) - } raw; - /* Procedure controller variable */ - struct{ - int pos; // ǰŵsample - int pitch; // pitch - int state; // ǰ״̬ - bool loop; // loop or not - float volume; // - } status; + struct{ + const void* data; // Ƶ + int length; // dataֽڳ + const void* end; // dataβ = (unsigned char*)data + size + int samplerate; // Ƶ + unsigned char bitdepth; // ÿsampleıس + int samples; // sample = size / (bitdepth / 8) + unsigned char channels; // channel1(mono)2(stereo) + } raw; + /* Procedure controller variable */ + struct{ + int pos; // ǰŵsample + int pitch; // pitch + int state; // ǰ״̬ + bool loop; // loop or not + float volume; // + } status; - }; + }; - class SDLSourceManager - { - public: - static SDLSourceManager* get(); + class SDLSourceManager + { + public: + static SDLSourceManager* get(); - /* Process function */ - void processCommands(); - void processSources(void* buffer, size_t size); - /* control flow */ - void removeAllSource(); - void removeSource(SDLSource* source); - void pushSource(SDLSource* source); - SDLSourceCommand* getCommand(); - void pushCommand(SDLSourceCommand* cmd); + /* Process function */ + void processCommands(); + void processSources(void* buffer, size_t size); + /* control flow */ + void removeAllSource(); + void removeSource(SDLSource* source); + void pushSource(SDLSource* source); + SDLSourceCommand* getCommand(); + void pushCommand(SDLSourceCommand* cmd); - private : - std::queue<SDLSourceCommand*> commands; - std::stack<SDLSourceCommand*> commandsPool; - std::vector<SDLSource*> sources; // processing sources - static SDLSourceManager* manager; + private : + std::queue<SDLSourceCommand*> commands; + std::stack<SDLSourceCommand*> commandsPool; + std::vector<SDLSource*> sources; // processing sources + static SDLSourceManager* manager; - }; + }; - class SourceException : public std::exception - { - const char * what() const throw () - { - return "Load Source Exception"; - } - }; + class SourceException : public std::exception + { + const char * what() const throw () + { + return "Load Source Exception"; + } + }; -} // audio + } // audio } // jin #endif // LIBJIN_MODULES_AUDIO && LIBJIN_AUDIO_SDLAUDIO |