Skip to content

Latest commit

 

History

History
224 lines (193 loc) · 5.94 KB

music_ogg.c

File metadata and controls

224 lines (193 loc) · 5.94 KB
 
Dec 31, 2011
Dec 31, 2011
2
SDL_mixer: An audio mixer library based on the SDL library
Jan 2, 2017
Jan 2, 2017
3
Copyright (C) 1997-2017 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
} else {
Jan 20, 2017
Jan 20, 2017
182
SDL_MixAudioFormat(snd, music->snd_available, mixer.format, mixable, music->volume);
May 22, 2013
May 22, 2013
183
184
185
186
187
188
189
190
}
music->len_available -= mixable;
music->snd_available += mixable;
len -= mixable;
snd += mixable;
}
return len;
191
192
193
194
195
}
/* Stop playback of a stream previously started with OGG_play() */
void OGG_stop(OGG_music *music)
{
May 22, 2013
May 22, 2013
196
music->playing = 0;
197
198
199
200
201
}
/* Close the given OGG stream */
void OGG_delete(OGG_music *music)
{
May 22, 2013
May 22, 2013
202
203
204
205
if ( music ) {
if ( music->cvt.buf ) {
SDL_free(music->cvt.buf);
}
Jun 2, 2013
Jun 2, 2013
206
207
if ( music->freesrc ) {
SDL_RWclose(music->src);
May 22, 2013
May 22, 2013
208
209
210
211
}
vorbis.ov_clear(&music->vf);
SDL_free(music);
}
212
213
}
Dec 20, 2001
Dec 20, 2001
214
215
216
/* 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
217
#ifdef OGG_USE_TREMOR
Apr 16, 2013
Apr 16, 2013
218
vorbis.ov_time_seek( &music->vf, (ogg_int64_t)(time * 1000.0) );
Mar 16, 2011
Mar 16, 2011
219
#else
May 12, 2006
May 12, 2006
220
vorbis.ov_time_seek( &music->vf, time );
Mar 16, 2011
Mar 16, 2011
221
#endif
Dec 20, 2001
Dec 20, 2001
222
223
}
224
#endif /* OGG_MUSIC */