You can subscribe to this list here.
| 2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(25) |
Jul
(288) |
Aug
(119) |
Sep
(31) |
Oct
(59) |
Nov
(458) |
Dec
(359) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2010 |
Jan
(268) |
Feb
(26) |
Mar
(36) |
Apr
(48) |
May
(119) |
Jun
(37) |
Jul
(173) |
Aug
(429) |
Sep
(137) |
Oct
(156) |
Nov
(59) |
Dec
(45) |
| 2011 |
Jan
(398) |
Feb
(257) |
Mar
(49) |
Apr
(5) |
May
(34) |
Jun
(11) |
Jul
(38) |
Aug
(12) |
Sep
(1) |
Oct
(49) |
Nov
(5) |
Dec
(10) |
| 2012 |
Jan
(21) |
Feb
(32) |
Mar
(20) |
Apr
(1) |
May
(2) |
Jun
|
Jul
(173) |
Aug
|
Sep
(25) |
Oct
(6) |
Nov
(44) |
Dec
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-26 01:13:23
|
Module: performous Branch: master Commit: 1c8423aebfa2f79d7c7ef3fac8a46a37e85d414e Author: Lasse Karkkainen <tro...@tr...> Date: Sun Jul 26 04:11:27 2009 +0300 Difficulty level and instrument selection. --- game/guitargraph.cc | 158 +++++++++++++++++++++++++++++++++---- game/guitargraph.hh | 134 +++++++++++++++++++++++++++++++- game/notes.hh | 9 ++- game/screen_sing.cc | 1 + game/songparser-ini.cc | 3 +- themes/default/bassneck.svg | 181 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 466 insertions(+), 20 deletions(-) |
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-26 01:13:19
|
Module: performous
Branch: master
Commit: 85b879f793d390bd32bb0438c153740a31672cb1
Author: Lasse Karkkainen <tro...@tr...>
Date: Sun Jul 26 01:17:02 2009 +0300
Print buttons on cursor. Crappy button.svg added, Yoda should have a better one.
Modified perspective.
---
game/guitargraph.cc | 25 ++++++++++---
game/guitargraph.hh | 1 +
themes/default/button.svg | 82 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 102 insertions(+), 6 deletions(-)
diff --git a/game/guitargraph.cc b/game/guitargraph.cc
index 9d08de3..7efc8cb 100644
--- a/game/guitargraph.cc
+++ b/game/guitargraph.cc
@@ -3,22 +3,22 @@
namespace {
const float past = -0.3f;
const float future = 3.0f;
- const float timescale = 30.0f;
+ const float timescale = 80.0f;
const float texCoordStep = -0.5f; // Two beat lines per neck texture => 0.5 tex units per beat
// Note: t is difference from playback time so it must be in range [past, future]
float time2y(float t) { return -timescale * (t - past) / (future - past); }
float time2a(float t) { return 1.0f - t / future; } // Note: we want 1.0 alpha already at zero t.
}
-GuitarGraph::GuitarGraph(Song const& song): m_song(song), m_neck("guitarneck.svg") {}
+GuitarGraph::GuitarGraph(Song const& song): m_song(song), m_neck("guitarneck.svg"), m_button("button.svg") {}
void GuitarGraph::draw(double time) {
if (m_song.tracks.empty()) return; // Can't render without tracks (FIXME: actually screen_song should choose a track for us)
Dimensions dimensions(1.0); // FIXME: bogus aspect ratio (is this fixable?)
- dimensions.screenBottom().fixedWidth(0.5f).left(-0.5f);
+ dimensions.screenBottom().fixedWidth(0.5f);
glutil::PushMatrix pmb;
glTranslatef(0.5 * (dimensions.x1() + dimensions.x2()), dimensions.y2(), 0.0f);
- glRotatef(80.0f, 1.0f, 0.0f, 0.0f);
+ glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
{ float s = dimensions.w() / 5.0f; glScalef(s, s, s); }
// Draw the neck
{
@@ -93,7 +93,7 @@ void GuitarGraph::draw(double time) {
glVertex2f(x + w, time2y(tBeg));
}
}
- glColor3f(1.0f, 1.0f, 1.0f);
+ glColor3f(0.0f, 0.0f, 0.0f);
// Draw the cursor
{
glutil::Begin block(GL_TRIANGLE_STRIP);
@@ -101,6 +101,19 @@ void GuitarGraph::draw(double time) {
glVertex2f(2.5f, time2y(0.01f));
glVertex2f(-2.5f, time2y(-0.01f));
glVertex2f(2.5f, time2y(-0.01f));
- }
+ }
+ for (int fret = 0; fret < 5; ++fret) {
+ float x = -2.0f + fret;
+ glutil::Color c = fretColors[fret];
+ if (true) {
+ c.r *= 0.5f;
+ c.g *= 0.5f;
+ c.b *= 0.5f;
+ }
+ glColor4fv(c);
+ m_button.dimensions.center(time2y(0.0)).middle(x);
+ m_button.draw();
+ }
+ glColor3f(1.0f, 1.0f, 1.0f);
}
diff --git a/game/guitargraph.hh b/game/guitargraph.hh
index 6f186a1..5b0c463 100644
--- a/game/guitargraph.hh
+++ b/game/guitargraph.hh
@@ -20,5 +20,6 @@ class GuitarGraph {
private:
Song const& m_song;
Texture m_neck;
+ Surface m_button;
};
diff --git a/themes/default/button.svg b/themes/default/button.svg
new file mode 100644
index 0000000..67f3086
--- /dev/null
+++ b/themes/default/button.svg
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="64"
+ height="64"
+ id="svg1901"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="button.svg"
+ sodipodi:docbase="/home/tsoots/ohj/translations/po"
+ version="1.0"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs1903">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective7" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8284271"
+ inkscape:cx="-1.2442731"
+ inkscape:cy="40"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ gridtolerance="10000"
+ inkscape:window-width="877"
+ inkscape:window-height="739"
+ inkscape:window-x="10"
+ inkscape:window-y="69"
+ showgrid="true"
+ inkscape:showpageshadow="false">
+ <inkscape:grid
+ type="xygrid"
+ id="grid2382"
+ visible="true"
+ enabled="true"
+ empspacing="8" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata1906">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Taso 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="opacity:1">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path2390"
+ sodipodi:cx="32"
+ sodipodi:cy="32"
+ sodipodi:rx="24"
+ sodipodi:ry="24"
+ d="M 56,32 A 24,24 0 1 1 8,32 A 24,24 0 1 1 56,32 z" />
+ </g>
+</svg>
|
|
From: Yoda-JM <yo...@us...> - 2009-07-25 11:39:15
|
Module: performous
Branch: 0.3
Commit: 12fd073b01436223373cc65d2bf46476e9a70697
Author: Vincent Le Ligeour <yo...@us...>
Date: Sat Jul 25 13:38:40 2009 +0200
Added performous 0.3.2 ebuild
---
.../performous/performous-0.3.2.ebuild | 124 ++++++++++++++++++++
1 files changed, 124 insertions(+), 0 deletions(-)
diff --git a/portage-overlay/games-arcade/performous/performous-0.3.2.ebuild b/portage-overlay/games-arcade/performous/performous-0.3.2.ebuild
new file mode 100644
index 0000000..41ae133
--- /dev/null
+++ b/portage-overlay/games-arcade/performous/performous-0.3.2.ebuild
@@ -0,0 +1,124 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /cvsroot/ultrastar-ng/UltraStar-ng/portage-overlay/games-arcade/performous/performous-9999.ebuild,v 1.10 2007/09/29 13:04:19 yoda-jm Exp $
+
+inherit games cmake-utils
+
+RESTRICT="nostrip"
+
+MY_PN=Performous
+MY_P=${MY_PN}-${PV}-Source
+SONGS_PN=ultrastar-songs
+
+DESCRIPTION="Karaoke game similar to Singstar"
+HOMEPAGE="http://performous.org"
+SRC_URI="mirror://sourceforge/${PN}/${MY_P}.tar.bz2
+ songs? (
+ mirror://sourceforge/${PN}/${SONGS_PN}-jc-1.zip
+ mirror://sourceforge/${PN}/${SONGS_PN}-libre-3.zip
+ mirror://sourceforge/${PN}/${SONGS_PN}-restricted-3.zip
+ mirror://sourceforge/${PN}/${SONGS_PN}-shearer-1.zip
+ )"
+
+LICENSE="GPL-2
+ songs? (
+ CCPL-Attribution-ShareAlike-NonCommercial-2.5
+ CCPL-Attribution-NonCommercial-NoDerivs-2.5
+ )"
+SLOT="0"
+KEYWORDS="~x86 ~amd64 ~ppc ~ppc64"
+
+IUSE="debug alsa portaudio pulseaudio jack songs gstreamer"
+
+RDEPEND="gnome-base/librsvg
+ dev-libs/boost
+ x11-libs/pango
+ dev-cpp/libxmlpp
+ media-libs/glew
+ media-libs/libsdl[joystick,opengl]
+ media-gfx/imagemagick
+ (
+ virtual/opengl
+ virtual/glu
+ )
+ >=media-video/ffmpeg-0.4.9_p20070616-r20
+ alsa? ( media-libs/alsa-lib )
+ jack? ( media-sound/jack-audio-connection-kit )
+ portaudio? ( media-libs/portaudio )
+ gstreamer? ( media-libs/gstreamer )
+ pulseaudio? ( media-sound/pulseaudio )
+ sys-apps/help2man
+ !games-arcade/ultrastar-ng"
+DEPEND="${RDEPEND}
+ >=dev-util/cmake-2.6.0"
+
+pkg_setup() {
+ games_pkg_setup
+ if ! built_with_use --missing true dev-libs/boost threads ; then
+ eerror "Please emerge dev-libs/boost with USE=threads"
+ fi
+}
+
+src_unpack() {
+ unpack "${MY_P}.tar.bz2"
+ mv "${MY_P}" "${P}"
+ if use songs; then
+ cd "${S}"
+ unpack "${SONGS_PN}-jc-1.zip"
+ unpack "${SONGS_PN}-libre-3.zip"
+ unpack "${SONGS_PN}-restricted-3.zip"
+ unpack "${SONGS_PN}-shearer-1.zip"
+ fi
+}
+
+src_compile() {
+ mkdir build
+ cd build
+ plugins="-DLIBDA_AUTODETECT_PLUGINS=false -DLIBDA_PLUGIN_TESTING=false"
+ if use alsa ; then
+ plugins="$plugins -DLIBDA_PLUGIN_ALSA=true"
+ else
+ plugins="$plugins -DLIBDA_PLUGIN_ALSA=false"
+ fi
+ if use jack ; then
+ plugins="$plugins -DLIBDA_PLUGIN_JACK=true"
+ else
+ plugins="$plugins -DLIBDA_PLUGIN_JACK=false"
+ fi
+ if use gstreamer ; then
+ plugins="$plugins -DLIBDA_PLUGIN_GSTREAMER=true"
+ else
+ plugins="$plugins -DLIBDA_PLUGIN_GSTREAMER=false"
+ fi
+ if use portaudio ; then
+ plugins="$plugins -DLIBDA_PLUGIN_PORTAUDIO=true"
+ else
+ plugins="$plugins -DLIBDA_PLUGIN_PORTAUDIO=false"
+ fi
+ if use pulseaudio ; then
+ plugins="$plugins -DLIBDA_PLUGIN_PULSE=true"
+ else
+ plugins="$plugins -DLIBDA_PLUGIN_PULSE=false"
+ fi
+ cmake \
+ -DCMAKE_CXX_FLAGS="${CXXFLAGS}" \
+ -DCMAKE_INSTALL_PREFIX="/usr" \
+ $plugins \
+ .. || die "cmake failed"
+ emake || die "emake failed"
+}
+
+src_install() {
+ cd build
+ emake DESTDIR="${D}" install || die "make install failed"
+ keepdir "/usr/ultrastar/songs"
+ rm -rf "${D}/usr/share/${PN}"/{applications,pixmaps}
+ if use songs; then
+ insinto "/usr/share/games/ultrastar"
+ doins -r ../songs || die "doins songs failed"
+ fi
+ doicon data/${PN}.xpm
+ domenu data/${PN}.desktop
+ dodoc ../docs/*.txt
+ prepgamesdirs
+}
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-25 08:32:32
|
Module: performous
Branch: master
Commit: a6dcb4d6314b680229d8afec66136780bd9b7cc7
Author: Lasse Karkkainen <tro...@tr...>
Date: Sat Jul 25 11:30:51 2009 +0300
Make cover browser stop at target if more than one second has elapsed since the previous frame (typically happens when the player has been in singing screen).
---
game/animvalue.hh | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/game/animvalue.hh b/game/animvalue.hh
index e3771a2..1f36eac 100644
--- a/game/animvalue.hh
+++ b/game/animvalue.hh
@@ -62,7 +62,11 @@ class AnimAcceleration {
double duration = seconds(curtime) - seconds(m_time);
m_time = curtime;
if (!(duration > 0.0)) return m_position; // Negative value or NaN, or no songs - skip processing
- if (duration > 1.0) duration = 1.0; // No more than one second per frame
+ if (duration > 1.0) {
+ // More than one second has elapsed, assume that we have stopped on target already
+ m_velocity = 0.0;
+ return m_position = m_target;
+ }
std::size_t rounds = 1.0 + 1000.0 * duration; // 1 ms or shorter timesteps
double t = duration / rounds;
for (std::size_t i = 0; i < rounds; ++i) {
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-25 08:32:31
|
Module: performous
Branch: 0.3
Commit: 4a963ae7ff6b44c578e4aad1304585b364b2ae78
Author: Lasse Karkkainen <tro...@tr...>
Date: Sat Jul 25 11:30:51 2009 +0300
Make cover browser stop at target if more than one second has elapsed since the previous frame (typically happens when the player has been in singing screen).
---
game/animvalue.hh | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/game/animvalue.hh b/game/animvalue.hh
index e3771a2..1f36eac 100644
--- a/game/animvalue.hh
+++ b/game/animvalue.hh
@@ -62,7 +62,11 @@ class AnimAcceleration {
double duration = seconds(curtime) - seconds(m_time);
m_time = curtime;
if (!(duration > 0.0)) return m_position; // Negative value or NaN, or no songs - skip processing
- if (duration > 1.0) duration = 1.0; // No more than one second per frame
+ if (duration > 1.0) {
+ // More than one second has elapsed, assume that we have stopped on target already
+ m_velocity = 0.0;
+ return m_position = m_target;
+ }
std::size_t rounds = 1.0 + 1000.0 * duration; // 1 ms or shorter timesteps
double t = duration / rounds;
for (std::size_t i = 0; i < rounds; ++i) {
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-25 07:52:12
|
Module: performous Branch: master Commit: e57db4ed937c4f0e50552b6f92b4c8560df1b514 Author: Lasse Karkkainen <tro...@tr...> Date: Sat Jul 25 10:51:47 2009 +0300 Use same fadeTime for in/out. --- game/audio.cc | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/game/audio.cc b/game/audio.cc index 865d70d..fbb2d21 100644 --- a/game/audio.cc +++ b/game/audio.cc @@ -75,7 +75,7 @@ void Audio::playMusic(std::vector<std::string> const& filenames, bool preview, d ch->add(boost::ref(*this)); m_volumeSetting = preview ? "audio/preview_volume" : "audio/music_volume"; ch->add(boost::ref(m_volume)); - m_mixer.fadein(da::shared_ref(ch), 0.5, startPos); + m_mixer.fadein(da::shared_ref(ch), fadeTime, startPos); if (!preview) pause(false); } |
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-25 07:35:24
|
Module: performous
Branch: master
Commit: bbc5af605a0e636710c80ff2120c913cb714053b
Author: Lasse Karkkainen <tro...@tr...>
Date: Sat Jul 25 10:34:41 2009 +0300
Fix volume control.
Fix race condition causing deadlocks and remove mutex from class Audio.
---
game/audio.cc | 31 ++++++++++++++-----------------
game/audio.hh | 4 ++--
libs/libda/include/libda/mixer.hpp | 4 ++--
3 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/game/audio.cc b/game/audio.cc
index 7e0eacd..865d70d 100644
--- a/game/audio.cc
+++ b/game/audio.cc
@@ -26,7 +26,6 @@ void Audio::open(std::string const& pdev, std::size_t rate, std::size_t frames)
}
bool Audio::operator()(da::pcm_data& areas) {
- boost::recursive_mutex::scoped_lock l(m_mutex);
std::size_t samples = areas.samples();
static double phase = 0.0;
// Synthesize tones
@@ -50,12 +49,16 @@ bool Audio::operator()(da::pcm_data& areas) {
areas.rawbuf[i] += value;
}
}
- return t < getLength();
+ // Set chain volume
+ double vol = config[m_volumeSetting].i();
+ if (vol > 0) vol = std::pow(10.0, (vol - 100.0) / 100.0 * 2.0);
+ m_volume.level(vol);
+ return true;
}
void Audio::playMusic(std::vector<std::string> const& filenames, bool preview, double fadeTime, double startPos) {
if (!isOpen()) return;
- boost::recursive_mutex::scoped_lock l(m_mutex);
+ da::lock_holder l = m_mixer.lock();
fadeout(fadeTime);
boost::shared_ptr<da::chain> ch(new da::chain());
for(std::vector<std::string>::const_iterator it = filenames.begin() ; it != filenames.end() ; ++it ) {
@@ -70,11 +73,8 @@ void Audio::playMusic(std::vector<std::string> const& filenames, bool preview, d
}
}
ch->add(boost::ref(*this));
- /*
m_volumeSetting = preview ? "audio/preview_volume" : "audio/music_volume";
ch->add(boost::ref(m_volume));
- */
- da::lock_holder l2 = m_mixer.lock();
m_mixer.fadein(da::shared_ref(ch), 0.5, startPos);
if (!preview) pause(false);
}
@@ -84,39 +84,36 @@ void Audio::playMusic(std::string const& filename, bool preview, double fadeTime
}
void Audio::stopMusic() {
- boost::recursive_mutex::scoped_lock l(m_mutex);
+ da::lock_holder l = m_mixer.lock();
m_notes = NULL;
m_mixer.clear();
m_streams.clear();
- std::cerr << "STOP!" << std::endl;
}
void Audio::fadeout(double fadeTime) {
- boost::recursive_mutex::scoped_lock l(m_mutex);
+ da::lock_holder l = m_mixer.lock();
m_notes = NULL;
m_mixer.fadeout(fadeTime);
m_streams.clear();
- std::cerr << "FADEOUT!" << fadeTime << std::endl;
}
double Audio::getPosition() const {
- boost::recursive_mutex::scoped_lock l(m_mutex);
+ da::lock_holder l = m_mixer.lock();
return m_streams.empty() ? getNaN() : m_streams.front()->pos();
}
double Audio::getLength() const {
- boost::recursive_mutex::scoped_lock l(m_mutex);
+ da::lock_holder l = m_mixer.lock();
return m_streams.empty() ? getNaN() : m_streams.front()->duration();
}
bool Audio::isPlaying() const {
- boost::recursive_mutex::scoped_lock l(m_mutex);
+ da::lock_holder l = m_mixer.lock();
return m_streams.empty() ? false : !m_streams.front()->eof();
}
void Audio::seek(double offset) {
- boost::recursive_mutex::scoped_lock l(m_mutex);
- da::lock_holder l2 = m_mixer.lock();
+ da::lock_holder l = m_mixer.lock();
for (size_t i = 0; i < m_streams.size(); ++i) {
Stream& s = *m_streams[i];
s.seek(clamp(s.pos() + offset, 0.0, s.duration()));
@@ -125,13 +122,13 @@ void Audio::seek(double offset) {
}
void Audio::seekPos(double pos) {
- boost::recursive_mutex::scoped_lock l(m_mutex);
- da::lock_holder l2 = m_mixer.lock();
+ da::lock_holder l = m_mixer.lock();
for (size_t i = 0; i < m_streams.size(); ++i) m_streams[i]->seek(pos);
pause(false);
}
void Audio::pause(bool state) {
+ da::lock_holder l = m_mixer.lock();
m_paused = state;
m_mixer.pause(m_paused);
}
diff --git a/game/audio.hh b/game/audio.hh
index f562e8a..74d0c6a 100644
--- a/game/audio.hh
+++ b/game/audio.hh
@@ -27,7 +27,6 @@ struct Stream {
/// crossfades songs
bool operator()(da::pcm_data& data) {
mpeg.audioQueue(data, m_pos);
- //if (volume.i() > 0) vol = std::pow(10.0, (volume.i() - 100.0) / 100.0 * 2.0);
return !eof();
}
void seek(double time) { m_pos = time * srate * 2.0; }
@@ -84,11 +83,12 @@ class Audio {
void toggleSynth(Notes const& notes) { m_notes = (m_notes ? NULL : ¬es); }
private:
- mutable boost::recursive_mutex m_mutex;
bool m_paused;
Notes const* volatile m_notes;
da::settings m_rs;
+ da::volume m_volume;
da::mixer m_mixer;
std::vector<boost::shared_ptr<Stream> > m_streams;
+ std::string m_volumeSetting;
};
diff --git a/libs/libda/include/libda/mixer.hpp b/libs/libda/include/libda/mixer.hpp
index 87bdc8c..20915ce 100644
--- a/libs/libda/include/libda/mixer.hpp
+++ b/libs/libda/include/libda/mixer.hpp
@@ -179,7 +179,7 @@ namespace da {
}
private:
callback_t m_stream;
- boost::recursive_mutex m_mutex;
+ mutable boost::recursive_mutex m_mutex;
friend class scoped_lock;
};
@@ -269,7 +269,7 @@ namespace da {
m_select.choose(p ? "paused" : "normal");
}
settings get_settings() { return m_settings; }
- lock_holder lock() { return lock_holder(new scoped_lock(m_mutex)); }
+ lock_holder lock() const { return lock_holder(new scoped_lock(m_mutex)); }
private:
void init() {
m_master.add(zero);
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-25 07:10:27
|
Module: performous Branch: master Commit: 1ad90f10912ff2cafb07d3a241b77d9f746a2bc1 Author: Lasse Karkkainen <tro...@tr...> Date: Sat Jul 25 10:09:13 2009 +0300 Fix fades (now done by libda). Restore synth mode. Preparing for proper volume control. --- game/audio.cc | 37 ++++++---- game/audio.hh | 35 ++-------- game/screen_songs.cc | 6 +- libs/libda/include/libda/mixer.hpp | 124 ++++++++++++++++++++++++++++-------- 4 files changed, 129 insertions(+), 73 deletions(-) |
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-25 03:49:40
|
Module: performous
Branch: master
Commit: 022990a4f52cd1b063228bb85b1df536a3b54230
Author: Lasse Karkkainen <tro...@tr...>
Date: Sat Jul 25 06:48:18 2009 +0300
Fix NULL pointer dereference in ffmpeg.cc when file open fails.
---
game/ffmpeg.cc | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/game/ffmpeg.cc b/game/ffmpeg.cc
index df38b23..a9a53b8 100644
--- a/game/ffmpeg.cc
+++ b/game/ffmpeg.cc
@@ -141,7 +141,7 @@ void FFmpeg::operator()() {
sigabrt = std::signal(SIGABRT, performous_ffmpeg_crash_hack);
sigsegv = std::signal(SIGSEGV, performous_ffmpeg_crash_hack);
#endif
- try { open(); } catch (std::exception const& e) { std::cerr << "FFMPEG failed to open " << m_filename << ": " << e.what() << std::endl; m_quit = true; }
+ try { open(); } catch (std::exception const& e) { std::cerr << "FFMPEG failed to open " << m_filename << ": " << e.what() << std::endl; m_quit = true; return; }
m_running = true;
audioQueue.setDuration(duration());
int errors = 0;
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-25 03:30:55
|
Module: performous
Branch: master
Commit: 10ba2a454d5d549e700a24e7b5ddd1b13697ca04
Author: Lasse Karkkainen <tro...@tr...>
Date: Sat Jul 25 06:29:26 2009 +0300
Added da::select which works as a switch-case for streams.
Implemented pause.
Removed old AudioSample code.
---
game/audio.cc | 12 ++++++--
game/audio.hh | 52 +----------------------------------
libs/libda/include/libda/mixer.hpp | 30 ++++++++++++++++++++-
3 files changed, 40 insertions(+), 54 deletions(-)
diff --git a/game/audio.cc b/game/audio.cc
index e5c5fc8..5a89b93 100644
--- a/game/audio.cc
+++ b/game/audio.cc
@@ -70,7 +70,7 @@ void Audio::playMusic(std::vector<std::string> const& filenames, bool preview, d
}
da::lock_holder l2 = m_mixer.lock();
for (size_t i = 0; i < m_streams.size(); ++i) m_mixer.add(da::shared_ref(m_streams[i]));
- if (!preview) m_paused = false;
+ if (!preview) pause(false);
}
void Audio::playMusic(std::string const& filename, bool preview, double fadeTime, double startPos) {
@@ -113,13 +113,19 @@ void Audio::seek(double offset) {
Stream& s = *m_streams[i];
s.seek(clamp(s.pos() + offset, 0.0, s.duration()));
}
- m_paused = false;
+ pause(false);
}
void Audio::seekPos(double pos) {
boost::recursive_mutex::scoped_lock l(m_mutex);
da::lock_holder l2 = m_mixer.lock();
for (size_t i = 0; i < m_streams.size(); ++i) m_streams[i]->seek(pos);
- m_paused = false;
+ pause(false);
+}
+
+void Audio::pause(bool state) {
+ m_paused = state;
+ da::lock_holder l2 = m_mixer.lock();
+ m_mixer.pause(m_paused);
}
diff --git a/game/audio.hh b/game/audio.hh
index b3125d3..0cf1b0e 100644
--- a/game/audio.hh
+++ b/game/audio.hh
@@ -13,55 +13,6 @@
using boost::int16_t;
-#if 0
-/// audiosamples for songfiles
-struct AudioSample {
- /// sample rate
- double srate;
- /// volume
- double volume;
- /// sample
- std::vector<int16_t> sample;
- /// current position in the sample
- unsigned int offset;
- AudioSample() {}
- /// constructor
- AudioSample(std::string const& filename, unsigned int sr): srate(sr), volume(), sample(), offset() {
- FFmpeg mpeg(false, true, filename, sr);
- while( !mpeg.audioQueue.eof() ) {
- std::vector<int16_t> buffer;
- mpeg.audioQueue.tryPop(buffer, 1024);
- sample.insert(sample.end(), buffer.begin(), buffer.end());
- if( sample.size() > 1024 * 256 ) break; // do not authorized sample > 256k
- }
- std:: cout << "Loading sample " << filename << " done (size: " << sample.size() << ")" << std::endl;
- }
- /// resets audio position
- void reset_position() {
- offset = 0;
- }
- /** plays and mixes samples
- */
- bool operator()(da::pcm_data& data) {
- std::size_t maxSamples = data.channels * data.frames;
- if( offset >= sample.size() ) return false;
- if( sample.size() - offset < maxSamples ) {
- // not enough data in sample
- for (size_t i = offset; i < sample.size(); ++i) {
- data.rawbuf[i-offset] += da::conv_from_s16(sample[i]);
- }
- offset = sample.size();
- } else {
- for (size_t i = offset; i < offset + maxSamples; ++i) {
- data.rawbuf[i-offset] += da::conv_from_s16(sample[i]);
- }
- offset += maxSamples;
- }
- return true;
- }
-};
-#endif
-
/// audiostream
/** allows buffering, fading and mixing of audiostreams
*/
@@ -150,7 +101,8 @@ class Audio {
/// callback for the audio backend (libda)
bool operator()(da::pcm_data& areas);
/// pauses and unpauses playback
- void togglePause() { m_paused = !m_paused; }
+ void togglePause() { pause(!m_paused); }
+ void pause(bool state = true);
/// toggles synth playback (F4)
void toggleSynth(Notes const& notes) { m_notes = (m_notes ? NULL : ¬es); }
diff --git a/libs/libda/include/libda/mixer.hpp b/libs/libda/include/libda/mixer.hpp
index 2153853..366bff3 100644
--- a/libs/libda/include/libda/mixer.hpp
+++ b/libs/libda/include/libda/mixer.hpp
@@ -155,10 +155,36 @@ namespace da {
};
typedef std::auto_ptr<scoped_lock> lock_holder;
+
+ template <typename Key> class select {
+ typedef std::map<Key, callback_t> streams;
+ public:
+ void choose(Key const& k) {
+ typename streams::iterator it = m_streams.find(k);
+ if (it == m_streams.end()) throw std::logic_error("da::select::key: Invalid key");
+ m_key = k;
+ m_stream = it->second;
+ }
+ void insert(Key const& k, callback_t const& cb) {
+ m_streams[k] = cb;
+ }
+ bool operator()(pcm_data& data) {
+ if (!m_stream) return false;
+ return m_stream(data);
+ }
+ private:
+ streams m_streams;
+ Key m_key;
+ callback_t m_stream;
+ };
class mixer {
public:
- mixer(): m_chain(zero), m_mutex(boost::ref(m_chain)) {}
+ mixer(): m_chain(zero), m_mutex(boost::ref(m_select)) {
+ m_select.insert("paused", zero);
+ m_select.insert("normal", boost::ref(m_chain));
+ pause(false);
+ }
mixer(settings& s): m_chain(zero), m_mutex(boost::ref(m_chain)) { start(s); }
void start(settings& s) { m_settings = s; start(); s = m_settings; }
void start() {
@@ -180,9 +206,11 @@ namespace da {
m_chain.streams.erase(m_chain.streams.begin() + 1, m_chain.streams.end());
m_chain.add(shared_ref(new fadeout(shared_ref(ch.release()), time)));
}
+ void pause(bool p) { m_select.choose(p ? "paused" : "normal"); }
settings get_settings() { return m_settings; }
lock_holder lock() { return lock_holder(new scoped_lock(m_mutex)); }
private:
+ select<std::string> m_select;
chain m_chain;
mutex_stream m_mutex;
settings m_settings;
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-25 02:50:32
|
Module: performous
Branch: master
Commit: 1c20692c7dc8a8acdd86ec26a060d4ca6b80fc99
Author: Lasse Karkkainen <tro...@tr...>
Date: Sat Jul 25 05:50:02 2009 +0300
Update all plugins for the new callback interface.
---
libs/libda/plugins/audio_dev_gst.cpp | 4 ++--
libs/libda/plugins/audio_dev_jack.cpp | 8 ++++----
libs/libda/plugins/audio_dev_pa18.cpp | 8 ++++----
libs/libda/plugins/audio_dev_pa19.cpp | 8 ++++----
libs/libda/plugins/audio_dev_pulse.cpp | 8 ++++----
libs/libda/plugins/audio_dev_tone.cpp | 4 ++--
6 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/libs/libda/plugins/audio_dev_gst.cpp b/libs/libda/plugins/audio_dev_gst.cpp
index 8af08fd..4dfc084 100644
--- a/libs/libda/plugins/audio_dev_gst.cpp
+++ b/libs/libda/plugins/audio_dev_gst.cpp
@@ -16,8 +16,8 @@ namespace {
std::vector<sample_t> buf(GST_BUFFER_SIZE(buffer)/sizeof(int16_t));
std::transform(iptr, iptr + buf.size(), buf.begin(), conv_from_s16);
std::size_t channels = self.s.channels();
- pcm_data data(&buf[0], (GST_BUFFER_SIZE(buffer) /sizeof(int16_t)) / channels, channels);
- self.s.callback()(data, self.s);
+ pcm_data data(&buf[0], (GST_BUFFER_SIZE(buffer) /sizeof(int16_t)) / channels, channels, self.s.rate());
+ self.s.callback()(data);
} catch (std::exception& e) {
self.s.debug(std::string("Exception from recording callback: ") + e.what());
}
diff --git a/libs/libda/plugins/audio_dev_jack.cpp b/libs/libda/plugins/audio_dev_jack.cpp
index 13b41bd..aea5a24 100644
--- a/libs/libda/plugins/audio_dev_jack.cpp
+++ b/libs/libda/plugins/audio_dev_jack.cpp
@@ -30,10 +30,10 @@ namespace {
std::vector<sample_t> buf;
buf.reserve(frames * m_s.channels());
for (jack_nframes_t fr = 0; fr < frames; ++fr) for (size_t ch = 0; ch < m_ports.size(); ++ch) buf.push_back(*samples[ch]++);
- pcm_data data(&buf[0], frames, m_ports.size());
+ pcm_data data(&buf[0], frames, m_ports.size(), m_s.rate());
m_s.set_frames(frames);
try {
- m_s.callback()(data, m_s);
+ m_s.callback()(data);
} catch (std::exception& e) {
m_s.debug(std::string("Exception from recording callback: ") + e.what());
}
@@ -85,10 +85,10 @@ namespace {
void shutdown() { m_client = NULL; m_s.debug("da::jack_playback: JACK server shutdown; processing terminated."); }
int callback(jack_nframes_t frames) {
std::vector<sample_t> buf(frames * m_s.channels());
- pcm_data data(&buf[0], frames, m_ports.size());
+ pcm_data data(&buf[0], frames, m_ports.size(), m_s.rate());
m_s.set_frames(frames);
try {
- m_s.callback()(data, m_s);
+ m_s.callback()(data);
} catch (std::exception& e) {
m_s.debug(std::string("Exception from playback callback: ") + e.what());
}
diff --git a/libs/libda/plugins/audio_dev_pa18.cpp b/libs/libda/plugins/audio_dev_pa18.cpp
index cddcf80..a28bd26 100644
--- a/libs/libda/plugins/audio_dev_pa18.cpp
+++ b/libs/libda/plugins/audio_dev_pa18.cpp
@@ -13,8 +13,8 @@ namespace {
try {
std::vector<sample_t> buf(frames * self.s.channels());
std::transform(iptr, iptr + buf.size(), buf.begin(), conv_from_s16);
- pcm_data data(&buf[0], frames, self.s.channels());
- self.s.callback()(data, self.s);
+ pcm_data data(&buf[0], frames, self.s.channels(), self.s.rate());
+ self.s.callback()(data);
} catch (std::exception& e) {
self.s.debug(std::string("Exception from recording callback: ") + e.what());
}
@@ -54,8 +54,8 @@ namespace {
iptr[i] = 0;
try {
std::vector<sample_t> buf(frames * self.s.channels());
- pcm_data data(&buf[0], frames, self.s.channels());
- self.s.callback()(data, self.s);
+ pcm_data data(&buf[0], frames, self.s.channels(), self.s.rate());
+ self.s.callback()(data);
for( unsigned int i = 0 ; i < frames*self.s.channels() ; i++ )
iptr[i] = da::conv_to_s16(data[i]);
} catch (std::exception& e) {
diff --git a/libs/libda/plugins/audio_dev_pa19.cpp b/libs/libda/plugins/audio_dev_pa19.cpp
index f431410..2383c13 100644
--- a/libs/libda/plugins/audio_dev_pa19.cpp
+++ b/libs/libda/plugins/audio_dev_pa19.cpp
@@ -13,8 +13,8 @@ namespace {
try {
std::vector<sample_t> buf(frames * self.s.channels());
std::transform(iptr, iptr + buf.size(), buf.begin(), conv_from_s16);
- pcm_data data(&buf[0], frames, self.s.channels());
- self.s.callback()(data, self.s);
+ pcm_data data(&buf[0], frames, self.s.channels(), self.s.rate());
+ self.s.callback()(data);
} catch (std::exception& e) {
self.s.debug(std::string("Exception from recording callback: ") + e.what());
}
@@ -68,8 +68,8 @@ namespace {
iptr[i] = 0;
try {
std::vector<sample_t> buf(frames * self.s.channels());
- pcm_data data(&buf[0], frames, self.s.channels());
- self.s.callback()(data, self.s);
+ pcm_data data(&buf[0], frames, self.s.channels(), self.s.rate());
+ self.s.callback()(data);
for( unsigned int i = 0 ; i < frames*self.s.channels() ; i++ )
iptr[i] = da::conv_to_s16(data[i]);
} catch (std::exception& e) {
diff --git a/libs/libda/plugins/audio_dev_pulse.cpp b/libs/libda/plugins/audio_dev_pulse.cpp
index 0b14ed2..30c35a0 100644
--- a/libs/libda/plugins/audio_dev_pulse.cpp
+++ b/libs/libda/plugins/audio_dev_pulse.cpp
@@ -52,9 +52,9 @@ namespace {
const std::size_t channels = m_s.channels();
buf.resize(m_s.frames() * channels);
if (pa_simple_read(m_stream, &buf[0], buf.size() * sizeof(sample_t), NULL) < 0) continue;
- pcm_data data(&buf[0], buf.size() / channels, channels);
+ pcm_data data(&buf[0], buf.size() / channels, channels, m_s.rate());
try {
- m_s.callback()(data, m_s);
+ m_s.callback()(data);
} catch (std::exception& e) {
m_s.debug(std::string("Exception from recording callback: ") + e.what());
}
@@ -105,9 +105,9 @@ namespace {
while (!m_quit) {
const std::size_t channels = m_s.channels();
buf.resize(m_s.frames() * channels);
- pcm_data data(&buf[0], buf.size() / channels, channels);
+ pcm_data data(&buf[0], buf.size() / channels, channels, m_s.rate());
try {
- m_s.callback()(data, m_s);
+ m_s.callback()(data);
} catch (std::exception& e) {
m_s.debug(std::string("Exception from playback callback: ") + e.what());
}
diff --git a/libs/libda/plugins/audio_dev_tone.cpp b/libs/libda/plugins/audio_dev_tone.cpp
index a0140f1..b126e8d 100644
--- a/libs/libda/plugins/audio_dev_tone.cpp
+++ b/libs/libda/plugins/audio_dev_tone.cpp
@@ -97,8 +97,8 @@ namespace {
try {
std::vector<sample_t> buf(s.frames() * s.channels());
std::generate(buf.begin(), buf.end(), accumgen(gen, s.channels()));
- pcm_data data(&buf[0], s.frames(), s.channels());
- s.callback()(data, s);
+ pcm_data data(&buf[0], s.frames(), s.channels(), s.rate());
+ s.callback()(data);
} catch (std::exception& e) {
s.debug(std::string("Exception from recording callback: ") + e.what());
}
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-25 02:50:29
|
Module: performous
Branch: master
Commit: 835b6cc355384926978fde665c1c7f404ab50b47
Author: Lasse Karkkainen <tro...@tr...>
Date: Sat Jul 25 05:41:55 2009 +0300
Add da::accumulator, a helper useful for summing the results of independent chains.
Add .samples() for pcm_data, doing the often needed multiplication channels * frames.
---
libs/libda/include/libda/audio.hpp | 1 +
libs/libda/include/libda/mixer.hpp | 30 ++++++++++++++++++++++++++++--
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/libs/libda/include/libda/audio.hpp b/libs/libda/include/libda/audio.hpp
index 8f95601..2fa7187 100644
--- a/libs/libda/include/libda/audio.hpp
+++ b/libs/libda/include/libda/audio.hpp
@@ -63,6 +63,7 @@ namespace da {
};
iter_by_ch begin(std::size_t ch) { return iter_by_ch(rawbuf, ch, channels); }
iter_by_ch end(std::size_t ch) { return iter_by_ch(rawbuf, ch, channels) + frames; }
+ std::size_t samples() const { return channels * frames; }
};
struct settings;
diff --git a/libs/libda/include/libda/mixer.hpp b/libs/libda/include/libda/mixer.hpp
index 3408e3d..2153853 100644
--- a/libs/libda/include/libda/mixer.hpp
+++ b/libs/libda/include/libda/mixer.hpp
@@ -43,7 +43,7 @@ namespace da {
void add(callback_t const& cb) {
streams.push_back(cb);
}
- /** Calls every scream in the chain and removes those that return false. **/
+ /** Calls every stream in the chain and removes those that return false. **/
bool operator()(pcm_data& data) {
streams_t::iterator wr = streams.begin();
for (streams_t::iterator it = wr; it != streams.end(); ++it) {
@@ -63,9 +63,35 @@ namespace da {
}
}
+ class accumulate: boost::noncopyable {
+ public:
+ typedef std::vector<callback_t> streams_t;
+ accumulate() {}
+ void add(callback_t const& cb) {
+ streams.push_back(cb);
+ }
+ /** Calls every stream in the chain and removes those that return false, summing the results. **/
+ bool operator()(pcm_data& data) {
+ std::vector<sample_t> buffer(data.samples());
+ pcm_data accumbuf(&buffer[0], data.frames, data.channels, data.rate);
+ streams_t::iterator wr = streams.begin();
+ for (streams_t::iterator it = wr; it != streams.end(); ++it) {
+ if ((*it)(accumbuf)) *wr++ = *it;
+ for (std::size_t i = 0; i < buffer.size(); ++i) {
+ data.rawbuf[i] += buffer[i];
+ buffer[i] = 0.0f;
+ }
+ }
+ if (wr != streams.end()) streams.erase(wr, streams.end());
+ return !streams.empty();
+ }
+ streams_t streams;
+ private:
+ };
+
class buffer: boost::noncopyable {
public:
- explicit buffer(size_t s): m_data(s) {}
+ explicit buffer(std::size_t s): m_data(s) {}
sample_t* begin() { return &m_data[0]; }
sample_t* end() { return begin() + m_data.size(); }
private:
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-25 02:50:29
|
Module: performous
Branch: master
Commit: 183f933b1a2370d1c56e5414534302404eab441a
Author: Lasse Karkkainen <tro...@tr...>
Date: Sat Jul 25 04:33:27 2009 +0300
Remove debug.
---
game/ffmpeg.cc | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/game/ffmpeg.cc b/game/ffmpeg.cc
index a291d34..df38b23 100644
--- a/game/ffmpeg.cc
+++ b/game/ffmpeg.cc
@@ -43,7 +43,6 @@ FFmpeg::~FFmpeg() {
}
double FFmpeg::duration() const {
- std::cout << m_running << ", " << pFormatCtx->duration << ", " << AV_TIME_BASE << std::endl;
double d = m_running ? pFormatCtx->duration / double(AV_TIME_BASE) : getNaN();
return d >= 0.0 ? d : getInf();
}
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-24 20:59:14
|
Module: performous
Branch: master
Commit: 1b57406abc6d95ec1b804df15d887300e3c7a3d5
Author: Lasse Karkkainen <tro...@tr...>
Date: Fri Jul 24 23:57:48 2009 +0300
Implement audio ringbuffer with 10 second history and a little bit of future.
Seeking backwards is broken, apparently because of FFMPEG bug.
---
game/ffmpeg.cc | 7 ++++-
game/ffmpeg.hh | 57 ++++++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 50 insertions(+), 14 deletions(-)
diff --git a/game/ffmpeg.cc b/game/ffmpeg.cc
index ae36a90..a291d34 100644
--- a/game/ffmpeg.cc
+++ b/game/ffmpeg.cc
@@ -27,6 +27,7 @@ FFmpeg::FFmpeg(bool _decodeVideo, bool _decodeAudio, std::string const& _filenam
FFmpeg::~FFmpeg() {
m_quit = true;
videoQueue.reset();
+ audioQueue.quit();
if (!m_thread) {
std::cerr << "FFMPEG crashed at some point, decoding " << m_filename << std::endl;
std::cerr << "Please restart Performous to avoid resource leaks and program crashes!" << std::endl;
@@ -143,10 +144,11 @@ void FFmpeg::operator()() {
#endif
try { open(); } catch (std::exception const& e) { std::cerr << "FFMPEG failed to open " << m_filename << ": " << e.what() << std::endl; m_quit = true; }
m_running = true;
- //audioQueue.setDuration(duration());
+ audioQueue.setDuration(duration());
int errors = 0;
while (!m_quit) {
try {
+ if (audioQueue.wantSeek()) m_seekTarget = 0.0;
if (m_seekTarget == m_seekTarget) seek_internal();
decodeNextFrame();
m_eof = false;
@@ -169,12 +171,13 @@ void FFmpeg::operator()() {
void FFmpeg::seek(double time, bool wait) {
m_seekTarget = time;
- videoQueue.reset(); // Empty this to unblock the internals in case buffers were full
+ videoQueue.reset(); audioQueue.reset(); // Empty these to unblock the internals in case buffers were full
if (wait) while (!m_quit && m_seekTarget == m_seekTarget) boost::thread::sleep(now() + 0.01);
}
void FFmpeg::seek_internal() {
videoQueue.reset();
+ audioQueue.reset();
int flags = 0;
if (m_seekTarget < position()) flags |= AVSEEK_FLAG_BACKWARD;
int stream = -1;
diff --git a/game/ffmpeg.hh b/game/ffmpeg.hh
index 8b51a03..2056e99 100644
--- a/game/ffmpeg.hh
+++ b/game/ffmpeg.hh
@@ -1,6 +1,7 @@
#pragma once
#include "util.hh"
+#include <boost/circular_buffer.hpp>
#include <boost/cstdint.hpp>
#include <boost/ptr_container/ptr_deque.hpp>
#include <boost/ptr_container/ptr_set.hpp>
@@ -110,36 +111,68 @@ class VideoFifo {
class AudioBuffer {
public:
- AudioBuffer(): m_eof(), m_sps(), m_duration(getNaN()) {}
+ AudioBuffer(size_t size = 1000000): m_data(size), m_pos(), m_posReq(), m_sps(), m_duration(getNaN()), m_quit() {}
+ /// Reset from FFMPEG side (seeking to beginning or terminate stream)
+ void reset() {
+ boost::mutex::scoped_lock l(m_mutex);
+ m_data.clear();
+ m_pos = 0;
+ l.unlock();
+ m_cond.notify_one();
+ }
+ void quit() {
+ boost::mutex::scoped_lock l(m_mutex);
+ m_quit = true;
+ l.unlock();
+ m_cond.notify_one();
+ }
/// set samples per second
void setSamplesPerSecond(unsigned sps) { m_sps = sps; }
/// get samples per second
unsigned getSamplesPerSecond() { return m_sps; }
void push(AudioFrame* f) {
+ if (f->data.empty()) return;
boost::mutex::scoped_lock l(m_mutex);
- if (f->data.empty()) {
- m_eof = true;
- m_duration = double(m_data.size()) / m_sps;
- } else m_data.insert(m_data.end(), f->data.begin(), f->data.end());
+ while (!condition()) m_cond.wait(l);
+ if (m_quit) return;
+ if (m_pos == 0 && f->timestamp != 0.0) {
+ //std::cerr << "Warning: The first audio frame begins at " << f->timestamp << " seconds instead of zero, compensating." << std::endl;
+ m_pos = f->timestamp * m_sps;
+ }
+ m_data.insert(m_data.end(), f->data.begin(), f->data.end());
+ m_pos += f->data.size();
}
bool operator()(da::pcm_data data, int64_t& pos) {
boost::mutex::scoped_lock l(m_mutex);
- int64_t samples = data.frames * data.channels;
- for (int64_t s = 0; s < samples; ++s) {
- size_t offset = pos++;
- if (offset < m_data.size()) data.rawbuf[s] += da::conv_from_s16(m_data[offset]);
+ size_t samples = data.frames * data.channels;
+ size_t idx = pos + m_data.size() - m_pos;
+ for (size_t s = 0; s < samples; ++s, ++idx) {
+ if (idx < m_data.size()) data.rawbuf[s] += da::conv_from_s16(m_data[idx]);
}
+ m_posReq = pos += samples;
+ l.unlock();
+ if (wantSeek()) reset();
+ if (condition()) m_cond.notify_one();
return !eof(pos);
}
- bool eof(int64_t pos) const { return m_eof && pos >= int64_t(m_data.size()); }
+ bool eof(int64_t pos) const { return double(pos) / m_sps >= m_duration; }
double duration() const { return m_duration; }
void setDuration(double seconds) { m_duration = seconds; }
+ bool wantSeek() {
+ size_t oldest = m_pos - m_data.size();
+ return oldest > 0 && m_posReq < int64_t(oldest);
+ }
private:
+ bool wantMore() { return int64_t(m_pos) - 30000 < m_posReq; }
+ bool condition() { return m_quit || wantMore() || wantSeek(); }
mutable boost::mutex m_mutex;
- std::vector<int16_t> m_data;
- bool m_eof;
+ boost::condition m_cond;
+ boost::circular_buffer<int16_t> m_data;
+ size_t m_pos;
+ int64_t m_posReq;
unsigned m_sps;
double m_duration;
+ bool m_quit;
};
// ffmpeg forward declarations
|
|
From: Yoda-JM <yo...@us...> - 2009-07-24 17:07:11
|
Module: performous
Branch: master
Commit: 06bd1451a61eee101a853e5ce02ac4661cd00136
Author: Vincent Le Ligeour <yo...@us...>
Date: Fri Jul 24 19:06:48 2009 +0200
Added Joystick events management
---
game/joystick.cc | 104 +++++++++++++++++++++++++++++++++++++++++++++--
game/joystick.hh | 49 ++++++++++++++++++++--
game/main.cc | 17 ++++++++
game/screen_practice.cc | 9 ++--
4 files changed, 167 insertions(+), 12 deletions(-)
diff --git a/game/joystick.cc b/game/joystick.cc
index a787e68..951a0c1 100644
--- a/game/joystick.cc
+++ b/game/joystick.cc
@@ -28,11 +28,33 @@ std::string Joystick::getDescription() const {
bool Joystick::buttonState(unsigned char _button_id) const {
return (SDL_JoystickGetButton(m_joystick, _button_id) != 0);
};
-unsigned char Joystick::hat(unsigned char _hat_id) const {
- return SDL_JoystickGetHat(m_joystick, _hat_id);
+JoystickEvent::HatDirection Joystick::hat(unsigned char _hat_id) const {
+ unsigned char direction = SDL_JoystickGetHat(m_joystick, _hat_id);
+ switch(direction) {
+ case SDL_HAT_LEFTUP:
+ return JoystickEvent::LEFT_UP;
+ case SDL_HAT_LEFT:
+ return JoystickEvent::LEFT;
+ case SDL_HAT_LEFTDOWN:
+ return JoystickEvent::LEFT_DOWN;
+ case SDL_HAT_UP:
+ return JoystickEvent::UP;
+ case SDL_HAT_CENTERED:
+ return JoystickEvent::CENTERED;
+ case SDL_HAT_DOWN:
+ return JoystickEvent::DOWN;
+ case SDL_HAT_RIGHTUP:
+ return JoystickEvent::RIGHT_UP;
+ case SDL_HAT_RIGHT:
+ return JoystickEvent::RIGHT;
+ case SDL_HAT_RIGHTDOWN:
+ return JoystickEvent::RIGHT_DOWN;
+ }
+ // we should not go here
+ return JoystickEvent::CENTERED;
};
-short Joystick::axe(unsigned char _axe_id) const {
- return SDL_JoystickGetAxis(m_joystick, _axe_id);
+short Joystick::axis(unsigned char _axis_id) const {
+ return SDL_JoystickGetAxis(m_joystick, _axis_id);
};
std::pair<int, int> Joystick::ball(int _ball_id) const {
int dx, dy;
@@ -40,6 +62,80 @@ std::pair<int, int> Joystick::ball(int _ball_id) const {
return std::pair<int,int>(dx,dy);
};
+void Joystick::addEvent(SDL_JoyAxisEvent event) {
+ JoystickEvent joy_event(JoystickEvent::AXIS_MOTION);
+
+ joy_event.axis_id = event.axis;
+ joy_event.axis_value = event.value;
+
+ m_events.push_back(joy_event);
+}
+void Joystick::addEvent(SDL_JoyBallEvent event) {
+ JoystickEvent joy_event(JoystickEvent::BALL_MOTION);
+
+ joy_event.ball_id = event.ball;
+ joy_event.ball_dx = event.xrel;
+ joy_event.ball_dy = event.yrel;
+
+ m_events.push_back(joy_event);
+}
+void Joystick::addEvent(SDL_JoyHatEvent event) {
+ JoystickEvent joy_event(JoystickEvent::HAT_MOTION);
+
+ joy_event.hat_id = event.hat;
+ switch(event.value) {
+ case SDL_HAT_LEFTUP:
+ joy_event.hat_direction = JoystickEvent::LEFT_UP;
+ break;
+ case SDL_HAT_LEFT:
+ joy_event.hat_direction = JoystickEvent::LEFT;
+ break;
+ case SDL_HAT_LEFTDOWN:
+ joy_event.hat_direction = JoystickEvent::LEFT_DOWN;
+ break;
+ case SDL_HAT_UP:
+ joy_event.hat_direction = JoystickEvent::UP;
+ break;
+ case SDL_HAT_CENTERED:
+ joy_event.hat_direction = JoystickEvent::CENTERED;
+ break;
+ case SDL_HAT_DOWN:
+ joy_event.hat_direction = JoystickEvent::DOWN;
+ break;
+ case SDL_HAT_RIGHTUP:
+ joy_event.hat_direction = JoystickEvent::RIGHT_UP;
+ break;
+ case SDL_HAT_RIGHT:
+ joy_event.hat_direction = JoystickEvent::RIGHT;
+ break;
+ case SDL_HAT_RIGHTDOWN:
+ joy_event.hat_direction = JoystickEvent::RIGHT_DOWN;
+ break;
+ default:
+ joy_event.hat_direction = JoystickEvent::CENTERED;
+ break;
+ }
+
+ m_events.push_back(joy_event);
+}
+void Joystick::addEvent(SDL_JoyButtonEvent event) {
+ JoystickEvent joy_event((event.type == SDL_JOYBUTTONDOWN) ? JoystickEvent::BUTTON_DOWN : JoystickEvent::BUTTON_UP);
+
+ joy_event.button_id = event.button;
+
+ m_events.push_back(joy_event);
+}
+bool Joystick::tryPollEvent(JoystickEvent& _event) {
+ if( m_events.empty() ) return false;
+
+ _event = m_events.front();
+ m_events.pop_front();
+ return true;
+}
+void Joystick::clearEvents() {
+ m_events.clear();
+}
+
void joysticks_init() {
unsigned int nbjoysticks = SDL_NumJoysticks();
std::cout << "Detecting " << nbjoysticks << " joysticks..." << std::endl;
diff --git a/game/joystick.hh b/game/joystick.hh
index ea1f4a4..a0003bf 100644
--- a/game/joystick.hh
+++ b/game/joystick.hh
@@ -1,5 +1,6 @@
#pragma once
+#include "SDL_events.h"
#include "SDL_joystick.h"
#include "audio.hh"
@@ -12,6 +13,31 @@
void joysticks_init();
+class JoystickEvent {
+ public:
+ enum Type {BUTTON_DOWN, BUTTON_UP, HAT_MOTION, AXIS_MOTION, BALL_MOTION};
+ JoystickEvent(): button_id(), hat_id(), hat_direction(CENTERED), axis_id(), axis_value(), ball_id(), ball_dx(), ball_dy() {};
+ JoystickEvent(Type _type): type(_type), button_id(), hat_id(), hat_direction(CENTERED), axis_id(), axis_value(), ball_id(), ball_dx(), ball_dy() {};
+ Type type;
+ // for BUTTON_DOWN and BUTTON_UP
+ unsigned char button_id;
+ // for HAT_MOTION
+ enum HatDirection {
+ LEFT_UP, UP, RIGHT_UP,
+ LEFT, CENTERED, RIGHT,
+ LEFT_DOWN, DOWN, RIGHT_DOWN
+ };
+ unsigned char hat_id;
+ HatDirection hat_direction;
+ // for AXIS_MOTION
+ unsigned char axis_id;
+ short axis_value;
+ // for BALL_MOTION
+ unsigned char ball_id;
+ short ball_dx;
+ short ball_dy;
+};
+
/// joystick class used for dealing with ps3 drumsets
class Joystick {
public:
@@ -23,14 +49,29 @@ class Joystick {
std::string getName() const;
/// get longer description of joystick
std::string getDescription() const;
- /// returns true if the button with _button_id is pressed
+ /// add an even from an SDL_JoyAxisEvent
+ void addEvent(SDL_JoyAxisEvent event);
+ /// add an even from an SDL_JoyBallEvent
+ void addEvent(SDL_JoyBallEvent event);
+ /// add an even from an SDL_JoyHatEvent
+ void addEvent(SDL_JoyHatEvent event);
+ /// add an even from an SDL_JoyButtonEvent
+ void addEvent(SDL_JoyButtonEvent event);
+ /// try to poll an event, return false if no more event is available
+ bool tryPollEvent(JoystickEvent& _event);
+ /// clear all the events
+ void clearEvents();
+ /// returns button state (true if pressed, else false)
bool buttonState(unsigned char _button_id) const;
- /// hi-hat
- unsigned char hat(unsigned char _hat_id) const;
- short axe(unsigned char _axe_id) const;
+ /// returns hi-hat state
+ JoystickEvent::HatDirection hat(unsigned char _hat_id) const;
+ /// returns axis state
+ short axis(unsigned char _axis_id) const;
+ /// returns ball state
std::pair<int, int> ball(int _ball_id) const;
private:
SDL_Joystick * m_joystick;
+ std::deque<JoystickEvent> m_events;
unsigned int m_id;
};
diff --git a/game/main.cc b/game/main.cc
index 3b2bae9..2efcaaa 100644
--- a/game/main.cc
+++ b/game/main.cc
@@ -1,6 +1,7 @@
#include "config.hh"
#include "fs.hh"
#include "screen.hh"
+#include "joystick.hh"
#include "screen_intro.hh"
#include "screen_songs.hh"
#include "screen_sing.hh"
@@ -44,6 +45,19 @@ static void checkEvents_SDL(ScreenManager& sm, Window& window) {
case SDL_VIDEORESIZE:
window.resize(event.resize.w, event.resize.h);
break;
+ case SDL_JOYAXISMOTION:
+ joysticks[event.jaxis.which].addEvent(event.jaxis);
+ break;
+ case SDL_JOYBALLMOTION:
+ joysticks[event.jball.which].addEvent(event.jball);
+ break;
+ case SDL_JOYHATMOTION:
+ joysticks[event.jhat.which].addEvent(event.jhat);
+ break;
+ case SDL_JOYBUTTONDOWN:
+ case SDL_JOYBUTTONUP:
+ joysticks[event.jbutton.which].addEvent(event.jbutton);
+ break;
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_ESCAPE) esc = false;
break;
@@ -75,6 +89,9 @@ static void checkEvents_SDL(ScreenManager& sm, Window& window) {
case GL_OUT_OF_MEMORY: std::cerr << "OpenGL error: invalid enum" << std::endl; break;
}
}
+ for(Joysticks::iterator it = joysticks.begin() ; it != joysticks.end() ; ++it ) {
+ it->second.clearEvents();
+ }
if( config["graphic/fullscreen"].b() != window.getFullscreen() )
window.setFullscreen(config["graphic/fullscreen"].b());
}
diff --git a/game/screen_practice.cc b/game/screen_practice.cc
index ba31139..7cd3339 100644
--- a/game/screen_practice.cc
+++ b/game/screen_practice.cc
@@ -40,9 +40,10 @@ void ScreenPractice::manageEvent(SDL_Event event) {
break;
}
}
- switch( event.type ) {
- case SDL_JOYBUTTONDOWN:
- switch( event.jbutton.button ) {
+ JoystickEvent joy_event;
+ for(Joysticks::iterator it = joysticks.begin() ; it != joysticks.end() ; ++it ) {
+ if( it->second.tryPollEvent(joy_event) && joy_event.type == JoystickEvent::BUTTON_DOWN) {
+ switch(joy_event.button_id) {
case PS3_DRUM_CONTROLLER_RED: // Snare drum
m_audio.playMusic(getDataPath("sounds/drum_snare.ogg"));
break;
@@ -62,7 +63,7 @@ void ScreenPractice::manageEvent(SDL_Event event) {
m_audio.playMusic(getDataPath("sounds/drum_bass.ogg"));
break;
}
- break;
+ }
}
}
|
|
From: Yoda-JM <yo...@us...> - 2009-07-24 08:37:37
|
Module: performous
Branch: 0.3
Commit: 5a82800e44a28a2abbd1cf7ffba92884b3136d33
Author: Vincent Le Ligeour <yo...@us...>
Date: Fri Jul 24 10:06:56 2009 +0200
Fixed bug reported by Markus (SDL key management problem)
---
game/screen_songs.cc | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/game/screen_songs.cc b/game/screen_songs.cc
index aac50e1..a939924 100644
--- a/game/screen_songs.cc
+++ b/game/screen_songs.cc
@@ -41,7 +41,7 @@ void ScreenSongs::manageEvent(SDL_Event event) {
SDLMod mod = event.key.keysym.mod;
if (m_jukebox) {
if (key == SDLK_ESCAPE || m_songs.empty()) m_jukebox = false;
- else if (key == SDLK_SPACE || (key == SDLK_PAUSE || (key == SDLK_p && mod && KMOD_CTRL))) m_audio.togglePause();
+ else if (key == SDLK_SPACE || (key == SDLK_PAUSE || (key == SDLK_p && mod & KMOD_CTRL))) m_audio.togglePause();
else if (key == SDLK_RETURN) sm->activateScreen("Sing");
else if (key == SDLK_LEFT) m_songs.advance(-1);
else if (key == SDLK_RIGHT) m_songs.advance(1);
@@ -59,7 +59,7 @@ void ScreenSongs::manageEvent(SDL_Event event) {
}
// The rest are only available when there are songs available
else if (m_songs.empty()) return;
- else if (key == SDLK_SPACE || (key == SDLK_PAUSE || (key == SDLK_p && mod && KMOD_CTRL))) m_audio.togglePause();
+ else if (key == SDLK_SPACE || (key == SDLK_PAUSE || (key == SDLK_p && mod & KMOD_CTRL))) m_audio.togglePause();
else if (key == SDLK_TAB && !(mod & KMOD_ALT)) m_songs.randomize();
else if (key == SDLK_RETURN) sm->activateScreen("Sing");
else if (key == SDLK_LEFT) m_songs.advance(-1);
|
|
From: Yoda-JM <yo...@us...> - 2009-07-24 08:07:34
|
Module: performous
Branch: master
Commit: 46918c73fbb8d9410a9818e5b8966c96802394e1
Author: Vincent Le Ligeour <yo...@us...>
Date: Fri Jul 24 10:06:56 2009 +0200
Fixed bug reported by Markus (SDL key management problem)
---
game/screen_songs.cc | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/game/screen_songs.cc b/game/screen_songs.cc
index 48aa52c..ed0aaca 100644
--- a/game/screen_songs.cc
+++ b/game/screen_songs.cc
@@ -41,7 +41,7 @@ void ScreenSongs::manageEvent(SDL_Event event) {
SDLMod mod = event.key.keysym.mod;
if (m_jukebox) {
if (key == SDLK_ESCAPE || m_songs.empty()) m_jukebox = false;
- else if (key == SDLK_SPACE || (key == SDLK_PAUSE || (key == SDLK_p && mod && KMOD_CTRL))) m_audio.togglePause();
+ else if (key == SDLK_SPACE || (key == SDLK_PAUSE || (key == SDLK_p && mod & KMOD_CTRL))) m_audio.togglePause();
else if (key == SDLK_RETURN) sm->activateScreen("Sing");
else if (key == SDLK_LEFT) m_songs.advance(-1);
else if (key == SDLK_RIGHT) m_songs.advance(1);
@@ -59,7 +59,7 @@ void ScreenSongs::manageEvent(SDL_Event event) {
}
// The rest are only available when there are songs available
else if (m_songs.empty()) return;
- else if (key == SDLK_SPACE || (key == SDLK_PAUSE || (key == SDLK_p && mod && KMOD_CTRL))) m_audio.togglePause();
+ else if (key == SDLK_SPACE || (key == SDLK_PAUSE || (key == SDLK_p && mod & KMOD_CTRL))) m_audio.togglePause();
else if (key == SDLK_TAB && !(mod & KMOD_ALT)) m_songs.randomize();
else if (key == SDLK_RETURN) sm->activateScreen("Sing");
else if (key == SDLK_LEFT) m_songs.advance(-1);
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-24 04:51:34
|
Module: performous
Branch: master
Commit: 4a51f0e538180564505e58fa0b65c7364d097566
Author: Lasse Karkkainen <tro...@tr...>
Date: Fri Jul 24 07:50:57 2009 +0300
Make song selector play all tracks and not just the first.
---
game/audio.cc | 9 +++------
game/screen_songs.cc | 7 ++++---
game/screen_songs.hh | 4 ++--
libs/libda/include/libda/mixer.hpp | 2 +-
4 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/game/audio.cc b/game/audio.cc
index 6a34d96..e5c5fc8 100644
--- a/game/audio.cc
+++ b/game/audio.cc
@@ -108,21 +108,18 @@ bool Audio::isPlaying() const {
void Audio::seek(double offset) {
boost::recursive_mutex::scoped_lock l(m_mutex);
+ da::lock_holder l2 = m_mixer.lock();
for (size_t i = 0; i < m_streams.size(); ++i) {
Stream& s = *m_streams[i];
s.seek(clamp(s.pos() + offset, 0.0, s.duration()));
- std::cout << "Seek by " << offset << " to " << s.pos() << std::endl;
}
m_paused = false;
}
void Audio::seekPos(double pos) {
boost::recursive_mutex::scoped_lock l(m_mutex);
- for (size_t i = 0; i < m_streams.size(); ++i) {
- Stream& s = *m_streams[i];
- s.seek(pos);
- std::cout << "Seek to " << pos << std::endl;
- }
+ da::lock_holder l2 = m_mixer.lock();
+ for (size_t i = 0; i < m_streams.size(); ++i) m_streams[i]->seek(pos);
m_paused = false;
}
diff --git a/game/screen_songs.cc b/game/screen_songs.cc
index 2909060..48aa52c 100644
--- a/game/screen_songs.cc
+++ b/game/screen_songs.cc
@@ -100,7 +100,8 @@ void ScreenSongs::draw() {
if (m_songbg.get()) m_songbg->draw();
if (m_video.get()) m_video->render(time);
if (!m_jukebox) theme->bg.draw();
- std::string music, songbg, video;
+ std::string songbg, video;
+ std::vector<std::string> music;
double videoGap = 0.0;
std::ostringstream oss_song, oss_order;
// Test if there are no songs
@@ -142,7 +143,7 @@ void ScreenSongs::draw() {
s.tex = TexCoords(); glColor3f(1.0, 1.0, 1.0); // Restore default attributes
}
}
- if (!song.music.empty()) music = song.music[0]; // FIXME: support multiple tracks
+ if (!song.music.empty()) music = song.music;
if (!song.background.empty()) songbg = song.path + song.background;
if (!song.video.empty()) { video = song.path + song.video; videoGap = song.videoGap; }
}
@@ -157,7 +158,7 @@ void ScreenSongs::draw() {
// Play/stop preview playback (if it is the time)
if (music != m_playing && m_playTimer.get() > 0.4) {
m_songbg.reset(); m_video.reset();
- if (music.empty()) m_audio.fadeout(); else m_audio.playMusic(music, m_jukebox ? 0.0 : 30.0, true, 0.5);
+ if (music.empty()) m_audio.fadeout(); else m_audio.playMusic(music, true, 1.0);
if (!songbg.empty()) try { m_songbg.reset(new Surface(songbg)); } catch (std::exception const&) {}
if (!video.empty() && config["graphic/video"].b()) m_video.reset(new Video(video, videoGap));
m_playing = music;
diff --git a/game/screen_songs.hh b/game/screen_songs.hh
index c640fb0..cf09b84 100644
--- a/game/screen_songs.hh
+++ b/game/screen_songs.hh
@@ -31,8 +31,8 @@ class ScreenSongs : public Screen {
boost::scoped_ptr<Surface> m_songbg;
boost::scoped_ptr<Video> m_video;
boost::scoped_ptr<ThemeSongs> theme;
- std::string m_playing;
- std::string m_playReq;
+ std::vector<std::string> m_playing;
+ std::vector<std::string> m_playReq;
AnimValue m_playTimer;
TextInput m_search;
boost::scoped_ptr<Surface> m_emptyCover;
diff --git a/libs/libda/include/libda/mixer.hpp b/libs/libda/include/libda/mixer.hpp
index 4b02360..3408e3d 100644
--- a/libs/libda/include/libda/mixer.hpp
+++ b/libs/libda/include/libda/mixer.hpp
@@ -49,7 +49,7 @@ namespace da {
for (streams_t::iterator it = wr; it != streams.end(); ++it) {
if ((*it)(data)) *wr++ = *it;
}
- if (wr != streams.end()) streams.erase(wr);
+ if (wr != streams.end()) streams.erase(wr, streams.end());
return !streams.empty();
}
streams_t streams;
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-24 03:18:32
|
Module: performous
Branch: master
Commit: ab6978ff0417e20972ddd1c9c93fbe68c2534fa6
Author: Lasse Karkkainen <tro...@tr...>
Date: Fri Jul 24 06:17:52 2009 +0300
A little bit of prebuffering time.
Remove separate playPreview.
---
game/audio.cc | 4 ++--
game/audio.hh | 9 ++-------
game/screen_songs.cc | 2 +-
3 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/game/audio.cc b/game/audio.cc
index 1ca9a5a..6a34d96 100644
--- a/game/audio.cc
+++ b/game/audio.cc
@@ -61,8 +61,8 @@ void Audio::playMusic(std::vector<std::string> const& filenames, bool preview, d
for(std::vector<std::string>::const_iterator it = filenames.begin() ; it != filenames.end() ; ++it ) {
try {
m_streams.push_back(boost::shared_ptr<Stream>(new Stream(*it, m_rs.rate(), preview ? config["audio/preview_volume"] : config["audio/music_volume"])));
- if (fadeTime > 0) m_streams.back()->fadein(fadeTime);
- if (startPos != 0.0) m_streams.back()->seek(startPos);
+ m_streams.back()->fadein(fadeTime);
+ m_streams.back()->seek(startPos);
} catch (std::runtime_error& e) {
std::cerr << "Error loading " << *it << " (" << e.what() << ")" << std::endl;
continue;
diff --git a/game/audio.hh b/game/audio.hh
index 4d1946a..b3125d3 100644
--- a/game/audio.hh
+++ b/game/audio.hh
@@ -123,14 +123,9 @@ class Audio {
* @param fadeTime time to fade
* @param startPos starting position
*/
- void playMusic(std::string const& filename, bool preview = false, double fadeTime = 0.1, double startPos = 0.0);
+ void playMusic(std::string const& filename, bool preview = false, double fadeTime = 0.1, double startPos = -0.1);
/// plays a list of songs
- void playMusic(std::vector<std::string> const& filenames, bool preview = false, double fadeTime = 0.1, double startPos = 0.0);
- /** Play a preview of the song, starting at startPos
- * @param filename the track filename
- * @param startPos starting position
- */
- void playPreview(std::string const& filename, double startPos) { playMusic(filename, true, 1.0, startPos); }
+ void playMusic(std::vector<std::string> const& filenames, bool preview = false, double fadeTime = 0.1, double startPos = -0.1);
/// get pause status
bool isPaused() { return m_paused; }
/// stops music
diff --git a/game/screen_songs.cc b/game/screen_songs.cc
index 80e0aa7..2909060 100644
--- a/game/screen_songs.cc
+++ b/game/screen_songs.cc
@@ -157,7 +157,7 @@ void ScreenSongs::draw() {
// Play/stop preview playback (if it is the time)
if (music != m_playing && m_playTimer.get() > 0.4) {
m_songbg.reset(); m_video.reset();
- if (music.empty()) m_audio.fadeout(); else m_audio.playPreview(music, m_jukebox ? 0.0 : 30.0);
+ if (music.empty()) m_audio.fadeout(); else m_audio.playMusic(music, m_jukebox ? 0.0 : 30.0, true, 0.5);
if (!songbg.empty()) try { m_songbg.reset(new Surface(songbg)); } catch (std::exception const&) {}
if (!video.empty() && config["graphic/video"].b()) m_video.reset(new Video(video, videoGap));
m_playing = music;
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-24 03:08:16
|
Module: performous Branch: master Commit: 7db51424e7556d0d9c947e9fc94cf33d0a45362a Author: Lasse Karkkainen <tro...@tr...> Date: Fri Jul 24 06:07:18 2009 +0300 Rewrote audio buffering/stream system in a new way so that it loads the entire song into buffer. Related fixes and cleanup everywhere. Pause is still broken. --- game/audio.cc | 33 +++++++--------- game/audio.hh | 35 ++++++----------- game/ffmpeg.cc | 6 +- game/ffmpeg.hh | 74 +++++++++++------------------------ game/screen_practice.cc | 12 +++--- game/screen_sing.cc | 15 +------ game/screen_sing.hh | 1 - libs/libda/include/libda/mixer.hpp | 6 +- 8 files changed, 65 insertions(+), 117 deletions(-) |
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-23 20:06:06
|
Module: performous Branch: master Commit: 42d57fa8fc02e22e082051ad21ee98cc32efd69f Author: Lasse Karkkainen <tro...@tr...> Date: Thu Jul 23 22:54:07 2009 +0300 Mixing with libda::mixer, but still using audio.hh Streams. Pause is currently broken and seeking works as usual (= badly). --- game/audio.cc | 110 +++++++---------------------- game/audio.hh | 35 ++++----- game/record.hh | 2 +- libs/libda/include/libda/audio.hpp | 5 +- libs/libda/include/libda/mixer.hpp | 124 +++++++++++++++++++++++++-------- libs/libda/plugins/audio_dev_alsa.cpp | 8 +- 6 files changed, 145 insertions(+), 139 deletions(-) |
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-23 20:06:06
|
Module: performous
Branch: master
Commit: 0dce4c7ba53fedae1e6e63b239ba950f9493ed5c
Author: Lasse Karkkainen <tro...@tr...>
Date: Thu Jul 23 23:04:41 2009 +0300
Fix fadeout with multiple streams.
---
libs/libda/include/libda/mixer.hpp | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libs/libda/include/libda/mixer.hpp b/libs/libda/include/libda/mixer.hpp
index 9e0e3ed..ce2cafc 100644
--- a/libs/libda/include/libda/mixer.hpp
+++ b/libs/libda/include/libda/mixer.hpp
@@ -92,7 +92,7 @@ namespace da {
class fadeout: boost::noncopyable {
public:
- fadeout(callback_t stream, double time = 1.0): m_stream(stream), m_pos(), m_time(time) { std::cerr << "fadeout" << std::endl; }
+ fadeout(callback_t stream, double time = 1.0): m_stream(stream), m_pos(), m_time(time) {}
bool operator()(pcm_data& data) {
bool ret = m_stream(data);
size_t end = m_time * data.rate;
@@ -151,7 +151,7 @@ namespace da {
if (m_chain.streams.size() == 1) return;
std::auto_ptr<chain> ch(new chain());
ch->streams = chain::streams_t(m_chain.streams.begin() + 1, m_chain.streams.end());
- m_chain.streams.erase(m_chain.streams.begin() + 1);
+ m_chain.streams.erase(m_chain.streams.begin() + 1, m_chain.streams.end());
m_chain.add(shared_ref(new fadeout(shared_ref(ch.release()), time)));
}
settings get_settings() { return m_settings; }
|
|
From: aperion <was...@us...> - 2009-07-22 14:32:17
|
Module: performous
Branch: ultraed
Commit: aec573babadcfa067bbf9dfa77526a61fe9bafde
Author: Christian Wasserthal <ap...@gm...>
Date: Wed Jul 22 16:31:19 2009 +0200
added two functions to the editor, to automatically adjust the #GAP
---
README.txt | 1 -
src/org/aperion/sound/FFTProject.java | 63 +++++++++++++++++++++++++++-
src/org/aperion/sound/swingui/MainGUI.java | 21 +++++++++
3 files changed, 83 insertions(+), 2 deletions(-)
diff --git a/README.txt b/README.txt
index b421a0e..f9d300a 100644
--- a/README.txt
+++ b/README.txt
@@ -22,7 +22,6 @@ What is not yet supported?
""""""""""""""""""""""""""
- take into account multiple channels
- use the harmonics to create a better contrast
- - changing notes
Dependencies.
diff --git a/src/org/aperion/sound/FFTProject.java b/src/org/aperion/sound/FFTProject.java
index 1bdde35..2066370 100644
--- a/src/org/aperion/sound/FFTProject.java
+++ b/src/org/aperion/sound/FFTProject.java
@@ -31,6 +31,8 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
+import javax.swing.JProgressBar;
+
import org.aperion.sound.TxtFile.NoteBar;
import org.aperion.util.AMath;
@@ -123,7 +125,7 @@ public class FFTProject{
}
}
catch(final ClassNotFoundException e){
- throw new IOException(e.toString());
+ throw new IOException(e.getMessage());
}
finally{
ois.close();
@@ -391,6 +393,65 @@ public class FFTProject{
}
}
+ public double linearGapSearch(final double stepInSeconds, final JProgressBar bar, final double[] harmonicWeights){
+ final double originalGap = txt.getGAP();
+ final int iMax = (int)((getLength()-txt.getNotes().last().getEndSecond()+originalGap)/stepInSeconds);
+ bar.setMinimum(0);
+ bar.setMaximum(iMax);
+ double bestGap = originalGap;
+ double bestScore = gapHelper(originalGap,harmonicWeights);
+ for(int i=0;i<iMax;i++){
+ bar.setValue(i);
+ final double score = gapHelper(i*stepInSeconds,harmonicWeights);
+ if(score>bestScore){
+ bestGap = i*stepInSeconds;
+ bestScore = score;
+ }
+ }
+ txt.setGAP(originalGap);
+ return bestGap;
+ }
+
+ public double optimizeGapLocally(final JProgressBar bar, final double[] harmonicWeights){
+ final double originalGap = txt.getGAP();
+ final double[] step = new double[]{0.1,0.01,0.001}; // seconds
+ double currentGap = originalGap;
+ double currentScore = gapHelper(originalGap,harmonicWeights);
+ bar.setMinimum(0);
+ bar.setMaximum(21*step.length);
+ for(int i=0;i<step.length;i++){
+ double bestGap = currentGap;
+ double bestScore = currentScore;
+ for(int j=-10;j<=10;j++){
+ bar.setValue(21*i+j+10);
+ final double score = gapHelper(currentGap+j*step[i],harmonicWeights);
+ if(score>bestScore){
+ bestGap = currentGap+j*step[i];
+ bestScore = score;
+ }
+ }
+ currentGap = bestGap;
+ currentScore = bestScore;
+ }
+ txt.setGAP(originalGap);
+ return currentGap;
+ }
+
+ /**
+ * Accumulates the note magnitudes with a different gap.
+ * @param newGap the #GAP to test
+ * @param harmonicWeights the harmonic weighting to use
+ * @return the sum of all note magnitudes
+ */
+ private double gapHelper(final double newGap, final double[] harmonicWeights){
+ txt.setGAP(newGap);
+ double score = 0d;
+ for(final NoteBar n:txt.getNotes()){
+ score += getHarmonicNoteMag(n,harmonicWeights);
+ }
+ return score;
+ }
+
/////////////////////////////////////////////////////////////////////////////////////////////////
public interface RepaintListener{
diff --git a/src/org/aperion/sound/swingui/MainGUI.java b/src/org/aperion/sound/swingui/MainGUI.java
index 30e7a5f..9ade467 100644
--- a/src/org/aperion/sound/swingui/MainGUI.java
+++ b/src/org/aperion/sound/swingui/MainGUI.java
@@ -61,6 +61,7 @@ import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
+import javax.swing.JProgressBar;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
@@ -151,6 +152,8 @@ public class MainGUI extends ClassLoader implements WindowListener, ActionListen
private final JMenuItem menuNotesAlign;
private final JMenuItem menuNotesTimer;
private final JMenuItem menuNotesClear;
+ private final JMenuItem menuNotesLinearGapSearch;
+ private final JMenuItem menuNotesOptimizeGap;
private final JButton playButton;
private final JButton stopButton;
@@ -286,6 +289,14 @@ public class MainGUI extends ClassLoader implements WindowListener, ActionListen
menuNotesClear.setMnemonic('c');
menuNotesClear.addActionListener(this);
menuNotes.add(menuNotesClear);
+ menuNotesLinearGapSearch = new JMenuItem("linear gap search");
+ menuNotesLinearGapSearch.setMnemonic('l');
+ menuNotesLinearGapSearch.addActionListener(this);
+ menuNotes.add(menuNotesLinearGapSearch);
+ menuNotesOptimizeGap = new JMenuItem("optimize gap locally");
+ menuNotesOptimizeGap.setMnemonic('o');
+ menuNotesOptimizeGap.addActionListener(this);
+ menuNotes.add(menuNotesOptimizeGap);
final JToolBar bar = new JToolBar();
bar.setFloatable(true);
@@ -844,6 +855,16 @@ public class MainGUI extends ClassLoader implements WindowListener, ActionListen
}
matchFreqBarToView();
}
+ else if(e.getSource()==menuNotesLinearGapSearch){
+ final JProgressBar bar = new JProgressBar(); // TODO there should be a progressbar somewhere to use
+ prj.getTextFile().setGAP(prj.linearGapSearch(0.5,bar,DEFAULT_HARMONIC_WEIGHTS));
+ cont.forceRepaint();
+ }
+ else if(e.getSource()==menuNotesOptimizeGap){
+ final JProgressBar bar = new JProgressBar(); // TODO there should be a progressbar somewhere to use
+ prj.getTextFile().setGAP(prj.optimizeGapLocally(bar,DEFAULT_HARMONIC_WEIGHTS));
+ cont.forceRepaint();
+ }
else{
throw new AssertionError();
}
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-21 14:30:24
|
Module: performous
Branch: master
Commit: 59208e93b7036b21e0b99bac873cdf3db6c02bb8
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Jul 21 03:52:09 2009 +0300
Adding mixer interface to libda.
Broke compatibility with older versions because callbacks now return bool instead of void. Return true to keep the old behavior.
---
game/audio.cc | 15 +++---
game/audio.hh | 4 +-
game/record.hh | 3 +-
libs/libda/include/libda/audio.hpp | 16 ++++---
libs/libda/include/libda/mixer.hpp | 93 ++++++++++++++++++++++++++++++++++++
5 files changed, 114 insertions(+), 17 deletions(-)
diff --git a/game/audio.cc b/game/audio.cc
index b49e06f..8c830e2 100644
--- a/game/audio.cc
+++ b/game/audio.cc
@@ -27,11 +27,11 @@ void Audio::open(std::string const& pdev, std::size_t rate, std::size_t frames)
m_playback.reset(new da::playback(m_rs));
}
-void Audio::operator()(da::pcm_data& areas, da::settings const&) {
+bool Audio::operator()(da::pcm_data& areas, da::settings const&) {
boost::recursive_mutex::scoped_lock l(m_mutex);
std::size_t samples = areas.channels * areas.frames;
static double phase = 0.0;
- std::fill(areas.m_buf, areas.m_buf + samples, 0.0f);
+ std::fill(areas.rawbuf, areas.rawbuf + samples, 0.0f);
if (!m_paused) {
if(m_need_resync) {
std::cout << "Audio need to be synched here" << std::endl;
@@ -61,13 +61,13 @@ void Audio::operator()(da::pcm_data& areas, da::settings const&) {
m_need_resync = false;
}
for (Streams::iterator it = m_streams.begin(); it != m_streams.end();) {
- it->playmix(areas.m_buf, samples);
+ it->playmix(areas.rawbuf, samples);
if (it->fade <= 0.0) { it = m_streams.erase(it); continue; }
++it;
}
}
for (boost::ptr_map<std::string, AudioSample>::iterator it = m_samples.begin(); it != m_samples.end();++it) {
- it->second->playmix(areas.m_buf, samples);
+ it->second->playmix(areas.rawbuf, samples);
}
// Synthesize tones
Notes const* n = m_notes;
@@ -75,8 +75,8 @@ void Audio::operator()(da::pcm_data& areas, da::settings const&) {
double t = getPosition();
Notes::const_iterator it = n->begin();
while (it != n->end() && it->end < t) ++it;
- for (size_t i = 0; i < samples; ++i) areas.m_buf[i] *= 0.3; // Decrease music volume
- if (it == n->end() || it->type == Note::SLEEP || it->begin > t) { phase = 0.0; return; }
+ for (size_t i = 0; i < samples; ++i) areas.rawbuf[i] *= 0.3; // Decrease music volume
+ if (it == n->end() || it->type == Note::SLEEP || it->begin > t) { phase = 0.0; return true; }
int n = it->note % 12;
double d = (n + 1) / 13.0;
double freq = MusicalScale().getNoteFreq(n + 12);
@@ -87,9 +87,10 @@ void Audio::operator()(da::pcm_data& areas, da::settings const&) {
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 / m_rs.rate();
}
- areas.m_buf[i] += value;
+ areas.rawbuf[i] += value;
}
}
+ return true;
}
void Audio::playMusic(std::vector<std::string> const& filenames, bool preview, double fadeTime, double startPos) {
diff --git a/game/audio.hh b/game/audio.hh
index 93d5917..76fc877 100644
--- a/game/audio.hh
+++ b/game/audio.hh
@@ -9,7 +9,7 @@
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/thread/recursive_mutex.hpp>
-#include <libda/audio.hpp>
+#include <libda/mixer.hpp>
using boost::int16_t;
@@ -162,7 +162,7 @@ class Audio {
double getPosition() const;
void operator()(); ///< Thread runs here, don't call directly
/// callback for the audio backend (libda)
- void operator()(da::pcm_data& areas, da::settings const&);
+ bool operator()(da::pcm_data& areas, da::settings const&);
/// pauses and unpauses playback
void togglePause() { m_paused = !m_paused; }
/// toggles synth playback (F4)
diff --git a/game/record.hh b/game/record.hh
index fe72f14..bc2f6dd 100644
--- a/game/record.hh
+++ b/game/record.hh
@@ -22,10 +22,11 @@ class Capture {
if (c.m_analyzers.size() < 4) c.m_analyzers.push_back(m_channels[ch] = new Analyzer(m_settings.rate()));
}
}
- void operator()(da::pcm_data& areas, da::settings const&) {
+ bool operator()(da::pcm_data& areas, da::settings const&) {
for(std::size_t ch = 0; ch < m_channels.size(); ++ch) {
if (m_channels[ch]) m_channels[ch]->input(areas.begin(ch), areas.end(ch));
}
+ return true;
}
}; // Device
boost::ptr_vector<Analyzer> m_analyzers; // This must come before the devices for correct destruction order
diff --git a/libs/libda/include/libda/audio.hpp b/libs/libda/include/libda/audio.hpp
index 52f3c4a..782ca8a 100644
--- a/libs/libda/include/libda/audio.hpp
+++ b/libs/libda/include/libda/audio.hpp
@@ -41,12 +41,12 @@ namespace da {
/** Provides various access iterators to a multich interleaved sample buffer. **/
class pcm_data {
public:
- sample_t* m_buf;
+ sample_t* rawbuf;
const std::size_t frames;
const std::size_t channels;
- pcm_data(sample_t* buf, std::size_t _frames, std::size_t _channels): m_buf(buf), frames(_frames), channels(_channels) {}
- sample_t& operator()(std::size_t frame, std::size_t channel) { return m_buf[frame * channels + channel]; }
- sample_t& operator[](std::size_t idx) { return m_buf[idx]; }
+ pcm_data(sample_t* buf, std::size_t _frames, std::size_t _channels): rawbuf(buf), frames(_frames), channels(_channels) {}
+ sample_t& operator()(std::size_t frame, std::size_t channel) { return rawbuf[frame * channels + channel]; }
+ sample_t& operator[](std::size_t idx) { return rawbuf[idx]; }
class iter_by_ch: public std::iterator<std::random_access_iterator_tag, sample_t> {
sample_t* m_buf;
std::size_t m_pos;
@@ -60,13 +60,15 @@ namespace da {
std::ptrdiff_t operator-(iter_by_ch const& rhs) const { return (m_pos - rhs.m_pos) / m_channels; }
// TODO: more operators
};
- iter_by_ch begin(std::size_t ch) { return iter_by_ch(m_buf, ch, channels); }
- iter_by_ch end(std::size_t ch) { return iter_by_ch(m_buf, ch, channels) + frames; }
+ iter_by_ch begin(std::size_t ch) { return iter_by_ch(rawbuf, ch, channels); }
+ iter_by_ch end(std::size_t ch) { return iter_by_ch(rawbuf, ch, channels) + frames; }
};
struct settings;
class pcm_data;
- typedef boost::function<void (pcm_data& it, settings const&)> callback_t;
+
+ /** The callback functor typedef. If the function returns false, it will be removed from the processing chain. **/
+ typedef boost::function<bool (pcm_data& it, settings const&)> callback_t;
struct settings {
static const std::size_t low;
diff --git a/libs/libda/include/libda/mixer.hpp b/libs/libda/include/libda/mixer.hpp
new file mode 100644
index 0000000..d502a7e
--- /dev/null
+++ b/libs/libda/include/libda/mixer.hpp
@@ -0,0 +1,93 @@
+#ifndef LIBDA_MIXER_HPP_INCLUDED
+#define LIBDA_MIXER_HPP_INCLUDED
+
+/**
+@file mixer.hpp LibDA mixer interface.
+
+Link with libda when you use this.
+**/
+
+#include "audio.hpp"
+#include <boost/scoped_ptr.hpp>
+#include <algorithm>
+
+namespace da {
+
+ template <typename T> class shared_reference_wrapper {
+ public:
+ explicit shared_reference_wrapper(boost::shared_ptr<T>& ptr): m_ptr(ptr) {}
+ operator T&() const { return *m_ptr; }
+ private:
+ boost::shared_ptr<T> m_ptr;
+ };
+
+ template <typename T> shared_reference_wrapper<T> shared_ref(boost::shared_ptr<T>& ptr) {
+ return shared_reference_wrapper<T>(ptr);
+ }
+
+ class chain {
+ public:
+ chain() {}
+ chain(callback_t const& cb): streams(1, cb) {}
+ typedef std::vector<callback_t> streams_t;
+ streams_t streams;
+ bool operator()(pcm_data& data, settings const& s) {
+ streams_t::iterator wr = streams.begin();
+ for (streams_t::iterator it = wr; it != streams.end(); ++it) {
+ if ((*it)(data, s)) *wr++ = *it;
+ }
+ streams.erase(wr);
+ return !streams.empty();
+ }
+ private:
+ };
+
+ namespace {
+ bool zero(pcm_data& data, settings const&) {
+ std::fill(data.rawbuf, data.rawbuf + (data.channels * data.frames), 0.0f);
+ return true;
+ }
+ }
+
+ class buffer {
+ public:
+ explicit buffer(size_t s): m_data(s) {}
+ sample_t* begin() { return &m_data[0]; }
+ sample_t* end() { return begin() + m_data.size(); }
+ private:
+ std::vector<sample_t> m_data;
+ };
+
+ class stream {
+ public:
+ bool operator()(pcm_data& data, settings const&) {
+ sample_t* b = m_buffer->begin();
+ sample_t* e = m_buffer->end();
+ size_t size = std::min(data.frames * data.channels, e - b - m_bufferpos);
+ for (size_t i = 0; i < size; ++i) {
+ data.rawbuf[i] = b[m_bufferpos++];
+ }
+ return true;
+ }
+ private:
+ uint64_t m_streampos;
+ boost::shared_ptr<buffer> m_buffer;
+ size_t m_bufferpos;
+ };
+
+ class mixer {
+ public:
+ mixer(settings s = settings()):
+ m_chain(zero),
+ m_settings(s.set_callback(m_chain)),
+ m_playback(m_settings)
+ {}
+ private:
+ chain m_chain;
+ settings m_settings;
+ playback m_playback;
+ };
+}
+
+#endif
+
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-21 14:30:24
|
Module: performous
Branch: master
Commit: d339c1ee60a5d23c6c055cd5705cf35063999215
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Jul 21 17:29:33 2009 +0300
Made Audio use da::mixer and connect itself to it as a stream.
---
game/audio.cc | 6 +++---
game/audio.hh | 4 ++--
libs/libda/include/libda/mixer.hpp | 31 ++++++++++++++++++++-----------
3 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/game/audio.cc b/game/audio.cc
index 8c830e2..82bcd37 100644
--- a/game/audio.cc
+++ b/game/audio.cc
@@ -16,15 +16,15 @@ Audio::Audio():
{}
void Audio::open(std::string const& pdev, std::size_t rate, std::size_t frames) {
- m_playback.reset();
+ m_mixer.reset();
stopMusic();
m_rs = da::settings(pdev)
- .set_callback(boost::ref(*this))
.set_channels(2)
.set_rate(rate)
.set_frames(frames)
.set_debug(std::cerr);
- m_playback.reset(new da::playback(m_rs));
+ m_mixer.reset(new da::mixer(m_rs));
+ m_mixer->add(boost::ref(*this));
}
bool Audio::operator()(da::pcm_data& areas, da::settings const&) {
diff --git a/game/audio.hh b/game/audio.hh
index 76fc877..6301310 100644
--- a/game/audio.hh
+++ b/game/audio.hh
@@ -125,7 +125,7 @@ class Audio {
/** Takes libda devstr and sample rate. Throws if the device fails. **/
void open(std::string const& pdev, std::size_t rate, std::size_t frames);
/// if audio is currently playing
- bool isOpen() const { return m_playback; }
+ bool isOpen() const { return m_mixer; }
/** Play a song beginning at startPos (defaults to 0)
* @param filename the track filename
* @param preview if the song preview is to play
@@ -178,7 +178,7 @@ class Audio {
bool m_need_resync;
Notes const* volatile m_notes;
da::settings m_rs;
- boost::scoped_ptr<da::playback> m_playback;
+ boost::scoped_ptr<da::mixer> m_mixer;
boost::ptr_map<std::string, AudioSample> m_samples;
};
diff --git a/libs/libda/include/libda/mixer.hpp b/libs/libda/include/libda/mixer.hpp
index d502a7e..fa23594 100644
--- a/libs/libda/include/libda/mixer.hpp
+++ b/libs/libda/include/libda/mixer.hpp
@@ -9,6 +9,7 @@ Link with libda when you use this.
#include "audio.hpp"
#include <boost/scoped_ptr.hpp>
+#include <boost/thread/mutex.hpp>
#include <algorithm>
namespace da {
@@ -25,21 +26,28 @@ namespace da {
return shared_reference_wrapper<T>(ptr);
}
- class chain {
+ class chain: boost::noncopyable {
+ typedef std::vector<callback_t> streams_t;
public:
chain() {}
- chain(callback_t const& cb): streams(1, cb) {}
- typedef std::vector<callback_t> streams_t;
- streams_t streams;
+ chain(callback_t const& cb): m_streams(1, cb) {}
+ void add(callback_t const& cb) {
+ boost::mutex::scoped_lock l(m_mutex);
+ m_streams.push_back(cb);
+ }
+ /** Calls every scream in the chain and removes those that return false. **/
bool operator()(pcm_data& data, settings const& s) {
- streams_t::iterator wr = streams.begin();
- for (streams_t::iterator it = wr; it != streams.end(); ++it) {
+ boost::mutex::scoped_lock l(m_mutex);
+ streams_t::iterator wr = m_streams.begin();
+ for (streams_t::iterator it = wr; it != m_streams.end(); ++it) {
if ((*it)(data, s)) *wr++ = *it;
}
- streams.erase(wr);
- return !streams.empty();
+ if (wr != m_streams.end()) m_streams.erase(wr);
+ return !m_streams.empty();
}
private:
+ streams_t m_streams;
+ boost::mutex m_mutex;
};
namespace {
@@ -49,7 +57,7 @@ namespace da {
}
}
- class buffer {
+ class buffer: boost::noncopyable {
public:
explicit buffer(size_t s): m_data(s) {}
sample_t* begin() { return &m_data[0]; }
@@ -58,7 +66,7 @@ namespace da {
std::vector<sample_t> m_data;
};
- class stream {
+ class stream: boost::noncopyable {
public:
bool operator()(pcm_data& data, settings const&) {
sample_t* b = m_buffer->begin();
@@ -79,9 +87,10 @@ namespace da {
public:
mixer(settings s = settings()):
m_chain(zero),
- m_settings(s.set_callback(m_chain)),
+ m_settings(s.set_callback(boost::ref(m_chain))),
m_playback(m_settings)
{}
+ void add(callback_t const& cb) { m_chain.add(cb); }
private:
chain m_chain;
settings m_settings;
|