|
From: Yoda-JM <yo...@us...> - 2010-08-15 14:52:36
|
Module: performous
Branch: joinmenu
Commit: d28fe6660eae95b465e5f58c35d3afde8129680c
Author: Lasse Karkkainen <tro...@tr...>
Date: Sun Jul 18 09:22:36 2010 +0300
Audio device configuration implemented (mostly)
---
data/schema.xml | 2 +-
game/audio.cc | 74 ++++++++++++++++++++++++++++++++++++++++--------------
2 files changed, 56 insertions(+), 20 deletions(-)
diff --git a/data/schema.xml b/data/schema.xml
index c41c864..26ebb9f 100644
--- a/data/schema.xml
+++ b/data/schema.xml
@@ -178,7 +178,7 @@ to save the current settings to XML.
<long>Affects instruments and dancing only. The total of USB (guitar or dance pad) latency combined with audio output latency. Adjust so that you can hit the notes best when playing by ear (not looking on screen). Use Ctrl+F5/F6 to adjust while performing.</long>
</locale>
</entry>
- <entry name="audio/device" type="string_list">
+ <entry name="audio/devices" type="string_list">
<stringvalue>in=2 dev="default" mics="blue,red"</stringvalue><!-- SingStar mics -->
<stringvalue>in=1 dev="Microphone"</stringvalue><!-- Rock Band branded Logitech mic -->
<stringvalue>in=1</stringvalue><!-- Any other microphone -->
diff --git a/game/audio.cc b/game/audio.cc
index 2c6a3b4..7071e50 100644
--- a/game/audio.cc
+++ b/game/audio.cc
@@ -213,9 +213,9 @@ struct Output {
struct Device {
// Init
- unsigned int in, out;
- double rate;
- std::string dev;
+ const unsigned int in, out;
+ const double rate;
+ const std::string dev;
portaudio::Stream stream;
std::vector<Analyzer*> mics;
Output* outptr;
@@ -236,8 +236,8 @@ struct Device {
float const* in = static_cast<float const*>(input);
float* out = static_cast<float*>(output);
for (std::size_t i = 0; i < mics.size(); ++i) {
- if (!mics[i]) continue; // Channel not used
- mics[i]->input(in, in + 1 * frames);
+ if (!mics[i]) continue; // No analyzer? -> Channel not used
+ mics[i]->input(in, in + 1 * frames); // FIXME: needs libda iterators for multiple channel support
}
if (outptr) outptr->callback(out, out + 2 * frames);
return paContinue;
@@ -253,21 +253,57 @@ struct Audio::Impl {
boost::ptr_vector<Analyzer> analyzers;
Output output;
bool playback;
- Impl() {
- devices.push_back(new Device(1, 2, 48000.0, ""));
- // One analyzer for mono input (TODO: fix callbackInput to allow more)
- analyzers.push_back(new Analyzer(48000.0));
- devices[0].mics[0] = &analyzers[0];
- playback = false;
- for (size_t i = 0; i < devices.size(); ++i) {
- Device& d = devices[i];
- // Assign playback output for the first available stereo output
- if (!playback && d.out == 2) {
- d.outptr = &output;
- playback = true;
+ Impl(): playback() {
+ // Parse audio devices from config
+ ConfigItem::StringList devs = config["audio/devices"].sl();
+ for (ConfigItem::StringList::const_iterator it = devs.begin(), end = devs.end(); it != end; ++it) {
+ try {
+ struct Params {
+ int in, out;
+ unsigned int rate;
+ std::string dev;
+ std::vector<int> mics;
+ } params = Params();
+ params.rate = 48000;
+ // Break into tokens:
+ std::istringstream iss(*it);
+ for (std::string token; std::getline(iss, token, ' '); ) {
+ // Parse key=value
+ std::istringstream iss2(token);
+ std::string key;
+ std::getline(iss2, key, '=');
+ if (key == "out") iss2 >> params.out;
+ else if (key == "in") iss2 >> params.in;
+ else if (key == "rate") iss2 >> params.rate;
+ else if (key == "dev") std::getline(iss2, params.dev);
+ else if (key == "mics") {
+ // Parse a comma-separated list of mics
+ for (std::string mic; std::getline(iss2, mic, ','); ) {
+ params.mics.push_back(0); // TODO/FIXME: implement
+ }
+
+ }
+ else throw std::runtime_error("Unknown device parameter " + key);
+ if (!iss2.eof()) throw std::runtime_error("Syntax error parsing device parameter " + key);
+ }
+ devices.push_back(new Device(params.in, params.out, params.rate, params.dev));
+ Device& d = devices.back();
+ // Assign mics for all channels of the device (TODO: proper assignments and limit the number of mics)
+ for (unsigned int i = 0; i < d.in; ++i) {
+ Analyzer* a = new Analyzer(d.rate);
+ analyzers.push_back(a);
+ d.mics[i] = a;
+ }
+ // Assign playback output for the first available stereo output
+ if (!playback && d.out == 2) {
+ d.outptr = &output;
+ playback = true;
+ }
+ // Start capture/playback on this device
+ d.start();
+ } catch(std::runtime_error& e) {
+ std::cerr << "Audio device '" << *it << "': " << e.what() << std::endl;
}
- // Start capture/playback on this device
- d.start();
}
}
};
|