dungeon_crawler

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