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