aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libjin/audio/sdl/audio.cpp34
-rw-r--r--src/libjin/audio/sdl/audio.h15
-rw-r--r--src/libjin/audio/sdl/source.cpp76
-rw-r--r--src/libjin/audio/sdl/source.h4
-rw-r--r--src/libjin/math/math.h6
-rw-r--r--src/libjin/utils/unittest.cpp7
6 files changed, 68 insertions, 74 deletions
diff --git a/src/libjin/audio/sdl/audio.cpp b/src/libjin/audio/sdl/audio.cpp
index 5277a3d..a26ea1a 100644
--- a/src/libjin/audio/sdl/audio.cpp
+++ b/src/libjin/audio/sdl/audio.cpp
@@ -1,3 +1,4 @@
+#include <iostream>
#include "audio.h"
#include "source.h"
@@ -6,35 +7,32 @@ namespace jin
namespace audio
{
- void SDLAudio::defaultCallback(void *userdata, Uint8 *stream, int size)
+ /* עcallbackƵ̵߳ */
+ void defaultCallback(void *userdata, Uint8 *stream, int size)
{
SDLAudio* audio = (SDLAudio*)userdata;
- SDL_LockAudioDevice(audio->audioDevice);
+ audio->lock();
audio->processCommands();
audio->processSources(stream, size);
- SDL_UnlockAudioDevice(audio->audioDevice);
+ audio->unlock();
}
onlyonce bool SDLAudio::_init(const SettingBase* s)
{
if (SDL_Init(SDL_INIT_AUDIO) < 0)
return false;
- SDLAudioSetting* setting = (SDLAudioSetting*)s;
SDL_AudioSpec spec;
- zero(spec);
- spec.freq = 44100;
- spec.format = AUDIO_S16SYS;
- spec.channels = 1;
- spec.samples = 2048;
+ spec.freq = 44100; // 44100 Hz
+ spec.format = AUDIO_S16SYS; // signed 16bits
+ spec.channels = 2; //
+ spec.samples = 1 << 15; // Uin16Χ2
spec.userdata = this;
spec.callback = defaultCallback;
audioDevice = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0);
if (audioDevice == 0)
- {
return false;
- }
- // start audio
+ /* start audio */
SDL_PauseAudioDevice(audioDevice, 0);
return true;
}
@@ -45,12 +43,22 @@ namespace audio
delete audio;
}
+ void SDLAudio::lock()
+ {
+ SDL_LockAudioDevice(audioDevice);
+ }
+
+ void SDLAudio::unlock()
+ {
+ SDL_UnlockAudioDevice(audioDevice);
+ }
+
void SDLAudio::processCommands()
{
SDLSourceManager::get()->processCommands();
}
- void SDLAudio::processSources(Uint8* buffer, int len)
+ void SDLAudio::processSources(void* buffer, size_t len)
{
SDLSourceManager::get()->processSources(buffer, len);
}
diff --git a/src/libjin/audio/sdl/audio.h b/src/libjin/audio/sdl/audio.h
index a0e63da..528fa7d 100644
--- a/src/libjin/audio/sdl/audio.h
+++ b/src/libjin/audio/sdl/audio.h
@@ -14,16 +14,6 @@ namespace audio
public:
- /*
- struct Setting : SettingBase
- {
- int rate; //
- int resolution; // ֱ
- char channels; //
- int samples; // ȡ
- };
- */
-
static inline Audio* get()
{
return audio != NULL ? audio : (audio = new SDLAudio());
@@ -42,9 +32,10 @@ namespace audio
/* process functions*/
void processCommands();
- void processSources(Uint8* buffer, int len);
+ void processSources(void* buffer, size_t len);
- static void defaultCallback(void *userdata, Uint8 *stream, int size);
+ void lock();
+ void unlock();
private:
diff --git a/src/libjin/audio/sdl/source.cpp b/src/libjin/audio/sdl/source.cpp
index e8490f5..3686a92 100644
--- a/src/libjin/audio/sdl/source.cpp
+++ b/src/libjin/audio/sdl/source.cpp
@@ -38,6 +38,12 @@ namespace audio
SDLSource* source;
};
+ typedef enum CHANNEL
+ {
+ MONO = 1, //
+ STEREO = 2, //
+ };
+
typedef MASK enum STATUS
{
PLAYING = 1,
@@ -122,7 +128,7 @@ namespace audio
raw.rate = wav.samplerate;
raw.bitdepth = wav.bitdepth;
raw.samples = raw.size / (wav.bitdepth / 8.f);
- raw.channel = wav.channels;
+ raw.channel = clamp(wav.channels, CHANNEL::MONO, CHANNEL::STEREO);
raw.silence = 0;
}
else
@@ -132,6 +138,7 @@ namespace audio
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) << 1;
+ raw.channel = clamp(raw.channel, CHANNEL::MONO, CHANNEL::STEREO);
raw.size = raw.samples << 1; // 2 bytes each sample
raw.bitdepth = 16;
raw.end = (char*)raw.data + raw.size;
@@ -275,56 +282,45 @@ Manager::get()->pushCommand(cmd); \
}
}
- shared void Manager::processSources(Uint8* buffer, int len)
+ /* AUDIO_S16SYS[size>>1] buffer */
+ shared void Manager::processSources(void* buf, size_t size)
{
- memset(buffer, 0, len);
- int16_t* buf16 = (int16_t*)buffer;
- int samples = len >> 1;
+ Sint16* buffer = (Sint16*)buf;
+ unsigned int samples = size >> 1;
+ memset(buffer, 0, size);
+ SDLSource* src = nullptr;
std::vector<SDLSource*>::iterator it = sources.begin();
- SDLSource* source = nullptr;
for (; it != sources.end();)
{
- 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))
+ src = *it;
+ if (src == nullptr)
+ goto next;
+ src->status.pos;
+ Sint16* source = (Sint16*)((char*)src->raw.data + src->status.pos);
+ unsigned int remain = src->raw.samples - (src->status.pos >> 1);
+ for (int i = 0; i < min(remain, samples); ++i)
{
- int16_t* src16 = (int16_t*)((char*)source->raw.data + source->status.pos);
- int remainsample = (source->raw.size - source->status.pos) >> 1;
- int bound = min(samples, remainsample);
- for (int i = 0; i < bound; ++i)
- {
- buf16[i] += src16[i]; // mix sources
- }
- source->status.pos += (bound << 1);
- if (remainsample < samples)
+ buffer[i] += (src->raw.channel == CHANNEL::STEREO ? source[i] : source[(i % 2) * 2]);
+ }
+ if (remain < samples)
+ {
+ if (!src->status.loop)
{
- if (source->status.loop)
- {
- int j = 0;
- for (int i = bound; i < samples; ++i)
- {
- int val = data16[j];
- buf16[i] += val;
- ++j;
- }
- source->status.pos = (j << 1);
- break;
- }
- else
- {
- it = sources.erase(it);
- continue;
- }
+ it = sources.erase(it);
+ continue;
}
+ int j = 0;
+ for (int i = samples - remain; i < samples; ++i, ++j)
+ buffer[i] += (src->raw.channel == CHANNEL::STEREO ? source[j] : source[j % 2 * 2]);
+ src->status.pos = (j << 1);
+ continue;
}
+ src->status.pos += (samples << 1);
+ next:
++it;
}
}
-
+
shared void Manager::removeSource(SDLSource* source)
{
std::vector<SDLSource*>::iterator it = sources.begin();
diff --git a/src/libjin/audio/sdl/source.h b/src/libjin/audio/sdl/source.h
index 743d4f0..2f9acb5 100644
--- a/src/libjin/audio/sdl/source.h
+++ b/src/libjin/audio/sdl/source.h
@@ -58,7 +58,7 @@ namespace audio
int rate; // Ƶ
unsigned char bitdepth; // ÿsampleıس
int samples; // sample = size / (bitdepth / 8)
- unsigned char channel; // channel12
+ unsigned char channel; // channel1(mono)2(stereo)
char silence; // 0
} raw;
@@ -83,7 +83,7 @@ namespace audio
/* Process function */
static void processCommands();
- static void processSources(Uint8* buffer, int len);
+ static void processSources(void* buffer, size_t size);
private:
diff --git a/src/libjin/math/math.h b/src/libjin/math/math.h
index f6a299e..849f74b 100644
--- a/src/libjin/math/math.h
+++ b/src/libjin/math/math.h
@@ -7,9 +7,9 @@
#include "matrix.h"
#include "quad.h"
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#define max(a,b) (((a) > (b)) ? (a) : (b))
-#define clamp(a, mi,ma) min(max(a,mi),ma)
+#define min(a,b) (a < b ? a : b)
+#define max(a,b) (a > b ? a : b)
+#define clamp(a, mi,ma) (min(max(a,mi),ma))
#define within(a,min,max) (a >= min && a <= max)
#define without(a,min,max) (a < min || a > max)
diff --git a/src/libjin/utils/unittest.cpp b/src/libjin/utils/unittest.cpp
index 062604e..ce72173 100644
--- a/src/libjin/utils/unittest.cpp
+++ b/src/libjin/utils/unittest.cpp
@@ -16,11 +16,10 @@ int main(int argc, char* argv[])
audio->init(0);
SDLSource* source = SDLSource::createSource("a.ogg");
SDLSource* source2 = SDLSource::createSource("a.wav");
- source->play();
- //source2->play();
- source2->setLoop(true);
//source->play();
- //source->setLoop(true);
+ source2->play();
+ source->setLoop(true);
+ source2->setLoop(true);
int i = 0;
while (true)
{