~ubuntu-branches/debian/sid/astromenace/sid

« back to all changes in this revision

Viewing changes to AstroMenaceSource/Core/Sound/Music.cpp

  • Committer: Package Import Robot
  • Author(s): Boris Pek
  • Date: 2013-04-09 02:04:25 UTC
  • Revision ID: package-import@ubuntu.com-20130409020425-a7fl9xk4diamw6di
Tags: upstream-1.3.1+repack
Import upstream version 1.3.1+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************************
 
2
 
 
3
        AstroMenace (Hardcore 3D space shooter with spaceship upgrade possibilities)
 
4
        Copyright © 2006-2012 Michael Kurinnoy, Viewizard
 
5
 
 
6
 
 
7
        AstroMenace is free software: you can redistribute it and/or modify
 
8
        it under the terms of the GNU General Public License as published by
 
9
        the Free Software Foundation, either version 3 of the License, or
 
10
        (at your option) any later version.
 
11
 
 
12
        AstroMenace is distributed in the hope that it will be useful,
 
13
        but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
15
        GNU General Public License for more details.
 
16
 
 
17
        You should have received a copy of the GNU General Public License
 
18
        along with AstroMenace. If not, see <http://www.gnu.org/licenses/>.
 
19
 
 
20
 
 
21
        Web Site: http://www.viewizard.com/
 
22
        Project: http://sourceforge.net/projects/openastromenace/
 
23
        E-mail: viewizard@viewizard.com
 
24
 
 
25
*************************************************************************************/
 
26
 
 
27
 
 
28
#include "Sound.h"
 
29
#include "../System/System.h"
 
30
 
 
31
 
 
32
 
 
33
ALboolean CheckALError();
 
34
ALboolean CheckALUTError();
 
35
 
 
36
 
 
37
 
 
38
 
 
39
//------------------------------------------------------------------------------------
 
40
//      Vorbis callback functions
 
41
//------------------------------------------------------------------------------------
 
42
size_t VorbisRead(void *ptr, size_t byteSize, size_t sizeToRead, void *datasource)
 
43
{
 
44
        // нужно возвращать кол-во прочитаных byteSize
 
45
        eFILE* vorbisData = (eFILE*)datasource;
 
46
        return vorbisData->fread(ptr, byteSize, sizeToRead);
 
47
}
 
48
 
 
49
 
 
50
int VorbisSeek(void *datasource, ogg_int64_t offset, int whence)
 
51
{
 
52
        eFILE* vorbisData = (eFILE*)datasource;
 
53
        return vorbisData->fseek(offset, whence);
 
54
}
 
55
 
 
56
 
 
57
int VorbisClose(void *UNUSED(datasource))
 
58
{// похоже, без этой функции у линукс версии vorbis проблемы, хотя по документации...
 
59
        return 1;
 
60
}
 
61
 
 
62
 
 
63
long VorbisTell(void *datasource)
 
64
{
 
65
        eFILE*  vorbisData = (eFILE*)datasource;
 
66
        return vorbisData->ftell();
 
67
}
 
68
 
 
69
 
 
70
 
 
71
 
 
72
 
 
73
//------------------------------------------------------------------------------------
 
74
// Читаем фрагмент ogg файла
 
75
//------------------------------------------------------------------------------------
 
76
bool eMusic::ReadOggBlock(ALuint BufID, size_t Size)
 
77
{
 
78
        // vars
 
79
        int                     current_section;
 
80
        unsigned int TotalRet = 0;
 
81
        long            ret = 0;
 
82
        char            *PCM;
 
83
 
 
84
        if (Size < 1) return false;
 
85
        PCM = new char[Size];
 
86
 
 
87
        // Read loop
 
88
        while (TotalRet < Size)
 
89
        {
 
90
                ret = ov_read(mVF, PCM + TotalRet, Size - TotalRet, 0, 2, 1, &current_section);
 
91
 
 
92
                // if end of file or read limit exceeded
 
93
                if (ret == 0) break;
 
94
                else if (ret < 0)               // Error in bitstream
 
95
                {
 
96
                        //
 
97
                }
 
98
                else
 
99
                {
 
100
                        TotalRet += ret;
 
101
                }
 
102
        }
 
103
        if (TotalRet > 0)
 
104
        {
 
105
                alBufferData(BufID, Format, PCM, TotalRet, Rate);
 
106
                CheckALError();
 
107
        }
 
108
        delete [] PCM;
 
109
        return (ret > 0);
 
110
}
 
111
 
 
112
 
 
113
 
 
114
 
 
115
 
 
116
 
 
117
 
 
118
//------------------------------------------------------------------------------------
 
119
// Проигрывание звука
 
120
//------------------------------------------------------------------------------------
 
121
bool eMusic::Play(const char * Name, float fVol, float fMainVol, bool Loop, const char *LoopFileName)
 
