This GitLab instance reached the end of its service life. It won't be possible to create new users or projects.

Please read the deprecation notice for more information concerning the deprecation timeline

Visit migration.git.tu-berlin.de (internal network only) to import your old projects to the new GitLab platform 📥

Commit 9092c6e8 by Henrik von Coler

Added waveshaper and wavefolder examples!

parent 119abd94
# define the compiler
CC = g++
# path(s) to include files
CFLAGS = -I.
# libraries to link
LDFLAGS = -ljack -llo -lsndfile -lyaml-cpp
SRCS = main.cpp waveshaper.cpp oscman.cpp yamlman.cpp transferfunction.cpp sinefolder.cpp tangentshaper.cpp
DEPS = oscman.h waveshaper.h yamlman.h transferfunction.h sinefolder.h tangentshaper.h
all: waveshaper
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
waveshaper: main.o waveshaper.o oscman.o yamlman.o transferfunction.o sinefolder.o tangentshaper.o
$(CC) -o waveshaper main.o waveshaper.o oscman.o yamlman.o transferfunction.o sinefolder.o tangentshaper.o $(LDFLAGS)
clean:
rm *.o waveshaper
port: 6666
path: "/gain"
dummy: "lsrg"
/**
* \file main.cpp
*
* \brief Just the main file ...
*
* \author Henrik von Coler
*
* \date $Date: 2019/04/15 $
*
*/
#include<iostream>
#include<stdlib.h>
#include<unistd.h>
#include"yamlman.h"
#include"waveshaper.h"
using std::cout;
using std::endl;
int main(int argc, char *argv[]){
if (argc < 3)
cout << "Need config file to start!" << endl;
else{
// process command line arguments
std::string configfile;
for (int i = 1; i < argc; i++)
{
if (i + 1 != argc)
{
if (strcmp(argv[i], "-c") == 0)
{
configfile = argv[i + 1];
i++;
}
}
}
// initialize objects
YamlMan *yaml_manager = new YamlMan(configfile);
Waveshaper *w = new Waveshaper(yaml_manager);
}
}
/**
* \file oscman.cpp
* \class OscMan
*
* \brief Class which parses the incoming OSC messages.
*
* \author Henrik von Coler
*
* \date 2019/03/18
*
*/
#include "oscman.h"
OscMan::OscMan(YamlMan *yaml_manager)
{
port = yaml_manager->return_port();
cout << "Receiving OSC on port: " << port << std::endl;
gain = 1.0;
try
{
st = new lo::ServerThread(port);
}
catch (int e)
{
std::cout << "Possibly a bad port!" << std::endl;
}
// Add the example handler to the server!
st->add_method(yaml_manager->return_path(), "f", gain_callback, this);
st->start();
std::cout << "Started OSC Server!" << std::endl;
}
int OscMan::gain_callback(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data )
{
// Do a static cast
OscMan* statCast = static_cast<OscMan*>(user_data);
std::cout << "Changed volume to: " << argv[0]->f << std::endl;
statCast->gain = argv[0]->f;
}
double OscMan::get_gain()
{
return gain;
}
/**
* \file oscman.h
* \class OscMan
*
* \brief Class which parses the incoming OSC messages.
*
* \author Henrik von Coler
*
* \date 2019/03/18$
*
*/
#ifndef OSCMAN_H
#define OSCMAN_H
// works with 'self built'
#include <lo/lo.h>
#include <lo/lo_cpp.h>
#include "yamlman.h"
#include<iostream>
#include<vector>
#include<string>
class OscMan
{
private:
/// the IP port to be opened
int port;
///
lo::ServerThread *st;
/// The actual gain value
double gain;
///
////// \brief OscMan::gain_callback
////// \param path
////// \param types
////// \param argv
////// \param argc
////// \param data
////// \param user_data
////// \return
static int gain_callback(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data);
public:
///
/// \brief OscMan::OscMan
/// The constructor
/// \param yaml_manager
///
OscMan(YamlMan *yaml_manager);
///
/// \brief OscMan::get_gain
/// \return the gain value [double]
///
double get_gain();
};
#endif
#include "sinefolder.h"
SineFolder::SineFolder()
{
scaler = 1.0;
}
void SineFolder::set(double s)
{
scaler = s;
}
double SineFolder::map(double in)
{
double val = std::max(-1.0,std::min(1.0,in));
double out = std::sin(scaler * 2*M_PI*val);
return out;
}
#ifndef SINEFOLDER_H
#define SINEFOLDER_H
#include <math.h>
#include <algorithm>
#include "transferfunction.h"
#include "sinefolder.h"
class SineFolder: public TransferFunction
{
public:
SineFolder();
void set(double s);
double map(double in);
private:
double scaler;
};
#endif // SINEFOLDER_H
#include "tangentshaper.h"
TangentShaper::TangentShaper()
{
scaler = 1.0;
}
void TangentShaper::set(double s)
{
scaler = s;
}
double TangentShaper::map(double in)
{
double val = std::max(-1.0,std::min(1.0,in));
double out = std::tanh(scaler * 2*M_PI*val);
return out;
}
#ifndef TANGENTSHAPER_H
#define TANGENTSHAPER_H
#include <math.h>
#include <algorithm>
#include "transferfunction.h"
#include "tangentshaper.h"
class TangentShaper: public TransferFunction
{
public:
TangentShaper();
void set(double s);
double map(double in);
private:
double scaler;
};
#endif // TANGENTSHAPER_H
#include "transferfunction.h"
TransferFunction::TransferFunction()
{
}
void TransferFunction::set(double p)
{
}
double TransferFunction::map(double in)
{
}
#ifndef TRANSFERFUNCTION_H
#define TRANSFERFUNCTION_H
#include <math.h>
#include <algorithm>
class TransferFunction
{
public:
TransferFunction();
virtual void set(double p);
virtual double map(double in);
private:
double scaler;
};
#endif // TRANSFERFUNCTION_H
/**
* \file gain_example.cpp
* \class GainExample
*
* \brief Simple example, passing the input to the output
* with gain modification through OSC.
*
* \author Henrik von Coler
*
* \date $Date: 2019/03/18 $
*
*/
#include"waveshaper.h"
using std::cout;
using std::endl;
Waveshaper::Waveshaper(YamlMan *yaml_manager){
// creating an OSC manager instance
oscman = new OscMan(yaml_manager);
trans_fun = new TangentShaper();
cout << "Starting Jack Client!" << endl;
this->client = jack_client_open("Waveshaper", JackNullOption, &status, NULL);
// connect the callback function
jack_set_process_callback(this->client, this->callback_process, this);
// allocate array
input_port = new jack_port_t*[nChannels];
for (int i=0; i<nChannels; i++)
{
std::string tmp_str = "input_" + std::to_string(i+1);
input_port[i] = jack_port_register (client, tmp_str.c_str(),
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsInput, 0);
}
output_port = new jack_port_t*[nChannels];
for (int i=0; i<nChannels; i++)
{
std::string tmp_str = "output_" + std::to_string(i+1);
output_port[i] = jack_port_register (client, tmp_str.c_str(),
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
}
out = new jack_default_audio_sample_t*;
in = new jack_default_audio_sample_t*;
jack_activate(this->client);
// connect inputs
jack_connect (client, "system:capture_1", jack_port_name(input_port[0]));
jack_connect (client, "system:capture_2", jack_port_name(input_port[1]));
// connect outputs
jack_connect (client, jack_port_name(output_port[0]), "system:playback_1");
jack_connect (client, jack_port_name(output_port[1]), "system:playback_2");
// run forever
sleep (-1);
}
int Waveshaper::process(jack_nframes_t nframes)
{
// get the recent gain value from the OSC manager
trans_fun->set(oscman->get_gain());
// get input buffers
for ( int i=0 ; i<nChannels; i++)
{
out[i] = (jack_default_audio_sample_t *)
jack_port_get_buffer(this->output_port[i], jack_get_buffer_size(client));
in[i] = (jack_default_audio_sample_t *)
jack_port_get_buffer(this->input_port[i], jack_get_buffer_size(client));
}
// write all input samples to output
for(int chanCNT=0; chanCNT<nChannels; chanCNT++)
{
for(int sampCNT=0; sampCNT<nframes; sampCNT++)
{
out[chanCNT][sampCNT] = trans_fun->map(in[chanCNT][sampCNT]);
}
}
return 0;
}
int Waveshaper::callback_process(jack_nframes_t x, void* object)
{
return static_cast<Waveshaper*>(object)->process(x);
}
/**
* \file gain_example.h
* \class GainExample
*
* \brief Simple example, passing the input to the output
* with gain modification through OSC.
*
* \author Henrik von Coler
*
* \date $Date: 2019/03/18 $
*
*/
#include<iostream>
#include<stdlib.h>
#include<unistd.h>
#include<jack/jack.h>
#include"oscman.h"
#include"sinefolder.h"
#include"tangentshaper.h"
#include"transferfunction.h"
using std::cout;
using std::endl;
class Waveshaper{
private:
/// \brief nChannels
/// the number of audio channels @todo (should not be hard-coded)
int nChannels = 2;
/// \brief client
/// the jack client, obviously
jack_client_t *client;
/// \brief status
/// gets the status from the jack server
jack_status_t status;
/// \brief input_port
/// the jack input ports
jack_port_t **input_port;
/// \brief output_port
/// the jack output ports
jack_port_t **output_port;
/// \brief in
///
/// \brief out
jack_default_audio_sample_t **in, **out;
/// The OSC manager object
OscMan *oscman;
TransferFunction *trans_fun;
/// \brief process
/// \param nframes
/// \return
///
int process (jack_nframes_t nframes);
///
/// \brief callback_process
/// is used to access the members of this
/// class in the static mode
/// \param x number of samples in the buffer
/// \param object void pointer
/// \return
///
static int callback_process(jack_nframes_t x, void* object);
public:
///
/// \brief GainExample
/// the constructor
/// \param yaml_manager
///
Waveshaper(YamlMan *yaml_manager);
};
#N canvas 188 506 450 300 10;
#X obj 125 130 osc~ 100;
#X obj 125 153 dac~;
#X floatatom 125 67 5 0 0 0 - - -, f 5;
#X obj 242 133 packOSC;
#X obj 242 156 udpsend;
#X msg 302 138 connect localhost 6666;
#X floatatom 242 49 5 0 0 0 - - -, f 5;
#X msg 242 71 /gain \$1;
#X connect 0 0 1 0;
#X connect 2 0 0 0;
#X connect 3 0 4 0;
#X connect 5 0 4 0;
#X connect 6 0 7 0;
#X connect 7 0 3 0;
/**
* \file yamlman.cpp
* \class YamlMan
*
* \author Henrik von Coler
*
* \version $Revision: 0.5 $
*
* \date $Date: 2016/08/18$
*
*/
#include "yamlman.h"
YamlMan::YamlMan(std::string filepath)
{
cout << "Loading config from YAML file: " << filepath << endl;
YAML::Node config = YAML::LoadFile(filepath);
// read values
port = config["port"].as<int>();
path = config["path"].as<std::string>();
}
int YamlMan::return_port()
{
return port;
}
std::string YamlMan::return_path()
{
return path;
}
/**
* \file yamlman.h
* \class YamlMan
*
* \brief Class which parses YAML files for parameters.
*
* YamlMan also keeps the parameter settings and offers
* getters for each, individually.
*
* \author Henrik von Coler
*
* \version $Revision: 0.5 $
*
* \date $Date: 2016/08/18$
*
*/
#ifndef YAMLMAN_H
#define YAMLMAN_H
#include<yaml-cpp/yaml.h>
#include<iostream>
#include<string.h>
using std::cout;
using std::endl;
using std::string;
class YamlMan
{
private:
/// \brief port
/// The OSC port to be used for receiving messages
int port;
/// \brief path
/// The OSC path used for the parameter
std::string path;
public:
/// \brief YamlMan
/// Constructor
/// \param filepath The path of the config file (*.yml)
YamlMan(std::string filepath);
/// \brief return_port
/// \return The OSC port to be used
int return_port();
/// \brief return_path
/// Returns the OSC path used
/// to change the gain of the signal.
///
/// \return The OSC path.
string return_path();
};
#endif // YAMLMAN_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment