dungeon_crawler
changeset 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 |
files | prototype/src/audio/stream.cc prototype/src/audio/stream.h |
diffstat | 2 files changed, 112 insertions(+), 3 deletions(-) [+] |
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 +}
2.1 --- a/prototype/src/audio/stream.h Wed Sep 19 01:08:41 2012 +0300 2.2 +++ b/prototype/src/audio/stream.h Wed Sep 19 05:22:43 2012 +0300 2.3 @@ -3,17 +3,32 @@ 2.4 2.5 #include <thread> 2.6 2.7 +struct AudioStreamBuffer { 2.8 + void *samples; 2.9 + int num_samples; 2.10 + int channels; 2.11 + int sample_rate; 2.12 +}; 2.13 + 2.14 class AudioStream { 2.15 private: 2.16 std::thread play_thread; 2.17 + bool done, loop; 2.18 + unsigned int poll_interval; 2.19 + unsigned int alsrc; 2.20 2.21 - virtual bool more_samples() = 0; 2.22 + virtual bool more_samples(AudioStreamBuffer *buf) = 0; 2.23 + 2.24 + void poll_loop(); 2.25 2.26 public: 2.27 + AudioStream(); 2.28 virtual ~AudioStream(); 2.29 2.30 - void play(); 2.31 + void play(bool loop = false); 2.32 void stop(); 2.33 + 2.34 + virtual void rewind() = 0; 2.35 }; 2.36 2.37 #endif // AUDIO_STREAM_H_