diff options
Diffstat (limited to 'src/libjin/audio')
-rw-r--r-- | src/libjin/audio/SDL/je_sdl_audio.cpp | 146 | ||||
-rw-r--r-- | src/libjin/audio/SDL/je_sdl_audio.h | 138 | ||||
-rw-r--r-- | src/libjin/audio/SDL/je_sdl_source.cpp | 404 | ||||
-rw-r--r-- | src/libjin/audio/SDL/je_sdl_source.h | 272 | ||||
-rw-r--r-- | src/libjin/audio/je_audio_manager.cpp | 15 | ||||
-rw-r--r-- | src/libjin/audio/je_audio_manager.h | 87 | ||||
-rw-r--r-- | src/libjin/audio/je_source.cpp | 30 | ||||
-rw-r--r-- | src/libjin/audio/je_source.h | 116 |
8 files changed, 1208 insertions, 0 deletions
diff --git a/src/libjin/audio/SDL/je_sdl_audio.cpp b/src/libjin/audio/SDL/je_sdl_audio.cpp new file mode 100644 index 0000000..c21d077 --- /dev/null +++ b/src/libjin/audio/SDL/je_sdl_audio.cpp @@ -0,0 +1,146 @@ +#include "../../core/je_configuration.h" +#if defined(jin_audio) && (jin_audio == jin_audio_sdl) + +#include <iostream> + +#include "../../math/je_math.h" +#include "../../utils/je_log.h" + +#include "je_sdl_audio.h" +#include "je_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<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) + { + 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<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() + { + 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 diff --git a/src/libjin/audio/SDL/je_sdl_audio.h b/src/libjin/audio/SDL/je_sdl_audio.h new file mode 100644 index 0000000..77162d4 --- /dev/null +++ b/src/libjin/audio/SDL/je_sdl_audio.h @@ -0,0 +1,138 @@ +#ifndef __JE_AUDIO_SDL_H__ +#define __JE_AUDIO_SDL_H__ +#include "../../core/je_configuration.h" +#if defined(jin_audio) && (jin_audio == jin_audio_sdl) + +#include <vector> + +#include "../je_audio_manager.h" + +#include "je_sdl_source.h" + +namespace JinEngine +{ + namespace Audio + { + namespace SDL + { + +#define SDLAUDIO_BITDEPTH 16 +#define SDLAUDIO_BYTEDEPTH (SDLAUDIO_BITDEPTH >> 3) +#define SDLAUDIO_CHANNELS 2 + + /// + /// Audio system SDL implementation. + /// + class SDLAudio : public AudioManager<SDLAudio> + { + public: + /// + /// SDL audio setting. + /// + struct Setting : SettingBase + { + public: + int samplerate; // Ƶ + int samples; // sample<=samplerate + }; + + /// + /// Play all sources whose state is playing. + /// + void play() override; + + /// + /// Stop and remove all sources from the queue. + /// + void stop() override; + + /// + /// Pause audio. + /// + void pause() override; + + /// + /// Resume audio. + /// + void resume() override; + + /// + /// Set global audio volume. + /// + void setVolume(float volume) override; + + /// + /// Process all commands in the queue. + /// + void processCommands(); + + /// + /// Process all sources. + /// + /// @param buffer Source buffer. + /// @param len Source length. + /// + void processSources(void* buffer, size_t len); + + /// + /// Process audio buffer. + /// + /// @param buffer Audio stream buffer. + /// @param len Length of stream buffer. + /// + void processBuffer(void* buffer, size_t len); + + /// + /// Goon process. + /// + /// @return True if sucessful, otherwise return false. + /// + bool goOnProcess(); + + /// + /// Lock audio device. + /// + void lock(); + + /// + /// Unlock audio device. + /// + void unlock(); + + private: + singleton(SDLAudio); + + /// + /// SDL audio constructor. + /// + SDLAudio() {}; + + /// + /// SDL audio destructor. + /// + ~SDLAudio() {}; + + /// + /// Initialize audio system. + /// + /// @param setting Audio setting. + /// + bool initSystem(const SettingBase* setting) override; + + /// + /// Quit audio system. + /// + void quitSystem() override; + + // Audio device id. + unsigned int audioDevice; + + }; + + } // namespace SDL + } // namespace Audio +} // namespace JinEngine + +#endif // (jin_audio) && (jin_audio == jin_audio_sdl) + +#endif // __JE_AUDIO_SDL_H__
\ No newline at end of file diff --git a/src/libjin/audio/SDL/je_sdl_source.cpp b/src/libjin/audio/SDL/je_sdl_source.cpp new file mode 100644 index 0000000..d417bf7 --- /dev/null +++ b/src/libjin/audio/SDL/je_sdl_source.cpp @@ -0,0 +1,404 @@ +#include "../../core/je_configuration.h" +#if defined(jin_audio) && (jin_audio == jin_audio_sdl) + +#include <exception> +#include <fstream> +#include <climits> + +#define STB_VORBIS_HEADER_ONLY +#include "stb/stb_vorbis.c" +#include "wav/wav.h" + +#include "../../math/je_math.h" +#include "../../utils/je_macros.h" + +#include "je_sdl_audio.h" +#include "je_sdl_source.h" + +using namespace JinEngine::Math; + +namespace JinEngine +{ + namespace Audio + { + namespace SDL + { + + +#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 + + //std::queue<Command*> Manager::commands; + //std::stack<Command*> Manager::commandsPool; + //std::vector<SDLSource*> Manager::sources; + 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)); + } + + void SDLSource::setLoop(bool loop) + { + ActionBool(SetLoop, loop); + } + + 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(); + } + + } // namespace SDL + } // namespace Audio +} // namespace JinEngine + +#endif // (jin_audio) && (jin_audio == jin_audio_sdl)
\ No newline at end of file diff --git a/src/libjin/audio/SDL/je_sdl_source.h b/src/libjin/audio/SDL/je_sdl_source.h new file mode 100644 index 0000000..bbc8c7a --- /dev/null +++ b/src/libjin/audio/SDL/je_sdl_source.h @@ -0,0 +1,272 @@ +#ifndef __JE_SOURCE_SDL_H__ +#define __JE_SOURCE_SDL_H__ +#include "../../core/je_configuration.h" +#if defined(jin_audio) && (jin_audio == jin_audio_sdl) + +#include <vector> +#include <queue> +#include <stack> +#include <exception> + +#include "../je_source.h" + +namespace JinEngine +{ + namespace Audio + { + namespace SDL + { + + typedef struct SDLSourceCommand; + + class SDLSourceManager; + + /// + /// Audio source SDL implementation. + /// + class SDLSource : public Source + { + public: + /// + /// Create source from raw source data file. + /// + /// @param file Audio source file. + /// @return Return source if create successful, otherwise return null. + /// + static SDLSource* createSource(const char* file); + + /// + /// Create source from raw source data. + /// + /// @param mem Source data. + /// @param size Source data size. + /// @return Return source if create successful, otherwise return null. + /// + static SDLSource* createSource(void* mem, size_t size); + + /// + /// Source destructor. + /// + ~SDLSource(); + + /// + /// Play source. + /// + void play() override; + + /// + /// Stop source. + /// + void stop() override; + + /// + /// Pause source. + /// + void pause() override; + + /// + /// Resume source. + /// + void resume() override; + + /// + /// Rewind source. + /// + void rewind() override; + + /// + /// Return if the source is stopped. + /// + /// @return True if the source is stopped, otherwise return false. + /// + bool isStopped() const override; + + /// + /// Return if the source is paused. + /// + /// @return True if the source is paused(, otherwise return false. + /// + bool isPaused() const override; + + /// + /// Set pitch. + /// + /// @param pitch Pitch of source. + /// + void setPitch(float pitch) override; + + /// + /// Set volume. + /// + /// @param volume Volume of source. + /// + void setVolume(float volume) override; + + /// + /// Set source loop. + /// + /// @param loop Looping or not. + /// + void setLoop(bool loop) override; + + /// + /// Set source rate. + /// + /// @param rate Rate of source. + /// + void setRate(float rate) override; + + /// + /// Handle a specific command. + /// + /// @param manager Audio manager. + /// @param cmd Source commad. + /// + inline void handle(SDLSourceManager* manager, SDLSourceCommand* cmd); + + /// + /// Process decoded source data. + /// + /// @param buffer Source data. + /// @param size Data size. + /// + inline void process(void* buffer, size_t size); + + protected: + /// + /// Source constructor. + /// + SDLSource(); + + /// + /// Decode wav file. + /// + /// @param mem Wav file data. + /// @param size Wav data size. + /// + void decode_wav(void* mem, int size); + + /// + /// Decode ogg file. + /// + /// @param mem ogg file data. + /// @param size ogg data size. + /// + void decode_ogg(void* mem, int size); + + /// + /// Check source state. + /// + /// @param state State to be checked. + /// @return True if state is given state, otherwise return false. + /// + inline bool is(int state) const + { + return (status.state & state) == state; + } + + // Source data. + 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; + + }; + + /// + /// Source manager. + /// + class SDLSourceManager + { + public: + /// + /// Get manager singleton. + /// + /// @return Singleton of SDL source manager. + /// + static SDLSourceManager* get(); + + /// + /// Process commands. + /// + void processCommands(); + + /// + /// Process sources. + /// + /// @param buffer Source data. + /// @param size Size of source data. + /// + void processSources(void* buffer, size_t size); + + /// + /// Clear source queue. + /// + /// This function will stop all sources. + /// + void removeAllSource(); + + /// + /// Remove specific source. + /// + /// @param source SDL audio source. + /// + void removeSource(SDLSource* source); + + /// + /// Push specific source into queue. + /// + /// @param source SDL audio source. + /// + void pushSource(SDLSource* source); + + /// + /// Get command from queue. + /// + /// @return Command at first place. + /// + SDLSourceCommand* getCommand(); + + /// + /// Push command. + /// + /// @param cmd Spcific command. + /// + void pushCommand(SDLSourceCommand* cmd); + + 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"; + } + }; + + } // namespace SDL + } // namespace Audio +} // namespace JinEngine + +#endif // (jin_audio) && (jin_audio == jin_audio_sdl) + +#endif // __JE_SOURCE_SDL_H__
\ No newline at end of file diff --git a/src/libjin/audio/je_audio_manager.cpp b/src/libjin/audio/je_audio_manager.cpp new file mode 100644 index 0000000..e451aa3 --- /dev/null +++ b/src/libjin/audio/je_audio_manager.cpp @@ -0,0 +1,15 @@ +#include "../core/je_configuration.h" +#if jin_audio + +#include "SDL2/SDL.h" +#include "je_audio_manager.h" + +namespace JinEngine +{ + namespace Audio + { + + } // namespace Audio +} // namespace JinEngine + +#endif // jin_audio diff --git a/src/libjin/audio/je_audio_manager.h b/src/libjin/audio/je_audio_manager.h new file mode 100644 index 0000000..120d38e --- /dev/null +++ b/src/libjin/audio/je_audio_manager.h @@ -0,0 +1,87 @@ +#ifndef __JE_AUDIO_H__ +#define __JE_AUDIO_H__ + +#include "../core/je_configuration.h" +#if defined(jin_audio) + +#include "../utils/je_macros.h" +#include "../common/je_subsystem.hpp" + +#include "SDL2/SDL.h" + +namespace JinEngine +{ + namespace Audio + { + + class Source; + + /// + /// Audio manager. + /// + template<class SubAudio> + class AudioManager : public Subsystem<SubAudio> + { + public: + /// + /// Audio state. + /// + enum State + { + PLAY , + STOP , + PAUSE, + }; + + /// + /// Play all sources whose state is playing. + /// + virtual void play() = 0; + + /// + /// Stop and remove all sources from the queue. + /// + virtual void stop() = 0; + + /// + /// Pause audio. + /// + virtual void pause() = 0; + + /// + /// Resume audio. + /// + virtual void resume() = 0; + + /// + /// Set global audio volume. + /// + virtual void setVolume(float volume) = 0; + + protected: + singleton(AudioManager); + + /// + /// AudioManager constructor. + /// + AudioManager() + : volume(1) + , state(State::PLAY) + {}; + + /// + /// AudioManager destructor. + /// + virtual ~AudioManager() {}; + + float volume; + State state; + + }; + + } // namespace Audio +} // namespace JinEngine + +#endif // jin_audio + +#endif // __JE_AUDIO_H__
\ No newline at end of file diff --git a/src/libjin/audio/je_source.cpp b/src/libjin/audio/je_source.cpp new file mode 100644 index 0000000..6bc1f4f --- /dev/null +++ b/src/libjin/audio/je_source.cpp @@ -0,0 +1,30 @@ +#include "../core/je_configuration.h" +#if defined(jin_audio) + +#include <cstring> + +#include "je_source.h" + +namespace JinEngine +{ + namespace Audio + { + + static int check_header(const void *data, int size, const char *str, int offset) { + int len = strlen(str); + return (size >= offset + len) && !memcmp((char*)data + offset, str, len); + } + + SourceType Source::getType(const void* mem, int size) + { + if(check_header(mem, size, "WAVE", 8)) + return SourceType::WAV; + if(check_header(mem, size, "OggS", 0)) + return SourceType::OGG; + return SourceType::INVALID; + } + + } // namespace Audio +} // namespace JinEngine + +#endif // jin_audio diff --git a/src/libjin/audio/je_source.h b/src/libjin/audio/je_source.h new file mode 100644 index 0000000..f60daf9 --- /dev/null +++ b/src/libjin/audio/je_source.h @@ -0,0 +1,116 @@ +#ifndef __JE_AUDIO_SOURCE_H__ +#define __JE_AUDIO_SOURCE_H__ +#include "../core/je_configuration.h" +#if defined(jin_audio) + +#include "SDL2/SDL.h" + +namespace JinEngine +{ + namespace Audio + { + + /// + /// Audio source encoding type. + /// + enum SourceType + { + INVALID = 0, + WAV, + OGG, + }; + + /// + /// Audio source. + /// + class Source + { + public: + /// + /// Source constructor. + /// + Source() {}; + + /// + /// Source destructor. + /// + virtual ~Source() {}; + + /// + /// Start playing source. + /// + virtual void play() = 0; + + /// + /// Stop playing source. + /// + virtual void stop() = 0; + + /// + /// Pause source. + /// + virtual void pause() = 0; + + /// + /// Resume source. + /// + virtual void resume() = 0; + + /// + /// Rewind source. + /// + virtual void rewind() = 0; + + /// + /// Whether the source is playing or not. + /// + virtual bool isStopped() const = 0; + + /// + /// Whether the source is paused or not. + /// + virtual bool isPaused() const = 0; + + /// + /// Set source pitch. + /// + /// @param pitch Pitch of source. + /// + virtual void setPitch(float pitch) = 0; + + /// + /// Set volume of source. + /// + /// @param volume Volume of source. + /// + virtual void setVolume(float volume) = 0; + + /// + /// Set source loop. + /// + /// @param loop Looping or not. + /// + virtual void setLoop(bool loop) = 0; + + /// + /// Set source rate. + /// + /// @param rate Rate of source. + /// + virtual void setRate(float rate) = 0; + + protected: + + /// + /// Get type of source data. + /// + static SourceType getType(const void* mem, int size); + + }; + + } // namespace Audio +} // namespace JinEngine + +#endif // jin_audio + +#endif // __JE_AUDIO_SOURCE_H__
\ No newline at end of file |