|
From: Lasse Kärkkäi. <tr...@us...> - 2010-08-12 22:45:08
|
Module: performous
Branch: master
Commit: 7b5d9e1559f236a44c38e8c82675f1d627423d94
Author: Vincent Le Ligeour <yo...@us...>
Date: Mon Jul 5 21:26:46 2010 +0200
Added note synth to audio code
---
game/audio.cc | 45 +++++++++++++++++++++++++++++++++++++++++++++
game/audio.hh | 2 +-
2 files changed, 46 insertions(+), 1 deletions(-)
diff --git a/game/audio.cc b/game/audio.cc
index ac93f15..1cb771a 100644
--- a/game/audio.cc
+++ b/game/audio.cc
@@ -102,6 +102,36 @@ struct Sample {
}
};
+struct Synth {
+ private:
+ Notes m_notes;
+ double srate; ///< Sample rate
+ public:
+ Synth(Notes const& notes, unsigned int sr) : m_notes(notes), srate(sr) {};
+ void operator()(float* begin, float* end, double position) {
+ static double phase = 0.0;
+ for (float *i = begin; i < end; ++i) *i *= 0.3; // Decrease music volume
+
+ std::vector<float> mixbuf(end - begin);
+ Notes::const_iterator it = m_notes.begin();
+
+ while (it != m_notes.end() && it->end < position) ++it;
+ if (it == m_notes.end() || it->type == Note::SLEEP || it->begin > position) { phase = 0.0; return; }
+ int note = it->note % 12;
+ double d = (note + 1) / 13.0;
+ double freq = MusicalScale().getNoteFreq(note + 12);
+ double value = 0.0;
+ // Synthesize tones
+ for (size_t i = 0, iend = mixbuf.size(); i != iend; ++i) {
+ if (i % 2 == 0) {
+ value = d * 0.2 * std::sin(phase) + 0.2 * std::sin(2 * phase) + (1.0 - d) * 0.2 * std::sin(4 * phase);
+ phase += 2.0 * M_PI * freq / srate;
+ }
+ begin[i] += value;
+ }
+ }
+};
+
struct Command {
enum { TRACK_FADE, SAMPLE_RESET } type;
@@ -112,6 +142,8 @@ struct Command {
struct Output {
boost::mutex mutex;
boost::mutex samples_mutex;
+ boost::mutex synth_mutex;
+ std::auto_ptr<Synth> synth;
std::auto_ptr<Music> preloading;
boost::ptr_vector<Music> playing, disposing;
boost::ptr_map<std::string, Sample> samples;
@@ -167,6 +199,13 @@ struct Output {
}
}
}
+ // Mix synth if available (should be done at the end)
+ {
+ boost::mutex::scoped_try_lock l(synth_mutex, boost::defer_lock);
+ if(l.try_lock() && synth.get() && !playing.empty()) {
+ (*synth.get())(begin, end, playing[0].pos());
+ }
+ }
}
};
@@ -326,5 +365,11 @@ void Audio::streamFade(std::string track, double fadeLevel) {
o.commands.push_back(cmd);
}
+void Audio::toggleSynth(Notes const& notes) {
+ Output& o = self->output;
+ boost::mutex::scoped_lock l(o.synth_mutex);
+ o.synth.get() ? o.synth.reset() : o.synth.reset(new Synth(notes, getSR()));
+}
+
boost::ptr_vector<Analyzer>& Audio::analyzers() { return self->analyzers; }
diff --git a/game/audio.hh b/game/audio.hh
index 1087c8f..dab6770 100644
--- a/game/audio.hh
+++ b/game/audio.hh
@@ -54,7 +54,7 @@ public:
void togglePause() { pause(!isPaused()); }
void pause(bool state = true);
bool isPaused() const;
- void toggleSynth(Notes const&) { /*m_notes = (m_notes ? NULL : ¬es); */} ///< toggles synth playback
+ void toggleSynth(Notes const&); ///< toggles synth playback
/// Adjust volume level of a single track (used for muting incorrectly played instruments). Range 0.0 to 1.0.
void streamFade(std::string track, double volume);
double getSR() const { return 48000.0; }
|