aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/audio/SDL/sdl_source.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2020-02-11 11:29:07 +0800
committerchai <chaifix@163.com>2020-02-11 11:29:07 +0800
commit160e1299ef3d95f8e8c48706d7f61dd3dc6c6b60 (patch)
treeabe5ae5242d9cc6caf6edf103e662c44e978fca0 /src/libjin/audio/SDL/sdl_source.cpp
parente095043485d1d298571af6d9eca7f0db9009ea7a (diff)
*修改 tab大小HEADmaster
Diffstat (limited to 'src/libjin/audio/SDL/sdl_source.cpp')
-rw-r--r--src/libjin/audio/SDL/sdl_source.cpp708
1 files changed, 354 insertions, 354 deletions
diff --git a/src/libjin/audio/SDL/sdl_source.cpp b/src/libjin/audio/SDL/sdl_source.cpp
index eae3eec..68e66c4 100644
--- a/src/libjin/audio/SDL/sdl_source.cpp
+++ b/src/libjin/audio/SDL/sdl_source.cpp
@@ -19,376 +19,376 @@ using namespace JinEngine::Math;
namespace JinEngine
{
- namespace Audio
- {
- namespace SDL
- {
+ 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
- };
+ 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()
- {
- memset(&status, 0, sizeof(status));
- memset(&raw, 0, sizeof(raw));
- status.volume = 1;
- }
-
- SDLSource::SDLSource(const char* file)
- : SDLSource()
- {
- std::ifstream fs;
- fs.open(file, std::ios::binary);
- if (!fs.is_open())
- {
- fs.close();
- return;
- }
- 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(buffer, size);
- free(buffer);
- }
-
- SDLSource::SDLSource(void* mem, size_t size)
- : SDLSource()
- {
- if (mem == nullptr)
- return;
- SourceType format = getType(mem, size);
- switch (format)
- {
- case OGG: decode_ogg(mem, size); break;
- case WAV: decode_wav(mem, size); break;
- }
- }
-
- 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;
- }
+ //std::queue<Command*> Manager::commands;
+ //std::stack<Command*> Manager::commandsPool;
+ //std::vector<SDLSource*> Manager::sources;
+ Manager* Manager::manager = nullptr;
+
+ SDLSource::SDLSource()
+ {
+ memset(&status, 0, sizeof(status));
+ memset(&raw, 0, sizeof(raw));
+ status.volume = 1;
+ }
+
+ SDLSource::SDLSource(const char* file)
+ : SDLSource()
+ {
+ std::ifstream fs;
+ fs.open(file, std::ios::binary);
+ if (!fs.is_open())
+ {
+ fs.close();
+ return;
+ }
+ 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(buffer, size);
+ free(buffer);
+ }
+
+ SDLSource::SDLSource(void* mem, size_t size)
+ : SDLSource()
+ {
+ if (mem == nullptr)
+ return;
+ SourceType format = getType(mem, size);
+ switch (format)
+ {
+ case OGG: decode_ogg(mem, size); break;
+ case WAV: decode_wav(mem, size); break;
+ }
+ }
+
+ 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)
+ 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)
+ 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
+ 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