Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/sound5/src/orxonox/sound/SoundStreamer.cc @ 6767

Last change on this file since 6767 was 6733, checked in by erwin, 15 years ago

Added some hacks, now the source is playing, but there are no processed buffers…

File size: 7.0 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 *      Erwin 'vaiursch' Herrsche
24 *   Co-authors:
25 *
26 */
27#include "SoundStreamer.h"
28
29#include <boost/thread.hpp>
30#include <al.h>
31#include <alc.h>
32#include <vorbis/vorbisfile.h>
33#include "SoundManager.h"
34#include "util/Sleep.h"
35
36namespace orxonox
37{
38    // vorbis callbacks
39    size_t readVorbis(void* ptr, size_t size, size_t nmemb, void* datasource);
40    int seekVorbis(void* datasource, ogg_int64_t offset, int whence);
41    long tellVorbis(void* datasource);
42
43    void orxonox::SoundStreamer::operator()(ALuint audioSource, DataStreamPtr dataStream)
44    {
45        COUT(4) << "Sound: Creating thread for " << dataStream->getName() << std::endl;
46
47        alSourcei(audioSource, AL_BUFFER, 0);
48
49        // Open file with custom streaming
50        ov_callbacks vorbisCallbacks;
51        vorbisCallbacks.read_func  = &readVorbis;
52        vorbisCallbacks.seek_func  = &seekVorbis;
53        vorbisCallbacks.tell_func  = &tellVorbis;
54        vorbisCallbacks.close_func = NULL;
55
56        OggVorbis_File vf;
57        int ret = ov_open_callbacks(dataStream.get(), &vf, NULL, 0, vorbisCallbacks);
58        if (ret < 0)
59        {
60            COUT(2) << "Sound: libvorbisfile: File does not seem to be an Ogg Vorbis bitstream" << std::endl;
61            ov_clear(&vf);
62            return;
63        }
64        vorbis_info* vorbisInfo;
65        vorbisInfo = ov_info(&vf, -1);
66        ALenum format;
67        if (vorbisInfo->channels == 1)
68            format = AL_FORMAT_MONO16;
69        else
70            format = AL_FORMAT_STEREO16;
71
72        char inbuffer[4096];
73        ALuint initbuffers[5];
74        alGenBuffers(5, initbuffers);
75        if (ALint error = alGetError()) {
76            COUT(2) << "Sound: Streamer: Could not generate buffer:" << getALErrorString(error) << std::endl;
77            return;
78        }
79        int current_section;
80
81        for(int i = 0; i < 5; i++)
82        {
83            long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
84            if (ret == 0)
85            {
86                break;
87            }
88            else if (ret < 0)
89            {
90                COUT(2) << "Sound: libvorbisfile: error reading the file" << std::endl;
91                ov_clear(&vf);
92                return;
93            }
94
95            alBufferData(initbuffers[i], format, &inbuffer, ret, vorbisInfo->rate);
96            if(ALint error = alGetError()) {
97                COUT(2) << "Sound: Could not fill buffer: " << getALErrorString(error) << std::endl;
98                break;
99             }
100             alSourceQueueBuffers(audioSource, 1, &initbuffers[i]);
101             if (ALint error = alGetError()) {
102                 COUT(2) << "Sound: Warning: Couldn't queue buffers: " << getALErrorString(error) << std::endl;
103             }
104        }
105
106        alSourcei(audioSource, AL_LOOPING, AL_TRUE);
107
108        alSourcePlay(audioSource);
109        if(ALint error = alGetError())
110            COUT(2) << "Sound: Could not start ambient sound" << std::endl;
111
112        while(true) // Stream forever, control through thread control
113        {
114
115            int info;
116            alGetSourcei(audioSource, AL_SOURCE_STATE, &info);
117            if(info == AL_PLAYING)
118                COUT(4) << "Sound: " << dataStream->getName() << " is playing." << std::endl;
119            else
120                COUT(4) << "Sound: " << dataStream->getName() << " is not playing." << std::endl;
121
122            if(alcGetCurrentContext() == NULL)
123            {
124                COUT(2) << "Sound: There is no context, terminating thread for " << dataStream->getName() << std::endl;
125                return;
126            }
127
128            int processed;
129            alGetSourcei(audioSource, AL_BUFFERS_PROCESSED, &processed);
130            if (ALint error = alGetError())
131                COUT(2) << "Sound: Warning: Couldn't get number of processed buffers: " << getALErrorString(error) << std::endl;
132            COUT(4) << "Sound: processed buffers: " << processed << std::endl;
133
134            if(processed > 0)
135            {
136                ALuint* buffers = new ALuint[processed];
137                alSourceUnqueueBuffers(audioSource, processed, buffers);
138                if (ALint error = alGetError())
139                    COUT(2) << "Sound: Warning: Couldn't unqueue buffers: " << getALErrorString(error) << std::endl;
140
141                for(int i = 0; i < processed; i++)
142                {
143                    long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
144                    if (ret == 0)
145                    {
146                        return;
147                    }
148                    else if (ret < 0)
149                    {
150                        COUT(2) << "Sound: libvorbisfile: error reading the file " << dataStream->getName() << std::endl;
151                        ov_clear(&vf);
152                        return;
153                    }
154
155                    alBufferData(buffers[i], format, &inbuffer, ret, vorbisInfo->rate);
156                    if(ALint error = alGetError()) {
157                        COUT(2) << "Sound: Could not fill buffer: " << getALErrorString(error) << std::endl;
158                        break;
159                    }
160                    alSourceQueueBuffers(audioSource, 1, &buffers[i]);
161                    if (ALint error = alGetError()) {
162                        COUT(2) << "Sound: Warning: Couldn't queue buffers: " << getALErrorString(error) << std::endl;
163                    }
164                }
165            }
166            try {
167                boost::this_thread::interruption_point();
168            }
169            catch(boost::thread_interrupted) {
170                COUT(4) << "Sound: Catched interruption. Terminating thread for " << dataStream->getName() << std::endl;
171                ALuint* buffers = new ALuint[5];
172                alSourceUnqueueBuffers(audioSource, 5, buffers);
173                if (ALint error = alGetError())
174                    COUT(2) << "Sound: Warning: Couldn't unqueue buffers: " << getALErrorString(error) << std::endl;
175
176                alDeleteBuffers(5, buffers);
177                if (ALint error = alGetError())
178                    COUT(2) << "Sound: Warning: Couldn't delete buffers: " << getALErrorString(error) << std::endl;
179
180                return;
181            }
182            msleep(50); // perhaps another value here is better
183        }
184    }
185}
Note: See TracBrowser for help on using the repository browser.