dungeon_crawler

annotate prototype/src/audio/sample.cc @ 69:45172d087ebe

fixed some windows compatibility crap fixed a terrible stack overrun in psys (TODO: remember to fix in libpsys too)
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 07 Oct 2012 03:42:44 +0200
parents aa9e28670ae2
children
rev   line source
nuclear@47 1 #include <stdio.h>
nuclear@47 2 #include <stdlib.h>
nuclear@69 3 #include <stdint.h>
nuclear@47 4 #include <assert.h>
nuclear@47 5 #include <vorbis/vorbisfile.h>
nuclear@47 6 #include "openal.h"
nuclear@47 7 #include "sample.h"
nuclear@47 8
nuclear@48 9
nuclear@48 10 #define CHECK_ERROR \
nuclear@48 11 do { \
nuclear@48 12 unsigned int err = alGetError(); \
nuclear@48 13 if(err != 0) { \
nuclear@48 14 fprintf(stderr, "%s:%d: AL error: %#x\n", __FILE__, __LINE__, err); \
nuclear@48 15 abort(); \
nuclear@48 16 } \
nuclear@48 17 } while(0)
nuclear@48 18
nuclear@48 19
nuclear@47 20 AudioSample::AudioSample()
nuclear@47 21 {
nuclear@47 22 albuffer = 0;
nuclear@47 23 }
nuclear@47 24
nuclear@47 25 AudioSample::~AudioSample()
nuclear@47 26 {
nuclear@47 27 destroy();
nuclear@47 28 }
nuclear@47 29
nuclear@47 30 void AudioSample::destroy()
nuclear@47 31 {
nuclear@47 32 if(albuffer) {
nuclear@47 33 alDeleteBuffers(1, &albuffer);
nuclear@47 34 albuffer = 0;
nuclear@47 35 }
nuclear@47 36 }
nuclear@47 37
nuclear@47 38 bool AudioSample::load(const char *fname)
nuclear@47 39 {
nuclear@47 40 OggVorbis_File vf;
nuclear@47 41 if(ov_fopen(fname, &vf) != 0) {
nuclear@47 42 fprintf(stderr, "failed to open ogg/vorbis file: %s\n", fname);
nuclear@47 43 return false;
nuclear@47 44 }
nuclear@47 45 vorbis_info *vinfo = ov_info(&vf, -1);
nuclear@47 46 ALenum alfmt = vinfo->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
nuclear@47 47
nuclear@47 48 printf("loading sample: %s: %ld samples/s, %s (%d chan)\n", fname, vinfo->rate,
nuclear@47 49 vinfo->channels == 1 ? "mono" : "stereo", vinfo->channels);
nuclear@47 50
nuclear@48 51 long num_samples = ov_pcm_total(&vf, -1) * vinfo->channels;
nuclear@47 52 int16_t *samples = new int16_t[num_samples];
nuclear@47 53
nuclear@47 54 long bufsz = num_samples * sizeof *samples;
nuclear@47 55 long total_read = 0;
nuclear@47 56 while(total_read < bufsz) {
nuclear@47 57 int bitstream;
nuclear@47 58 long rd = ov_read(&vf, (char*)samples + total_read, bufsz, 0, 2, 1, &bitstream);
nuclear@47 59 if(!rd) {
nuclear@47 60 bufsz = total_read;
nuclear@47 61 printf("%s: unexpected eof while reading: %s\n", __FUNCTION__, fname);
nuclear@47 62 } else {
nuclear@47 63 total_read += rd;
nuclear@47 64 }
nuclear@47 65 }
nuclear@47 66
nuclear@47 67 assert(alGetError() == AL_NO_ERROR);
nuclear@47 68
nuclear@47 69 unsigned int bufobj = 0;
nuclear@47 70 alGenBuffers(1, &bufobj);
nuclear@47 71 if(alGetError()) {
nuclear@47 72 fprintf(stderr, "failed to create OpenAL buffer\n");
nuclear@47 73 goto err;
nuclear@47 74 }
nuclear@47 75
nuclear@47 76 alBufferData(bufobj, alfmt, samples, bufsz, vinfo->rate);
nuclear@48 77 CHECK_ERROR;
nuclear@47 78 if(alGetError()) {
nuclear@47 79 fprintf(stderr, "failed to load sample data into OpenAL buffer: %u\n", bufobj);
nuclear@47 80 goto err;
nuclear@47 81 }
nuclear@47 82
nuclear@47 83 ov_clear(&vf);
nuclear@47 84 delete [] samples;
nuclear@47 85
nuclear@47 86 destroy(); // cleanup previous buffer if any
nuclear@47 87 albuffer = bufobj;
nuclear@47 88 return true;
nuclear@47 89
nuclear@47 90 err:
nuclear@47 91 delete [] samples;
nuclear@47 92 ov_clear(&vf);
nuclear@47 93 if(bufobj) {
nuclear@47 94 alDeleteBuffers(1, &bufobj);
nuclear@47 95 }
nuclear@47 96 return false;
nuclear@47 97 }
nuclear@48 98
nuclear@48 99 AudioSample *load_audio_sample(const char *fname)
nuclear@48 100 {
nuclear@48 101 AudioSample *s = new AudioSample;
nuclear@48 102
nuclear@48 103 if(!s->load(fname)) {
nuclear@48 104 delete s;
nuclear@48 105 s = 0;
nuclear@48 106 }
nuclear@48 107 return s;
nuclear@48 108 }
nuclear@48 109
nuclear@48 110 void destroy_audio_sample(AudioSample *s)
nuclear@48 111 {
nuclear@48 112 delete s;
nuclear@48 113 }