#include <deque>
#include <list>
#include <stdexcept>
-#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/cstdint.hpp>
#include "hash.hh"
#include "log.hh"
-#include "manager.hh"
#include "sound.hh"
#include "resource.hh"
#include "timer.hh"
#ifndef BUF_SIZE
-#define BUF_SIZE (4096)
+#define BUF_SIZE (4096 * 64)
#endif
-#define NUM_BUFFERS (16)
+#define NUM_BUFFERS (4)
namespace moof {
+/*] Sound backend
+ *************************************************************************/
+
class sound_backend
{
public:
alcMakeContextCurrent(0);
alcDestroyContext(al_context);
alcCloseDevice(al_device);
- log_info("unloaded sound device ALSA");
}
}
class sound_resource;
typedef resource_handle<sound_resource> sound_handle;
+MOOF_REGISTER_RESOURCE(sound_resource, ogg, sounds);
-class sound_resource_loader
-{
-public:
-
- sound_resource_loader()
- {
- resource::register_type<sound_resource>("ogg");
- }
-
- ~sound_resource_loader()
- {
- resource::unregister_type("ogg");
- }
-};
-
-static sound_resource_loader loader;
-
-
-// SOUND BUFFER
+/*] Sound buffer
+ *************************************************************************/
class buffer
{
alBufferData(buffer_, format, data, size, freq);
retain_counts_[buffer_] = 1;
- log_warning("ctor buffer:", buffer_);
}
buffer(const buffer& buf)
{
alSourceQueueBuffers(source, 1, &buffer_);
retain();
- log_warning("queued buffer:", buffer_);
}
}
{
ALuint buf = (ALuint)-1;
alSourceUnqueueBuffers(source, 1, &buf);
- log_warning("unqueued buffer:", buf);
return buffer(buf);
}
void set(ALuint source) const
{
- log_warning("set buffer:", buffer_);
if (*this) alSourcei(source, AL_BUFFER, buffer_);
}
{
alDeleteBuffers(1, &buffer_);
retain_counts_.erase(it);
- log_warning("kill buffer:", buffer_);
}
}
-// SOUND RESOURCE
+/*] Sound resource
+ *************************************************************************/
class sound_resource : public boost::noncopyable
{
sound_resource(const std::string& path)
{
- log_info("audio path is", path);
if (ov_fopen((char*)path.c_str(), &file_) < 0)
{
throw std::runtime_error("problem reading audio: " + path);
}
else if (result == 0 && size > 0)
{
- log_info("loaded", size, "bytes from vorbis");
vorbis_info* info = ov_info(&file_, section);
buffer_ = buffer(data, size,
get_audio_format(info), info->rate);
buf = buffer_;
- log_info("this section is", section);
- log_info("audio format is", get_audio_format(info));
- log_info("audio freq is", info->rate);
return true;
}
else
if (result > 0)
{
- log_info("loaded", result, "bytes from vorbis");
vorbis_info* info = ov_info(&file_, section);
buf = buffer(data, result, get_audio_format(info), info->rate);
sample = ov_pcm_tell(&file_);
- log_info("this section is", section);
- log_info("next sample is", sample);
- log_info("audio format is", get_audio_format(info));
- log_info("audio freq is", info->rate);
return true;
}
};
+/*] Sound class
+ *************************************************************************/
class sound::impl
{
init();
}
- impl(const std::string& path)
+ impl(const std::string& name)
{
- log_info("sound::impl constructor");
init();
- enqueue(path);
+ enqueue(name);
}
void init()
sample_ = 0;
alGenSources(1, &source_);
- log_error("alGenSources:", alGetError());
ALfloat zero[] = {0.0f, 0.0f, 0.0f};
alSourcef(source_, AL_PITCH, 1.0f);
alSourcef(source_, AL_GAIN, 1.0f);
alSourcefv(source_, AL_POSITION, zero);
alSourcefv(source_, AL_VELOCITY, zero);
- log_error("init:", alGetError());
}
~impl()
if (handle->read(buf))
{
- log_info("playing source...");
buf.set(source_);
alSourcei(source_, AL_LOOPING, is_looping_);
alSourcePlay(source_);
if (!is_playing_)
{
alSourcei(source_, AL_LOOPING, false);
- log_error("set not looping:", alGetError());
sound_handle handle = queue_.front();
ALint queued = 0;
alGetSourcei(source_, AL_BUFFERS_QUEUED, &queued);
- log_info("buffers queued:", queued);
}
}
if (!stream_timer_.is_valid())
{
stream_timer_.init(boost::bind(&impl::stream_update, this, _1, _2),
- 0.01, timer::repeat);
+ SCALAR(0.5), timer::repeat);
}
- log_info("streaming source...");
alSourcePlay(source_);
- log_error("playing:", alGetError());
is_playing_ = true;
}
// begin the next buffer in the queue
handle->read(buf, sample_);
buf.queue(source_);
- log_info("loading new buffer");
}
else if (is_looping_)
{
// reload the same buffer
- log_info("looping same buffer");
-
queue_.push_back(handle);
handle->read(buf, sample_);
buf.queue(source_);
}
- void sample(const std::string& path)
+ void sample(const std::string& name)
{
stop();
alSourcei(source_, AL_BUFFER, AL_NONE);
queue_.clear();
- enqueue(path);
+ enqueue(name);
}
- void enqueue(const std::string& path)
+ void enqueue(const std::string& name)
{
- sound_handle handle = resource::load(path);
+ sound_handle handle = resource::load(name, "ogg");
queue_.push_back(handle);
}
sound::sound(const std::string& path) :
// pass through
- impl_(new sound::impl(path))
-{
- log_info("sound constructor");
-}
+ impl_(new sound::impl(path)) {}
void sound::sample(const std::string& path)
void sound::play()
-{
- // pass through
- impl_->play();
-}
-
-void sound::stream()
{
// pass through
impl_->stream();
{
if (is_playing()) pause();
else play();
- // TODO: what about streaming sources?
}
bool sound::is_playing() const