sintonia/library/ecasound-2.7.2/libecasound/audiogate.cpp

251 lines
6.7 KiB
C++

// ------------------------------------------------------------------------
// audiogate.cpp: Signal gates.
// Copyright (C) 1999-2002,2005-2008,2010 Kai Vehmanen
// Copyrtigh (C) 2008 Andrew Lees
//
// Attributes:
// eca-style-version: 3
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// ------------------------------------------------------------------------
#include <kvu_numtostr.h>
#include "samplebuffer.h"
#include "samplebuffer_functions.h"
#include "audiogate.h"
#include "eca-logger.h"
GATE_BASE::~GATE_BASE(void)
{
}
void GATE_BASE::process(void)
{
analyze(target);
if (is_open() == false) {
target->length_in_samples(0);
}
}
void GATE_BASE::init(SAMPLE_BUFFER* sbuf)
{
gate_open = false;
target = sbuf;
}
void TIME_CROP_GATE::analyze(SAMPLE_BUFFER* sbuf)
{
parameter_t etime = begtime_rep + durtime_rep;
parameter_t curtime = static_cast<parameter_t>(position_in_samples_rep) / samples_per_second();
if (curtime >= begtime_rep) {
/* note: handle the special case where a zero open time
* has been requested */
if (begtime_rep == etime)
open_gate();
else if (curtime < etime)
open_gate();
else
close_gate();
}
else
close_gate();
position_in_samples_rep += sbuf->length_in_samples();
}
TIME_CROP_GATE::TIME_CROP_GATE (CHAIN_OPERATOR::parameter_t open_at, CHAIN_OPERATOR::parameter_t duration)
{
begtime_rep = open_at;
durtime_rep = duration;
position_in_samples_rep = 0;
ECA_LOG_MSG(ECA_LOGGER::info, "Time crop gate created; opens at " +
kvu_numtostr(begtime_rep) + " seconds and stays open for " +
kvu_numtostr(durtime_rep) + " seconds.\n");
}
CHAIN_OPERATOR::parameter_t TIME_CROP_GATE::get_parameter(int param) const
{
switch (param) {
case 1:
return begtime_rep;
case 2:
return durtime_rep;
}
return 0.0;
}
void TIME_CROP_GATE::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
{
switch (param) {
case 1:
begtime_rep = value;
position_in_samples_rep = 0;
break;
case 2:
durtime_rep = value;
break;
}
}
void TIME_CROP_GATE::set_samples_per_second(SAMPLE_SPECS::sample_rate_t new_value)
{
double ratio (new_value);
ratio /= samples_per_second();
/* note: as we store position as samples, changes in sampling rate
* require recalculation of position */
position_in_samples_rep = static_cast<SAMPLE_SPECS::sample_pos_t>(position_in_samples_rep * ratio);
ECA_SAMPLERATE_AWARE::set_samples_per_second(new_value);
}
THRESHOLD_GATE::THRESHOLD_GATE (CHAIN_OPERATOR::parameter_t threshold_openlevel,
CHAIN_OPERATOR::parameter_t threshold_closelevel,
bool use_rms)
{
openlevel_rep = threshold_openlevel / 100.0;
closelevel_rep = threshold_closelevel / 100.0;
rms_rep = use_rms;
reopen_count_param_rep = 0;
is_opened_rep = is_closed_rep = false;
if (rms_rep) {
ECA_LOG_MSG(ECA_LOGGER::info, "Threshold gate created; open threshold " +
kvu_numtostr(openlevel_rep * 100) + "%, close threshold " +
kvu_numtostr(closelevel_rep * 100) + "%, using RMS volume.");
}
else {
ECA_LOG_MSG(ECA_LOGGER::info, "Threshold gate created; open threshold " +
kvu_numtostr(openlevel_rep * 100) + "%, close threshold " +
kvu_numtostr(closelevel_rep * 100) + "%, using peak volume.");
}
}
void THRESHOLD_GATE::init(SAMPLE_BUFFER* sbuf)
{
reopens_left_rep = reopen_count_param_rep;
is_opened_rep = false;
is_closed_rep = false;
GATE_BASE::init(sbuf);
}
void THRESHOLD_GATE::analyze(SAMPLE_BUFFER* sbuf)
{
if (rms_rep == true)
avolume_rep = SAMPLE_BUFFER_FUNCTIONS::RMS_volume(*sbuf) / SAMPLE_SPECS::max_amplitude;
else
avolume_rep = SAMPLE_BUFFER_FUNCTIONS::average_amplitude(*sbuf) / SAMPLE_SPECS::max_amplitude;
if (is_opened_rep == false) {
if (avolume_rep > openlevel_rep) {
open_gate();
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Threshold gate opened (reopen count = " + kvu_numtostr(reopens_left_rep) + ")");
is_opened_rep = true;
is_closed_rep = false;
}
}
else if (is_closed_rep == false) {
if (avolume_rep < closelevel_rep) {
close_gate();
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Threshold gate closed (reopens left = " + kvu_numtostr(reopens_left_rep) + ")");
is_closed_rep = true;
if (reopens_left_rep != 0) {
is_opened_rep = false;
if (reopens_left_rep > 0)
--reopens_left_rep;
} else {
// - Could we stop the engine and exit here, maybe? -AL/2008-Jul
// - Not from a chain operator, but the audio object
// that writes the stream to a file could in
// theory react in a special way to the 0-length
// samplebuffers we generate when the gate is closed... -KV/2008-Jul
}
}
}
}
CHAIN_OPERATOR::parameter_t THRESHOLD_GATE::get_parameter(int param) const
{
switch (param) {
case 1:
return openlevel_rep * 100.0;
case 2:
return closelevel_rep * 100.0;
case 3:
if (rms_rep)
return 1.0;
else
return 0.0;
case 4:
return reopen_count_param_rep;
}
return 0.0;
}
void THRESHOLD_GATE::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
{
switch (param) {
case 1:
openlevel_rep = value / 100.0;
break;
case 2:
closelevel_rep = value / 100.0;
break;
case 3:
rms_rep = (value != 0);
break;
case 4:
reopen_count_param_rep = static_cast<int>(value);
break;
}
}
void MANUAL_GATE::analyze(SAMPLE_BUFFER* sbuf)
{
if (is_open() == true &&
open_rep != true) {
close_gate();
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Manual gate closed");
}
else if (is_open() != true &&
open_rep == true) {
open_gate();
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Manual gate opened");
}
}
CHAIN_OPERATOR::parameter_t MANUAL_GATE::get_parameter(int param) const
{
switch (param) {
case 1:
return open_rep == true ? 1 : 0;
}
return 0.0;
}
void MANUAL_GATE::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
{
switch (param) {
case 1:
if (value > 0)
open_rep = true;
else
open_rep = false;
break;
}
}