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 }
|