FIFE  2008.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
soundclip.cpp
1 /***************************************************************************
2  * Copyright (C) 2005-2011 by the FIFE team *
3  * http://www.fifengine.net *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 
24 // Platform specific includes
25 #include <sstream>
26 
27 // 3rd party library includes
28 
29 // FIFE includes
30 // These includes are split up in two parts, separated by one empty line
31 // First block: files included from the FIFE root src directory
32 // Second block: files included from the same folder
33 #include "util/base/exception.h"
34 #include "util/log/logger.h"
35 #include "loaders/native/audio/ogg_loader.h"
36 
37 #include "soundclip.h"
38 
39 namespace FIFE {
40  static Logger _log(LM_AUDIO);
41 
42  SoundClip::SoundClip(IResourceLoader* loader) :
43  IResource(createUniqueClipName(), loader),
44  m_isstream(false),
45  m_decoder(NULL),
46  m_deletedecoder(false) {
47 
48  }
49 
50  SoundClip::SoundClip(const std::string& name, IResourceLoader* loader) :
51  IResource(name, loader),
52  m_isstream(false),
53  m_decoder(NULL),
54  m_deletedecoder(false) {
55 
56  }
57 
58  void SoundClip::load(){
59  if (m_loader){
60  m_loader->load(this);
61  }
62  else { //no loader specified so find one to use
63  if(m_name.find(".ogg", m_name.size() - 4) != std::string::npos) {
64  OggLoader loader;
65  loader.load(this);
66  } else {
67  FL_WARN(_log, LMsg() << "No audio-decoder available for file \"" << m_name << "\"!");
68  throw InvalidFormat("Error: Ogg loader can't load files without ogg extension");
69  }
70  }
71 
72  assert(m_decoder); //should be set by now
73 
74  m_isstream = m_decoder->needsStreaming();
75 
76  if (!m_isstream) {
77 
78  // only for non-streaming buffers
79  SoundBufferEntry* ptr = new SoundBufferEntry();
80 
81  // iterate the bufs and fill them with data
82  for (int32_t i = 0; i < BUFFER_NUM; i++) {
83 
84  if (m_decoder->decode(BUFFER_LEN)) {
85  // EOF or error
86  break;
87  }
88 
89  // generate buffer and fill it with data
90  alGenBuffers(1, &ptr->buffers[i]);
91 
92  alBufferData(ptr->buffers[i], m_decoder->getALFormat(), m_decoder->getBuffer(),
93  m_decoder->getBufferSize(), m_decoder->getSampleRate());
94 
95  CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error copying data to buffers")
96 
97  ptr->usedbufs++;
98  }
99 
100  m_decoder->releaseBuffer();
101 
102  // push the buffer information to the vector
103  m_buffervec.push_back(ptr);
104 
105  }
106 
107  m_state = IResource::RES_LOADED;
108  }
109 
110  void SoundClip::free(){
111  if (m_state == IResource::RES_LOADED) {
112  if (m_isstream) {
113  // erase all elements from the list
114  std::vector<SoundBufferEntry*>::iterator it;
115 
116  for (it = m_buffervec.begin(); it != m_buffervec.end(); ++it) {
117  if ((*it)->buffers[0] != 0) {
118  alDeleteBuffers(BUFFER_NUM, (*it)->buffers);
119  }
120  delete (*it);
121  }
122  m_buffervec.clear();
123  }
124  else {
125  // for non-streaming soundclips
126  SoundBufferEntry* ptr = m_buffervec.at(0);
127 
128  for(uint32_t i = 0; i < ptr->usedbufs; i++) {
129  alDeleteBuffers(1, &ptr->buffers[i]);
130  }
131  }
132  }
133  m_state = IResource::RES_NOT_LOADED;
134  }
135 
137  // create new sound buffer entry
138  SoundBufferEntry* ptr = new SoundBufferEntry();
139  ptr->usedbufs=0;
140  alGenBuffers(BUFFER_NUM, ptr->buffers);
141 
142  CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error creating streaming-buffers")
143 
144  m_buffervec.push_back(ptr);
145 
146  return m_buffervec.size()-1;
147  }
148 
149  bool SoundClip::setStreamPos(uint32_t streamid, SoundPositionType type, float value) {
150  uint64_t pos = 0;
151 
152  // convert position to bytes
153  switch (type) {
154  case SD_BYTE_POS:
155  pos = static_cast<uint64_t>(value);
156  break;
157  case SD_TIME_POS:
158  value *= m_decoder->getSampleRate();
159  case SD_SAMPLE_POS:
160  pos = static_cast<uint64_t>((m_decoder->getBitResolution() / 8) * (m_decoder->isStereo() ? 2 : 1) * value);
161  break;
162  }
163 
164  if (pos > m_decoder->getDecodedLength()) {
165  // EOF!
166  return true;
167  }
168 
169  // set cursor position
170  m_buffervec.at(streamid)->deccursor = pos;
171  return false;
172  }
173 
174  float SoundClip::getStreamPos(uint32_t streamid, SoundPositionType type) const{
175  uint64_t pos = m_buffervec.at(streamid)->deccursor;
176  switch(type) {
177  case SD_BYTE_POS:
178  return pos;
179  case SD_SAMPLE_POS:
180  return pos / (m_decoder->getBitResolution() / 8 * (m_decoder->isStereo() ? 2 : 1));
181  case SD_TIME_POS:
182  return pos / (m_decoder->getBitResolution() / 8 * (m_decoder->isStereo() ? 2 : 1) * m_decoder->getSampleRate());
183  }
184  return 0.0f;
185  }
186 
187  void SoundClip::acquireStream(uint32_t streamid) {
188 
189  SoundBufferEntry* ptr = m_buffervec.at(streamid);
190 
191  for (int32_t i = 0; i < BUFFER_NUM; i++) {
192  getStream(streamid, ptr->buffers[i]);
193  }
194  }
195 
196  bool SoundClip::getStream(uint32_t streamid, ALuint buffer) {
197 
198  SoundBufferEntry* ptr = m_buffervec.at(streamid);
199 
200  if (ptr->deccursor >= m_decoder->getDecodedLength()) {
201  // EOF!
202  return true;
203  }
204 
205  // set cursor of decoder
206  m_decoder->setCursor(ptr->deccursor);
207 
208  // Error while decoding file?
209  if (m_decoder->decode(BUFFER_LEN)) {
210  throw Exception("error while reading from audio file");
211  }
212 
213  // fill the buffer with data
214  alBufferData(buffer, m_decoder->getALFormat(),
215  m_decoder->getBuffer(), m_decoder->getBufferSize(), m_decoder->getSampleRate());
216 
217  m_decoder->releaseBuffer();
218 
219  // update cursor
220  ptr->deccursor += BUFFER_LEN;
221 
222  CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error catching stream")
223 
224  return false;
225  }
226 
227  void SoundClip::quitStreaming(uint32_t streamid) {
228  // release the buffers
229  SoundBufferEntry* ptr = m_buffervec.at(streamid);
230  alDeleteBuffers(BUFFER_NUM, ptr->buffers);
231  ptr->buffers[0] = 0;
232  }
233 
234  SoundClip::~SoundClip() {
235  free();
236 
237  // delete decoder
238  if (m_deletedecoder && m_decoder != NULL) {
239  delete m_decoder;
240  }
241  }
242 
243  std::string SoundClip::createUniqueClipName() {
244  // automated counting for name generation, in case the user doesn't provide a name
245  static uint32_t uniqueNumber = 0;
246  static std::string baseName = "soundclip";
247 
248  std::ostringstream oss;
249  oss << uniqueNumber << "_" << baseName;
250 
251  const std::string name = oss.str();
252  ++uniqueNumber;
253 
254  return name;
255  }
256 }
bool getStream(uint32_t streamid, ALuint buffer)
Definition: soundclip.cpp:196
void acquireStream(uint32_t streamid)
Definition: soundclip.cpp:187
SoundPositionType
Definition: soundclip.h:44
float getStreamPos(uint32_t streamid, SoundPositionType type) const
Definition: soundclip.cpp:174
void quitStreaming(uint32_t streamid)
Definition: soundclip.cpp:227
bool setStreamPos(uint32_t streamid, SoundPositionType type, float value)
Definition: soundclip.cpp:149
uint32_t beginStreaming()
Definition: soundclip.cpp:136