dungeon_crawler
diff prototype/src/audio/stream.cc @ 54:995191474cc0
writting the stream audio player
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 19 Sep 2012 05:22:43 +0300 |
parents | 1ea56011c1ff |
children | 4c427e28ca00 |
line diff
1.1 --- a/prototype/src/audio/stream.cc Wed Sep 19 01:08:41 2012 +0300 1.2 +++ b/prototype/src/audio/stream.cc Wed Sep 19 05:22:43 2012 +0300 1.3 @@ -1,13 +1,107 @@ 1.4 +#include <stdio.h> 1.5 #include "stream.h" 1.6 +#include "openal.h" 1.7 + 1.8 +AudioStream::AudioStream() 1.9 +{ 1.10 + alsrc = 0; 1.11 + poll_interval = 250; 1.12 + done = true; 1.13 + loop = false; 1.14 +} 1.15 1.16 AudioStream::~AudioStream() 1.17 { 1.18 + stop(); 1.19 } 1.20 1.21 -void AudioStream::play() 1.22 +void AudioStream::play(bool loop) 1.23 { 1.24 + this->loop = loop; 1.25 + done = false; 1.26 + play_thread = std::thread(&AudioStream::poll_loop, this); 1.27 } 1.28 1.29 void AudioStream::stop() 1.30 { 1.31 + if(alsrc) { 1.32 + done = true; 1.33 + alSourceStop(alsrc); 1.34 + play_thread.join(); 1.35 + } 1.36 } 1.37 + 1.38 +static ALenum alformat(AudioStreamBuffer *buf) 1.39 +{ 1.40 + return buf->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; 1.41 +} 1.42 + 1.43 +// thread function 1.44 +void AudioStream::poll_loop() 1.45 +{ 1.46 + static const int num_buffers = 3; 1.47 + AudioStreamBuffer buf; 1.48 + unsigned int albuf[num_buffers]; 1.49 + 1.50 + alGenSources(1, &alsrc); 1.51 + alGenBuffers(num_buffers, albuf); 1.52 + 1.53 + for(int i=0; i<num_buffers; i++) { 1.54 + if(more_samples(&buf)) { 1.55 + alSourceQueueBuffers(alsrc, 1, albuf + i); 1.56 + } else { 1.57 + break; 1.58 + } 1.59 + } 1.60 + 1.61 + while(!done) { 1.62 + /* find out how many (if any) of the queued buffers are 1.63 + * done, and free to be reused. 1.64 + */ 1.65 + int num_buf_done; 1.66 + alGetSourcei(alsrc, AL_BUFFERS_PROCESSED, &num_buf_done); 1.67 + for(int i=0; i<num_buf_done; i++) { 1.68 + // unqueue a buffer... 1.69 + unsigned int buf_id; 1.70 + alSourceUnqueueBuffers(alsrc, 1, &buf_id); 1.71 + 1.72 + // if there are more data, fill it up and requeue it 1.73 + if(more_samples(&buf)) { 1.74 + int bufsz = buf.num_samples * buf.channels * 2; // 2 is for 16bit samples 1.75 + alBufferData(buf_id, alformat(&buf), buf.samples, bufsz, buf.sample_rate); 1.76 + if(alGetError()) { 1.77 + fprintf(stderr, "failed to load sample data into OpenAL buffer\n"); 1.78 + } 1.79 + } else { 1.80 + // no more data... 1.81 + if(loop) { 1.82 + rewind(); 1.83 + } else { 1.84 + done = true; 1.85 + } 1.86 + } 1.87 + } 1.88 + 1.89 + if(num_buf_done) { 1.90 + // make sure playback didn't stop 1.91 + int state; 1.92 + alGetSourcei(alsrc, AL_SOURCE_STATE, &state); 1.93 + if(state != AL_PLAYING) { 1.94 + alSourcePlay(alsrc); 1.95 + } 1.96 + } 1.97 + 1.98 + std::chrono::milliseconds dur{poll_interval}; 1.99 + std::this_thread::sleep_for(dur); 1.100 + } 1.101 + 1.102 + // done with the data, wait for the source to stop playing before cleanup 1.103 + int state; 1.104 + while(alGetSourcei(alsrc, AL_SOURCE_STATE, &state), state == AL_PLAYING) { 1.105 + std::this_thread::yield(); 1.106 + } 1.107 + 1.108 + alDeleteBuffers(num_buffers, albuf); 1.109 + alDeleteSources(1, &alsrc); 1.110 + alsrc = 0; 1.111 +}