[DEV] end of rework (step 1) ==> it work
This commit is contained in:
parent
775226987e
commit
ca312d1dac
@ -15,15 +15,15 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
#undef __class__
|
||||||
|
#define __class__ "audio::ess::Effects"
|
||||||
|
|
||||||
audio::ess::Effect::Effect(const std::shared_ptr<audio::river::Manager>& _manager) :
|
audio::ess::Effects::Effects(const std::shared_ptr<audio::river::Manager>& _manager) :
|
||||||
m_manager(_manager),
|
m_manager(_manager) {
|
||||||
m_position(0) {
|
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
//Set stereo output:
|
//Set stereo output:
|
||||||
std::vector<audio::channel> channelMap;
|
std::vector<audio::channel> channelMap;
|
||||||
channelMap.push_back(audio::channel_frontLeft);
|
channelMap.push_back(audio::channel_frontCenter);
|
||||||
channelMap.push_back(audio::channel_frontRight);
|
|
||||||
m_interface = m_manager->createOutput(48000,
|
m_interface = m_manager->createOutput(48000,
|
||||||
channelMap,
|
channelMap,
|
||||||
audio::format_int16,
|
audio::format_int16,
|
||||||
@ -32,10 +32,10 @@ audio::ess::Effect::Effect(const std::shared_ptr<audio::river::Manager>& _manage
|
|||||||
EWOLSA_ERROR("can not allocate output interface ... ");
|
EWOLSA_ERROR("can not allocate output interface ... ");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_interface->setName("audio::ess::Effect");
|
m_interface->setName("audio::ess::Effects");
|
||||||
m_interface->addVolumeGroup("EFFECT");
|
m_interface->addVolumeGroup("EFFECT");
|
||||||
// set callback mode ...
|
// set callback mode ...
|
||||||
m_interface->setOutputCallback(std::bind(&audio::ess::Effect::onDataNeeded,
|
m_interface->setOutputCallback(std::bind(&audio::ess::Effects::onDataNeeded,
|
||||||
this,
|
this,
|
||||||
std::placeholders::_1,
|
std::placeholders::_1,
|
||||||
std::placeholders::_2,
|
std::placeholders::_2,
|
||||||
@ -43,11 +43,12 @@ audio::ess::Effect::Effect(const std::shared_ptr<audio::river::Manager>& _manage
|
|||||||
std::placeholders::_4,
|
std::placeholders::_4,
|
||||||
std::placeholders::_5,
|
std::placeholders::_5,
|
||||||
std::placeholders::_6));
|
std::placeholders::_6));
|
||||||
|
m_interface->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
audio::ess::Effect::~Effect() {
|
audio::ess::Effects::~Effects() {
|
||||||
if (m_interface != nullptr) {
|
if (m_interface != nullptr) {
|
||||||
m_interface.stop();
|
m_interface->stop();
|
||||||
}
|
}
|
||||||
m_interface.reset();
|
m_interface.reset();
|
||||||
m_manager.reset();
|
m_manager.reset();
|
||||||
@ -56,7 +57,32 @@ audio::ess::Effect::~Effect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void audio::ess::Effect::onDataNeeded(void* _data,
|
static bool playData(const std::shared_ptr<audio::ess::LoadedFile>& _file, int32_t& _position, int16_t* _bufferInterlace, int32_t _nbSample) {
|
||||||
|
if ( _file == nullptr
|
||||||
|
|| _file->m_data.size() == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int32_t processTimeMax = std::min(_nbSample, _file->m_nbSamples - _position);
|
||||||
|
processTimeMax = std::max(0, processTimeMax);
|
||||||
|
int16_t * pointer = _bufferInterlace;
|
||||||
|
int16_t * newData = &_file->m_data[_position];
|
||||||
|
//EWOLSA_DEBUG("AUDIO : Play slot... nb sample : " << processTimeMax << " playTime=" <<m_playTime << " nbCannels=" << nbChannels);
|
||||||
|
for (int32_t iii=0; iii<processTimeMax; iii++) {
|
||||||
|
int32_t tmppp = int32_t(*_bufferInterlace) + int32_t(*newData);
|
||||||
|
*_bufferInterlace = std::avg(-32767, tmppp, 32766);
|
||||||
|
//EWOLSA_DEBUG("AUDIO : element : " << *pointer);
|
||||||
|
_bufferInterlace++;
|
||||||
|
newData++;
|
||||||
|
}
|
||||||
|
_position += processTimeMax;
|
||||||
|
// check end of playing ...
|
||||||
|
if (_file->m_nbSamples <= _position) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio::ess::Effects::onDataNeeded(void* _data,
|
||||||
const audio::Time& _playTime,
|
const audio::Time& _playTime,
|
||||||
const size_t& _nbChunk,
|
const size_t& _nbChunk,
|
||||||
enum audio::format _format,
|
enum audio::format _format,
|
||||||
@ -65,265 +91,76 @@ void audio::ess::Effect::onDataNeeded(void* _data,
|
|||||||
if (_format != audio::format_int16) {
|
if (_format != audio::format_int16) {
|
||||||
EWOLSA_ERROR("call wrong type ... (need int16_t)");
|
EWOLSA_ERROR("call wrong type ... (need int16_t)");
|
||||||
}
|
}
|
||||||
std::unique_lock<std::mutex> lck(localMutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
if (m_current != m_next) {
|
auto it = m_playing.begin();
|
||||||
EWOLSA_INFO("change track " << (m_curent!=nullptr?-1:m_current->getUId()) << " ==> " << (m_next!=nullptr?-1:m_next->getUId()));
|
while (it != m_playing.end()) {
|
||||||
m_curent = m_next;
|
bool ret = playData((*it).first, (*it).second, static_cast<int16_t*>(_data), _nbChunk);
|
||||||
m_position = 0;
|
if (ret == true) {
|
||||||
|
it = m_playing.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
if (m_curent == nullptr) {
|
|
||||||
// nothing to play ...
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m_current->m_data.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int32_t processTimeMax = std::min(_nbChunk*_map.size(), m_current->m_nbSamples - m_position);
|
|
||||||
processTimeMax = std::max(0, processTimeMax);
|
|
||||||
int16_t * pointer = static_cast<int16_t*>(_data);
|
|
||||||
int16_t * newData = &m_current->m_data[m_posiion];
|
|
||||||
EWOLSA_DEBUG("AUDIO : Play slot... nb sample : " << processTimeMax << " map=" << _map << " _nbChunk=" << _nbChunk);
|
|
||||||
for (int32_t iii=0; iii<processTimeMax; iii++) {
|
|
||||||
*pointer++ = *newData++;
|
|
||||||
}
|
|
||||||
m_position += processTimeMax;
|
|
||||||
// check end of playing ...
|
|
||||||
if (m_current->m_nbSamples <= m_position) {
|
|
||||||
m_position = 0;
|
|
||||||
m_current.reset();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::Effect::load(const std::string& _file, const std::string& _name) {
|
void audio::ess::Effects::load(const std::string& _file, const std::string& _name) {
|
||||||
auto it = m_list.find(_name);
|
// load the file:
|
||||||
if (it != m_list.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::shared_ptr<audio::ess::LoadedFile> tmp = std::make_shared<audio::ess::LoadedFile>(_file, 2);
|
std::shared_ptr<audio::ess::LoadedFile> tmp = std::make_shared<audio::ess::LoadedFile>(_file, 2);
|
||||||
if (tmp == nullptr) {
|
if (tmp == nullptr) {
|
||||||
EWOLSA_ERROR("can not load audio Effect = " << _file);
|
EWOLSA_ERROR("can not load audio Effects = " << _file);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
m_list.insert(std::pair<std::string,std::shared_ptr<audio::ess::LoadedFile>>(_name,tmp));
|
int32_t id = -1;
|
||||||
|
for (size_t iii=0; iii<m_list.size(); ++iii) {
|
||||||
|
if (m_list[iii].first == _name) {
|
||||||
|
id = iii;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (-1 <= id) {
|
||||||
|
m_list.push_back(std::pair<std::string,std::shared_ptr<audio::ess::LoadedFile>>(_name,tmp));
|
||||||
|
} else {
|
||||||
|
m_list[id].second = tmp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::Effect::play(const std::string& _name) {
|
int32_t audio::ess::Effects::getId(const std::string& _name) {
|
||||||
auto it = m_list.find(_name);
|
|
||||||
if (it != m_list.end()) {
|
|
||||||
EWOLSA_ERROR("Can not Play Effect : " << _name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// in all case we stop the current playing Effect ...
|
|
||||||
stop();
|
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
m_next = *it;
|
for (size_t iii=0; iii<m_list.size(); ++iii) {
|
||||||
EWOLSA_INFO("Playing track " << (m_curent!=nullptr?-1:m_current->getUId()) << " request next : " << m_next->getUId());
|
if (m_list[iii].first == _name) {
|
||||||
}
|
|
||||||
|
|
||||||
void audio::ess::Effect::stop() {
|
|
||||||
if (m_curent == nullptr) {
|
|
||||||
EWOLSA_INFO("No current audio is playing");
|
|
||||||
}
|
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
|
||||||
m_curent.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio::ess::Effect::clear() {
|
|
||||||
stop();
|
|
||||||
m_current.reset();
|
|
||||||
m_next.reset();
|
|
||||||
m_position = 0;
|
|
||||||
m_list.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static std::mutex localMutex;
|
|
||||||
static bool effectsMute = false;
|
|
||||||
static float effectsVolume = 0;
|
|
||||||
static int32_t effectsVolumeApply = 1<<16;
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------
|
|
||||||
// Effects ...
|
|
||||||
//----------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class RequestPlay {
|
|
||||||
private:
|
|
||||||
bool m_freeSlot;
|
|
||||||
audio::ess::LoadedFile* m_effect; // reference to the effects
|
|
||||||
int32_t m_playTime; // position in sample playing in the audio effects
|
|
||||||
public :
|
|
||||||
RequestPlay(audio::ess::LoadedFile * _effect) :
|
|
||||||
m_freeSlot(false),
|
|
||||||
m_effect(_effect),
|
|
||||||
m_playTime(0) {
|
|
||||||
|
|
||||||
};
|
|
||||||
void reset(audio::ess::LoadedFile * _effect) {
|
|
||||||
m_effect=_effect;
|
|
||||||
m_playTime=0;
|
|
||||||
m_freeSlot=false;
|
|
||||||
};
|
|
||||||
bool isFree() {
|
|
||||||
return m_freeSlot;
|
|
||||||
};
|
|
||||||
void play(int16_t * _bufferInterlace, int32_t _nbSample, int32_t _nbChannels) {
|
|
||||||
if (true == m_freeSlot) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m_effect->m_data.size() == 0) {
|
|
||||||
m_freeSlot = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int32_t processTimeMax = std::min(_nbSample, m_effect->m_nbSamples - m_playTime);
|
|
||||||
processTimeMax = std::max(0, processTimeMax);
|
|
||||||
int16_t * pointer = _bufferInterlace;
|
|
||||||
int16_t * newData = &m_effect->m_data[m_playTime];
|
|
||||||
//EWOLSA_DEBUG("AUDIO : Play slot... nb sample : " << processTimeMax << " playTime=" <<m_playTime << " nbCannels=" << nbChannels);
|
|
||||||
for (int32_t iii=0; iii<processTimeMax; iii++) {
|
|
||||||
// TODO : set volume and spacialisation ...
|
|
||||||
for (int32_t jjj=0; jjj<_nbChannels; jjj++) {
|
|
||||||
int32_t tmppp = *pointer + ((((int32_t)*newData)*effectsVolumeApply)>>16);
|
|
||||||
*pointer = std::avg(-32767, tmppp, 32766);
|
|
||||||
//EWOLSA_DEBUG("AUDIO : element : " << *pointer);
|
|
||||||
pointer++;
|
|
||||||
}
|
|
||||||
newData++;
|
|
||||||
}
|
|
||||||
m_playTime += processTimeMax;
|
|
||||||
// check end of playing ...
|
|
||||||
if (m_effect->m_nbSamples <= m_playTime) {
|
|
||||||
m_freeSlot=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
std::vector<audio::ess::LoadedFile*> ListEffects;
|
|
||||||
std::vector<RequestPlay*> ListEffectsPlaying;
|
|
||||||
|
|
||||||
void audio::ess::effects::init() {
|
|
||||||
audio::ess::effects::volumeSet(0);
|
|
||||||
audio::ess::effects::muteSet(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio::ess::effects::unInit() {
|
|
||||||
audio::ess::effects::volumeSet(-1000);
|
|
||||||
audio::ess::effects::muteSet(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t audio::ess::effects::add(const std::string& _file) {
|
|
||||||
for (size_t iii=0; iii<ListEffects.size(); iii++) {
|
|
||||||
if (ListEffects[iii] == nullptr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (ListEffects[iii]->m_file == _file) {
|
|
||||||
ListEffects[iii]->m_requestedTime++;
|
|
||||||
return iii;
|
return iii;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// effect does not exist ... create a new one ...
|
m_list.push_back(std::pair<std::string,std::shared_ptr<audio::ess::LoadedFile>>(_name,nullptr));
|
||||||
audio::ess::LoadedFile * tmpEffect = new audio::ess::LoadedFile(_file);
|
EWOLSA_WARNING("Can not find element name : '" << _name << "' added it ... (empty) ");
|
||||||
if (nullptr == tmpEffect) {
|
return m_list.size()-1;
|
||||||
EWOLSA_ERROR("Error to load the effects : \"" << _file << "\"");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ListEffects.push_back(tmpEffect);
|
|
||||||
return ListEffects.size()-1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::effects::rm(int32_t _effectId) {
|
void audio::ess::Effects::play(int32_t _id, const vec3& _pos) {
|
||||||
// find element ...
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
if (_effectId <0 || _effectId >= (int64_t)ListEffects.size()) {
|
if ( _id < 0
|
||||||
EWOLSA_ERROR("Wrong effect ID : " << _effectId << " != [0.." << ListEffects.size()-1 << "] == > can not remove it ...");
|
|| _id >= m_list.size()) {
|
||||||
|
EWOLSA_ERROR(" Can not play element audio with ID=" << _id << " out of [0.." << m_list.size() << "[");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ListEffects[_effectId] == nullptr) {
|
m_playing.push_back(std::pair<std::shared_ptr<audio::ess::LoadedFile>, int32_t>(m_list[_id].second, 0));
|
||||||
EWOLSA_ERROR("effect ID : " << _effectId << " == > has already been removed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// check number of requested
|
|
||||||
if (ListEffects[_effectId]->m_requestedTime <= 0) {
|
|
||||||
EWOLSA_ERROR("effect ID : " << _effectId << " == > request more than predicted a removed of an effects");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ListEffects[_effectId]->m_requestedTime--;
|
|
||||||
// mark to be removed ... TODO : Really removed it when no other element readed it ...
|
|
||||||
// TODO : ...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void audio::ess::Effects::play(const std::string& _name, const vec3& _pos) {
|
||||||
void audio::ess::effects::play(int32_t _effectId, float _xxx, float _yyy) {
|
play(getId(_name),_pos);
|
||||||
if (_effectId <0 || _effectId >= (int64_t)ListEffects.size()) {
|
|
||||||
EWOLSA_ERROR("Wrong effect ID : " << _effectId << " != [0.." << ListEffects.size()-1 << "] == > can not play it ...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ListEffects[_effectId] == nullptr) {
|
|
||||||
EWOLSA_ERROR("effect ID : " << _effectId << " == > has been removed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EWOLSA_VERBOSE("effect play : " << _effectId );
|
|
||||||
// try to find an empty slot :
|
|
||||||
for (size_t iii=0; iii<ListEffectsPlaying.size(); iii++) {
|
|
||||||
if (ListEffectsPlaying[iii]->isFree()) {
|
|
||||||
ListEffectsPlaying[iii]->reset(ListEffects[_effectId]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RequestPlay* newPlay = new RequestPlay(ListEffects[_effectId]);
|
|
||||||
if (nullptr == newPlay) {
|
|
||||||
EWOLSA_CRITICAL("Allocation error of a playing element : " << _effectId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ListEffectsPlaying.push_back(newPlay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void audio::ess::Effects::stop() {
|
||||||
float audio::ess::effects::volumeGet() {
|
if (m_playing.size() == 0) {
|
||||||
return effectsVolume;
|
EWOLSA_INFO("No current audio is playing");
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uptateEffectVolume() {
|
|
||||||
if (effectsMute == true) {
|
|
||||||
effectsVolumeApply = 0;
|
|
||||||
} else {
|
|
||||||
// convert in an fixpoint value
|
|
||||||
// V2 = V1*10^(db/20)
|
|
||||||
double coef = pow(10, (effectsVolume/20) );
|
|
||||||
effectsVolumeApply = (int32_t)(coef * (double)(1<<16));
|
|
||||||
}
|
}
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
m_playing.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::effects::volumeSet(float _newVolume) {
|
void audio::ess::Effects::clear() {
|
||||||
effectsVolume = _newVolume;
|
stop();
|
||||||
effectsVolume = std::avg(-100.0f, effectsVolume, 20.0f);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
EWOLSA_INFO("Set Effect Volume at " << _newVolume << "dB == > " << effectsVolume << "dB");
|
m_list.clear();
|
||||||
uptateEffectVolume();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool audio::ess::effects::muteGet() {
|
|
||||||
return effectsMute;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void audio::ess::effects::muteSet(bool _newMute) {
|
|
||||||
effectsMute = _newMute;
|
|
||||||
EWOLSA_INFO("Set effects Mute at " << _newMute);
|
|
||||||
uptateEffectVolume();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void audio::ess::effects::getData(int16_t* _bufferInterlace, int32_t _nbSample, int32_t _nbChannels) {
|
|
||||||
for (size_t iii = 0; iii < ListEffectsPlaying.size(); ++iii) {
|
|
||||||
if (ListEffectsPlaying[iii]!= nullptr) {
|
|
||||||
ListEffectsPlaying[iii]->play(_bufferInterlace, _nbSample, _nbChannels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#define __EWOLSA_EFFECTS_H__
|
#define __EWOLSA_EFFECTS_H__
|
||||||
|
|
||||||
#include <etk/types.h>
|
#include <etk/types.h>
|
||||||
|
#include <etk/math/Vector3D.h>
|
||||||
#include <audio/river/Interface.h>
|
#include <audio/river/Interface.h>
|
||||||
#include <audio/river/Manager.h>
|
#include <audio/river/Manager.h>
|
||||||
#include <audio/ess/LoadedFile.h>
|
#include <audio/ess/LoadedFile.h>
|
||||||
@ -18,14 +19,14 @@
|
|||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
namespace ess {
|
namespace ess {
|
||||||
class Effect {
|
class Effects {
|
||||||
private:
|
private:
|
||||||
mutable std::mutex m_mutex;
|
mutable std::mutex m_mutex;
|
||||||
std::shared_ptr<audio::river::Manager> m_manager;
|
std::shared_ptr<audio::river::Manager> m_manager;
|
||||||
std::shared_ptr<audio::river::Interface> m_interface;
|
std::shared_ptr<audio::river::Interface> m_interface;
|
||||||
public:
|
public:
|
||||||
Effect(const std::shared_ptr<audio::river::Manager>& _manager);
|
Effects(const std::shared_ptr<audio::river::Manager>& _manager);
|
||||||
~Effect();
|
~Effects();
|
||||||
private:
|
private:
|
||||||
void onDataNeeded(void* _data,
|
void onDataNeeded(void* _data,
|
||||||
const audio::Time& _playTime,
|
const audio::Time& _playTime,
|
||||||
@ -38,8 +39,8 @@ namespace audio {
|
|||||||
public:
|
public:
|
||||||
void load(const std::string& _file, const std::string& _name);
|
void load(const std::string& _file, const std::string& _name);
|
||||||
int32_t getId(const std::string& _name);
|
int32_t getId(const std::string& _name);
|
||||||
void play(const std::string& _name, const vec3& pos = vec3(0,0,0));
|
void play(const std::string& _name, const vec3& _pos = vec3(0,0,0));
|
||||||
void play(int32_t _id, const vec3& pos = vec3(0,0,0));
|
void play(int32_t _id, const vec3& _pos = vec3(0,0,0));
|
||||||
void stop();
|
void stop();
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
@ -13,101 +13,142 @@
|
|||||||
#include <audio/river/Manager.h>
|
#include <audio/river/Manager.h>
|
||||||
#include <audio/ess/ess.h>
|
#include <audio/ess/ess.h>
|
||||||
#include <audio/ess/debug.h>
|
#include <audio/ess/debug.h>
|
||||||
|
#include <ejson/ejson.h>
|
||||||
|
|
||||||
|
#undef __class__
|
||||||
|
#define __class__ "audio::ess"
|
||||||
|
|
||||||
class OutputInterface {
|
std::shared_ptr<audio::river::Manager> g_audioManager;
|
||||||
private:
|
std::shared_ptr<audio::ess::Effects> g_effects;
|
||||||
std::shared_ptr<audio::river::Manager> m_manager;
|
std::shared_ptr<audio::ess::Music> g_music;
|
||||||
std::shared_ptr<audio::river::Interface> m_interface;
|
|
||||||
public:
|
|
||||||
OutputInterface() {
|
|
||||||
m_manager = audio::river::Manager::create("testApplication");
|
|
||||||
//Set stereo output:
|
|
||||||
std::vector<audio::channel> channelMap;
|
|
||||||
channelMap.push_back(audio::channel_frontLeft);
|
|
||||||
channelMap.push_back(audio::channel_frontRight);
|
|
||||||
m_interface = m_manager->createOutput(48000,
|
|
||||||
channelMap,
|
|
||||||
audio::format_int16,
|
|
||||||
"speaker");
|
|
||||||
if (m_interface == nullptr) {
|
|
||||||
EWOLSA_ERROR("can not allocate output interface ... ");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_interface->setName("audio::ess::basicOutput");
|
|
||||||
// set callback mode ...
|
|
||||||
m_interface->setOutputCallback(std::bind(&OutputInterface::onDataNeeded,
|
|
||||||
this,
|
|
||||||
std::placeholders::_1,
|
|
||||||
std::placeholders::_2,
|
|
||||||
std::placeholders::_3,
|
|
||||||
std::placeholders::_4,
|
|
||||||
std::placeholders::_5,
|
|
||||||
std::placeholders::_6));
|
|
||||||
m_interface->start();
|
|
||||||
}
|
|
||||||
~OutputInterface() {
|
|
||||||
if (m_interface == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_interface->stop();
|
|
||||||
m_interface.reset();
|
|
||||||
m_manager.reset();
|
|
||||||
}
|
|
||||||
void onDataNeeded(void* _data,
|
|
||||||
const audio::Time& _playTime,
|
|
||||||
const size_t& _nbChunk,
|
|
||||||
enum audio::format _format,
|
|
||||||
uint32_t _sampleRate,
|
|
||||||
const std::vector<audio::channel>& _map) {
|
|
||||||
if (_format != audio::format_int16) {
|
|
||||||
EWOLSA_ERROR("call wrong type ... (need int16_t)");
|
|
||||||
}
|
|
||||||
// call music
|
|
||||||
audio::ess::music::getData(static_cast<int16_t*>(_data), _nbChunk, _map.size());
|
|
||||||
// call Effects
|
|
||||||
audio::ess::effects::getData(static_cast<int16_t*>(_data), _nbChunk, _map.size());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::shared_ptr<OutputInterface> g_ioInterface;
|
|
||||||
|
|
||||||
void audio::ess::init() {
|
void audio::ess::init() {
|
||||||
g_ioInterface = std::make_shared<OutputInterface>();
|
g_audioManager = audio::river::Manager::create("ewol-sound-set");
|
||||||
|
g_effects = std::make_shared<audio::ess::Effects>(g_audioManager);
|
||||||
|
g_music = std::make_shared<audio::ess::Music>(g_audioManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::unInit() {
|
void audio::ess::unInit() {
|
||||||
g_ioInterface.reset();
|
g_effects.reset();
|
||||||
|
g_music.reset();
|
||||||
|
g_audioManager.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::loadSoundSet(const std::string& _data) {
|
void audio::ess::soundSetParse(const std::string& _data) {
|
||||||
|
ejson::Document doc;
|
||||||
|
doc.parse(_data);
|
||||||
|
std11::shared_ptr<ejson::Object> obj = doc.getObject("musics");
|
||||||
|
if ( obj != nullptr
|
||||||
|
&& g_music != nullptr) {
|
||||||
|
for (auto &it : obj->getKeys()) {
|
||||||
|
std::string file = obj->getStringValue(it);
|
||||||
|
EWOLSA_INFO("load Music : '" << it << "' file=" << file);
|
||||||
|
g_music->load(file, it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
obj = doc.getObject("effects");
|
||||||
|
if ( obj != nullptr
|
||||||
|
&& g_effects != nullptr) {
|
||||||
|
for (auto &it : obj->getKeys()) {
|
||||||
|
std::string file = obj->getStringValue(it);
|
||||||
|
EWOLSA_INFO("load Effect : '" << it << "' file=" << file);
|
||||||
|
g_effects->load(file, it);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::loadSoundSet(const etk::FSNode& _file) {
|
void audio::ess::soundSetLoad(const std::string& _file) {
|
||||||
|
soundSetParse(etk::FSNodeReadAllData(_file));
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::musicPlay(const std::string& _name) {
|
void audio::ess::musicPlay(const std::string& _name) {
|
||||||
|
if (g_music == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_music->play(_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::musicStop() {
|
void audio::ess::musicStop() {
|
||||||
|
if (g_music == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_music->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::musicVolume(float _dB) {
|
void audio::ess::musicSetVolume(float _dB) {
|
||||||
|
if (g_audioManager == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_audioManager->setVolume("MUSIC", _dB);
|
||||||
|
}
|
||||||
|
|
||||||
|
float audio::ess::musicGetVolume() {
|
||||||
|
if (g_audioManager == nullptr) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
return g_audioManager->getVolume("MUSIC");
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio::ess::musicSetMute(bool _mute) {
|
||||||
|
if (g_audioManager == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_audioManager->setMute("MUSIC", _mute);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool audio::ess::musicGetMute() {
|
||||||
|
if (g_audioManager == nullptr) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
return g_audioManager->getMute("MUSIC");
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t audio::ess::effectGetId(const std::string& _name) {
|
int32_t audio::ess::effectGetId(const std::string& _name) {
|
||||||
|
if (g_effects == nullptr) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
return g_effects->getId(_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::effectPlay(int32_t _name, const vec2& _pos=vec2(0,0)) {
|
void audio::ess::effectPlay(int32_t _id, const vec3& _pos) {
|
||||||
|
if (g_effects == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_effects->play(_id, _pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::effectPlay(const std::string& _name, const vec2& _pos=vec2(0,0)) {
|
void audio::ess::effectPlay(const std::string& _name, const vec3& _pos) {
|
||||||
|
if (g_effects == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_effects->play(_name, _pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio::ess::effectSetVolume(float _dB) {
|
||||||
|
if (g_audioManager == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_audioManager->setVolume("EFFECT", _dB);
|
||||||
|
}
|
||||||
|
|
||||||
|
float audio::ess::effectGetVolume() {
|
||||||
|
if (g_audioManager == nullptr) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
return g_audioManager->getVolume("EFFECT");
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio::ess::effectSetMute(bool _mute) {
|
||||||
|
if (g_audioManager == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_audioManager->setMute("EFFECT", _mute);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool audio::ess::effectGetMute() {
|
||||||
|
if (g_audioManager == nullptr) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
return g_audioManager->getMute("EFFECT");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,16 +19,23 @@ namespace audio {
|
|||||||
void init();
|
void init();
|
||||||
void unInit();
|
void unInit();
|
||||||
|
|
||||||
void loadSoundSet(const std::string& _data);
|
void soundSetParse(const std::string& _data);
|
||||||
void loadSoundSet(const etk::FSNode& _file);
|
void soundSetLoad(const std::string& _file);
|
||||||
|
|
||||||
void musicPlay(const std::string& _name);
|
void musicPlay(const std::string& _name);
|
||||||
void musicStop();
|
void musicStop();
|
||||||
void musicVolume(float _dB);
|
void musicSetVolume(float _dB);
|
||||||
|
float musicGetVolume();
|
||||||
|
void musicSetMute(bool _mute);
|
||||||
|
bool musicGetMute();
|
||||||
|
|
||||||
int32_t effectGetId(const std::string& _name);
|
int32_t effectGetId(const std::string& _name);
|
||||||
void effectPlay(int32_t _name, const vec2& _pos=vec2(0,0));
|
void effectPlay(int32_t _id, const vec3& _pos=vec3(0,0,0));
|
||||||
void effectPlay(const std::string& _name, const vec2& _pos=vec2(0,0));
|
void effectPlay(const std::string& _name, const vec3& _pos=vec3(0,0,0));
|
||||||
|
void effectSetVolume(float _dB);
|
||||||
|
float effectGetVolume();
|
||||||
|
void effectSetMute(bool _mute);
|
||||||
|
bool effectGetMute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
#include <audio/ess/LoadedFile.h>
|
#include <audio/ess/LoadedFile.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#undef __class__
|
||||||
|
#define __class__ "audio::ess::Music"
|
||||||
|
|
||||||
audio::ess::Music::Music(const std::shared_ptr<audio::river::Manager>& _manager) :
|
audio::ess::Music::Music(const std::shared_ptr<audio::river::Manager>& _manager) :
|
||||||
m_manager(_manager),
|
m_manager(_manager),
|
||||||
m_position(0) {
|
m_position(0) {
|
||||||
@ -41,11 +44,12 @@ audio::ess::Music::Music(const std::shared_ptr<audio::river::Manager>& _manager)
|
|||||||
std::placeholders::_4,
|
std::placeholders::_4,
|
||||||
std::placeholders::_5,
|
std::placeholders::_5,
|
||||||
std::placeholders::_6));
|
std::placeholders::_6));
|
||||||
|
m_interface->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
audio::ess::Music::~Music() {
|
audio::ess::Music::~Music() {
|
||||||
if (m_interface != nullptr) {
|
if (m_interface != nullptr) {
|
||||||
m_interface.stop();
|
m_interface->stop();
|
||||||
}
|
}
|
||||||
m_interface.reset();
|
m_interface.reset();
|
||||||
m_manager.reset();
|
m_manager.reset();
|
||||||
@ -66,21 +70,21 @@ void audio::ess::Music::onDataNeeded(void* _data,
|
|||||||
}
|
}
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
if (m_current != m_next) {
|
if (m_current != m_next) {
|
||||||
EWOLSA_INFO("change track " << (m_curent!=nullptr?-1:m_current->getUId()) << " ==> " << (m_next!=nullptr?-1:m_next->getUId()));
|
EWOLSA_INFO("change track " << (m_current==nullptr?-1:m_current->getUId()) << " ==> " << (m_next==nullptr?-1:m_next->getUId()));
|
||||||
m_curent = m_next;
|
m_current = m_next;
|
||||||
m_position = 0;
|
m_position = 0;
|
||||||
}
|
}
|
||||||
if (m_curent == nullptr) {
|
if (m_current == nullptr) {
|
||||||
// nothing to play ...
|
// nothing to play ...
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_current->m_data.size() == 0) {
|
if (m_current->m_data.size() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int32_t processTimeMax = std::min(_nbChunk*_map.size(), m_current->m_nbSamples - m_position);
|
int32_t processTimeMax = std::min(int32_t(_nbChunk*_map.size()), int32_t(m_current->m_nbSamples - m_position));
|
||||||
processTimeMax = std::max(0, processTimeMax);
|
processTimeMax = std::max(0, processTimeMax);
|
||||||
int16_t * pointer = static_cast<int16_t*>(_data);
|
int16_t * pointer = static_cast<int16_t*>(_data);
|
||||||
int16_t * newData = &m_current->m_data[m_posiion];
|
int16_t * newData = &m_current->m_data[m_position];
|
||||||
EWOLSA_DEBUG("AUDIO : Play slot... nb sample : " << processTimeMax << " map=" << _map << " _nbChunk=" << _nbChunk);
|
EWOLSA_DEBUG("AUDIO : Play slot... nb sample : " << processTimeMax << " map=" << _map << " _nbChunk=" << _nbChunk);
|
||||||
for (int32_t iii=0; iii<processTimeMax; iii++) {
|
for (int32_t iii=0; iii<processTimeMax; iii++) {
|
||||||
*pointer++ = *newData++;
|
*pointer++ = *newData++;
|
||||||
@ -109,23 +113,23 @@ void audio::ess::Music::load(const std::string& _file, const std::string& _name)
|
|||||||
|
|
||||||
void audio::ess::Music::play(const std::string& _name) {
|
void audio::ess::Music::play(const std::string& _name) {
|
||||||
auto it = m_list.find(_name);
|
auto it = m_list.find(_name);
|
||||||
if (it != m_list.end()) {
|
if (it == m_list.end()) {
|
||||||
EWOLSA_ERROR("Can not Play music : " << _name);
|
EWOLSA_ERROR("Can not Play music : " << _name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// in all case we stop the current playing music ...
|
// in all case we stop the current playing music ...
|
||||||
stop();
|
stop();
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
m_next = *it;
|
m_next = it->second;
|
||||||
EWOLSA_INFO("Playing track " << (m_curent!=nullptr?-1:m_current->getUId()) << " request next : " << m_next->getUId());
|
EWOLSA_INFO("Playing track " << (m_current==nullptr?-1:m_current->getUId()) << " request next : " << m_next->getUId());
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::Music::stop() {
|
void audio::ess::Music::stop() {
|
||||||
if (m_curent == nullptr) {
|
if (m_current == nullptr) {
|
||||||
EWOLSA_INFO("No current audio is playing");
|
EWOLSA_INFO("No current audio is playing");
|
||||||
}
|
}
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
m_curent.reset();
|
m_current.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio::ess::Music::clear() {
|
void audio::ess::Music::clear() {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <audio/river/Manager.h>
|
#include <audio/river/Manager.h>
|
||||||
#include <audio/ess/LoadedFile.h>
|
#include <audio/ess/LoadedFile.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
@ -43,7 +44,7 @@ namespace audio {
|
|||||||
void play(const std::string& _name);
|
void play(const std::string& _name);
|
||||||
void stop();
|
void stop();
|
||||||
void clear();
|
void clear();
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ def create(target):
|
|||||||
])
|
])
|
||||||
|
|
||||||
# name of the dependency
|
# name of the dependency
|
||||||
myModule.add_module_depend(['etk', 'audio-river', 'ogg'])
|
myModule.add_module_depend(['etk', 'audio-river', 'ogg', 'ejson'])
|
||||||
if target.name=="Android":
|
if target.name=="Android":
|
||||||
# TODO : Change this ...
|
# TODO : Change this ...
|
||||||
myModule.add_export_flag('c++', ["-pthread", "-frtti", "-fexceptions"])
|
myModule.add_export_flag('c++', ["-pthread", "-frtti", "-fexceptions"])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user