annotate src/ljvorbis.c @ 0:c84446dfb3f5

initial add
author paulo@localhost
date Fri, 13 Mar 2009 00:39:12 -0700
parents
children
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