Fix "no remove aqua speed" bug when player leaves the water
[ryzomcore.git] / nel / src / sound / audio_decoder_vorbis.cpp
blob45a8da7f6575a9e2cce01281f42c68c4ac53c363
1 /**
2 * \file audio_decoder_vorbis.cpp
3 * \brief CAudioDecoderVorbis
4 * \date 2012-04-11 09:35GMT
5 * \author Jan Boon (Kaetemi)
6 * CAudioDecoderVorbis
7 */
9 // NeL - MMORPG Framework <https://wiki.ryzom.dev/>
10 // Copyright (C) 2008-2012 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
12 // This source file has been modified by the following contributors:
13 // Copyright (C) 2016 Winch Gate Property Limited
15 // This program is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU Affero General Public License as
17 // published by the Free Software Foundation, either version 3 of the
18 // License, or (at your option) any later version.
20 // This program is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 // GNU Affero General Public License for more details.
25 // You should have received a copy of the GNU Affero General Public License
26 // along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "stdsound.h"
29 #include <nel/sound/audio_decoder_vorbis.h>
31 // STL includes
33 // NeL includes
34 #include <nel/misc/debug.h>
36 // Project includes
38 using namespace std;
39 using namespace NLMISC;
41 namespace NLSOUND {
43 size_t vorbisReadFunc(void *ptr, size_t size, size_t nmemb, void *datasource)
45 CAudioDecoderVorbis *audio_decoder_vorbis = (CAudioDecoderVorbis *)datasource;
46 NLMISC::IStream *stream = audio_decoder_vorbis->getStream();
47 nlassert(stream->isReading());
48 sint32 length = (sint32)(size * nmemb);
49 if (length > audio_decoder_vorbis->getStreamSize() - stream->getPos())
50 length = audio_decoder_vorbis->getStreamSize() - stream->getPos();
51 stream->serialBuffer((uint8 *)ptr, length);
52 return length;
55 int vorbisSeekFunc(void *datasource, ogg_int64_t offset, int whence)
57 if (whence == SEEK_CUR && offset == 0)
59 // nlwarning(NLSOUND_XAUDIO2_PREFIX "This seek call doesn't do a damn thing, wtf.");
60 return 0; // ooookkaaaaaayyy
63 CAudioDecoderVorbis *audio_decoder_vorbis = (CAudioDecoderVorbis *)datasource;
65 NLMISC::IStream::TSeekOrigin origin;
66 switch (whence)
68 case SEEK_SET:
69 origin = NLMISC::IStream::begin;
70 break;
71 case SEEK_CUR:
72 origin = NLMISC::IStream::current;
73 break;
74 case SEEK_END:
75 origin = NLMISC::IStream::end;
76 break;
77 default:
78 // nlwarning(NLSOUND_XAUDIO2_PREFIX "Seeking to fake origin.");
79 return -1;
82 if (audio_decoder_vorbis->getStream()->seek(SEEK_SET ? audio_decoder_vorbis->getStreamOffset() + (sint32)offset : (sint32)offset, origin)) return 0;
83 else return -1;
86 //int vorbisCloseFunc(void *datasource)
87 //{
88 // //CAudioDecoderVorbis *audio_decoder_vorbis = (CAudioDecoderVorbis *)datasource;
89 //}
91 long vorbisTellFunc(void *datasource)
93 CAudioDecoderVorbis *audio_decoder_vorbis = (CAudioDecoderVorbis *)datasource;
94 return (long)(audio_decoder_vorbis->getStream()->getPos() - audio_decoder_vorbis->getStreamOffset());
97 static ov_callbacks OV_CALLBACKS_NLMISC_STREAM = {
98 (size_t (*)(void *, size_t, size_t, void *)) vorbisReadFunc,
99 (int (*)(void *, ogg_int64_t, int)) vorbisSeekFunc,
100 (int (*)(void *)) NULL, //vorbisCloseFunc,
101 (long (*)(void *)) vorbisTellFunc
104 CAudioDecoderVorbis::CAudioDecoderVorbis(NLMISC::IStream *stream, bool loop)
105 : _Stream(stream), _Loop(loop), _IsMusicEnded(false), _StreamSize(0)
107 _StreamOffset = stream->getPos();
108 stream->seek(0, NLMISC::IStream::end);
109 _StreamSize = stream->getPos();
110 stream->seek(_StreamOffset, NLMISC::IStream::begin);
111 ov_open_callbacks(this, &_OggVorbisFile, NULL, 0, OV_CALLBACKS_NLMISC_STREAM);
114 CAudioDecoderVorbis::~CAudioDecoderVorbis()
116 ov_clear(&_OggVorbisFile);
119 /// Get information on a music file (only artist and title at the moment).
120 bool CAudioDecoderVorbis::getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title, float &length)
122 CAudioDecoderVorbis mbv(stream, false); // just opens and closes the oggvorbisfile thing :)
123 vorbis_comment *vc = ov_comment(&mbv._OggVorbisFile, -1);
124 char *title_c = vorbis_comment_query(vc, "title", 0);
125 if (title_c) title = title_c; else title.clear();
126 char *artist_c = vorbis_comment_query(vc, "artist", 0);
127 if (artist_c) artist = artist_c; else artist.clear();
128 length = (float)ov_time_total(&mbv._OggVorbisFile, -1);
129 return true;
132 uint32 CAudioDecoderVorbis::getRequiredBytes()
134 return 0; // no minimum requirement of bytes to buffer out
137 uint32 CAudioDecoderVorbis::getNextBytes(uint8 *buffer, uint32 minimum, uint32 maximum)
139 sint current_section = 0; // ???
140 if (_IsMusicEnded) return 0;
141 nlassert(minimum <= maximum); // can't have this..
142 uint32 bytes_read = 0;
143 #ifdef NL_BIG_ENDIAN
144 sint endianness = 1;
145 #else
146 sint endianness = 0;
147 #endif
150 // signed 16-bit or unsigned 8-bit little-endian samples
151 sint br = ov_read(&_OggVorbisFile, (char *)&buffer[bytes_read], maximum - bytes_read,
152 endianness, // Specifies big or little endian byte packing. 0 for little endian, 1 for b ig endian. Typical value is 0.
153 getBitsPerSample() == 8 ? 1 : 2,
154 getBitsPerSample() == 8 ? 0 : 1, // Signed or unsigned data. 0 for unsigned, 1 for signed. Typically 1.
155 &current_section);
156 // nlinfo(NLSOUND_XAUDIO2_PREFIX "current_section: %i", current_section);
157 if (br > 0)
159 bytes_read += (uint32)br;
161 else if (br == 0) // EOF
163 if (_Loop)
165 ov_pcm_seek(&_OggVorbisFile, 0);
166 //_Stream->seek(0, NLMISC::IStream::begin);
168 else
170 _IsMusicEnded = true;
171 break;
174 else
176 // error
177 switch(br)
179 case OV_HOLE:
180 nlwarning("ov_read returned OV_HOLE");
181 break;
182 case OV_EINVAL:
183 nlwarning("ov_read returned OV_EINVAL");
184 break;
185 case OV_EBADLINK:
186 nlwarning("ov_read returned OV_EBADLINK");
187 break;
188 default:
189 nlwarning("ov_read returned %d", br);
192 } while (bytes_read < minimum);
193 return bytes_read;
196 uint8 CAudioDecoderVorbis::getChannels()
198 vorbis_info *vi = ov_info(&_OggVorbisFile, -1);
199 if (vi) return (uint8)vi->channels;
200 nlwarning("ov_info returned NULL");
201 return 0;
204 uint CAudioDecoderVorbis::getSamplesPerSec()
206 vorbis_info *vi = ov_info(&_OggVorbisFile, -1);
207 if (vi) return (uint)vi->rate;
208 nlwarning("ov_info returned NULL");
209 return 0;
212 uint8 CAudioDecoderVorbis::getBitsPerSample()
214 return 16;
217 bool CAudioDecoderVorbis::isMusicEnded()
219 return _IsMusicEnded;
222 float CAudioDecoderVorbis::getLength()
224 return (float)ov_time_total(&_OggVorbisFile, -1);
227 void CAudioDecoderVorbis::setLooping(bool loop)
229 _Loop = loop;
232 } /* namespace NLSOUND */
234 /* end of file */