Re: [ecasound] loop devices

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [ecasound] loop devices
From: janne halttunen (jhalttun_AT_pp.htv.fi)
Date: Wed Dec 18 2002 - 13:20:20 EET


On Mon, 16 Dec 2002 02:08:42 +0200 (EET)
Kai Vehmanen <k_AT_eca.cx> wrote:

> On Sat, 14 Dec 2002, janne halttunen wrote:
>
> > # ecasound -a 1 -i samples/Bass2.wav -o loop,1 -a 2 -i samples/bassin.wav -o loop,1 -a 3 -i loop,1 -o rtnull
>
> You cannot have two "loop,1" objects as outputs. If you want to route
> audio from multiple chains to a loop device, you have to select
> multiple chains and attach the loop device to them all, i.e.
> "-a:1,2 -o loop,1".

Yeah, well I thought that since the above line is semantically equivalent to the one above, it really should be made to be valid to pass such line to ecasound.

So, my first stab at c++, here's the result:

$ ./ecasound -a 1 -i samples/Bass2.wav -o loop,1 -a 2 -i samples/bassin.wav -o loop,1 -a 3 -i loop,1 -o rtnull -c
****************************************************************************
* ecasound v2.2.0-rc1 (C) 1997-2002 Kai Vehmanen
****************************************************************************
- [ Session created ] ------------------------------------------------------
- [ Chainsetup created (cmdline) ] -----------------------------------------
(eca-chainsetup-parser) Note! Intepreting as -a:1 -i:samples/Bass2.wav -a:2 -i:samples/bassin.wav -a:3 -i:loop,1 -o:rtnull -a:1,2 -o:loop,1
ecasound ('h' for help)>

the code should be able to handle more exotic (even insane) cases, like:

$ ./ecasound -a 1,2 -i loop,1 -a 3,4 -i samples/bassin.wav -o loop,1 -a 5 -i loop,1 -o rtnull -c
****************************************************************************
* ecasound v2.2.0-rc1 (C) 1997-2002 Kai Vehmanen
****************************************************************************
- [ Session created ] ------------------------------------------------------
- [ Chainsetup created (cmdline) ] -----------------------------------------
(eca-chainsetup-parser) Note! Intepreting as -a:3,4 -i:samples/bassin.wav -o:loop,1 -a:5 -o:rtnull -a:1,2,5 -i:loop,1
(eca-session) Note! Unable to create a valid chainsetup from the command-line arguments.
ecasound ('h' for help)>

here's the patch:

--- ecasound-cvs/libecasound/eca-chainsetup-parser.cpp 2002-11-19 15:49:39.000000000 +0200
+++ ecasound-cvs-mod/libecasound/eca-chainsetup-parser.cpp 2002-12-18 13:00:51.000000000 +0200
@@ -223,6 +223,143 @@
     }
     ++p;
   }
+
+ /* enter hack2: convert multiple same audio-objects to one expression */
+
+ std::vector<string> chains;
+ std::vector<string> inputs;
+ std::vector<string> outputs;
+
+ const std::string empty = "__empty__";
+
+ p = opts.begin();
+
+ while(p != opts.end()) {
+
+ if ( p->size() > 2 ) {
+
+ if ( (*p)[1] == 'a' ) {
+
+ if ( inputs.size() < chains.size() )
+ inputs.push_back(empty);
+ if ( outputs.size() < chains.size() )
+ outputs.push_back(empty);
+
+ chains.push_back(*p);
+ }
+ if ( (*p)[1] == 'i' ) {
+ inputs.push_back(*p);
+ }
+ if ( (*p)[1] == 'o' ) {
+ outputs.push_back(*p);
+ }
+ }
+ ++p;
+ }
+
+ std::vector<string>::iterator it;
+ bool tampered = false;
+
+ for ( int i=0; i < chains.size(); i++ ) {
+
+ if ( inputs.size() > i ) {
+ if ( inputs.at(i) != empty ) {
+
+ for ( int a=0; a < inputs.size(); a++ ) {
+ if ( a != i && inputs.at(a) == inputs.at(i) && inputs.at(i) != empty ) {
+
+ std::string s1 = chains.at(i);
+
+ std::vector<string> args = kvu_get_arguments(chains.at(a));
+ for ( int o=0; o < args.size(); o++ ) {
+ s1.append(",");
+ s1.append( args.at(o) );
+ }
+ std::string s2 = inputs.at(i);
+
+ it=inputs.begin()+i;
+ inputs.erase(it);
+ inputs.insert(it, empty);
+
+ it=inputs.begin()+a;
+ inputs.erase(it);
+ inputs.insert(it, empty);
+
+ for ( int o=0; o < opts.size(); o++ ) {
+ if ( opts.at(o) == s2 ) {
+ it=opts.begin()+o;
+ opts.erase(it);
+ }
+ }
+ opts.push_back(s1);
+ opts.push_back(s2);
+
+ tampered = true;
+ }
+ }
+ }
+ }
+ if ( outputs.size() > i ) {
+ if ( outputs.at(i) != empty ) {
+
+ for ( int a=0; a < outputs.size(); a++ ) {
+ if ( a != i && outputs.at(a) == outputs.at(i) ) {
+
+ std::string s1 = chains.at(i);
+
+ std::vector<string> args = kvu_get_arguments(chains.at(a));
+ for ( int o=0; o < args.size(); o++ ) {
+ s1.append(",");
+ s1.append( args.at(o) );
+ }
+ std::string s2 = outputs.at(i);
+
+ it=outputs.begin()+i;
+ outputs.erase(it);
+ outputs.insert(it, empty);
+
+ it=outputs.begin()+a;
+ outputs.erase(it);
+ outputs.insert(it, empty);
+
+ for ( int o=0; o < opts.size(); o++ ) {
+ if ( opts.at(o) == s2 ) {
+ it=opts.begin()+o;
+ opts.erase(it);
+ }
+ }
+ opts.push_back(s1);
+ opts.push_back(s2);
+
+ tampered = true;
+ }
+ }
+ }
+ }
+ }
+ if ( tampered ) {
+
+ for ( int i=0; i < chains.size(); i++ ) {
+ if ( inputs.size() > i && outputs.size() > i) {
+ if ( inputs.at(i) == empty && outputs.at(i) == empty ) {
+ for ( int o=0; o < opts.size(); o++ ) {
+ if ( opts.at(o) == chains.at(i) ) {
+ it=opts.begin()+o;
+ opts.erase(it);
+ }
+ }
+ }
+ }
+ }
+ std::string s = "";
+ p = opts.begin();
+ while(p != opts.end()) {
+ s.append(*p+" ");
+ ++p;
+ }
+ ECA_LOG_MSG(ECA_LOGGER::info, "(eca-chainsetup-parser) Note! Intepreting as "+s);
+ }
+
 }
 
 /**

Yeah, I know it's bit longish, and there can be some stupidisms in there due to my ignorance of the subletities of the language, but it seemed to work with my simple example cases.

cheers,

janne


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Wed Dec 18 2002 - 13:18:00 EET