143 lines
2.9 KiB
C++
143 lines
2.9 KiB
C++
#include <fishbone/foundation.h>
|
|
|
|
fishbone::Mixer::Mixer() {
|
|
this->mutex = new fishbone::Mutex();
|
|
|
|
#define LOADER(X) this->loaders.push_back(new fishbone::X##SoundLoader());
|
|
FB_SOUND_LOADERS
|
|
#undef LOADER
|
|
|
|
this->position[0] = 0;
|
|
this->position[1] = 0;
|
|
this->position[2] = 0;
|
|
}
|
|
|
|
fishbone::Mixer::~Mixer() {
|
|
for(int i = 0; i < this->sounds.size(); i++) {
|
|
delete this->sounds[i];
|
|
}
|
|
for(int i = 0; i < this->loaders.size(); i++) {
|
|
delete this->loaders[i];
|
|
}
|
|
|
|
delete this->mutex;
|
|
}
|
|
|
|
void fishbone::Mixer::read(short* buffer, size_t frames) {
|
|
float* tmp = new float[frames * 2];
|
|
|
|
for(int i = 0; i < frames * 2; i++) tmp[i] = 0;
|
|
|
|
this->lock();
|
|
for(int i = 0; i < this->sounds.size(); i++) {
|
|
size_t ask;
|
|
short* req;
|
|
size_t got;
|
|
float la = 1, ra = 1;
|
|
|
|
if(this->sounds[i]->isPaused()) continue;
|
|
|
|
if(this->sounds[i]->is3d) {
|
|
float r[3];
|
|
float angle, v;
|
|
float d;
|
|
float lf, rf;
|
|
|
|
for(int j = 0; j < 3; j++) r[j] = this->position[i] - this->sounds[i]->position[j];
|
|
|
|
angle = atan2(r[2], r[0]);
|
|
v = cos(angle);
|
|
|
|
d = sqrt(r[0] * r[0] + r[1] * r[1] + r[2] * r[2]);
|
|
|
|
lf = 1.0 - v;
|
|
rf = 1.0 + v;
|
|
|
|
la = 1.0 / (1.0 + lf + d * d);
|
|
ra = 1.0 / (1.0 + rf + d * d);
|
|
}
|
|
|
|
ask = frames * this->sounds[i]->rate / fishbone::Mixer::rate;
|
|
req = new short[ask * this->sounds[i]->channels];
|
|
got = this->sounds[i]->read(req, ask) * fishbone::Mixer::rate / this->sounds[i]->rate;
|
|
|
|
if(got <= 0) {
|
|
delete[] req;
|
|
|
|
if(this->sounds[i]->isLoop()) {
|
|
this->sounds[i]->seek(0);
|
|
} else {
|
|
this->sounds[i]->pauseNoLock();
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
for(int j = 0; j < got; j++) {
|
|
short l, r;
|
|
|
|
if(this->sounds[i]->channels == 1) {
|
|
l = r = req[j * this->sounds[i]->rate / fishbone::Mixer::rate];
|
|
} else if(this->sounds[i]->channels == 2) {
|
|
l = req[(j * this->sounds[i]->rate / fishbone::Mixer::rate) * 2 + 0];
|
|
r = req[(j * this->sounds[i]->rate / fishbone::Mixer::rate) * 2 + 1];
|
|
}
|
|
|
|
if(this->sounds[i]->is3d){
|
|
l = (l + r) / 2;
|
|
r = l;
|
|
}
|
|
|
|
tmp[2 * j + 0] += l / 32767.0 * la * this->sounds[i]->volume;
|
|
tmp[2 * j + 1] += r / 32767.0 * ra * this->sounds[i]->volume;
|
|
}
|
|
|
|
delete[] req;
|
|
}
|
|
this->unlock();
|
|
|
|
for(int i = 0; i < frames * 2; i++) buffer[i] = tmp[i] * 32767;
|
|
|
|
delete[] tmp;
|
|
}
|
|
|
|
fishbone::Sound* fishbone::Mixer::open(const char* path) {
|
|
fishbone::File f(path, "r");
|
|
unsigned char* buffer;
|
|
fishbone::Sound* snd;
|
|
|
|
if(!f.good) return nullptr;
|
|
|
|
buffer = new unsigned char[f.size];
|
|
|
|
f.read(buffer, f.size);
|
|
|
|
for(int i = 0; i < this->loaders.size(); i++) {
|
|
snd = this->loaders[i]->open(this, buffer, f.size);
|
|
|
|
if(snd != nullptr) break;
|
|
}
|
|
|
|
delete[] buffer;
|
|
|
|
if(snd != nullptr) {
|
|
if(snd->channels != 1 && snd->channels != 2) {
|
|
delete snd;
|
|
return nullptr;
|
|
}
|
|
|
|
this->lock();
|
|
this->sounds.push_back(snd);
|
|
this->unlock();
|
|
}
|
|
|
|
return snd;
|
|
}
|
|
|
|
void fishbone::Mixer::lock() {
|
|
this->mutex->lock();
|
|
}
|
|
|
|
void fishbone::Mixer::unlock() {
|
|
this->mutex->unlock();
|
|
}
|