[DEV] good way to threaded load ogg file
This commit is contained in:
parent
e9b5966fb7
commit
078af947d9
@ -17,26 +17,28 @@
|
|||||||
ewolsa::LoadedFile::LoadedFile(const std::string& _fileName, int8_t _nbChanRequested) :
|
ewolsa::LoadedFile::LoadedFile(const std::string& _fileName, int8_t _nbChanRequested) :
|
||||||
m_file(_fileName),
|
m_file(_fileName),
|
||||||
m_nbSamples(0),
|
m_nbSamples(0),
|
||||||
|
m_nbSamplesTotal(0),
|
||||||
|
m_nbChanRequested(_nbChanRequested),
|
||||||
m_requestedTime(1),
|
m_requestedTime(1),
|
||||||
m_data(NULL){
|
m_data(NULL) {
|
||||||
std::string tmpName = std::tolower(_fileName);
|
m_stopRequested = false;
|
||||||
|
std::string tmpName = std::tolower(m_file);
|
||||||
// select the corect Loader :
|
// select the corect Loader :
|
||||||
if (end_with(tmpName, ".wav") == true) {
|
if (end_with(tmpName, ".wav") == true) {
|
||||||
m_data = ewolsa::wav::loadAudioFile(_fileName, _nbChanRequested, m_nbSamples);
|
m_data = ewolsa::wav::loadAudioFile(m_file, m_nbChanRequested, m_nbSamples);
|
||||||
|
m_nbSamplesTotal = m_nbSamples;
|
||||||
} else if (end_with(tmpName, ".ogg") == true) {
|
} else if (end_with(tmpName, ".ogg") == true) {
|
||||||
m_data = ewolsa::ogg::loadAudioFile(_fileName, _nbChanRequested, m_nbSamples);
|
pthread_create(&m_thread2, NULL, &ewolsa::ogg::loadFileThreadedMode, this);
|
||||||
} else {
|
} else {
|
||||||
EWOLSA_ERROR("Extention not managed '" << _fileName << "' Sopported extention : .wav / .ogg");
|
EWOLSA_ERROR("Extention not managed '" << m_file << "' Sopported extention : .wav / .ogg");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_data == NULL) {
|
|
||||||
// write an error ...
|
|
||||||
EWOLSA_ERROR("Can not open file : " << _fileName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ewolsa::LoadedFile::~LoadedFile(void) {
|
ewolsa::LoadedFile::~LoadedFile(void) {
|
||||||
|
m_stopRequested = true;
|
||||||
|
// TODO : wait end of thread...
|
||||||
if (m_data != NULL) {
|
if (m_data != NULL) {
|
||||||
delete[] m_data;
|
delete[] m_data;
|
||||||
m_data = NULL;
|
m_data = NULL;
|
||||||
|
@ -11,14 +11,21 @@
|
|||||||
#define __EWOLSA_LOADED_FILE_H__
|
#define __EWOLSA_LOADED_FILE_H__
|
||||||
|
|
||||||
#include <etk/types.h>
|
#include <etk/types.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
namespace ewolsa {
|
namespace ewolsa {
|
||||||
class LoadedFile {
|
class LoadedFile {
|
||||||
public :
|
private:
|
||||||
|
pthread_t m_thread2;
|
||||||
|
public:
|
||||||
|
bool m_stopRequested;
|
||||||
|
public:
|
||||||
LoadedFile(const std::string& _fileName, int8_t _nbChanRequested=1);
|
LoadedFile(const std::string& _fileName, int8_t _nbChanRequested=1);
|
||||||
~LoadedFile(void);
|
~LoadedFile(void);
|
||||||
std::string m_file;
|
std::string m_file;
|
||||||
int32_t m_nbSamples;
|
int32_t m_nbSamples;
|
||||||
|
int32_t m_nbSamplesTotal;
|
||||||
|
int32_t m_nbChanRequested;
|
||||||
int32_t m_requestedTime;
|
int32_t m_requestedTime;
|
||||||
int16_t* m_data;
|
int16_t* m_data;
|
||||||
public:
|
public:
|
||||||
|
@ -12,10 +12,12 @@
|
|||||||
#include <ewolsa/decOgg.h>
|
#include <ewolsa/decOgg.h>
|
||||||
#include <tremor/ivorbiscodec.h>
|
#include <tremor/ivorbiscodec.h>
|
||||||
#include <tremor/ivorbisfile.h>
|
#include <tremor/ivorbisfile.h>
|
||||||
|
#include <ewolsa/LoadedFile.h>
|
||||||
|
|
||||||
|
|
||||||
static size_t LocalReadFunc(void *ptr, size_t size, size_t nmemb, void *datasource) {
|
static size_t LocalReadFunc(void *ptr, size_t size, size_t nmemb, void *datasource) {
|
||||||
etk::FSNode* file = static_cast<etk::FSNode*>(datasource);
|
etk::FSNode* file = static_cast<etk::FSNode*>(datasource);
|
||||||
|
EWOLSA_DEBUG("read : " << size << " " << nmemb);
|
||||||
return file->fileRead(ptr, size, nmemb);
|
return file->fileRead(ptr, size, nmemb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,26 +61,27 @@ int16_t* ewolsa::ogg::loadAudioFile(const std::string& _filename, int8_t _nbChan
|
|||||||
};
|
};
|
||||||
etk::FSNode fileAccess(_filename);
|
etk::FSNode fileAccess(_filename);
|
||||||
// Start loading the XML :
|
// Start loading the XML :
|
||||||
EWOLSA_DEBUG("open file (OGG) \"" << fileAccess << "\"");
|
//EWOLSA_DEBUG("open file (OGG) \"" << fileAccess << "\"");
|
||||||
if (false == fileAccess.exist()) {
|
if (false == fileAccess.exist()) {
|
||||||
EWOLSA_ERROR("File Does not exist : \"" << fileAccess << "\"");
|
//EWOLSA_ERROR("File Does not exist : \"" << fileAccess << "\"");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
int32_t fileSize = fileAccess.fileSize();
|
int32_t fileSize = fileAccess.fileSize();
|
||||||
if (0 == fileSize) {
|
if (0 == fileSize) {
|
||||||
EWOLSA_ERROR("This file is empty : \"" << fileAccess << "\"");
|
//EWOLSA_ERROR("This file is empty : \"" << fileAccess << "\"");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (false == fileAccess.fileOpenRead()) {
|
if (false == fileAccess.fileOpenRead()) {
|
||||||
EWOLSA_ERROR("Can not open the file : \"" << fileAccess << "\"");
|
//EWOLSA_ERROR("Can not open the file : \"" << fileAccess << "\"");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (ov_open_callbacks(&fileAccess, &vf, NULL, 0, tmpCallback) < 0) {
|
if (ov_open_callbacks(&fileAccess, &vf, NULL, 0, tmpCallback) < 0) {
|
||||||
EWOLSA_ERROR("Input does not appear to be an Ogg bitstream.");
|
//EWOLSA_ERROR("Input does not appear to be an Ogg bitstream.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
vorbis_info *vi=ov_info(&vf,-1);
|
vorbis_info *vi=ov_info(&vf,-1);
|
||||||
_nbSampleOut = ov_pcm_total(&vf,-1) / vi->channels;
|
_nbSampleOut = ov_pcm_total(&vf,-1) / vi->channels;
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
char **ptr=ov_comment(&vf,-1)->user_comments;
|
char **ptr=ov_comment(&vf,-1)->user_comments;
|
||||||
while(*ptr){
|
while(*ptr){
|
||||||
@ -90,9 +93,10 @@ int16_t* ewolsa::ogg::loadAudioFile(const std::string& _filename, int8_t _nbChan
|
|||||||
EWOLSA_DEBUG("Encoded by: " << ov_comment(&vf,-1)->vendor);
|
EWOLSA_DEBUG("Encoded by: " << ov_comment(&vf,-1)->vendor);
|
||||||
EWOLSA_DEBUG("time: " << ((float)_nbSampleOut/(float)vi->rate)/60.0);
|
EWOLSA_DEBUG("time: " << ((float)_nbSampleOut/(float)vi->rate)/60.0);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
int16_t* outputData = new int16_t[_nbSampleOut*_nbChan*sizeof(int16_t)];
|
int16_t* outputData = new int16_t[_nbSampleOut*_nbChan*sizeof(int16_t)];
|
||||||
if (NULL == outputData) {
|
if (NULL == outputData) {
|
||||||
EWOLSA_ERROR("Allocation ERROR try to allocate " << (int32_t)(_nbSampleOut*_nbChan*sizeof(int16_t) ) << "bytes");
|
//EWOLSA_ERROR("Allocation ERROR try to allocate " << (int32_t)(_nbSampleOut*_nbChan*sizeof(int16_t) ) << "bytes");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
int32_t pos = 0;
|
int32_t pos = 0;
|
||||||
@ -104,7 +108,7 @@ int16_t* ewolsa::ogg::loadAudioFile(const std::string& _filename, int8_t _nbChan
|
|||||||
eof=1;
|
eof=1;
|
||||||
} else if (ret < 0) {
|
} else if (ret < 0) {
|
||||||
if(ret==OV_EBADLINK){
|
if(ret==OV_EBADLINK){
|
||||||
EWOLSA_ERROR("Corrupt bitstream section! Exiting.");
|
//EWOLSA_ERROR("Corrupt bitstream section! Exiting.");
|
||||||
// TODO : Remove pointer data ...
|
// TODO : Remove pointer data ...
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -129,7 +133,7 @@ int16_t* ewolsa::ogg::loadAudioFile(const std::string& _filename, int8_t _nbChan
|
|||||||
}
|
}
|
||||||
pos += ret;
|
pos += ret;
|
||||||
} else {
|
} else {
|
||||||
EWOLSA_ERROR("Can not convert " << (int32_t)vi->channels << " channels in " << _nbChan << " channels");
|
//EWOLSA_ERROR("Can not convert " << (int32_t)vi->channels << " channels in " << _nbChan << " channels");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fwrite(pcmout,1,ret,stdout);
|
// fwrite(pcmout,1,ret,stdout);
|
||||||
@ -138,7 +142,113 @@ int16_t* ewolsa::ogg::loadAudioFile(const std::string& _filename, int8_t _nbChan
|
|||||||
}
|
}
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
ov_clear(&vf);
|
ov_clear(&vf);
|
||||||
EWOLSA_DEBUG("Done.");
|
//EWOLSA_DEBUG("Done.");
|
||||||
return outputData;
|
return outputData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* ewolsa::ogg::loadFileThreadedMode(void *_ptr) {
|
||||||
|
ewolsa::LoadedFile* self = (ewolsa::LoadedFile*)_ptr;
|
||||||
|
if (self == NULL) {
|
||||||
|
EWOLSA_ERROR("NULL handle");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
self->m_data = NULL;
|
||||||
|
self->m_nbSamples = 0;
|
||||||
|
self->m_nbSamplesTotal = 0;
|
||||||
|
OggVorbis_File vf;
|
||||||
|
int32_t current_section;
|
||||||
|
ov_callbacks tmpCallback = {
|
||||||
|
LocalReadFunc,
|
||||||
|
localSeekFunc,
|
||||||
|
localCloseFunc,
|
||||||
|
localTellFunc
|
||||||
|
};
|
||||||
|
EWOLSA_WARNING("open file (OGG) '" << self->m_file << "'");
|
||||||
|
etk::FSNode fileAccess(self->m_file);
|
||||||
|
// Start loading the XML :
|
||||||
|
if (false == fileAccess.exist()) {
|
||||||
|
EWOLSA_ERROR("File Does not exist : '" << fileAccess << "'");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
int32_t fileSize = fileAccess.fileSize();
|
||||||
|
if (0 == fileSize) {
|
||||||
|
EWOLSA_ERROR("This file is empty : '" << fileAccess << "'");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
EWOLSA_WARNING("ogg file size = " << fileSize);
|
||||||
|
if (false == fileAccess.fileOpenRead()) {
|
||||||
|
EWOLSA_ERROR("Can not open the file : '" << fileAccess << "'");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (ov_open_callbacks(&fileAccess, &vf, NULL, 0, tmpCallback) < 0) {
|
||||||
|
EWOLSA_ERROR("Input does not appear to be an Ogg bitstream.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
vorbis_info *vi=ov_info(&vf,-1);
|
||||||
|
self->m_nbSamplesTotal = ov_pcm_total(&vf,-1) / vi->channels;
|
||||||
|
{
|
||||||
|
char **ptr=ov_comment(&vf,-1)->user_comments;
|
||||||
|
while(*ptr){
|
||||||
|
EWOLSA_DEBUG("comment : " << *ptr);
|
||||||
|
++ptr;
|
||||||
|
}
|
||||||
|
EWOLSA_DEBUG("Bitstream is " << (int32_t)vi->channels << " channel, " << (int32_t)vi->rate << "Hz");
|
||||||
|
EWOLSA_DEBUG("Decoded length: " << self->m_nbSamplesTotal << " samples");
|
||||||
|
EWOLSA_DEBUG("Encoded by: " << ov_comment(&vf,-1)->vendor);
|
||||||
|
EWOLSA_DEBUG("time: " << ((float)self->m_nbSamplesTotal/(float)vi->rate)/60.0);
|
||||||
|
}
|
||||||
|
self->m_data = new int16_t[self->m_nbSamplesTotal*self->m_nbChanRequested*sizeof(int16_t)];
|
||||||
|
if (NULL == self->m_data) {
|
||||||
|
EWOLSA_ERROR("Allocation ERROR try to allocate " << (int32_t)(self->m_nbSamplesTotal*self->m_nbChanRequested*sizeof(int16_t) ) << "bytes");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->m_nbSamples = 0;
|
||||||
|
char pcmout[4096];
|
||||||
|
bool eof = false;
|
||||||
|
while ( eof == false
|
||||||
|
&& self->m_stopRequested == false) {
|
||||||
|
long ret=ov_read(&vf, pcmout, sizeof(pcmout), ¤t_section);
|
||||||
|
if (ret == 0) {
|
||||||
|
/* EOF */
|
||||||
|
eof = true;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
if(ret==OV_EBADLINK){
|
||||||
|
EWOLSA_ERROR("Corrupt bitstream section! Exiting.");
|
||||||
|
// TODO : Remove pointer data ...
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int16_t* pointerIn = (int16_t*)pcmout;
|
||||||
|
int16_t* pointerOut = self->m_data+self->m_nbSamples;
|
||||||
|
if (self->m_nbChanRequested == vi->channels) {
|
||||||
|
memcpy(pointerOut, pointerIn, ret);
|
||||||
|
self->m_nbSamples += ret/2;
|
||||||
|
} else {
|
||||||
|
if ( self->m_nbChanRequested == 1
|
||||||
|
&& vi->channels == 2) {
|
||||||
|
for (int32_t iii=0; iii<ret/4 ; ++iii) {
|
||||||
|
pointerOut[iii] = pointerIn[iii*2];
|
||||||
|
}
|
||||||
|
self->m_nbSamples += ret/4;
|
||||||
|
} else if ( self->m_nbChanRequested == 2
|
||||||
|
&& vi->channels == 1) {
|
||||||
|
for (int32_t iii=0; iii<ret/2 ; ++iii) {
|
||||||
|
pointerOut[iii*2] = pointerIn[iii];
|
||||||
|
pointerOut[iii*2+1] = pointerIn[iii];
|
||||||
|
}
|
||||||
|
self->m_nbSamples += ret;
|
||||||
|
} else {
|
||||||
|
EWOLSA_ERROR("Can not convert " << (int32_t)vi->channels << " channels in " << self->m_nbChanRequested << " channels");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fwrite(pcmout,1,ret,stdout);
|
||||||
|
EWOLSA_DEBUG("get data : " << (int32_t)ret << " Bytes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* cleanup */
|
||||||
|
ov_clear(&vf);
|
||||||
|
EWOLSA_DEBUG("Done.");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
namespace ewolsa {
|
namespace ewolsa {
|
||||||
namespace ogg {
|
namespace ogg {
|
||||||
int16_t* loadAudioFile(const std::string& _filename, int8_t _nbChan, int32_t& _nbSampleOut);
|
int16_t* loadAudioFile(const std::string& _filename, int8_t _nbChan, int32_t& _nbSampleOut);
|
||||||
|
void* loadFileThreadedMode(void *_ptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,11 +80,12 @@ void ewolsa::music::preLoad(const std::string& _file) {
|
|||||||
}
|
}
|
||||||
ewolsa::LoadedFile* tmp = new ewolsa::LoadedFile(_file, 2);
|
ewolsa::LoadedFile* tmp = new ewolsa::LoadedFile(_file, 2);
|
||||||
if (tmp != NULL) {
|
if (tmp != NULL) {
|
||||||
|
/*
|
||||||
if (tmp->m_data == NULL) {
|
if (tmp->m_data == NULL) {
|
||||||
EWOLSA_ERROR("Music has no data ... : " << _file);
|
EWOLSA_ERROR("Music has no data ... : " << _file);
|
||||||
delete(tmp);
|
delete(tmp);
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
std::unique_lock<std::mutex> lck(localMutex);
|
std::unique_lock<std::mutex> lck(localMutex);
|
||||||
musicListRead.push_back(tmp);
|
musicListRead.push_back(tmp);
|
||||||
} else {
|
} else {
|
||||||
@ -187,6 +188,9 @@ void ewolsa::music::getData(int16_t * _bufferInterlace, int32_t _nbSample, int32
|
|||||||
EWOLSA_ERROR("request read an unexisting audio track ... : " << musicCurrentRead << "/" << musicListRead.size());
|
EWOLSA_ERROR("request read an unexisting audio track ... : " << musicCurrentRead << "/" << musicListRead.size());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (musicListRead[musicCurrentRead]->m_data == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int32_t processTimeMax = etk_min(_nbSample*_nbChannels, musicListRead[musicCurrentRead]->m_nbSamples - musicPositionReading);
|
int32_t processTimeMax = etk_min(_nbSample*_nbChannels, musicListRead[musicCurrentRead]->m_nbSamples - musicPositionReading);
|
||||||
processTimeMax = etk_max(0, processTimeMax);
|
processTimeMax = etk_max(0, processTimeMax);
|
||||||
int16_t * pointer = _bufferInterlace;
|
int16_t * pointer = _bufferInterlace;
|
||||||
|
@ -22,6 +22,8 @@ def create(target):
|
|||||||
|
|
||||||
# name of the dependency
|
# name of the dependency
|
||||||
myModule.add_module_depend(['ewol', 'airtaudio', 'ogg'])
|
myModule.add_module_depend(['ewol', 'airtaudio', 'ogg'])
|
||||||
|
if target.name=="Android":
|
||||||
|
myModule.add_export_flag_CC("-pthread -frtti -fexceptions")
|
||||||
|
|
||||||
myModule.add_export_path(tools.get_current_path(__file__))
|
myModule.add_export_path(tools.get_current_path(__file__))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user