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.cpp216
1 files changed, 119 insertions, 97 deletions
diff --git a/src/libjin/audio/sdl/source.cpp b/src/libjin/audio/sdl/source.cpp
index 1a5c5d1..51b67e4 100644
--- a/src/libjin/audio/sdl/source.cpp
+++ b/src/libjin/audio/sdl/source.cpp
@@ -8,11 +8,15 @@
#define STB_VORBIS_HEADER_ONLY
#include "3rdparty/stb/stb_vorbis.c"
+#include "audio.h"
+
namespace jin
{
namespace audio
{
+#define BITS 8
+
typedef struct SDLSourceCommand
{
typedef enum Action
@@ -75,6 +79,7 @@ namespace audio
char* buffer = (char*)malloc(size);
memset(buffer, 0, size);
fs.read(buffer, size);
+ fs.close();
SDLSource* source = createSource(buffer, size);
free(buffer);
return source;
@@ -85,17 +90,15 @@ namespace audio
if (mem == nullptr)
return nullptr;
SDLSource* source = new SDLSource();
-#define parse(FMT) case FMT : source->load##FMT(mem, size); break
try
{
SourceType format = getType(mem, size);
switch (format)
{
- parse(OGG);
- parse(WAV);
+ case OGG: source->decode_ogg(mem, size); break;
+ case WAV: source->decode_wav(mem, size); break;
}
}
-#undef parse
catch (SourceException& exp)
{
delete source;
@@ -117,37 +120,44 @@ namespace audio
raw.data = 0;
}
- void SDLSource::loadWAV(void* mem, int size)
+ void SDLSource::decode_wav(void* mem, int size)
{
wav_t wav;
if (wav_read(&wav, mem, size) == 0)
{
- raw.data = wav.data;
- raw.size = wav.length * wav.bitdepth / 8;
- raw.end = (char*)raw.data + raw.size;
- raw.rate = wav.samplerate;
- raw.bitdepth = wav.bitdepth;
- raw.samples = raw.size / (wav.bitdepth / 8.f);
- raw.channel = clamp(wav.channels, CHANNEL::MONO, CHANNEL::STEREO);
- raw.silence = 0;
+ raw.data = wav.data;
+ raw.length = wav.length * wav.bitdepth / 8;
+ 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(wav.channels, CHANNEL::MONO, CHANNEL::STEREO);
}
else
throw SourceException();
}
- void SDLSource::loadOGG(void* mem, int size)
+ void SDLSource::decode_ogg(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;
- raw.silence = 0;
-
- if (raw.samples < 0)
- {
- throw SourceException();
- }
+ 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;
+ raw.length = samples * channels * sizeof(short);
+ raw.bitdepth = bitdepth;
+ raw.end = (char*)data + raw.length;
}
#define ActionNone(T)\
@@ -227,6 +237,85 @@ Manager::get()->pushCommand(cmd); \
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:
+ //float 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
+ 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 /*˫*/)
+ {
+ /* Ƶļsampleᱻ */
+ sample = buffer + i * SDLAUDIO_BYTEDEPTH;
+ origin = *sample;
+ if (bitdepth == 8)
+ {
+ clip = *clip8;
+ }
+ else if (bitdepth == 16)
+ clip = *clip16;
+
+ }
+ }
+
Manager* Manager::get()
{
return (manager == nullptr ? manager = new Manager() : manager);
@@ -243,43 +332,7 @@ Manager::get()->pushCommand(cmd); \
{
source = cmd->source;
if (source != nullptr)
- {
- switch (cmd->action)
- {
- case Command::Action::Play:
- removeSource(source);
- pushSource(source);
- source->status.state = PLAYING;
- source->status.pos = 0; // rewind
- break;
- case Command::Action::Stop:
- manager->removeSource(source);
- source->status.state = STOPPED;
- source->status.pos = 0; // rewind
- break;
- case Command::Action::Pause:
- manager->removeSource(source);
- source->status.state = PAUSED;
- break;
- case Command::Action::Resume:
- manager->removeSource(source);
- manager->pushSource(source);
- source->status.state = PLAYING;
- break;
- case Command::Action::Rewind:
- source->status.state = PLAYING;
- source->status.pos = 0;
- break;
- case Command::Action::SetVolume:
- //float cmd->parameter._float;
- break;
- case Command::Action::SetLoop:
- source->status.loop = cmd->parameter._boolean;
- break;
- /*case Command::Action::SetRate:
- */
- }
- }
+ source->handle(manager, cmd);
}
commands.pop();
}
@@ -288,38 +341,15 @@ Manager::get()->pushCommand(cmd); \
/* AUDIO_S16SYS[size>>1] buffer */
shared void Manager::processSources(void* buf, size_t size)
{
- Sint16* buffer = (Sint16*)buf;
- unsigned int samples = size >> 1;
- memset(buffer, 0, 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)
- 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)
- {
- buffer[i] += (src->raw.channel == CHANNEL::STEREO ? source[i] : source[(i % 2) * 2]);
- }
- if (remain < samples)
- {
- if (!src->status.loop)
- {
- 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:
+ if (src != nullptr)
+ src->process(buf, size);
++it;
}
}
@@ -360,13 +390,5 @@ Manager::get()->pushCommand(cmd); \
return new Command();
}
- shared void Manager::collectCommand(Command* cmd)
- {
- if (cmd != nullptr)
- {
- commandsPool.push(cmd);
- }
- }
-
}
} \ No newline at end of file