FIFE
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
soundclip.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2013 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"
36 
37 #include "soundclip.h"
38 
39 namespace FIFE {
40  static Logger _log(LM_AUDIO);
41 
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 
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 
75 
76  if (!m_isstream) {
77 
78  // only for non-streaming buffers
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(),
94 
95  CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error copying data to buffers")
96 
97  ptr->usedbufs++;
98  }
99 
101 
102  // push the buffer information to the vector
103  m_buffervec.push_back(ptr);
104 
105  }
106 
108  }
109 
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  }
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 
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 
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
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(),
216 
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 
228  // release the buffers
229  SoundBufferEntry* ptr = m_buffervec.at(streamid);
230  alDeleteBuffers(BUFFER_NUM, ptr->buffers);
231  ptr->buffers[0] = 0;
232  }
233 
235  free();
236 
237  // delete decoder
238  if (m_deletedecoder && m_decoder != NULL) {
239  delete m_decoder;
240  }
241  }
242 
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 }
#define FL_WARN(logger, msg)
Definition: logger.h:72
const uint32_t BUFFER_LEN
Definition: soundconfig.h:46
bool getStream(uint32_t streamid, ALuint buffer)
Refill a processed buffer with new data.
Definition: soundclip.cpp:196
bool m_deletedecoder
Definition: soundclip.h:144
ALuint buffers[BUFFER_NUM]
Definition: soundclip.h:51
Helper class to create log strings out from separate parts Usage: LMsg(&quot;some text&quot;) &lt;&lt; variable &lt;&lt; &quot;...
Definition: logger.h:82
virtual void releaseBuffer()=0
Releases the buffer returned by getBuffer()
bool isStereo() const
Tests if the audio data is stereo data or mono.
Definition: sounddecoder.h:92
IResourceLoader * m_loader
Definition: resource.h:80
static Logger _log(LM_AUDIO)
#define CHECK_OPENAL_LOG(logger, level, msg)
Definition: fife_openal.h:61
virtual uint64_t getBufferSize()=0
Returns the byte-size of the buffer returned by getBuffer().
virtual void load()
Definition: soundclip.cpp:58
Exception base class.
Definition: exception.h:43
virtual void * getBuffer() const =0
Returns the next decoded buffer.
virtual bool decode(uint64_t length)=0
Request the decoding of the next part of the stream.
virtual void free()
Definition: soundclip.cpp:110
bool needsStreaming() const
A stream or not?
Definition: sounddecoder.h:59
void acquireStream(uint32_t streamid)
Fills the streaming-buffers with initial data.
Definition: soundclip.cpp:187
SoundPositionType
Different types of audio-file positions.
Definition: soundclip.h:44
uint32_t usedbufs
Definition: soundclip.h:52
virtual uint64_t getDecodedLength() const =0
Returns the decoded length of the file in bytes.
std::string createUniqueClipName()
Definition: soundclip.cpp:243
int16_t getBitResolution() const
Returns the bit resolution.
Definition: sounddecoder.h:108
std::string m_name
Definition: resource.h:79
Definition: soundclip.h:50
float getStreamPos(uint32_t streamid, SoundPositionType type) const
Gets the stream position.
Definition: soundclip.cpp:174
ResourceState m_state
Definition: resource.h:81
virtual bool setCursor(uint64_t pos)=0
Sets the current position in the file (in bytes)
uint64_t getSampleRate() const
Returns the sample rate.
Definition: sounddecoder.h:114
std::vector< SoundBufferEntry * > m_buffervec
Definition: soundclip.h:145
void quitStreaming(uint32_t streamid)
Quits Streaming.
Definition: soundclip.cpp:227
uint64_t deccursor
Definition: soundclip.h:53
virtual void load(IResource *res)
Definition: ogg_loader.cpp:43
SoundClip(IResourceLoader *loader=0)
Definition: soundclip.cpp:42
virtual void load(IResource *resource)=0
const int16_t BUFFER_NUM
Definition: soundconfig.h:43
Create a Logger instance to communicate with LogManager Logger stores information about the current m...
Definition: logger.h:211
unsigned int uint32_t
Definition: core.h:40
SoundDecoder * m_decoder
Definition: soundclip.h:143
bool setStreamPos(uint32_t streamid, SoundPositionType type, float value)
Sets the stream position.
Definition: soundclip.cpp:149
uint32_t beginStreaming()
Starts streaming the soundclip.
Definition: soundclip.cpp:136
ALenum getALFormat() const
Returns the openAL-Format of the audio file.
Definition: sounddecoder.h:98