diff options
Diffstat (limited to 'src/libjin')
-rw-r--r-- | src/libjin/audio/sdl/audio.cpp | 30 | ||||
-rw-r--r-- | src/libjin/audio/sdl/audio.h | 14 | ||||
-rw-r--r-- | src/libjin/audio/sdl/source.cpp | 264 | ||||
-rw-r--r-- | src/libjin/audio/sdl/source.h | 118 | ||||
-rw-r--r-- | src/libjin/audio/source.h | 6 | ||||
-rw-r--r-- | src/libjin/fs/filesystem.cpp | 16 | ||||
-rw-r--r-- | src/libjin/fs/filesystem.h | 2 | ||||
-rw-r--r-- | src/libjin/render/jsl.cpp | 2 | ||||
-rw-r--r-- | src/libjin/utils/unittest.cpp | 22 |
9 files changed, 346 insertions, 128 deletions
diff --git a/src/libjin/audio/sdl/audio.cpp b/src/libjin/audio/sdl/audio.cpp index 7870329..d753587 100644 --- a/src/libjin/audio/sdl/audio.cpp +++ b/src/libjin/audio/sdl/audio.cpp @@ -1,22 +1,29 @@ #include "audio.h" +#include "source.h" namespace jin { namespace audio { + static void defaultCallback(void *userdata, Uint8 *stream, int size) + { + SDLAudio* audio = (SDLAudio*)userdata; + audio->processCommands(); + audio->processSources(stream, size); + } + onlyonce bool SDLAudio::_init(const SettingBase* s) { if (SDL_Init(SDL_INIT_AUDIO) < 0) return false; - - const SDLAudioSetting* setting = (SDLAudioSetting*)s; + SDLAudioSetting* setting = (SDLAudioSetting*)s; SDL_AudioSpec spec; zero(spec); - spec.freq = setting->rate; - spec.format = setting->resolution; - spec.channels = setting->channels; - spec.samples = setting->samples; + spec.freq = 44100; + spec.format = AUDIO_S16SYS; + spec.channels = 1; + spec.samples = 2048; spec.userdata = this; spec.callback = defaultCallback; @@ -36,17 +43,14 @@ namespace audio delete audio; } - shared void SDLAudio::defaultCallback(void *userdata, Uint8 *stream, int size) + void SDLAudio::processCommands() { - SDLAudio* audio = (SDLAudio*)userdata; - int16_t* buffer = (int16_t*)stream; - int len = size >> 1; - audio->processSources(len); + SDLSourceManager::get()->processCommands(); } - void SDLAudio::processSources(int len) + void SDLAudio::processSources(Uint8* buffer, int len) { - + SDLSourceManager::get()->processSources(buffer, len); } void SDLAudio::play() {} diff --git a/src/libjin/audio/sdl/audio.h b/src/libjin/audio/sdl/audio.h index 969fbd9..53d0d76 100644 --- a/src/libjin/audio/sdl/audio.h +++ b/src/libjin/audio/sdl/audio.h @@ -16,6 +16,7 @@ namespace audio public: + /* struct Setting : SettingBase { int rate; // @@ -23,6 +24,7 @@ namespace audio char channels; // int samples; // ȡ }; + */ static inline Audio* get() { @@ -40,6 +42,10 @@ namespace audio void setVolume(float volume) override; float getVolume() override; + /* process functions*/ + void processCommands(); + void processSources(Uint8* buffer, int len); + private: SDLAudio() {} @@ -50,14 +56,6 @@ namespace audio unsigned int audioDevice; - std::vector<SDLSource*> sources; - - static void defaultCallback(void *udata, Uint8 *stream, int len); - - /* process functions*/ - void processCommands(); - void processSources(int len); - }; typedef SDLAudio::Setting SDLAudioSetting; diff --git a/src/libjin/audio/sdl/source.cpp b/src/libjin/audio/sdl/source.cpp index ecdf5b5..7d71ce7 100644 --- a/src/libjin/audio/sdl/source.cpp +++ b/src/libjin/audio/sdl/source.cpp @@ -1,34 +1,132 @@ +#include <exception> + +#include "../../math/math.h" #include "../../utils/macros.h" #include "source.h" +#include "3rdparty/wav/wav.h" +#define STB_VORBIS_HEADER_ONLY +#include "3rdparty/stb/stb_vorbis.c" namespace jin { namespace audio { - shared std::queue<SDLSource::Command*> SDLSource::commands; - shared std::stack<SDLSource::Command*> SDLSource::commandsPool; + 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 STATUS + { + PLAYING = 2, + PAUSED = 4, + STOPPED = 8 + }; + +#define Command SDLSourceCommand +#define Action Command::Action +#define Manager SDLSourceManager + + shared std::queue<Command*> Manager::commands; + shared std::stack<Command*> Manager::commandsPool; + shared std::vector<SDLSource*> Manager::sources; + shared Manager* Manager::manager = nullptr; + + SDLSource::SDLSource(Type format, void* mem, int size) + : pos(0) + , pitch(0) + , status(0) + , loop(false) + { + memset(&raw, 0, sizeof(raw)); + try + { + switch (format) + { + case WAV: + loadWAV(mem, size); + break; + case OGG: + loadOGG(mem, size); + break; + } + } + catch(SourceException& exp) + { + + }; + } + + void SDLSource::loadWAV(void* mem, int size) + { + wav_t wav; + if (wav_read(&wav, mem, size) == 0) + { + raw.data = wav.data; + raw.length = wav.length; + raw.end = (char*)raw.data + raw.length; + raw.rate = wav.samplerate; + raw.bitdepth = wav.bitdepth; + raw.samples = wav.length / (wav.bitdepth / 8.f); + raw.channel = wav.channels; + raw.silence = 0; + } + else + throw SourceException(); + } + + 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); + if (raw.samples < 0) + { + throw SourceException(); + } + } - void SDLSource::generateSamples(Uint8* streamIn, int len) + SDLSource::~SDLSource() { } + #define ActionNone(T)\ do{\ -Command* cmd = getCommand(); \ -cmd->action = Command::Action::T; \ -cmd->source = this; \ -commands.push(cmd); \ +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 = getCommand(); \ -cmd->action = Command::Action::T; \ -cmd->ARGT = ARG; \ -cmd->source = this; \ -commands.push(cmd); \ +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) @@ -63,7 +161,7 @@ commands.push(cmd); \ void SDLSource::isStopped() const { - + } void SDLSource::isPaused() const {} @@ -81,7 +179,7 @@ commands.push(cmd); \ bool SDLSource::setLoop(bool loop) { - ActionFloat(SetLoop, loop); + ActionBool(SetLoop, loop); return false; } @@ -90,43 +188,106 @@ commands.push(cmd); \ ActionFloat(SetRate, rate); } - shared SDLSource::Command* SDLSource::getCommand() + Manager* Manager::get() { - if (!commandsPool.empty()) - { - Command* cmd = commandsPool.top(); - commandsPool.pop(); - } - return new Command(); + return (manager == nullptr ? manager = new Manager() : manager); } - shared void SDLSource::collectCommand(SDLSource::Command* cmd) + shared void Manager::processCommands() { - if (cmd != nullptr && cmd != NULL) - { - commandsPool.push(cmd); - } - } - - shared void SDLSource::processCommand() - { - Command* cmd = NULL; - Source* source = NULL; + Command* cmd = nullptr; + SDLSource* source = nullptr; while (!commands.empty()) { cmd = commands.front(); - source = cmd->source; - + source = cmd->source; + if (source != nullptr && cmd != nullptr) + { + switch (cmd->action) + { + case Command::Action::Play: + removeSource(source); + pushSource(source); + source->status = PLAYING; + source->pos = 0; // rewind + break; + case Command::Action::Stop: + manager->removeSource(source); + source->status = STOPPED; + source->pos = 0; // rewind + break; + case Command::Action::Pause: + source->status = PAUSED; + break; + case Command::Action::Resume: + source->status = PLAYING; + break; + case Command::Action::Rewind: + source->status = PLAYING; + source->pos = 0; + break; + case Command::Action::SetVolume: + break; + case Command::Action::SetLoop: + source->loop = cmd->parameter._boolean; + break; + /*case Command::Action::SetRate: + */ + } + } commands.pop(); } } - shared void SDLSource::processSource() + shared void Manager::processSources(Uint8* buffer, int len) { + memset(buffer, 0, len); + int16_t* buf16 = (int16_t*)buffer; + int samples = len >> 1; + std::vector<SDLSource*>::iterator it = sources.begin(); + SDLSource* source = nullptr; + for (; it != sources.end(); ++it) + { + 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)) + { + int16_t* src16 = (int16_t*)((char*)source->raw.data + source->pos); + int remainsample = (source->raw.length - source->pos) >> 1; + int bound = min(samples, remainsample); + for (int i = 0; i < bound; ++i) + { + buf16[i] += src16[i]; // mix sources + } + source->pos += (bound << 1); + if (source->pos == 0) + { + if (source->loop) + { + int j = 0; + for (int i = bound; i < samples; ++i, ++j) + { + int val = data16[j]; + buf16[i] += val; + } + source->pos = (j << 1); + continue; + } + else + { + sources.erase(it); + } + } + } + } } - shared void SDLSource::removeSource(SDLSource* source) + shared void Manager::removeSource(SDLSource* source) { std::vector<SDLSource*>::iterator it = sources.begin(); for (it = sources.begin(); it != sources.end(); ++it) @@ -139,5 +300,34 @@ commands.push(cmd); \ } } + shared void Manager::pushSource(SDLSource* source) + { + if(source != nullptr) + sources.push_back(source); + } + + shared void Manager::pushCommand(SDLSourceCommand* cmd) + { + commands.push(cmd); + } + + shared Command* Manager::getCommand() + { + if (!commandsPool.empty()) + { + Command* cmd = commandsPool.top(); + commandsPool.pop(); + } + return new Command(); + } + + shared void Manager::collectCommand(Command* cmd) + { + if (cmd != nullptr) + { + commandsPool.push(cmd); + } + } + } -} +}
\ No newline at end of file diff --git a/src/libjin/audio/sdl/source.h b/src/libjin/audio/sdl/source.h index 682ff50..d97590e 100644 --- a/src/libjin/audio/sdl/source.h +++ b/src/libjin/audio/sdl/source.h @@ -4,11 +4,7 @@ #include <vector> #include <queue> #include <stack> - -#include "3rdparty/wav/wav.h" -#define STB_VORBIS_HEADER_ONLY -#include "3rdparty/stb/stb_vorbis.c" -#undef STB_VORBIS_HEADER_ONLY +#include <exception> #include "../source.h" @@ -17,15 +13,21 @@ namespace jin namespace audio { + struct SDLSourceCommand; + class SDLSource : public Source { public: - SDLSource() {} - ~SDLSource() {} + enum Type + { + WAV = 1, + OGG = 2, + }; - void generateSamples(Uint8* streamIn, int len); + SDLSource(Type format, void* mem, int size) ; + ~SDLSource(); /* ISource interface */ void play() override; @@ -41,52 +43,70 @@ namespace audio bool setLoop(bool loop) override; void setRate(float rate) override; - /* process function */ - static void processCommand(); - static void processSource(); - static void removeSource(SDLSource* source); - private: - struct Command + friend class SDLSourceManager; + + void loadWAV(void* mem, int size); + void loadOGG(void* mem, int size); + + inline bool is(int state) { return (status & state) == state; } + + struct { - 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; - }; - SDLSource* source; - }; + const void* data; // Ƶ + int length; // dataֽڳ + void* end; // dataβ = (unsigned char*)data + length + int rate; // Ƶ + unsigned char bitdepth; // ÿsampleıس + int samples; // sample = length / (bitdepth / 8) + unsigned char channel; // channel12 + char silence; // 0 + } raw; + + /* Procedure controller variable */ + int pos; // ǰŵλ + int pitch; // pitch + int status; // ǰ״̬ + bool loop; // loop or not + + }; + + class SDLSourceManager + { + + public: + + static SDLSourceManager* get(); - static std::queue<Command*> commands; - static std::stack<Command*> commandsPool; - static Command* getCommand(); - static void collectCommand(Command* cmd); - - static std::vector<SDLSource*> sources; - - void* data; - void* pos; - int length; - int pitch; - bool paused; - bool playing; - bool stopped; + /* Process function */ + static void processCommands(); + static void processSources(Uint8* buffer, int len); + + private: + + friend class SDLSource; + + static void removeSource(SDLSource* source); + static void pushSource(SDLSource* source); + static SDLSourceCommand* getCommand(); + static void pushCommand(SDLSourceCommand* cmd); + static void collectCommand(SDLSourceCommand* cmd); + static SDLSourceManager* manager; + + static std::queue<SDLSourceCommand*> commands; + static std::stack<SDLSourceCommand*> commandsPool; + static std::vector<SDLSource*> sources; // processing sources + + }; + + class SourceException : public std::exception + { + const char * what() const throw () + { + return "Load Source Exception"; + } }; } diff --git a/src/libjin/audio/source.h b/src/libjin/audio/source.h index 4ed8752..b625758 100644 --- a/src/libjin/audio/source.h +++ b/src/libjin/audio/source.h @@ -33,13 +33,13 @@ namespace audio public: + Source() {}; + virtual ~Source() {}; + /* ISource interface */ protected: - Source(); - virtual ~Source(); - }; } diff --git a/src/libjin/fs/filesystem.cpp b/src/libjin/fs/filesystem.cpp index 72f1144..af94034 100644 --- a/src/libjin/fs/filesystem.cpp +++ b/src/libjin/fs/filesystem.cpp @@ -12,7 +12,7 @@ namespace fs Filesystem::Filesystem() { - S = sm_newshared(); + S = smtnewshared(); } Filesystem* Filesystem::get() @@ -25,10 +25,10 @@ namespace fs */ void Filesystem::mount(const char * path) { - int err = sm_mount(S, path); + int err = smtmount(S, path); if (err) { - printf("%s mounted path %s", sm_errstr(err), path); + printf("%s mounted path %s", smterrstr(err), path); exit(1); } } @@ -38,7 +38,7 @@ namespace fs */ int Filesystem::read(const char* path, Buffer* buffer) { - buffer->data = sm_read(S, path, &buffer->size); + buffer->data = smtread(S, path, &buffer->size); if (buffer->data == 0) return 0; return 1; @@ -46,22 +46,22 @@ namespace fs const char* Filesystem::getFull(const char* path) { - return sm_fullpath(S, path); + return smtfullpath(S, path); } bool Filesystem::isDir(const char* path) { - return sm_isdir(S, path); + return smtisdir(S, path); } bool Filesystem::isFile(const char* path) { - return sm_isreg(S, path); + return smtisreg(S, path); } bool Filesystem::exists(const char* path) { - return sm_exists(S, path) == 0; + return smtexists(S, path) == 0; } } diff --git a/src/libjin/fs/filesystem.h b/src/libjin/fs/filesystem.h index 8c8ef04..15f0b9f 100644 --- a/src/libjin/fs/filesystem.h +++ b/src/libjin/fs/filesystem.h @@ -48,7 +48,7 @@ namespace fs static Filesystem* fs; - sm_Shared* S; + smtShared* S; }; } diff --git a/src/libjin/render/jsl.cpp b/src/libjin/render/jsl.cpp index e883104..f4e1cb0 100644 --- a/src/libjin/render/jsl.cpp +++ b/src/libjin/render/jsl.cpp @@ -16,7 +16,7 @@ namespace render "uniform Image _tex0_; \n" "%s \n" "void main(){ \n" - "gl_FragColor = effect(gl_Color, _tex0_, gl_TexCoord[0].xy, gl_FragCoord.xy);\n" + " gl_FragColor = effect(gl_Color, _tex0_, gl_TexCoord[0].xy, gl_FragCoord.xy);\n" "}\0"; shared JSLProgram* JSLProgram::currentJSLProgram = nullptr; diff --git a/src/libjin/utils/unittest.cpp b/src/libjin/utils/unittest.cpp index b64f394..df1a2b6 100644 --- a/src/libjin/utils/unittest.cpp +++ b/src/libjin/utils/unittest.cpp @@ -1,20 +1,26 @@ #include "utils.h" #if UNITTEST +#include <iostream> #include <stdio.h> +#include <fstream> +#include "../audio/sdl/source.h" #include "../audio/sdl/audio.h" using namespace jin::audio; - +using namespace std; +int length = 2226052; +char buf[2226052]; int main(int argc, char* argv[]) { Audio* audio = SDLAudio::get(); - SDLAudioSetting setting; - setting.rate = 44100; - setting.resolution = AUDIO_S16SYS; /*signed 16 - bit samples in native byte order*/ - setting.channels = 2; - setting.samples = 44100; - audio->init(&setting); + audio->init(0); + ifstream fs; + fs.open("a.wav", ios::binary); + fs.read(buf, length); + SDLSource source(SDLSource::WAV, buf, length); + source.play(); + source.setLoop(true); while (true) { SDL_Delay(100); @@ -23,4 +29,4 @@ int main(int argc, char* argv[]) return 0; } -#endif +#endif
\ No newline at end of file |