00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <sstream>
00026
00027
00028
00029
00030
00031
00032
00033 #include "util/base/exception.h"
00034 #include "util/log/logger.h"
00035 #include "loaders/native/audio/ogg_loader.h"
00036
00037 #include "soundclip.h"
00038
00039 namespace FIFE {
00040 static Logger _log(LM_AUDIO);
00041
00042 SoundClip::SoundClip(IResourceLoader* loader) :
00043 IResource(createUniqueClipName(), loader),
00044 m_isstream(false),
00045 m_decoder(NULL),
00046 m_deletedecoder(false) {
00047
00048 }
00049
00050 SoundClip::SoundClip(const std::string& name, IResourceLoader* loader) :
00051 IResource(name, loader),
00052 m_isstream(false),
00053 m_decoder(NULL),
00054 m_deletedecoder(false) {
00055
00056 }
00057
00058 void SoundClip::load(){
00059 if (m_loader){
00060 m_loader->load(this);
00061 }
00062 else {
00063 if(m_name.find(".ogg", m_name.size() - 4) != std::string::npos) {
00064 OggLoader loader;
00065 loader.load(this);
00066 } else {
00067 FL_WARN(_log, LMsg() << "No audio-decoder available for file \"" << m_name << "\"!");
00068 throw InvalidFormat("Error: Ogg loader can't load files without ogg extension");
00069 }
00070 }
00071
00072 assert(m_decoder);
00073
00074 m_isstream = m_decoder->needsStreaming();
00075
00076 if (!m_isstream) {
00077
00078
00079 SoundBufferEntry* ptr = new SoundBufferEntry();
00080
00081
00082 for (int32_t i = 0; i < BUFFER_NUM; i++) {
00083
00084 if (m_decoder->decode(BUFFER_LEN)) {
00085
00086 break;
00087 }
00088
00089
00090 alGenBuffers(1, &ptr->buffers[i]);
00091
00092 alBufferData(ptr->buffers[i], m_decoder->getALFormat(), m_decoder->getBuffer(),
00093 m_decoder->getBufferSize(), m_decoder->getSampleRate());
00094
00095 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error copying data to buffers")
00096
00097 ptr->usedbufs++;
00098 }
00099
00100 m_decoder->releaseBuffer();
00101
00102
00103 m_buffervec.push_back(ptr);
00104
00105 }
00106
00107 m_state = IResource::RES_LOADED;
00108 }
00109
00110 void SoundClip::free(){
00111 if (m_state == IResource::RES_LOADED) {
00112 if (m_isstream) {
00113
00114 std::vector<SoundBufferEntry*>::iterator it;
00115
00116 for (it = m_buffervec.begin(); it != m_buffervec.end(); ++it) {
00117 if ((*it)->buffers[0] != 0) {
00118 alDeleteBuffers(BUFFER_NUM, (*it)->buffers);
00119 }
00120 delete (*it);
00121 }
00122 m_buffervec.clear();
00123 }
00124 else {
00125
00126 SoundBufferEntry* ptr = m_buffervec.at(0);
00127
00128 for(uint32_t i = 0; i < ptr->usedbufs; i++) {
00129 alDeleteBuffers(1, &ptr->buffers[i]);
00130 }
00131 }
00132 }
00133 m_state = IResource::RES_NOT_LOADED;
00134 }
00135
00136 uint32_t SoundClip::beginStreaming() {
00137
00138 SoundBufferEntry* ptr = new SoundBufferEntry();
00139 ptr->usedbufs=0;
00140 alGenBuffers(BUFFER_NUM, ptr->buffers);
00141
00142 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error creating streaming-buffers")
00143
00144 m_buffervec.push_back(ptr);
00145
00146 return m_buffervec.size()-1;
00147 }
00148
00149 bool SoundClip::setStreamPos(uint32_t streamid, SoundPositionType type, float value) {
00150 uint64_t pos = 0;
00151
00152
00153 switch (type) {
00154 case SD_BYTE_POS:
00155 pos = static_cast<uint64_t>(value);
00156 break;
00157 case SD_TIME_POS:
00158 value *= m_decoder->getSampleRate();
00159 case SD_SAMPLE_POS:
00160 pos = static_cast<uint64_t>((m_decoder->getBitResolution() / 8) * (m_decoder->isStereo() ? 2 : 1) * value);
00161 break;
00162 }
00163
00164 if (pos > m_decoder->getDecodedLength()) {
00165
00166 return true;
00167 }
00168
00169
00170 m_buffervec.at(streamid)->deccursor = pos;
00171 return false;
00172 }
00173
00174 float SoundClip::getStreamPos(uint32_t streamid, SoundPositionType type) const{
00175 uint64_t pos = m_buffervec.at(streamid)->deccursor;
00176 switch(type) {
00177 case SD_BYTE_POS:
00178 return pos;
00179 case SD_SAMPLE_POS:
00180 return pos / (m_decoder->getBitResolution() / 8 * (m_decoder->isStereo() ? 2 : 1));
00181 case SD_TIME_POS:
00182 return pos / (m_decoder->getBitResolution() / 8 * (m_decoder->isStereo() ? 2 : 1) * m_decoder->getSampleRate());
00183 }
00184 return 0.0f;
00185 }
00186
00187 void SoundClip::acquireStream(uint32_t streamid) {
00188
00189 SoundBufferEntry* ptr = m_buffervec.at(streamid);
00190
00191 for (int32_t i = 0; i < BUFFER_NUM; i++) {
00192 getStream(streamid, ptr->buffers[i]);
00193 }
00194 }
00195
00196 bool SoundClip::getStream(uint32_t streamid, ALuint buffer) {
00197
00198 SoundBufferEntry* ptr = m_buffervec.at(streamid);
00199
00200 if (ptr->deccursor >= m_decoder->getDecodedLength()) {
00201
00202 return true;
00203 }
00204
00205
00206 m_decoder->setCursor(ptr->deccursor);
00207
00208
00209 if (m_decoder->decode(BUFFER_LEN)) {
00210 throw Exception("error while reading from audio file");
00211 }
00212
00213
00214 alBufferData(buffer, m_decoder->getALFormat(),
00215 m_decoder->getBuffer(), m_decoder->getBufferSize(), m_decoder->getSampleRate());
00216
00217 m_decoder->releaseBuffer();
00218
00219
00220 ptr->deccursor += BUFFER_LEN;
00221
00222 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error catching stream")
00223
00224 return false;
00225 }
00226
00227 void SoundClip::quitStreaming(uint32_t streamid) {
00228
00229 SoundBufferEntry* ptr = m_buffervec.at(streamid);
00230 alDeleteBuffers(BUFFER_NUM, ptr->buffers);
00231 ptr->buffers[0] = 0;
00232 }
00233
00234 SoundClip::~SoundClip() {
00235 free();
00236
00237
00238 if (m_deletedecoder && m_decoder != NULL) {
00239 delete m_decoder;
00240 }
00241 }
00242
00243 std::string SoundClip::createUniqueClipName() {
00244
00245 static uint32_t uniqueNumber = 0;
00246 static std::string baseName = "soundclip";
00247
00248 std::ostringstream oss;
00249 oss << uniqueNumber << "_" << baseName;
00250
00251 const std::string name = oss.str();
00252 ++uniqueNumber;
00253
00254 return name;
00255 }
00256 }