|
From: Yoda-JM <yo...@us...> - 2010-08-15 14:51:56
|
Module: performous
Branch: joinmenu
Commit: da7996816460ccd179e6a3244f76aaa196be7276
Author: Vincent Le Ligeour <yo...@us...>
Date: Sun Jun 20 21:16:30 2010 +0200
Added draft of sample playing
---
game/audio.cc | 75 +++++++++++++++++++++++++++++++++++++++++++++-
game/audio.hh | 7 ++++-
game/ffmpeg.hh | 2 +-
game/screen_practice.cc | 3 ++
4 files changed, 83 insertions(+), 4 deletions(-)
diff --git a/game/audio.cc b/game/audio.cc
index b82be8d..fcdb3bc 100644
--- a/game/audio.cc
+++ b/game/audio.cc
@@ -68,10 +68,46 @@ public:
}
};
+#define MAX_SAMPLE_SIZE 2000000
+
+// rename to Sample once totally implemented
+struct SampleNew {
+ private:
+ std::vector<float> sample_buf;
+ unsigned int srate;
+ double m_pos;
+ public:
+ SampleNew(std::string filename, unsigned sr) : srate(sr), m_pos() {
+ FFmpeg mpeg(false, true, filename, sr);
+ // here transfer all the samples to sample_buf
+ //
+ sample_buf.resize(MAX_SAMPLE_SIZE);
+ }
+ bool operator()(float* begin, float* end) {
+ if( m_pos >= sample_buf.size()) {
+ // No more data to play in this sample
+ return false;
+ }
+ for (size_t i = 0, iend = end - begin; i != iend; ++i) {
+ if(m_pos + i > sample_buf.size()) {
+ // no more data to fill
+ break;
+ }
+ begin[i] += sample_buf[m_pos + i];
+ }
+ m_pos += end - begin;
+ }
+ void seek(double time) {
+ m_pos = time * srate * 2.0;
+ }
+};
+
+
struct Audio::Impl {
boost::mutex mutex;
std::auto_ptr<Music> preloading;
boost::ptr_vector<Music> playing, disposing;
+ boost::ptr_map<std::string, SampleNew> playing_samples, sleeping_samples;
portaudio::Init init;
boost::ptr_vector<portaudio::Stream> streams;
volatile bool paused;
@@ -101,6 +137,12 @@ struct Audio::Impl {
if (!l.owns_lock()) keep = true; // Cannot dispose without lock
if (keep) ++i; else disposing.transfer(disposing.end(), playing.begin() + i, playing);
}
+ for(boost::ptr_map<std::string, SampleNew>::iterator it = playing_samples.begin() ; it != playing_samples.end() ; ++it) {
+ boost::mutex::scoped_try_lock l(mutex);
+ if( (*it->second)(begin, end) == false && l.owns_lock()) {
+ sleeping_samples.transfer(sleeping_samples.end(), it, playing_samples);
+ }
+ }
}
int operator()(void const* input, void* output, unsigned long frames, const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags) try {
float const* in = static_cast<float const*>(input);
@@ -123,8 +165,37 @@ bool Audio::isOpen() const {
boost::mutex::scoped_lock l(self->mutex);
return !self->streams.empty();
}
-
-void Audio::play(Sample const& s, std::string const& volumeSetting) {
+
+void Audio::loadSample(std::string streamId, std::string filename) {
+ std::cout << ">>> Loading sample \"" << streamId << "\"" << std::endl;
+ {
+ boost::mutex::scoped_lock l(self->mutex);
+ self->sleeping_samples.insert(streamId, new SampleNew(filename, getSR()));
+ }
+}
+void Audio::playSample(std::string streamId) {
+ boost::mutex::scoped_lock l(self->mutex);
+ boost::ptr_map<std::string, SampleNew>::iterator it = self->sleeping_samples.find(streamId);
+ if( it == self->sleeping_samples.end() ) {
+ boost::ptr_map<std::string, SampleNew>::iterator it = self->playing_samples.find(streamId);
+ if( it == self->playing_samples.end() ) {
+ throw std::runtime_error("Cannot play sample : " + streamId);
+ } else {
+ it->second->seek(0.0);
+ }
+ } else {
+ it->second->seek(0.0);
+ self->playing_samples.transfer(self->playing_samples.end(), it, self->sleeping_samples);
+ }
+}
+
+void Audio::unloadSample(std::string streamId) {
+ std::cout << ">>> Unloading sample \"" << streamId << "\"" << std::endl;
+ {
+ boost::mutex::scoped_lock l(self->mutex);
+ self->sleeping_samples.erase(streamId);
+ self->playing_samples.erase(streamId);
+ }
}
void Audio::playMusic(std::map<std::string,std::string> const& filenames, bool preview, double fadeTime, double startPos) {
diff --git a/game/audio.hh b/game/audio.hh
index ab310a8..8475e3d 100644
--- a/game/audio.hh
+++ b/game/audio.hh
@@ -11,10 +11,12 @@
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/scoped_ptr.hpp>
+// TODO: should be removed
struct Sample {
Sample(std::string, unsigned) {}
};
+
/** @short High level audio playback API **/
class Audio {
struct Impl;
@@ -34,7 +36,10 @@ public:
/// plays a list of songs
void playMusic(std::map<std::string,std::string> const& filenames, bool preview = false, double fadeTime = 0.5, double startPos = 0.0);
/// plays a sample
- void play(Sample const& s, std::string const& volumeSetting);
+ void loadSample(std::string streamId, std::string filename);
+ void playSample(std::string streamId);
+ void unloadSample(std::string streamId);
+ void play(Sample const& s, std::string const& volumeSetting) {};// TODO: remove
/// stops music
void stopMusic();
/// fades music out
diff --git a/game/ffmpeg.hh b/game/ffmpeg.hh
index 246f436..877b145 100644
--- a/game/ffmpeg.hh
+++ b/game/ffmpeg.hh
@@ -32,7 +32,7 @@ struct VideoFrame {
int width, ///< width of frame
height; ///< height of frame
/// data array
- std::vector<uint8_t> data;
+ std::vector<uint8_t> data;
/// constructor
VideoFrame(double ts, int w, int h): timestamp(ts), width(w), height(h) {}
VideoFrame(): timestamp(getInf()) {} // EOF marker
diff --git a/game/screen_practice.cc b/game/screen_practice.cc
index 3c18e3d..335650d 100644
--- a/game/screen_practice.cc
+++ b/game/screen_practice.cc
@@ -19,6 +19,7 @@ void ScreenPractice::enter() {
b->dimensions.screenBottom().left(-0.4 + i * 0.2).fixedWidth(0.04);
}
unsigned int sr = m_audio.getSR();
+ m_audio.loadSample("drum bass", getPath("sounds/drum_bass.ogg"));
m_samples.push_back(Sample(getPath("sounds/drum_bass.ogg"), sr));
m_samples.push_back(Sample(getPath("sounds/drum_snare.ogg"), sr));
m_samples.push_back(Sample(getPath("sounds/drum_hi-hat.ogg"), sr));
@@ -28,6 +29,7 @@ void ScreenPractice::enter() {
}
void ScreenPractice::exit() {
+ m_audio.unloadSample("drum bass");
m_vumeters.clear();
m_samples.clear();
theme.reset();
@@ -43,6 +45,7 @@ void ScreenPractice::manageEvent(SDL_Event event) {
&& input::detail::devices[event.jbutton.which].type_match(input::DRUMS)) {
int b = input::buttonFromSDL(input::detail::devices[event.jbutton.which].type(), event.jbutton.button);
if (b != -1) m_audio.play(m_samples[unsigned(b) % m_samples.size()], "audio/fail_volume");
+ m_audio.playSample("drum bass");
}
}
|