FIFE  be64c707dea6b3250bd4355bf5c825d25920087d
sounddecoder_ogg.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2019 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 
26 // 3rd party library includes
27 
28 // FIFE includes
29 // These includes are split up in two parts, separated by one empty line
30 // First block: files included from the FIFE root src directory
31 // Second block: files included from the same folder
32 #include "util/log/logger.h"
33 #include "util/base/exception.h"
34 
35 #include "sounddecoder_ogg.h"
36 
37 namespace FIFE {
41  static Logger _log(LM_AUDIO);
42 
43  /* OggVorbis Callback functions
44  */
45  namespace OGG_cb {
46  static size_t read(void *ptr, size_t size, size_t nmemb, void *datasource) {
47  RawData* rdp = reinterpret_cast<RawData*>(datasource);
48  size_t restlen = rdp->getDataLength()-rdp->getCurrentIndex();
49  size_t len = (restlen<=size*nmemb)?restlen:size*nmemb;
50  if (len) {
51  rdp->readInto(reinterpret_cast<uint8_t *>(ptr), len);
52  }
53  return len;
54  }
55 
56  static int32_t seek(void *datasource, ogg_int64_t offset, int32_t whence) {
57  RawData* rdp = reinterpret_cast<RawData*>(datasource);
58  switch (whence) {
59  case SEEK_SET:
60  (*rdp).setIndex(static_cast<uint32_t>(offset));
61  return 0;
62  case SEEK_CUR:
63  (*rdp).moveIndex(static_cast<uint32_t>(offset));
64  return 0;
65  case SEEK_END:
66  (*rdp).setIndex( (*rdp).getDataLength() -1 + static_cast<uint32_t>(offset));
67  return 0;
68  }
69  return -1;
70  }
71 
72  static int32_t close(void *datasource) { return 0; }
73 
74  static long tell(void *datasource) {
75  RawData* rdp = reinterpret_cast<RawData*>(datasource);
76  return (*rdp).getCurrentIndex();
77  }
78  }
79 
81 
82  ov_callbacks ocb = {
84  };
85 
86  if (0 > ov_open_callbacks(m_file.get(), &m_ovf, 0, 0, ocb)) {
87  throw InvalidFormat("Error opening OggVorbis file");
88  }
89 
90 
91  vorbis_info* vi = ov_info(&m_ovf, -1);
92  if (!vi) {
93  throw InvalidFormat("Error fetching OggVorbis info");
94  }
95 
96  if (!ov_seekable(&m_ovf)) {
97  throw InvalidFormat("OggVorbis file has to be seekable");
98  }
99 
100  m_isstereo = vi->channels == 2;
101  m_samplerate = vi->rate;
102  m_is8bit = false;
103  m_declength = (m_isstereo ? 2 : 1) * 2 * ov_pcm_total(&m_ovf, -1);
104  m_datasize = 0;
105  m_data = NULL;
106  }
107 
109  releaseBuffer();
110  ov_clear(&m_ovf);
111  }
112 
113  bool SoundDecoderOgg::decode(uint64_t length) {
114  int32_t stream = 0;
115  int32_t ret = 0;
116 
117  // release buffer and allocate new memory
118  releaseBuffer();
119  m_data = new char[length];
120 
121  // decode the stream
122  m_datasize = 0;
123 
124  while (length-m_datasize > 0) {
125  ret = ov_read(&m_ovf, m_data + m_datasize, length-m_datasize, 0, 2, 1, &stream);
126  if (ret > 0) {
127  m_datasize += ret;
128  } else if (ret == OV_HOLE) {
129  continue;
130  } else if (ret == 0 || ret <= OV_EREAD) {
131  break;
132  }
133  }
134 
135  return m_datasize == 0;
136  }
137 
138  bool SoundDecoderOgg::setCursor(uint64_t pos) {
139  if (ov_pcm_seek(&m_ovf, pos / ((m_isstereo ? 2 : 1) * 2)) == 0) {
140  return true;
141  }
142  return false;
143  }
144 
146  if (m_data != NULL) {
147  delete[] m_data;
148  m_data = NULL;
149  }
150  }
151 }
static long tell(void *datasource)
static int32_t seek(void *datasource, ogg_int64_t offset, int32_t whence)
static Logger _log(LM_AUDIO)
uint32_t getDataLength() const
get the complete datalength
Definition: rawdata.cpp:75
void releaseBuffer()
Releases the buffer returned by getBuffer()
bool setCursor(uint64_t pos)
Sets the current position in the file (in bytes)
uint32_t getCurrentIndex() const
get the current index
Definition: rawdata.cpp:79
std::unique_ptr< RawData > m_file
static int32_t close(void *datasource)
void readInto(uint8_t *buffer, size_t len)
read len bytes into buffer
Definition: rawdata.cpp:94
SoundDecoderOgg(RawData *ptr)
void setIndex(uint32_t index)
set the current index
Definition: rawdata.cpp:83
unsigned int uint32_t
Definition: core.h:40
bool decode(uint64_t length)
Request the decoding of the next part of the stream.
Used to access diffrent kinds of data.
Definition: rawdata.h:48
static size_t read(void *ptr, size_t size, size_t nmemb, void *datasource)