Mercurial > hg > index.fcgi > lj > lj046-2players
comparison src/ljvorbis.c @ 0:c84446dfb3f5
initial add
author | paulo@localhost |
---|---|
date | Fri, 13 Mar 2009 00:39:12 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a2968046ba79 |
---|---|
1 /* | |
2 | |
3 ljvorbis.c | |
4 Simple wrapper around vorbisfile for use with the Allegro library | |
5 copyright 2006 Damian Yerrick | |
6 based on vorbisfile example | |
7 copyright 1994-2004 Xiph.Org Foundation | |
8 licensed under a BSD style license set forth in COPYING-OGG.txt | |
9 | |
10 */ | |
11 | |
12 #define ALLEGRO_USE_CONSOLE | |
13 #include <stdio.h> | |
14 #include "ljvorbis.h" | |
15 | |
16 #define VORBIS_BYTEDEPTH 2 // number of bytes per sample; 2 means 16-bit | |
17 #define VORBIS_ENDIAN 0 // 0: x86/little; 2: ppc/big | |
18 #define VORBIS_SIGNED 0 // 0: unsigned; 1: signed; Allegro uses unsigned | |
19 | |
20 LJVorbis *LJVorbis_open(const char *filename) { | |
21 LJVorbis *ogg = malloc(sizeof(LJVorbis)); | |
22 if (!ogg) { | |
23 return NULL; | |
24 } | |
25 ogg->fp = fopen(filename, "rb"); | |
26 if (!ogg->fp) { | |
27 free(ogg); | |
28 return NULL; | |
29 } | |
30 if (ov_open(ogg->fp, &(ogg->vf), NULL, 0) < 0) { | |
31 fclose(ogg->fp); | |
32 free(ogg); | |
33 return NULL; | |
34 } | |
35 vorbis_info *vi=ov_info(&(ogg->vf),-1); | |
36 ogg->rate = vi->rate; | |
37 ogg->channels = vi->channels; | |
38 ogg->length = ov_pcm_total(&(ogg->vf),-1); | |
39 ogg->loopPoint = 0; | |
40 ogg->voice = NULL; | |
41 ogg->paused = 0; | |
42 return ogg; | |
43 } | |
44 | |
45 void LJVorbis_setLoop(LJVorbis *ogg, unsigned long int loopPoint) { | |
46 if (ogg) { | |
47 if (loopPoint < ogg->length) { | |
48 ogg->loopPoint = loopPoint; | |
49 } else { | |
50 ogg->loopPoint = 0; | |
51 } | |
52 } | |
53 } | |
54 | |
55 int LJVorbis_start(LJVorbis *ogg, int bufferSize, int vol, int pan) { | |
56 if (ogg) { | |
57 | |
58 // if restarting, stop first | |
59 if (ogg->voice) { | |
60 LJVorbis_stop(ogg); | |
61 } | |
62 ogg->voice = play_audio_stream(bufferSize, | |
63 8 * VORBIS_BYTEDEPTH, | |
64 ogg->channels > 1, | |
65 ogg->rate, | |
66 vol, pan); | |
67 ogg->bufferSize = bufferSize; | |
68 if (!ogg->voice) { | |
69 return -1; | |
70 } | |
71 ov_pcm_seek(&(ogg->vf), 0); | |
72 return 0; | |
73 } | |
74 return -1; | |
75 } | |
76 | |
77 void LJVorbis_stop(LJVorbis *ogg) { | |
78 if (ogg && ogg->voice) { | |
79 stop_audio_stream(ogg->voice); | |
80 ogg->voice = NULL; | |
81 } | |
82 } | |
83 | |
84 void LJVorbis_close(LJVorbis *ogg) { | |
85 if (ogg) { | |
86 LJVorbis_stop(ogg); | |
87 ov_clear(&(ogg->vf)); // finalize decoder and close the file | |
88 // thanks kesiev for reminding me that ov_clear closes the file itself | |
89 free(ogg); | |
90 } | |
91 } | |
92 | |
93 void LJVorbis_pause(LJVorbis *ogg, int value) { | |
94 if (ogg && ogg->voice) { | |
95 int hwVoice = ogg->voice->voice; | |
96 voice_set_frequency(hwVoice, value ? 0 : ogg->rate); | |
97 ogg->paused = value ? 1 : 0; | |
98 } | |
99 } | |
100 | |
101 int LJVorbis_poll(LJVorbis *ogg) { | |
102 if (!ogg || !ogg->voice) { | |
103 return -1; | |
104 } | |
105 char *buf = get_audio_stream_buffer(ogg->voice); | |
106 int eofReached = 0; | |
107 | |
108 if (buf) { | |
109 // the number of bytes left in this buffer | |
110 long int bytesLeft = ogg->bufferSize * VORBIS_BYTEDEPTH * ogg->channels; | |
111 | |
112 while (bytesLeft > 0) { | |
113 long ret=ov_read(&(ogg->vf), | |
114 buf, | |
115 bytesLeft, | |
116 VORBIS_ENDIAN, | |
117 VORBIS_BYTEDEPTH, | |
118 VORBIS_SIGNED, | |
119 &(ogg->bitstream)); | |
120 if (ret == 0) { | |
121 // try to seek back to the beginning of the file | |
122 int pcmErr = ov_pcm_seek(&(ogg->vf), ogg->loopPoint); | |
123 if (pcmErr) { | |
124 /* EOF */ | |
125 eofReached = 1; | |
126 bytesLeft = 0; | |
127 } | |
128 } else if (ret < 0) { | |
129 // Stream error. Just ignore it. | |
130 } else { | |
131 /* FIXME: handle sample rate changes, etc */ | |
132 // advance forward in the buffer | |
133 buf += ret; | |
134 bytesLeft -= ret; | |
135 } | |
136 } | |
137 free_audio_stream_buffer(ogg->voice); | |
138 } | |
139 return eofReached; | |
140 } | |
141 | |
142 #ifdef LJVORBIS_DEMO | |
143 int main(){ | |
144 int eofReached = 0; | |
145 LJVorbis *ogg = LJVorbis_open("AM-3P.ogg"); | |
146 | |
147 if (!ogg) { | |
148 fprintf(stderr, "Could not open AM-3P.ogg.\n"); | |
149 exit(1); | |
150 } | |
151 LJVorbis_setLoop(ogg, 650772); | |
152 | |
153 if (allegro_init() < 0 | |
154 || install_timer() < 0 | |
155 || set_gfx_mode(GFX_SAFE, 320, 200, 0, 0) < 0 | |
156 || install_keyboard() < 0 | |
157 || install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL) < 0) { | |
158 allegro_exit(); | |
159 LJVorbis_close(ogg); | |
160 fprintf(stderr, "Could not start Allegro library: %s\n", allegro_error); | |
161 exit(1); | |
162 } | |
163 | |
164 /* Throw the comments plus a few lines about the bitstream we're | |
165 decoding */ | |
166 if (0) | |
167 { | |
168 char line1[80], line2[80]; | |
169 | |
170 usprintf(line1,"%d channels, %u Hz", ogg->channels, ogg->rate); | |
171 usprintf(line2,"length: %lu samples", ogg->length); | |
172 alert(line1, line2, "ready?", | |
173 "Play", 0, 13, 0); | |
174 } | |
175 | |
176 if (LJVorbis_start(ogg, 1024, 192, 128) < 0) { | |
177 LJVorbis_close(ogg); | |
178 alert("Could not allocate voice", | |
179 "for playing audio.", | |
180 "", | |
181 "OK", 0, 13, 0); | |
182 exit(1); | |
183 } | |
184 | |
185 while(!eofReached){ | |
186 eofReached = LJVorbis_poll(ogg); | |
187 rest(16); | |
188 | |
189 if (keypressed()) { | |
190 int scancode; | |
191 ureadkey(&scancode); | |
192 | |
193 if (scancode == KEY_P) { | |
194 LJVorbis_pause(ogg, !ogg->paused); | |
195 } else if (scancode == KEY_ESC) { | |
196 eofReached = 1; | |
197 } | |
198 } | |
199 } | |
200 | |
201 /* cleanup */ | |
202 LJVorbis_close(ogg); | |
203 return(0); | |
204 } | |
205 END_OF_MAIN(); | |
206 #endif |