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