dungeon_crawler

annotate prototype/src/audio/sample.cc @ 48:aa9e28670ae2

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