aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/Audio/SDL
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin/Audio/SDL')
-rw-r--r--src/libjin/Audio/SDL/SDLAudio.cpp60
-rw-r--r--src/libjin/Audio/SDL/SDLAudio.h11
-rw-r--r--src/libjin/Audio/SDL/SDLSource.cpp94
-rw-r--r--src/libjin/Audio/SDL/SDLSource.h28
4 files changed, 105 insertions, 88 deletions
diff --git a/src/libjin/Audio/SDL/SDLAudio.cpp b/src/libjin/Audio/SDL/SDLAudio.cpp
index a41382b..f7ca70d 100644
--- a/src/libjin/Audio/SDL/SDLAudio.cpp
+++ b/src/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<SDLAudio*>(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/src/libjin/Audio/SDL/SDLAudio.h b/src/libjin/Audio/SDL/SDLAudio.h
index 6837126..f2a4fab 100644
--- a/src/libjin/Audio/SDL/SDLAudio.h
+++ b/src/libjin/Audio/SDL/SDLAudio.h
@@ -3,6 +3,7 @@
#include "../../modules.h"
#if JIN_MODULES_AUDIO && JIN_AUDIO_SDLAUDIO
+#include "SDLSource.h"
#include <vector>
#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/src/libjin/Audio/SDL/SDLSource.cpp b/src/libjin/Audio/SDL/SDLSource.cpp
index 18ba855..c868df5 100644
--- a/src/libjin/Audio/SDL/SDLSource.cpp
+++ b/src/libjin/Audio/SDL/SDLSource.cpp
@@ -3,14 +3,13 @@
#include <exception>
#include <fstream>
-
+#include <climits>
#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<Command*> Manager::commands;
- shared std::stack<Command*> Manager::commandsPool;
- shared std::vector<SDLSource*> Manager::sources;
+ //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::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<int>(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<int>(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<SDLSource*>::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/src/libjin/Audio/SDL/SDLSource.h b/src/libjin/Audio/SDL/SDLSource.h
index 5c6aefc..9a3dd9b 100644
--- a/src/libjin/Audio/SDL/SDLSource.h
+++ b/src/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<SDLSourceCommand*> commands;
+ std::stack<SDLSourceCommand*> commandsPool;
+ std::vector<SDLSource*> sources; // processing sources
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