Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/sound/SoundBuffer.cc @ 7858

Last change on this file since 7858 was 6502, checked in by rgrieder, 14 years ago

Removed a ton of msvc warnings revealed with OGRE v1.7 (they removed the warning suppressors in OgrePrerequisites.h).
All of them are conversions from one type to another that might be lossy (mostly double to float, please always use "3.7f" instead of "3.7" as constants when using floats).

  • Property svn:eol-style set to native
File size: 5.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Reto Grieder
24 *      Erwin 'vaiursch' Herrsche
25 *   Co-authors:
26 *      ...
27 *
28 */
29
30#include "SoundBuffer.h"
31
32#include <AL/alut.h>
33#include <vorbis/vorbisfile.h>
34
35#include "util/Exception.h"
36#include "util/StringUtils.h"
37#include "sound/SoundManager.h"
38
39namespace orxonox
40{
41    SoundBuffer::SoundBuffer(const std::string& filename, std::list<shared_ptr<SoundBuffer> >::iterator poolIterator)
42        : filename_(filename)
43        , audioBuffer_(AL_NONE)
44        , poolIterator_(poolIterator)
45    {
46        if (this->filename_.empty())
47            ThrowException(General, "SoundBuffer construction: fileInfo was NULL");
48
49        // Get resource info
50        shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(filename);
51        if (fileInfo == NULL)
52        {
53            COUT(2) << "Sound: Warning: Sound file '" << filename << "' not found" << std::endl;
54            return;
55        }
56        // Open data stream
57        DataStreamPtr dataStream = Resource::open(fileInfo);
58
59        const std::string& extension = this->filename_.substr(this->filename_.find_last_of('.') + 1);
60        if (getLowercase(extension) == "ogg")
61        {
62            // Try ogg loader
63            this->loadOgg(fileInfo, dataStream);
64        }
65        else
66        {
67            // Try standard OpenAL loader
68            this->loadStandard(fileInfo, dataStream);
69        }
70    }
71
72    SoundBuffer::~SoundBuffer()
73    {
74        // Destroy buffer
75        alDeleteBuffers(1, &this->audioBuffer_);
76    }
77
78    unsigned int SoundBuffer::getSize() const
79    {
80        ALint size;
81        alGetBufferi(this->audioBuffer_, AL_SIZE, &size);
82        return alGetError() ? 0 : size;
83    }
84
85    void SoundBuffer::loadStandard(const shared_ptr<ResourceInfo>& fileInfo, DataStreamPtr dataStream)
86    {
87        // Read everything into a temporary buffer
88        char* buffer = new char[fileInfo->size];
89        dataStream->read(buffer, fileInfo->size);
90        dataStream->seek(0);
91
92        this->audioBuffer_ = alutCreateBufferFromFileImage(buffer, fileInfo->size);
93        delete[] buffer;
94
95        if (!alIsBuffer(this->audioBuffer_))
96            ThrowException(General, "Sound Error: Standard file loader failed: " << alutGetErrorString(alutGetError()));
97    }
98
99    size_t readVorbis(void* ptr, size_t size, size_t nmemb, void* datasource)
100    {
101        return static_cast<Ogre::DataStream*>(datasource)->read(ptr, size * nmemb);
102    }
103
104    int seekVorbis(void* datasource, ogg_int64_t offset, int whence)
105    {
106        Ogre::DataStream* stream = static_cast<Ogre::DataStream*>(datasource);
107        switch (whence)
108        {
109        case SEEK_SET:
110            stream->seek((size_t)offset);
111            break;
112        case SEEK_CUR:
113            stream->skip((size_t)offset);
114            break;
115        case SEEK_END:
116            stream->seek(stream->size() + (size_t)offset);
117            break;
118        default:
119            return -1;
120        }
121        return 0;
122    }
123
124    long tellVorbis(void* datasource)
125    {
126        return static_cast<long>(static_cast<Ogre::DataStream*>(datasource)->tell());
127    }
128
129    void SoundBuffer::loadOgg(const shared_ptr<ResourceInfo>& fileInfo, DataStreamPtr dataStream)
130    {
131        char inbuffer[256*1024];
132        std::vector<char> outbuffer;
133        outbuffer.reserve(80*1024*1024);
134
135        // Open file with custom streaming
136        ov_callbacks vorbisCallbacks;
137        vorbisCallbacks.read_func  = &readVorbis;
138        vorbisCallbacks.seek_func  = &seekVorbis;
139        vorbisCallbacks.tell_func  = &tellVorbis;
140        vorbisCallbacks.close_func = NULL;
141
142        OggVorbis_File vf;
143        int ret = ov_open_callbacks(dataStream.get(), &vf, NULL, 0, vorbisCallbacks);
144        if (ret < 0)
145        {
146            COUT(2) << "Sound: libvorbisfile: File does not seem to be an Ogg Vorbis bitstream" << std::endl;
147            ov_clear(&vf);
148            ThrowException(General, "Sound Error: Ogg file loader failed when opening the bitstream");
149        }
150
151        int current_section;
152        int eof = false;
153        while (!eof)
154        {
155            long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
156            if (ret == 0)
157            {
158                eof = true;
159            }
160            else if (ret < 0)
161            {
162                COUT(2) << "Sound: libvorbisfile: error reading the file" << std::endl;
163                ov_clear(&vf);
164                ThrowException(General, "Sound Error: Ogg file loader failed when decoding the file");
165            }
166            else
167            {
168                outbuffer.insert(outbuffer.end(), inbuffer, inbuffer + ret);
169            }
170        }
171
172        vorbis_info* vorbisInfo;
173        vorbisInfo = ov_info(&vf, -1);
174        ALenum format;
175        if (vorbisInfo->channels == 1)
176            format = AL_FORMAT_MONO16;
177        else
178            format = AL_FORMAT_STEREO16;
179
180        alGenBuffers(1, &this->audioBuffer_);
181        alBufferData(this->audioBuffer_, format, &outbuffer[0], outbuffer.size(), vorbisInfo->rate);
182        ov_clear(&vf);
183
184        if (!alIsBuffer(this->audioBuffer_))
185            ThrowException(General, "Sound: Ogg file loader failed when creating the buffer.");
186    }
187}
Note: See TracBrowser for help on using the repository browser.