aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/audio/sdl/source.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin/audio/sdl/source.cpp')
-rw-r--r--src/libjin/audio/sdl/source.cpp76
1 files changed, 36 insertions, 40 deletions
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();