aboutsummaryrefslogtreecommitdiff
path: root/src/libjin
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin')
-rw-r--r--src/libjin/audio/sdl/audio.cpp30
-rw-r--r--src/libjin/audio/sdl/audio.h14
-rw-r--r--src/libjin/audio/sdl/source.cpp264
-rw-r--r--src/libjin/audio/sdl/source.h118
-rw-r--r--src/libjin/audio/source.h6
-rw-r--r--src/libjin/fs/filesystem.cpp16
-rw-r--r--src/libjin/fs/filesystem.h2
-rw-r--r--src/libjin/render/jsl.cpp2
-rw-r--r--src/libjin/utils/unittest.cpp22
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