From 727fbae9d16f531c47e2462c40d8a5065e4d9909 Mon Sep 17 00:00:00 2001 From: chai Date: Sun, 29 Jul 2018 13:09:14 +0800 Subject: *update --- build/.vs/libjin/v14/.suo | Bin 55296 -> 227328 bytes build/libjin.sln | 10 ++++ build/libjin/libjin.vcxproj | 7 +++ build/libjin/libjin.vcxproj.filters | 30 ++++++++++++ libjin/Audio/Audio.h | 25 ++++++---- libjin/Audio/SDL/SDLAudio.cpp | 60 +++++++++++++++-------- libjin/Audio/SDL/SDLAudio.h | 11 ++--- libjin/Audio/SDL/SDLSource.cpp | 94 ++++++++++++++++++------------------ libjin/Audio/SDL/SDLSource.h | 28 ++++++----- libjin/Core/Game.cpp | 2 + libjin/Core/Game.h | 7 ++- libjin/Math/Math.h | 6 +++ libjin/modules.h | 6 ++- test/02Audio/audiotest.cpp | 70 +++++++++++++++++++++++++++ 14 files changed, 255 insertions(+), 101 deletions(-) create mode 100644 test/02Audio/audiotest.cpp diff --git a/build/.vs/libjin/v14/.suo b/build/.vs/libjin/v14/.suo index c8eff31..90cd23a 100644 Binary files a/build/.vs/libjin/v14/.suo and b/build/.vs/libjin/v14/.suo differ diff --git a/build/libjin.sln b/build/libjin.sln index c66426f..8f9bfae 100644 --- a/build/libjin.sln +++ b/build/libjin.sln @@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libjin", "libjin\libjin.vcx EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "01HelloWorld", "01HelloWorld\01HelloWorld.vcxproj", "{F1B984AA-F46D-46C9-9A5A-7606A30E0599}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "02Audio", "02Audio\02Audio.vcxproj", "{A2D75980-B0AC-498C-B507-4727B4A38E83}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -31,6 +33,14 @@ Global {F1B984AA-F46D-46C9-9A5A-7606A30E0599}.Release|x64.Build.0 = Release|x64 {F1B984AA-F46D-46C9-9A5A-7606A30E0599}.Release|x86.ActiveCfg = Release|Win32 {F1B984AA-F46D-46C9-9A5A-7606A30E0599}.Release|x86.Build.0 = Release|Win32 + {A2D75980-B0AC-498C-B507-4727B4A38E83}.Debug|x64.ActiveCfg = Debug|x64 + {A2D75980-B0AC-498C-B507-4727B4A38E83}.Debug|x64.Build.0 = Debug|x64 + {A2D75980-B0AC-498C-B507-4727B4A38E83}.Debug|x86.ActiveCfg = Debug|Win32 + {A2D75980-B0AC-498C-B507-4727B4A38E83}.Debug|x86.Build.0 = Debug|Win32 + {A2D75980-B0AC-498C-B507-4727B4A38E83}.Release|x64.ActiveCfg = Release|x64 + {A2D75980-B0AC-498C-B507-4727B4A38E83}.Release|x64.Build.0 = Release|x64 + {A2D75980-B0AC-498C-B507-4727B4A38E83}.Release|x86.ActiveCfg = Release|Win32 + {A2D75980-B0AC-498C-B507-4727B4A38E83}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/build/libjin/libjin.vcxproj b/build/libjin/libjin.vcxproj index aa8e12e..32422b3 100644 --- a/build/libjin/libjin.vcxproj +++ b/build/libjin/libjin.vcxproj @@ -49,6 +49,9 @@ + + + @@ -105,7 +108,11 @@ + + + + diff --git a/build/libjin/libjin.vcxproj.filters b/build/libjin/libjin.vcxproj.filters index 7e1e033..c302314 100644 --- a/build/libjin/libjin.vcxproj.filters +++ b/build/libjin/libjin.vcxproj.filters @@ -79,6 +79,15 @@ {5685d2ab-4373-4b9c-9cd1-634b1916b09c} + + {712750f2-e78b-46a4-b837-55fd4486b3bd} + + + {0fb5fedc-24df-47f0-a90f-a20e21baa90c} + + + {52a242f9-da0d-4c1d-a6ea-5ad17557feae} + @@ -177,6 +186,15 @@ Tilemap + + Tools\XML + + + Tools\Json + + + Tools\CSV + @@ -349,6 +367,18 @@ Tools\Component + + Tools\EventMsgCenter + + + Tools\XML + + + Tools\Json + + + Tools\CSV + diff --git a/libjin/Audio/Audio.h b/libjin/Audio/Audio.h index 5b43729..6c3468e 100644 --- a/libjin/Audio/Audio.h +++ b/libjin/Audio/Audio.h @@ -20,23 +20,30 @@ namespace audio public: + enum State + { + PLAY , + STOP , + PAUSE, + }; + virtual void play() = 0; virtual void stop() = 0; - virtual bool pause() = 0; - virtual bool pause(Source* source) = 0; - virtual bool resume() = 0; - virtual bool resume(Source* source) = 0; - virtual void rewind() = 0; + virtual void pause() = 0; + virtual void resume() = 0; virtual void setVolume(float volume) = 0; - virtual float getVolume() = 0; protected: - Audio() {}; + Audio() + : volume(1) + , state(State::PLAY) + {}; virtual ~Audio() {}; - SINGLETON(Audio); - + + float volume; + State state; }; } diff --git a/libjin/Audio/SDL/SDLAudio.cpp b/libjin/Audio/SDL/SDLAudio.cpp index a41382b..f7ca70d 100644 --- a/libjin/Audio/SDL/SDLAudio.cpp +++ b/libjin/Audio/SDL/SDLAudio.cpp @@ -18,15 +18,20 @@ namespace audio 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(); } onlyonce bool SDLAudio::initSystem(const SettingBase* s) { +#if JIN_DEBUG Loghelper::log(Loglevel::LV_INFO, "Init Audio System"); +#endif if (SDL_Init(SDL_INIT_AUDIO) < 0) return false; @@ -68,6 +73,20 @@ namespace audio 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(); @@ -78,45 +97,44 @@ namespace audio SDLSourceManager::get()->processSources(buffer, len); } - void SDLAudio::play() {} - - void SDLAudio::stop() {} - - bool SDLAudio::pause() + void SDLAudio::processBuffer(void* buff, size_t len) { - return false; + 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; + } } - bool SDLAudio::pause(Source* source) + void SDLAudio::play() { - return false; + state = State::PLAY; } - bool SDLAudio::resume() + void SDLAudio::stop() { - return false; + state = State::STOP; } - bool SDLAudio::resume(Source* source) + void SDLAudio::pause() { - return false; + state = State::PAUSE; } - - void SDLAudio::rewind() + + void SDLAudio::resume() { - + state = State::PLAY; } void SDLAudio::setVolume(float volume) { - + this->volume = clamp(volume, 0.0f, 1.0f); } - float SDLAudio::getVolume() - { - return 0.f; - } - } } diff --git a/libjin/Audio/SDL/SDLAudio.h b/libjin/Audio/SDL/SDLAudio.h index 6837126..f2a4fab 100644 --- a/libjin/Audio/SDL/SDLAudio.h +++ b/libjin/Audio/SDL/SDLAudio.h @@ -3,6 +3,7 @@ #include "../../modules.h" #if JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO +#include "SDLSource.h" #include #include "../audio.h" @@ -30,17 +31,15 @@ namespace audio /* IAudio interface */ void play() override; void stop() override; - bool pause() override; - bool pause(Source* source) override; - bool resume() override; - bool resume(Source* source) override; - void rewind() override; + void pause() override; + void resume() override; void setVolume(float volume) override; - float getVolume() override; /* process functions*/ void processCommands(); void processSources(void* buffer, size_t len); + void processBuffer(void* buffer, size_t len); + bool goOnProcess(); void lock(); void unlock(); diff --git a/libjin/Audio/SDL/SDLSource.cpp b/libjin/Audio/SDL/SDLSource.cpp index 18ba855..c868df5 100644 --- a/libjin/Audio/SDL/SDLSource.cpp +++ b/libjin/Audio/SDL/SDLSource.cpp @@ -3,14 +3,13 @@ #include #include - +#include #include "../../math/math.h" #include "../../utils/macros.h" #include "SDLSource.h" #include "../../3rdparty/wav/wav.h" #define STB_VORBIS_HEADER_ONLY #include "../../3rdparty/stb/stb_vorbis.c" - #include "SDLAudio.h" namespace jin @@ -64,9 +63,9 @@ namespace audio #define Action Command::Action #define Manager SDLSourceManager - shared std::queue Manager::commands; - shared std::stack Manager::commandsPool; - shared std::vector Manager::sources; + //shared std::queue Manager::commands; + //shared std::stack Manager::commandsPool; + //shared std::vector Manager::sources; shared Manager* Manager::manager = nullptr; SDLSource* SDLSource::createSource(const char* file) @@ -116,6 +115,7 @@ namespace audio { memset(&status, 0, sizeof(status)); memset(&raw, 0, sizeof(raw)); + status.volume = 1; } SDLSource::~SDLSource() @@ -131,12 +131,12 @@ namespace audio if (wav_read(&wav, mem, size) == 0) { raw.data = wav.data; - raw.length = wav.length * wav.bitdepth / 8; + raw.length = wav.length * wav.channels * wav.bitdepth / 8; + raw.channels = clamp(wav.channels, CHANNEL::MONO, CHANNEL::STEREO); raw.end = (char*)raw.data + raw.length; raw.samplerate = wav.samplerate; raw.bitdepth = wav.bitdepth; - raw.samples = raw.length / (wav.bitdepth / 8.f) / wav.channels; - raw.channels = clamp(wav.channels, CHANNEL::MONO, CHANNEL::STEREO); + raw.samples = wav.length; } else throw SourceException(); @@ -159,8 +159,8 @@ namespace audio raw.channels = channels; raw.samplerate = samplerate; raw.data = data; - raw.samples = samples; - raw.length = samples * channels * sizeof(short); + raw.samples = samples; // 左右声道加起来才算一个sample + raw.length = samples * channels * sizeof(short); // 左右声道加起来才算一个sample raw.bitdepth = bitdepth; raw.end = (char*)data + raw.length; } @@ -228,7 +228,7 @@ Manager::get()->pushCommand(cmd); \ void SDLSource::setVolume(float volume) { - ActionFloat(SetVolume, volume); + ActionFloat(SetVolume, clamp(volume, 0.0f, 1.0f)); } bool SDLSource::setLoop(bool loop) @@ -274,7 +274,7 @@ Manager::get()->pushCommand(cmd); \ status.pos = 0; break; case Command::Action::SetVolume: - //float cmd->parameter._float; + status.volume = cmd->parameter._float; break; case Command::Action::SetLoop: status.loop = cmd->parameter._boolean; @@ -285,39 +285,31 @@ Manager::get()->pushCommand(cmd); \ inline void SDLSource::process(void* buf, size_t size) { short* buffer = (short*)buf; // AUDIO_S16SYS - unsigned int samples = size / SDLAUDIO_BYTEDEPTH; - short* sample; - short origin; - - const char bitdepth = raw.bitdepth; - const char channles = raw.channels; - - int pos = status.pos; - int pitch = status.pitch; - int state = status.state; - bool loop = status.loop; - int volume = status.volume; - short* clip16 = nullptr; - char* clip8 = nullptr; - int clip = 0; - - if (bitdepth == 8) - clip8 = (char*)raw.data; - else if (bitdepth == 16) - clip16 = (short*)raw.data; - - for (int i = 0; i < samples; i+=2 /*双声道*/) + int samples = (size / SDLAUDIO_BYTEDEPTH) >> 1; // 双声道 + const char L = 0, R = 1; + for (int i = 0; i < samples; ++i) { - /* 音频文件的sample将会被拷贝到这里 */ - sample = buffer + i * SDLAUDIO_BYTEDEPTH; - origin = *sample; - if (bitdepth == 8) + char* source = (char*)raw.data + status.pos * (raw.bitdepth / 8) * raw.channels; + short left = 0; + short right = 0; + if (raw.bitdepth == 16) + { + left = ((short*)source)[L] * status.volume; + right = ((short*)source)[L + raw.channels - 1] * status.volume; + } + else if (raw.bitdepth == 8) { - clip = *clip8; + left = source[L] << 8; // << 8 放大到16bits + right = source[L + raw.channels - 1] << 8; } - else if (bitdepth == 16) - clip = *clip16; - + short* sample = buffer + (i << 1); + sample[L] = clamp(sample[L] + left, SHRT_MIN, SHRT_MAX); // 左声道 + sample[R] = clamp(sample[R] + right, 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; } } @@ -326,7 +318,7 @@ Manager::get()->pushCommand(cmd); \ return (manager == nullptr ? manager = new Manager() : manager); } - shared void Manager::processCommands() + void Manager::processCommands() { Command* cmd = nullptr; SDLSource* source = nullptr; @@ -344,7 +336,7 @@ Manager::get()->pushCommand(cmd); \ } /* AUDIO_S16SYS[size>>1] buffer */ - shared void Manager::processSources(void* buf, size_t size) + void Manager::processSources(void* buf, size_t size) { /* clear render buffer */ memset(buf, 0, size); @@ -359,7 +351,7 @@ Manager::get()->pushCommand(cmd); \ } } - shared void Manager::removeSource(SDLSource* source) + void Manager::removeSource(SDLSource* source) { std::vector::iterator it = sources.begin(); for (it = sources.begin(); it != sources.end(); ) @@ -373,18 +365,23 @@ Manager::get()->pushCommand(cmd); \ } } - shared void Manager::pushSource(SDLSource* source) + void Manager::removeAllSource() + { + sources.clear(); + } + + void Manager::pushSource(SDLSource* source) { if(source != nullptr) sources.push_back(source); } - shared void Manager::pushCommand(SDLSourceCommand* cmd) + void Manager::pushCommand(SDLSourceCommand* cmd) { commands.push(cmd); } - shared Command* Manager::getCommand() + Command* Manager::getCommand() { if (!commandsPool.empty()) { @@ -395,6 +392,7 @@ Manager::get()->pushCommand(cmd); \ return new Command(); } + } } diff --git a/libjin/Audio/SDL/SDLSource.h b/libjin/Audio/SDL/SDLSource.h index 5c6aefc..9a3dd9b 100644 --- a/libjin/Audio/SDL/SDLSource.h +++ b/libjin/Audio/SDL/SDLSource.h @@ -72,7 +72,7 @@ namespace audio int pitch; // pitch int state; // 当前状态 bool loop; // loop or not - int volume; // 音量 + float volume; // 音量 } status; }; @@ -85,20 +85,22 @@ namespace audio static SDLSourceManager* get(); /* Process function */ - static void processCommands(); - static void processSources(void* buffer, size_t size); - - static void removeSource(SDLSource* source); - static void pushSource(SDLSource* source); - static SDLSourceCommand* getCommand(); - static void pushCommand(SDLSourceCommand* cmd); - + void processCommands(); + void processSources(void* buffer, size_t size); + + void removeAllSource(); + void removeSource(SDLSource* source); + void pushSource(SDLSource* source); + SDLSourceCommand* getCommand(); + void pushCommand(SDLSourceCommand* cmd); + + private : + + std::queue commands; + std::stack commandsPool; + std::vector sources; // processing sources static SDLSourceManager* manager; - static std::queue commands; - static std::stack commandsPool; - static std::vector sources; // processing sources - }; class SourceException : public std::exception diff --git a/libjin/Core/Game.cpp b/libjin/Core/Game.cpp index ffd8015..929cc07 100644 --- a/libjin/Core/Game.cpp +++ b/libjin/Core/Game.cpp @@ -19,6 +19,7 @@ namespace core void Game::run() { + SAFECALL(_onLoad); Window* wnd = Window::get(); const int FPS = wnd ? wnd->getFPS() : 60; const int MS_PER_UPDATE = 1000.0f / FPS; @@ -59,6 +60,7 @@ namespace core _onEvent = s->eventHandler; _onUpdate = s->updater; _onDraw = s->drawer; + _onLoad = s->loader; return true; } diff --git a/libjin/Core/Game.h b/libjin/Core/Game.h index 090e7c6..9359487 100644 --- a/libjin/Core/Game.h +++ b/libjin/Core/Game.h @@ -16,6 +16,7 @@ namespace core { public: + typedef void(*onLoad)(); typedef void(*onEvent)(jin::input::Event* e); typedef void(*onUpdate)(float dt); typedef void(*onDraw)(); @@ -25,6 +26,7 @@ namespace core onEvent eventHandler; onUpdate updater; onDraw drawer; + onLoad loader; }; void run(); @@ -38,9 +40,10 @@ namespace core SINGLETON(Game); - onEvent _onEvent; + onEvent _onEvent; onUpdate _onUpdate; - onDraw _onDraw; + onDraw _onDraw; + onLoad _onLoad; bool _running; diff --git a/libjin/Math/Math.h b/libjin/Math/Math.h index 5b34f4c..d4bd202 100644 --- a/libjin/Math/Math.h +++ b/libjin/Math/Math.h @@ -65,6 +65,12 @@ namespace math return a > upper ? upper : a; } + template + inline T lerp(T a, T b, float t) + { + return a + t * (b - a); + } + } } diff --git a/libjin/modules.h b/libjin/modules.h index c117ef7..171c691 100644 --- a/libjin/modules.h +++ b/libjin/modules.h @@ -28,11 +28,13 @@ #define JIN_MODULES_TILEMAP 1 #define JIN_MODULES_UI 1 - + #define JIN_MODULES_TOOLS 1 #define JIN_TOOLS_COMPONENT 1 #define JIN_TOOLS_EVENTMSGCENTER 1 #define JIN_TOOLS_XML 1 +#define JIN_TOOLS_CSV 1 +#define JIN_TOOLS_JSON 1 #define JIN_MODULES_THREAD 1 @@ -43,6 +45,6 @@ * 开启Debug */ -#define JIN_DEBUG 1 +#define JIN_DEBUG 1 #endif \ No newline at end of file diff --git a/test/02Audio/audiotest.cpp b/test/02Audio/audiotest.cpp new file mode 100644 index 0000000..d4b8975 --- /dev/null +++ b/test/02Audio/audiotest.cpp @@ -0,0 +1,70 @@ +#include +#include "jin.h" + +using namespace jin::core; +using namespace jin::graphics; +using namespace jin::input; +using namespace jin::audio; + +void onEvent(jin::input::Event* e) +{ + static Game* game = Game::get(); + if (e->type == EventType::QUIT) + game->stop(); +} + +void onUpdate(float dt) +{ + +} + +void onDraw() +{ + +} + +int main(int argc, char* argv[]) +{ + Game* game = Game::get(); + Game::Setting setting; + setting.eventHandler = onEvent; + setting.updater = onUpdate; + setting.drawer = onDraw; + setting.loader = nullptr; + game->init(&setting); + + Window* wnd = Window::get(); + Window::Setting wndSetting; + wndSetting.width = 600; + wndSetting.height = 512; + wndSetting.title = "test"; + wndSetting.fps = 60; + wndSetting.vsync = false; + wndSetting.fullscreen = false; + wndSetting.resizable = false; + wnd->init(&wndSetting); + + SDLAudio* audio = SDLAudio::get(); + SDLAudio::Setting audioSetting; + audioSetting.samplerate = 44100; + audioSetting.samples = 44100; + audio->init(&audioSetting); + + SDLSource* src = SDLSource::createSource("a.ogg"); + src->play(); + src->setLoop(false); + + SDLSource* src2 = SDLSource::createSource("a.wav"); + src2->setLoop(true); + src2->play(); + + audio->setVolume(0.7); + + game->run(); + + game->quit(); + audio->quit(); + wnd->quit(); + + return 0; +} \ No newline at end of file -- cgit v1.1-26-g67d0