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