Skip to content

Latest commit

 

History

History
163 lines (127 loc) · 4.29 KB

load_ogg.c

File metadata and controls

163 lines (127 loc) · 4.29 KB
 
1
2
/*
SDL_mixer: An audio mixer library based on the SDL library
Dec 8, 2008
Dec 8, 2008
3
Copyright (C) 1997-2009 Sam Lantinga
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
This is the source needed to decode an Ogg Vorbis into a waveform.
This file by Vaclav Slavik (vaclav.slavik@matfyz.cz).
*/
/* $Id$ */
#ifdef OGG_MUSIC
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL_mutex.h"
#include "SDL_endian.h"
#include "SDL_timer.h"
#include "SDL_mixer.h"
May 12, 2006
May 12, 2006
36
#include "dynamic_ogg.h"
37
38
39
40
41
42
43
44
45
#include "load_ogg.h"
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);
}
static int sdl_seek_func(void *datasource, ogg_int64_t offset, int whence)
{
Feb 26, 2003
Feb 26, 2003
46
return SDL_RWseek((SDL_RWops*)datasource, (int)offset, whence);
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
}
static int sdl_close_func_freesrc(void *datasource)
{
return SDL_RWclose((SDL_RWops*)datasource);
}
static int sdl_close_func_nofreesrc(void *datasource)
{
return SDL_RWseek((SDL_RWops*)datasource, 0, SEEK_SET);
}
static long sdl_tell_func(void *datasource)
{
return SDL_RWtell((SDL_RWops*)datasource);
}
/* don't call this directly; use Mix_LoadWAV_RW() for now. */
SDL_AudioSpec *Mix_LoadOGG_RW (SDL_RWops *src, int freesrc,
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
{
OggVorbis_File vf;
ov_callbacks callbacks;
vorbis_info *info;
Uint8 *buf;
int bitstream = -1;
long samplesize;
long samples;
int read, to_read;
int must_close = 1;
int was_error = 1;
if ( (!src) || (!audio_buf) || (!audio_len) ) /* sanity checks. */
goto done;
May 12, 2006
May 12, 2006
83
84
85
if ( Mix_InitOgg() < 0 )
goto done;
86
87
88
89
90
91
callbacks.read_func = sdl_read_func;
callbacks.seek_func = sdl_seek_func;
callbacks.tell_func = sdl_tell_func;
callbacks.close_func = freesrc ?
sdl_close_func_freesrc : sdl_close_func_nofreesrc;
May 12, 2006
May 12, 2006
92
if (vorbis.ov_open_callbacks(src, &vf, NULL, 0, callbacks) != 0)
93
94
95
96
97
98
99
{
SDL_SetError("OGG bitstream is not valid Vorbis stream!");
goto done;
}
must_close = 0;
May 12, 2006
May 12, 2006
100
info = vorbis.ov_info(&vf, -1);
101
102
103
104
105
106
107
108
109
110
*audio_buf = NULL;
*audio_len = 0;
memset(spec, '\0', sizeof (SDL_AudioSpec));
spec->format = AUDIO_S16;
spec->channels = info->channels;
spec->freq = info->rate;
spec->samples = 4096; /* buffer size */
May 12, 2006
May 12, 2006
111
samples = (long)vorbis.ov_pcm_total(&vf, -1);
112
113
114
115
116
117
118
119
*audio_len = spec->size = samples * spec->channels * 2;
*audio_buf = malloc(*audio_len);
if (*audio_buf == NULL)
goto done;
buf = *audio_buf;
to_read = *audio_len;
Jul 15, 2007
Jul 15, 2007
120
121
122
123
124
#ifdef OGG_USE_TREMOR
for (read = vorbis.ov_read(&vf, (char *)buf, to_read, &bitstream);
read > 0;
read = vorbis.ov_read(&vf, (char *)buf, to_read, &bitstream))
#else
May 12, 2006
May 12, 2006
125
for (read = vorbis.ov_read(&vf, (char *)buf, to_read, 0/*LE*/, 2/*16bit*/, 1/*signed*/, &bitstream);
126
read > 0;
May 12, 2006
May 12, 2006
127
read = vorbis.ov_read(&vf, (char *)buf, to_read, 0, 2, 1, &bitstream))
Jul 15, 2007
Jul 15, 2007
128
#endif
129
130
131
132
133
134
135
136
{
if (read == OV_HOLE || read == OV_EBADLINK)
break; /* error */
to_read -= read;
buf += read;
}
May 12, 2006
May 12, 2006
137
vorbis.ov_clear(&vf);
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
was_error = 0;
/* Don't return a buffer that isn't a multiple of samplesize */
samplesize = ((spec->format & 0xFF)/8)*spec->channels;
*audio_len &= ~(samplesize-1);
done:
if (src && must_close)
{
if (freesrc)
SDL_RWclose(src);
else
SDL_RWseek(src, 0, SEEK_SET);
}
if ( was_error )
spec = NULL;
May 12, 2006
May 12, 2006
156
157
Mix_QuitOgg();
158
159
160
161
162
163
return(spec);
} /* Mix_LoadOGG_RW */
/* end of load_ogg.c ... */
#endif