122
{
 
123
        Volume = fVol;
 
124
        MainVolume = fMainVol;
 
125
 
 
126
        if (LoopFileName == 0)
 
127
        {
 
128
                LoopPart[0] = 0;
 
129
        }
 
130
        else
 
131
        {
 
132
                strcpy(LoopPart, LoopFileName);
 
133
        }
 
134
 
 
135
        FadeInSw = false;
 
136
        FadeInStartVol = Volume;
 
137
        FadeInEndVol = Volume;
 
138
        FadeOutSw = false;
 
139
        FadeTime = 0.0f;
 
140
        FadeAge = 0.0f;
 
141
        LastTime = vw_GetTime();
 
142
        mVF = 0;
 
143
 
 
144
        // Position of the source sound.
 
145
        ALfloat SourcePos[] = { 0.0f, 0.0f, 0.0f }; // -1.0 1.0 по иксам это баланс
 
146
        // Velocity of the source sound.
 
147
        ALfloat SourceVel[] = { 0.0f, 0.0f, 0.0f };
 
148
 
 
149
        alGenSources(1, &Source);
 
150
        if(!CheckALError()) return AL_FALSE;
 
151
 
 
152
        alSourcef (Source, AL_PITCH,    1.0      ); // 1.0 only!!!
 
153
        alSourcef (Source, AL_GAIN,     fVol*fMainVol    ); // фактически громкость
 
154
        alSourcefv(Source, AL_POSITION, SourcePos);
 
155
        alSourcefv(Source, AL_VELOCITY, SourceVel);
 
156
        alSourcei (Source, AL_SOURCE_RELATIVE, AL_TRUE);
 
157
        alSourcei(Source, AL_LOOPING, AL_FALSE);
 
158
        alGetError(); // сброс ошибок
 
159
        Looped = Loop;
 
160
 
 
161
 
 
162
        // делаем буфер...
 
163
 
 
164
        // Open Ogg file
 
165
        MusicFile = vw_fopen(Name);
 
166
        if (MusicFile == 0) return false;
 
167
 
 
168
        int      i, DynBuffs = 1, BlockSize;
 
169
 
 
170
        // OggVorbis specific structures
 
171
        ov_callbacks    cb;
 
172
        // Fill cb struct
 
173
        cb.close_func   = VorbisClose;
 
174
        cb.read_func    = VorbisRead;
 
175
        cb.seek_func    = VorbisSeek;
 
176
        cb.tell_func    = VorbisTell;
 
177
        // Create OggVorbis_File struct
 
178
        mVF = new OggVorbis_File;
 
179
 
 
180
        // Generate local buffers
 
181
        if (ov_open_callbacks(MusicFile, mVF, NULL, 0, cb) < 0)
 
182
        {
 
183
                // This is not ogg bitstream. Return
 
184
                return false;
 
185
        }
 
186
 
 
187
 
 
188
 
 
189
        // Check for existance of sound
 
190
        BlockSize       = DYNBUF_SIZE;
 
191
        DynBuffs        = NUM_OF_DYNBUF;
 
192
 
 
193
        // Return vorbis_comment and vorbis_info structures
 
194
        mComment                = ov_comment(mVF, -1);
 
195
        mInfo                   = ov_info(mVF, -1);
 
196
 
 
197
        // Fill buffer infos
 
198
        Rate            = mInfo->rate;
 
199
        Format          = (mInfo->channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
 
200
 
 
201
        // Create buffers
 
202
        alGenBuffers(DynBuffs, Buffers);
 
203
        if (!CheckALError()) return false;
 
204
 
 
205
        for (i = 0; i < DynBuffs; i++)
 
206
        {
 
207
                // Read amount (DYNBUF_SIZE) data into each buffer
 
208
                ReadOggBlock(Buffers[i], BlockSize);
 
209
                if (!CheckALError()) return false;
 
210
 
 
211
                alSourceQueueBuffers(Source, 1, &Buffers[i]);
 
212
                if (!CheckALError()) return false;
 
213
        }
 
214
 
 
215
 
 
216
 
 
217
 
 
218
        // запускаем на проигрывание
 
219
 
 
220
        alSourcePlay(Source);
 
221
        if(!CheckALError()) return AL_FALSE;
 
222
 
 
223
        return AL_TRUE;
 
224
}
 
225
 
 
226
 
 
227
 
 
228
//------------------------------------------------------------------------------------
 
229
// обновление потока
 
230
//------------------------------------------------------------------------------------
 
231
bool eMusic::Update()
 
232
{
 
233
        int      Processed = 0;
 
234
 
 
235
        alGetSourcei(Source, AL_BUFFERS_PROCESSED, &Processed);
 
236
 
 
237
        // We still have processed buffers
 
238
        while (Processed--)
 
239
        {
 
240
                // не создаем новые буферы, просто берем уже использованный и заполняем новыми данными
 
241
                // а потом ставим его опять в очередь
 
242
                ALuint bufferID;
 
243
                alSourceUnqueueBuffers(Source, 1, &bufferID);
 
244
                if (!CheckALError()) return true;
 
245
 
 
246
                if (ReadOggBlock(bufferID, DYNBUF_SIZE) != 0)
 
247
                {
 
248
                        alSourceQueueBuffers(Source, 1, &bufferID);
 
249
                        if (!CheckALError()) return true;
 
250
                }
 
251
                else
 
252
                {
 
253
 
 
254
                        if (LoopPart[0] != 0)
 
255
                        {
 
256
                                if (mVF != 0){ov_clear(mVF);delete mVF; mVF = 0;}
 
257
                                if (MusicFile != 0)
 
258
                                {
 
259
                                        vw_fclose(MusicFile);
 
260
                                }
 
261
 
 
262
                                // Open Ogg file
 
263
                                MusicFile = vw_fopen(LoopPart);
 
264
                                if (MusicFile != 0)
 
265
                                {
 
266
                                        // OggVorbis specific structures
 
267
                                        ov_callbacks    cb;
 
268
                                        // Fill cb struct
 
269
                                        cb.close_func   = VorbisClose;
 
270
                                        cb.read_func    = VorbisRead;
 
271
                                        cb.seek_func    = VorbisSeek;
 
272
                                        cb.tell_func    = VorbisTell;
 
273
                                        // Create OggVorbis_File struct
 
274
                                        mVF = new OggVorbis_File;
 
275
 
 
276
                                        // Generate local buffers
 
277
                                        if (ov_open_callbacks(MusicFile, mVF, NULL, 0, cb) < 0)
 
278
                                        {
 
279
                                                // This is not ogg bitstream. Return
 
280
                                                return false;
 
281
                                        }
 
282
 
 
283
                                }
 
284
                                else return false;
 
285
 
 
286
                                Looped = true;
 
287
                                LoopPart[0] = 0;
 
288
                        }
 
289
 
 
290
 
 
291
                        // если не нужно больше повторять - выходим
 
292
                        if (!Looped) return false;
 
293
 
 
294
                        // устанавливаем на начало
 
295
                        ov_pcm_seek(mVF, 0);
 
296
                        alSourceQueueBuffers(Source, 1, &bufferID);
 
297
                        if (!CheckALError()) return true;
 
298
 
 
299
                }
 
300
        }
 
301
 
 
302
 
 
303
        // обрабатываем эффекты
 
304
        float TimeDelta = vw_GetTime() - LastTime;
 
305
 
 
306
        if (FadeInSw)
 
307
        if (Volume < FadeInEndVol)
 
308
        {
 
309
                FadeTime += TimeDelta;
 
310
                Volume = FadeInEndVol*(FadeTime/FadeAge);
 
311
                alSourcef(Source, AL_GAIN, MainVolume*Volume );
 
312
                alGetError(); // сброс ошибок
 
313
        }
 
314
 
 
315
        if (FadeOutSw)
 
316
        if (Volume > 0.0f)
 
317
        {
 
318
                FadeTime += TimeDelta;
 
319
                Volume = FadeInStartVol*((FadeAge-FadeTime)/FadeAge);
 
320
                alSourcef(Source, AL_GAIN, MainVolume*Volume);
 
321
                alGetError(); // сброс ошибок
 
322
                if (Volume <= 0.0f) return false;
 
323
        }
 
324
 
 
325
        LastTime = vw_GetTime();
 
326
 
 
327
 
 
328
 
 
329
        // если по какой-то причине перестали играть...
 
330
        ALint TMPS;
 
331
        alGetSourcei(Source, AL_SOURCE_STATE, &TMPS);
 
332
        alGetError(); // сброс ошибок
 
333
        if (TMPS == AL_STOPPED) return false;
 
334
 
 
335
        return true;
 
336
}
 
337
 
 
338
 
 
339
 
 
340
 
 
341
 
 
342
//------------------------------------------------------------------------------------
 
343
// установка громкости
 
344
//------------------------------------------------------------------------------------
 
345
void eMusic::SetMainVolume(float NewMainVolume)
 
346
{
 
347
        // если это не источник, уходим
 
348
        if (!alIsSource(Source)) return;
 
349
 
 
350
        MainVolume = NewMainVolume;
 
351
        alSourcef(Source, AL_GAIN,     MainVolume*Volume );
 
352
}
 
353
 
 
354
 
 
355
 
 
356
//------------------------------------------------------------------------------------
 
357
// плавное появление
 
358
//------------------------------------------------------------------------------------
 
359
void eMusic::FadeIn(float EndVol, float Time)
 
360
{
 
361
        FadeInSw = true;
 
362
        FadeOutSw = false;
 
363
        FadeInEndVol = EndVol;
 
364
        FadeTime = 0.0f; // начинаем с нуля!
 
365
        FadeAge = Time;
 
366
        LastTime = vw_GetTime();
 
367
}
 
368
 
 
369
 
 
370
 
 
371
//------------------------------------------------------------------------------------
 
372
// плавное уход на 0 с текущего
 
373
//------------------------------------------------------------------------------------
 
374
void eMusic::FadeOut(float Time)
 
375
{
 
376
        FadeOutSw = true;
 
377
        FadeInSw = false;
 
378
        FadeInStartVol = Volume;
 
379
        FadeTime = 0.0f; // начинаем с нуля!
 
380
        FadeAge = Time;
 
381
        LastTime = vw_GetTime();
 
382
}
 
383
 
 
384
 
 
385
 
 
386