Mercurial > hg > index.fcgi > lj > lj046-2players
diff src/ljvorbis.c @ 0:c84446dfb3f5
initial add
author | paulo@localhost |
---|---|
date | Fri, 13 Mar 2009 00:39:12 -0700 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/ljvorbis.c Fri Mar 13 00:39:12 2009 -0700 1.3 @@ -0,0 +1,206 @@ 1.4 +/* 1.5 + 1.6 +ljvorbis.c 1.7 +Simple wrapper around vorbisfile for use with the Allegro library 1.8 +copyright 2006 Damian Yerrick 1.9 +based on vorbisfile example 1.10 +copyright 1994-2004 Xiph.Org Foundation 1.11 +licensed under a BSD style license set forth in COPYING-OGG.txt 1.12 + 1.13 +*/ 1.14 + 1.15 +#define ALLEGRO_USE_CONSOLE 1.16 +#include <stdio.h> 1.17 +#include "ljvorbis.h" 1.18 + 1.19 +#define VORBIS_BYTEDEPTH 2 // number of bytes per sample; 2 means 16-bit 1.20 +#define VORBIS_ENDIAN 0 // 0: x86/little; 2: ppc/big 1.21 +#define VORBIS_SIGNED 0 // 0: unsigned; 1: signed; Allegro uses unsigned 1.22 + 1.23 +LJVorbis *LJVorbis_open(const char *filename) { 1.24 + LJVorbis *ogg = malloc(sizeof(LJVorbis)); 1.25 + if (!ogg) { 1.26 + return NULL; 1.27 + } 1.28 + ogg->fp = fopen(filename, "rb"); 1.29 + if (!ogg->fp) { 1.30 + free(ogg); 1.31 + return NULL; 1.32 + } 1.33 + if (ov_open(ogg->fp, &(ogg->vf), NULL, 0) < 0) { 1.34 + fclose(ogg->fp); 1.35 + free(ogg); 1.36 + return NULL; 1.37 + } 1.38 + vorbis_info *vi=ov_info(&(ogg->vf),-1); 1.39 + ogg->rate = vi->rate; 1.40 + ogg->channels = vi->channels; 1.41 + ogg->length = ov_pcm_total(&(ogg->vf),-1); 1.42 + ogg->loopPoint = 0; 1.43 + ogg->voice = NULL; 1.44 + ogg->paused = 0; 1.45 + return ogg; 1.46 +} 1.47 + 1.48 +void LJVorbis_setLoop(LJVorbis *ogg, unsigned long int loopPoint) { 1.49 + if (ogg) { 1.50 + if (loopPoint < ogg->length) { 1.51 + ogg->loopPoint = loopPoint; 1.52 + } else { 1.53 + ogg->loopPoint = 0; 1.54 + } 1.55 + } 1.56 +} 1.57 + 1.58 +int LJVorbis_start(LJVorbis *ogg, int bufferSize, int vol, int pan) { 1.59 + if (ogg) { 1.60 + 1.61 + // if restarting, stop first 1.62 + if (ogg->voice) { 1.63 + LJVorbis_stop(ogg); 1.64 + } 1.65 + ogg->voice = play_audio_stream(bufferSize, 1.66 + 8 * VORBIS_BYTEDEPTH, 1.67 + ogg->channels > 1, 1.68 + ogg->rate, 1.69 + vol, pan); 1.70 + ogg->bufferSize = bufferSize; 1.71 + if (!ogg->voice) { 1.72 + return -1; 1.73 + } 1.74 + ov_pcm_seek(&(ogg->vf), 0); 1.75 + return 0; 1.76 + } 1.77 + return -1; 1.78 +} 1.79 + 1.80 +void LJVorbis_stop(LJVorbis *ogg) { 1.81 + if (ogg && ogg->voice) { 1.82 + stop_audio_stream(ogg->voice); 1.83 + ogg->voice = NULL; 1.84 + } 1.85 +} 1.86 + 1.87 +void LJVorbis_close(LJVorbis *ogg) { 1.88 + if (ogg) { 1.89 + LJVorbis_stop(ogg); 1.90 + ov_clear(&(ogg->vf)); // finalize decoder and close the file 1.91 + // thanks kesiev for reminding me that ov_clear closes the file itself 1.92 + free(ogg); 1.93 + } 1.94 +} 1.95 + 1.96 +void LJVorbis_pause(LJVorbis *ogg, int value) { 1.97 + if (ogg && ogg->voice) { 1.98 + int hwVoice = ogg->voice->voice; 1.99 + voice_set_frequency(hwVoice, value ? 0 : ogg->rate); 1.100 + ogg->paused = value ? 1 : 0; 1.101 + } 1.102 +} 1.103 + 1.104 +int LJVorbis_poll(LJVorbis *ogg) { 1.105 + if (!ogg || !ogg->voice) { 1.106 + return -1; 1.107 + } 1.108 + char *buf = get_audio_stream_buffer(ogg->voice); 1.109 + int eofReached = 0; 1.110 + 1.111 + if (buf) { 1.112 + // the number of bytes left in this buffer 1.113 + long int bytesLeft = ogg->bufferSize * VORBIS_BYTEDEPTH * ogg->channels; 1.114 + 1.115 + while (bytesLeft > 0) { 1.116 + long ret=ov_read(&(ogg->vf), 1.117 + buf, 1.118 + bytesLeft, 1.119 + VORBIS_ENDIAN, 1.120 + VORBIS_BYTEDEPTH, 1.121 + VORBIS_SIGNED, 1.122 + &(ogg->bitstream)); 1.123 + if (ret == 0) { 1.124 + // try to seek back to the beginning of the file 1.125 + int pcmErr = ov_pcm_seek(&(ogg->vf), ogg->loopPoint); 1.126 + if (pcmErr) { 1.127 + /* EOF */ 1.128 + eofReached = 1; 1.129 + bytesLeft = 0; 1.130 + } 1.131 + } else if (ret < 0) { 1.132 + // Stream error. Just ignore it. 1.133 + } else { 1.134 + /* FIXME: handle sample rate changes, etc */ 1.135 + // advance forward in the buffer 1.136 + buf += ret; 1.137 + bytesLeft -= ret; 1.138 + } 1.139 + } 1.140 + free_audio_stream_buffer(ogg->voice); 1.141 + } 1.142 + return eofReached; 1.143 +} 1.144 + 1.145 +#ifdef LJVORBIS_DEMO 1.146 +int main(){ 1.147 + int eofReached = 0; 1.148 + LJVorbis *ogg = LJVorbis_open("AM-3P.ogg"); 1.149 + 1.150 + if (!ogg) { 1.151 + fprintf(stderr, "Could not open AM-3P.ogg.\n"); 1.152 + exit(1); 1.153 + } 1.154 + LJVorbis_setLoop(ogg, 650772); 1.155 + 1.156 + if (allegro_init() < 0 1.157 + || install_timer() < 0 1.158 + || set_gfx_mode(GFX_SAFE, 320, 200, 0, 0) < 0 1.159 + || install_keyboard() < 0 1.160 + || install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL) < 0) { 1.161 + allegro_exit(); 1.162 + LJVorbis_close(ogg); 1.163 + fprintf(stderr, "Could not start Allegro library: %s\n", allegro_error); 1.164 + exit(1); 1.165 + } 1.166 + 1.167 + /* Throw the comments plus a few lines about the bitstream we're 1.168 + decoding */ 1.169 + if (0) 1.170 + { 1.171 + char line1[80], line2[80]; 1.172 + 1.173 + usprintf(line1,"%d channels, %u Hz", ogg->channels, ogg->rate); 1.174 + usprintf(line2,"length: %lu samples", ogg->length); 1.175 + alert(line1, line2, "ready?", 1.176 + "Play", 0, 13, 0); 1.177 + } 1.178 + 1.179 + if (LJVorbis_start(ogg, 1024, 192, 128) < 0) { 1.180 + LJVorbis_close(ogg); 1.181 + alert("Could not allocate voice", 1.182 + "for playing audio.", 1.183 + "", 1.184 + "OK", 0, 13, 0); 1.185 + exit(1); 1.186 + } 1.187 + 1.188 + while(!eofReached){ 1.189 + eofReached = LJVorbis_poll(ogg); 1.190 + rest(16); 1.191 + 1.192 + if (keypressed()) { 1.193 + int scancode; 1.194 + ureadkey(&scancode); 1.195 + 1.196 + if (scancode == KEY_P) { 1.197 + LJVorbis_pause(ogg, !ogg->paused); 1.198 + } else if (scancode == KEY_ESC) { 1.199 + eofReached = 1; 1.200 + } 1.201 + } 1.202 + } 1.203 + 1.204 + /* cleanup */ 1.205 + LJVorbis_close(ogg); 1.206 + return(0); 1.207 +} 1.208 +END_OF_MAIN(); 1.209 +#endif