Skip to content

Latest commit

 

History

History
225 lines (194 loc) · 5.96 KB

music_ogg.c

File metadata and controls

225 lines (194 loc) · 5.96 KB
 
Dec 31, 2011
Dec 31, 2011
2
SDL_mixer: An audio mixer library based on the SDL library
Feb 15, 2013
Feb 15, 2013
3
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
Dec 31, 2011
Dec 31, 2011
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
20
21
*/
Dec 14, 2001
Dec 14, 2001
22
/* $Id$ */
Dec 14, 2001
Dec 14, 2001
23
24
25
26
27
28
#ifdef OGG_MUSIC
/* This file supports Ogg Vorbis music streams */
#include <stdio.h>
Dec 18, 2001
Dec 18, 2001
29
#include <stdlib.h>
30
31
32
#include <string.h>
#include "SDL_mixer.h"
May 12, 2006
May 12, 2006
33
#include "dynamic_ogg.h"
34
35
36
37
38
39
40
41
42
43
#include "music_ogg.h"
/* This is the format of the audio mixer data */
static SDL_AudioSpec mixer;
/* Initialize the Ogg Vorbis player, with the given mixer settings
This function returns 0, or -1 if there was an error.
*/
int OGG_init(SDL_AudioSpec *mixerfmt)
{
May 22, 2013
May 22, 2013
44
45
mixer = *mixerfmt;
return(0);
46
47
48
49
50
}
/* Set the volume for an OGG stream */
void OGG_setvolume(OGG_music *music, int volume)
{
May 22, 2013
May 22, 2013
51
music->volume = volume;
52
53
}
Aug 22, 2004
Aug 22, 2004
54
55
56
57
58
static size_t sdl_read_func(void *ptr, size_t size, size_t nmemb, void *datasource)
{
return SDL_RWread((SDL_RWops*)datasource, ptr, size, nmemb);
}
Jul 7, 2014
Jul 7, 2014
59
static int sdl_seek_func(void *datasource, ogg_int64_t offset, int whence)
Aug 22, 2004
Aug 22, 2004
60
{
Jul 7, 2014
Jul 7, 2014
61
return (int)SDL_RWseek((SDL_RWops*)datasource, offset, whence);
Aug 22, 2004
Aug 22, 2004
62
63
}
Jul 7, 2014
Jul 7, 2014
64
static long sdl_tell_func(void *datasource)
Aug 22, 2004
Aug 22, 2004
65
{
Jul 7, 2014
Jul 7, 2014
66
return (long)SDL_RWtell((SDL_RWops*)datasource);
Aug 22, 2004
Aug 22, 2004
67
68
69
}
/* Load an OGG stream from an SDL_RWops object */
Jun 2, 2013
Jun 2, 2013
70
OGG_music *OGG_new_RW(SDL_RWops *src, int freesrc)
Aug 22, 2004
Aug 22, 2004
71
{
May 22, 2013
May 22, 2013
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
OGG_music *music;
ov_callbacks callbacks;
if ( !Mix_Init(MIX_INIT_OGG) ) {
return(NULL);
}
SDL_memset(&callbacks, 0, sizeof(callbacks));
callbacks.read_func = sdl_read_func;
callbacks.seek_func = sdl_seek_func;
callbacks.tell_func = sdl_tell_func;
music = (OGG_music *)SDL_malloc(sizeof *music);
if ( music ) {
/* Initialize the music structure */
Jun 1, 2013
Jun 1, 2013
87
SDL_memset(music, 0, (sizeof *music));
Jun 2, 2013
Jun 2, 2013
88
89
music->src = src;
music->freesrc = freesrc;
May 22, 2013
May 22, 2013
90
91
92
93
OGG_stop(music);
OGG_setvolume(music, MIX_MAX_VOLUME);
music->section = -1;
Jun 2, 2013
Jun 2, 2013
94
if ( vorbis.ov_open_callbacks(src, &music->vf, NULL, 0, callbacks) < 0 ) {
May 22, 2013
May 22, 2013
95
SDL_SetError("Not an Ogg Vorbis audio stream");
Jun 2, 2013
Jun 2, 2013
96
SDL_free(music);
May 22, 2013
May 22, 2013
97
98
99
100
101
102
103
return(NULL);
}
} else {
SDL_OutOfMemory();
return(NULL);
}
return(music);
Aug 22, 2004
Aug 22, 2004
104
105
}
106
107
108
/* Start playback of a given OGG stream */
void OGG_play(OGG_music *music)
{
May 22, 2013
May 22, 2013
109
music->playing = 1;
110
111
112
113
114
}
/* Return non-zero if a stream is currently playing */
int OGG_playing(OGG_music *music)
{
May 22, 2013
May 22, 2013
115
return(music->playing);
116
117
118
119
120
}
/* Read some Ogg stream data and convert it for output */
static void OGG_getsome(OGG_music *music)
{
May 22, 2013
May 22, 2013
121
122
123
124
int section;
int len;
char data[4096];
SDL_AudioCVT *cvt;
Jul 15, 2007
Jul 15, 2007
126
#ifdef OGG_USE_TREMOR
May 22, 2013
May 22, 2013
127
len = vorbis.ov_read(&music->vf, data, sizeof(data), &section);
Jul 15, 2007
Jul 15, 2007
128
#else
May 22, 2013
May 22, 2013
129
len = vorbis.ov_read(&music->vf, data, sizeof(data), 0, 2, 1, &section);
Jul 15, 2007
Jul 15, 2007
130
#endif
May 22, 2013
May 22, 2013
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
if ( len <= 0 ) {
if ( len == 0 ) {
music->playing = 0;
}
return;
}
cvt = &music->cvt;
if ( section != music->section ) {
vorbis_info *vi;
vi = vorbis.ov_info(&music->vf, -1);
SDL_BuildAudioCVT(cvt, AUDIO_S16, vi->channels, vi->rate,
mixer.format,mixer.channels,mixer.freq);
if ( cvt->buf ) {
SDL_free(cvt->buf);
}
cvt->buf = (Uint8 *)SDL_malloc(sizeof(data)*cvt->len_mult);
music->section = section;
}
if ( cvt->buf ) {
Jun 1, 2013
Jun 1, 2013
151
SDL_memcpy(cvt->buf, data, len);
May 22, 2013
May 22, 2013
152
153
154
155
156
157
158
159
160
161
162
163
if ( cvt->needed ) {
cvt->len = len;
SDL_ConvertAudio(cvt);
} else {
cvt->len_cvt = len;
}
music->len_available = music->cvt.len_cvt;
music->snd_available = music->cvt.buf;
} else {
SDL_SetError("Out of memory");
music->playing = 0;
}
164
165
166
}
/* Play some of a stream previously started with OGG_play() */
Nov 19, 2005
Nov 19, 2005
167
int OGG_playAudio(OGG_music *music, Uint8 *snd, int len)
May 22, 2013
May 22, 2013
169
170
171
172
173
174
175
176
177
178
179
int mixable;
while ( (len > 0) && music->playing ) {
if ( ! music->len_available ) {
OGG_getsome(music);
}
mixable = len;
if ( mixable > music->len_available ) {
mixable = music->len_available;
}
if ( music->volume == MIX_MAX_VOLUME ) {
Jun 1, 2013
Jun 1, 2013
180
SDL_memcpy(snd, music->snd_available, mixable);
May 22, 2013
May 22, 2013
181
182
183
184
185
186
187
188
189
190
191
} else {
SDL_MixAudio(snd, music->snd_available, mixable,
music->volume);
}
music->len_available -= mixable;
music->snd_available += mixable;
len -= mixable;
snd += mixable;
}
return len;
192
193
194
195
196
}
/* Stop playback of a stream previously started with OGG_play() */
void OGG_stop(OGG_music *music)
{
May 22, 2013
May 22, 2013
197
music->playing = 0;
198
199
200
201
202
}
/* Close the given OGG stream */
void OGG_delete(OGG_music *music)
{
May 22, 2013
May 22, 2013
203
204
205
206
if ( music ) {
if ( music->cvt.buf ) {
SDL_free(music->cvt.buf);
}
Jun 2, 2013
Jun 2, 2013
207
208
if ( music->freesrc ) {
SDL_RWclose(music->src);
May 22, 2013
May 22, 2013
209
210
211
212
}
vorbis.ov_clear(&music->vf);
SDL_free(music);
}
213
214
}
Dec 20, 2001
Dec 20, 2001
215
216
217
/* Jump (seek) to a given position (time is in seconds) */
void OGG_jump_to_time(OGG_music *music, double time)
{
Mar 16, 2011
Mar 16, 2011
218
#ifdef OGG_USE_TREMOR
Apr 16, 2013
Apr 16, 2013
219
vorbis.ov_time_seek( &music->vf, (ogg_int64_t)(time * 1000.0) );
Mar 16, 2011
Mar 16, 2011
220
#else
May 12, 2006
May 12, 2006
221
vorbis.ov_time_seek( &music->vf, time );
Mar 16, 2011
Mar 16, 2011
222
#endif
Dec 20, 2001
Dec 20, 2001
223
224
}
225
#endif /* OGG_MUSIC */