1
// ------------------------------------------------------------------------
2
// preset.cpp: Class for representing effect presets
3
// Copyright (C) 2000-2002,2004-2005 Kai Vehmanen
4
// Copyright (C) 2001 Arto Hamara
7
// eca-style-version: 3
9
// This program is free software; you can redistribute it and/or modify
10
// it under the terms of the GNU General Public License as published by
11
// the Free Software Foundation; either version 2 of the License, or
12
// (at your option) any later version.
14
// This program is distributed in the hope that it will be useful,
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
// GNU General Public License for more details.
19
// You should have received a copy of the GNU General Public License
20
// along with this program; if not, write to the Free Software
21
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
// ------------------------------------------------------------------------
29
#include <kvu_numtostr.h>
30
#include <kvu_utils.h>
32
#include "eca-chain.h"
33
#include "eca-chainop.h"
34
#include "generic-controller.h"
35
#include "eca-object-factory.h"
36
#include "samplebuffer.h"
37
#include "eca-logger.h"
38
#include "eca-error.h"
40
#include "preset_impl.h"
49
impl_repp = new PRESET_impl();
50
impl_repp->parsed_rep = false;
53
PRESET::PRESET(const string& formatted_string)
55
impl_repp = new PRESET_impl();
56
parse(formatted_string);
61
vector<SAMPLE_BUFFER*>::iterator p = buffers.begin();
62
while(p != buffers.end()) {
63
if (p != buffers.begin()) delete *p; // first buffer points to an
64
// outside buffer -> not
69
vector<CHAIN*>::iterator q = chains.begin();
70
while(q != chains.end()) {
75
for(size_t n = 0; n < impl_repp->pardesclist_rep.size(); n++) {
76
delete impl_repp->pardesclist_rep[n];
77
impl_repp->pardesclist_rep[n] = 0;
80
// NOTE: chainops and controllers are deleted in CHAIN::~CHAIN()
86
PRESET* PRESET::clone(void) const
88
vector<parameter_t> param_values;
89
for(int n = 0; n < number_of_params(); n++) {
90
param_values.push_back(get_parameter(n + 1));
92
PRESET* preset = new PRESET(impl_repp->parse_string_rep);
93
for(int n = 0; n < preset->number_of_params(); n++) {
94
preset->set_parameter(n + 1, param_values[n]);
99
PRESET* PRESET::new_expr(void) const
101
return new PRESET(impl_repp->parse_string_rep);
104
void PRESET::set_samples_per_second(SAMPLE_SPECS::sample_rate_t v)
106
for(size_t q = 0; q < chains.size(); q++) {
107
chains[q]->set_samples_per_second(v);
110
for(size_t n = 0; n < impl_repp->gctrls_rep.size(); n++) {
111
impl_repp->gctrls_rep[n]->set_samples_per_second(v);
115
ECA_SAMPLERATE_AWARE::set_samples_per_second(v);
118
string PRESET::name(void) const
120
return impl_repp->name_rep;
123
string PRESET::description(void) const
125
return impl_repp->description_rep;
128
void PRESET::set_name(const string& v)
130
impl_repp->name_rep = v;
134
* Whether preset data has been parsed
136
bool PRESET::is_parsed(void) const
138
return impl_repp->parsed_rep;
141
void PRESET::parameter_description(int param, struct PARAM_DESCRIPTION *pd) const
143
if (param > 0 && param <= static_cast<int>(impl_repp->pardesclist_rep.size()))
144
*pd = *impl_repp->pardesclist_rep[param - 1];
148
* Parse preset data from the formatted string given
152
* formatted_string.empty() == false
154
* is_parsed() == true
156
void PRESET::parse(const string& formatted_string)
159
DBC_REQUIRE(formatted_string.empty() == false);
162
impl_repp->parse_string_rep = formatted_string;
164
chains.push_back(new CHAIN());
165
chains.back()->set_samples_per_second(samples_per_second());
167
// FIXME: add support for quotes (ie. "one token with space" style)
168
vector<string> tokens = kvu_string_to_words(formatted_string);
169
vector<string>::const_iterator p = tokens.begin();
170
while(p != tokens.end()) {
171
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Parsing: " + *p + ".");
173
/* case 1: new chain */
178
/* case 2: preset specific option */
179
else if (is_preset_option(*p) == true) {
180
parse_preset_option(*p);
183
/* case 3: ecasound cop option */
185
parse_operator_option(*p);
191
impl_repp->parsed_rep = true;
194
DBC_ENSURE(is_parsed() == true);
198
bool PRESET::is_preset_option(const string& arg) const
200
if (arg.size() < 2 ||
201
arg[0] != '-') return false;
206
if (arg.size() < 3) return false;
220
void PRESET::parse_preset_option(const string& arg)
222
if (arg.size() < 2) return;
223
if (arg[0] != '-') return;
227
if (arg.size() < 3) return;
231
/* -pd:preset_description */
232
impl_repp->description_rep = kvu_get_argument_number(1, arg);
238
if (arg.size() < 4) return;
242
/* -ppd:x,y,z (param default values) */
243
set_preset_defaults(kvu_get_arguments(arg));
249
/* -ppn:x,y,z (param names) */
250
set_preset_param_names(kvu_get_arguments(arg));
256
/* -ppl:x,y,z (param lower bounds) */
257
set_preset_lower_bounds(kvu_get_arguments(arg));
263
/* -ppu:x,y,z (param upper bounds) */
264
set_preset_upper_bounds(kvu_get_arguments(arg));
270
/* -ppt:x,y,z (param toggle) */
271
set_preset_toggles(kvu_get_arguments(arg));
277
ECA_LOG_MSG(ECA_LOGGER::info, "Unknown preset option (1) " + arg + ".");
285
default: { ECA_LOG_MSG(ECA_LOGGER::info, "Unknown preset option (2) " + arg + "."); break; }
293
default: { ECA_LOG_MSG(ECA_LOGGER::info, "Unknown preset option (3) " + arg + "."); break; }
298
void PRESET::extend_pardesc_vector(int number)
300
while (static_cast<int>(impl_repp->pardesclist_rep.size()) < number) {
301
DBC_DECLARE(size_t oldsize = impl_repp->pardesclist_rep.size());
302
impl_repp->pardesclist_rep.push_back(new OPERATOR::PARAM_DESCRIPTION());
303
// cerr << "(preset) adding pardesclist_rep item." << endl;
304
DBC_CHECK(impl_repp->pardesclist_rep.size() == oldsize + 1);
308
void PRESET::set_preset_defaults(const vector<string>& args)
310
extend_pardesc_vector(args.size());
311
for(size_t n = 0; n < args.size(); n++) {
312
if (args[n].size() > 0 && args[n][0] == '-') continue;
313
impl_repp->pardesclist_rep[n]->default_value = atof(args[n].c_str());
314
set_parameter(n + 1, impl_repp->pardesclist_rep[n]->default_value);
315
// cerr << "(preset) setting default for " << n << " to " << impl_repp->pardesclist_rep[n]->default_value << "." << endl;
319
void PRESET::set_preset_param_names(const vector<string>& args)
321
impl_repp->preset_param_names_rep.resize(args.size());
322
for(size_t n = 0; n < args.size(); n++) {
323
impl_repp->preset_param_names_rep[n] = args[n];
324
// cerr << "(preset) setting param name for " << n << " to " << impl_repp->preset_param_names_rep[n] << "." << endl;
328
void PRESET::set_preset_lower_bounds(const vector<string>& args)
330
extend_pardesc_vector(args.size());
331
for(size_t n = 0; n < args.size(); n++) {
332
if (args[n].size() > 0 && args[n][0] == '-') {
333
impl_repp->pardesclist_rep[n]->bounded_below = false;
336
impl_repp->pardesclist_rep[n]->bounded_below = true;
337
impl_repp->pardesclist_rep[n]->lower_bound = atof(args[n].c_str());
338
// cerr << "(preset) setting lowbound for " << n << " to " << impl_repp->pardesclist_rep[n]->lower_bound << "." << endl;
343
void PRESET::set_preset_upper_bounds(const vector<string>& args)
345
extend_pardesc_vector(args.size());
346
for(size_t n = 0; n < args.size(); n++) {
347
if (args[n].size() > 0 && args[n][0] == '-') {
348
impl_repp->pardesclist_rep[n]->bounded_above = false;
351
impl_repp->pardesclist_rep[n]->bounded_above = true;
352
impl_repp->pardesclist_rep[n]->upper_bound = atof(args[n].c_str());
353
// cerr << "(preset) setting upperbound for " << n << " to " << impl_repp->pardesclist_rep[n]->upper_bound << "." << endl;
358
void PRESET::set_preset_toggles(const vector<string>& args)
360
extend_pardesc_vector(args.size());
361
for(size_t n = 0; n < args.size(); n++) {
363
impl_repp->pardesclist_rep[n]->integer = false;
364
impl_repp->pardesclist_rep[n]->logarithmic = false;
365
impl_repp->pardesclist_rep[n]->output = false;
366
impl_repp->pardesclist_rep[n]->toggled = false;
368
if (args[n].find("i") != string::npos)
369
impl_repp->pardesclist_rep[n]->integer = true;
370
if (args[n].find("l") != string::npos)
371
impl_repp->pardesclist_rep[n]->logarithmic = true;
372
if (args[n].find("o") != string::npos)
373
impl_repp->pardesclist_rep[n]->output = true;
374
if (args[n].find("t") != string::npos)
375
impl_repp->pardesclist_rep[n]->toggled = true;
377
ECA_LOG_MSG(ECA_LOGGER::user_objects,
378
string("Setting preset toggles: integer=")
379
+ kvu_numtostr(impl_repp->pardesclist_rep[n]->integer)
381
+ kvu_numtostr(impl_repp->pardesclist_rep[n]->logarithmic)
383
+ kvu_numtostr(impl_repp->pardesclist_rep[n]->output)
385
+ kvu_numtostr(impl_repp->pardesclist_rep[n]->toggled)
390
void PRESET::parse_operator_option(const string& arg)
393
GENERIC_CONTROLLER* gctrl;
395
/* phase 1: parse for cop definitions -eabc:1.0,%param1,2.0 */
396
vector<int> arg_indices;
397
vector<int> arg_slave_indices;
398
vector<string> ps_parts(kvu_get_number_of_arguments(arg));
399
for(int i = 0; i < kvu_get_number_of_arguments(arg); i++) {
400
string onearg = kvu_get_argument_number(i + 1, arg);
401
if(onearg.size() > 0 && onearg[0] == '%') {
403
// FIXME: what if %xxx options are given in the "wrong" order?
405
size_t preset_index = atoi(kvu_get_argument_number(i + 1, arg).substr(1).c_str());
406
if (preset_index <= arg_indices.size()) {
407
preset_index = arg_indices.size() + 1;
409
arg_indices.push_back(preset_index);
410
arg_slave_indices.push_back(i + 1);
413
// make sure param is mentioned in param_names list
414
if (impl_repp->preset_param_names_rep.size() < preset_index) {
415
impl_repp->preset_param_names_rep.resize(preset_index);
416
impl_repp->preset_param_names_rep[preset_index - 1] = string("arg-") + kvu_numtostr(preset_index);
421
ps_parts[i] = onearg;
425
DBC_CHECK(arg_indices.size() == arg_slave_indices.size());
427
/* phase 2: 'ps' is set to -eabc:1.0,2.0,2.0 (no %-params) */
428
string ps = "-" + kvu_get_argument_prefix(arg) + ":" + kvu_vector_to_string(ps_parts, ",");
429
// cerr << "Creating object from '" << ps << "'." << endl;
431
/* phase 3: create an object using 'ps' */
432
DYNAMIC_OBJECT<SAMPLE_SPECS::sample_t>* object = 0;
434
cop = ECA_OBJECT_FACTORY::create_chain_operator(ps);
435
if (cop == 0) cop = ECA_OBJECT_FACTORY::create_ladspa_plugin(ps);
437
chains.back()->add_chain_operator(cop);
438
chains.back()->selected_chain_operator_as_target();
442
if (kvu_get_argument_prefix(ps) == "kx")
443
chains.back()->selected_controller_as_target();
445
gctrl = ECA_OBJECT_FACTORY::create_controller(ps);
447
impl_repp->gctrls_rep.push_back(gctrl);
448
chains.back()->add_controller(gctrl);
454
/* phase 4: create an object using 'ps' */
456
for(int i = 0; i < static_cast<int>(arg_indices.size()); i++) {
458
// NOTE: there's a one-to-many connection between
459
// presets' parameters and 'object-param' pairs
460
// (ie. one preset-parameter can control
461
// multiple object params (param_objects and
464
size_t preset_index = arg_indices[i];
466
// NOTE: for instance for LADSPA plugins -el:label,par1,par2
467
// number_of_args is 3, but number_of_params is 2!
468
int slave_index = arg_slave_indices[i];
469
slave_index -= kvu_get_number_of_arguments(arg) - object->number_of_params();
471
if (preset_index > impl_repp->slave_param_objects_rep.size()) {
472
impl_repp->slave_param_objects_rep.resize(preset_index);
473
impl_repp->slave_param_indices_rep.resize(preset_index);
476
impl_repp->slave_param_objects_rep[preset_index - 1].push_back(object);
477
impl_repp->slave_param_indices_rep[preset_index - 1].push_back(slave_index);
479
// cerr << "Linking preset parameter " << preset_index << " to object '" << impl_repp->slave_param_objects_rep[preset_index - 1].back()->name() << "', and its parameter '" << impl_repp->slave_param_objects_rep[preset_index - 1].back()->get_parameter_name(impl_repp->slave_param_indices_rep[preset_index - 1].back()) << "'." << endl;
481
DBC_CHECK(impl_repp->slave_param_objects_rep.size() == impl_repp->slave_param_indices_rep.size());
486
void PRESET::add_chain(void)
488
chains.push_back(new CHAIN());
489
buffers.push_back(new SAMPLE_BUFFER());
493
string PRESET::parameter_names(void) const
495
return kvu_vector_to_string(impl_repp->preset_param_names_rep, ",");
498
void PRESET::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
500
if (param > 0 && param <= static_cast<int>(impl_repp->slave_param_objects_rep.size())) {
501
for(size_t n = 0; n < impl_repp->slave_param_objects_rep[param - 1].size(); n++) {
502
DBC_CHECK(static_cast<int>(impl_repp->slave_param_indices_rep.size()) > param - 1);
503
DBC_CHECK(impl_repp->slave_param_indices_rep[param - 1].size() > n);
504
int index = impl_repp->slave_param_indices_rep[param - 1][n];
505
// cerr << "Setting preset " << name() << " param " << param << " (" << impl_repp->slave_param_objects_rep[param-1][n]->get_parameter_name(param) << "), of object " << impl_repp->slave_param_objects_rep[param-1][n]->name() << ", with index number " << index << ", to value " << value << "." << endl;
506
impl_repp->slave_param_objects_rep[param-1][n]->set_parameter(index, value);
511
CHAIN_OPERATOR::parameter_t PRESET::get_parameter(int param) const
513
if (param > 0 && param <= static_cast<int>(impl_repp->slave_param_objects_rep.size())) {
514
DBC_CHECK(static_cast<int>(impl_repp->slave_param_indices_rep.size()) > param - 1);
515
DBC_CHECK(impl_repp->slave_param_indices_rep[param - 1].size() > 0);
517
if (impl_repp->slave_param_indices_rep[param - 1].size() > 0) {
518
int index = impl_repp->slave_param_indices_rep[param - 1][0];
519
DBC_CHECK(index > 0);
521
// cerr << "Getting preset " << name() << " param " << param << ", index number " << index cerr << " with value " << impl_repp->slave_param_objects_rep[param-1][0]->get_parameter(index) << "." << endl;
522
return impl_repp->slave_param_objects_rep[param-1][0]->get_parameter(index);
528
void PRESET::init(SAMPLE_BUFFER *insample)
530
DBC_CHECK(samples_per_second() > 0);
532
first_buffer = insample;
533
chains[0]->set_samples_per_second(samples_per_second());
534
chains[0]->init(first_buffer, first_buffer->number_of_channels(), first_buffer->number_of_channels());
535
for(size_t q = 1; q < chains.size(); q++) {
536
DBC_CHECK(q - 1 < buffers.size());
537
buffers[q - 1]->length_in_samples(first_buffer->length_in_samples());
538
buffers[q - 1]->number_of_channels(first_buffer->number_of_channels());
539
chains[q]->set_samples_per_second(samples_per_second());
540
chains[q]->init(buffers[q - 1],
541
first_buffer->number_of_channels(),
542
first_buffer->number_of_channels());
545
for(size_t n = 0; n < impl_repp->gctrls_rep.size(); n++) {
546
impl_repp->gctrls_rep[n]->init();
547
impl_repp->gctrls_rep[n]->set_samples_per_second(samples_per_second());
551
void PRESET::process(void)
553
vector<SAMPLE_BUFFER*>::iterator p = buffers.begin();
554
while(p != buffers.end()) {
555
(*p)->copy(*first_buffer);
559
vector<CHAIN*>::iterator q = chains.begin();
560
while(q != chains.end()) {
565
if (chains.size() > 1) {
566
first_buffer->divide_by(chains.size());
568
while(p != buffers.end()) {
569
first_buffer->add_with_weight(**p, static_cast<int>(chains.size()));