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 9b2479b4 by Jonas Margraf
parents 0cc0b313 b9a6eff5
# define the compiler
CC = g++
# path(s) to include files
CFLAGS = -I.
# libraries to link
LDFLAGS = -ljack -llo -lrtmidi
SRCS = main.cpp midi_sine_example.cpp oscman.cpp midiman.cpp sinusoid.cpp
DEPS = midi_sine_example.h oscman.h midiman.h sinusoid.h
all: midi_sine_example
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
midi_sine_example: main.o midi_sine_example.o oscman.o midiman.o sinusoid.o
$(CC) -o midi_sine_example main.o midi_sine_example.o oscman.o midiman.o sinusoid.o $(LDFLAGS)
clean:
rm *.o midi_sine_example
/**
* \struct noteMessage
*
*
* \brief Structure for holding Note (on,off) messages.
*
*
* \author Henrik von Coler
*
* \version $Revision: 0.5 $
*
* \date $Date: 2005/04/14 14:16:20 $
*
* Contact: von_coler@intelligent-noise-solutions.de
*
*
*/
#ifndef DATATYPES_H
#define DATATYPES_H
typedef struct {
int noteNumber = -1; /// @var noteNumber The note number
double velocity = -1;
bool hasBeenProcessed = false;
}noteMessage;
typedef struct {
int ctlNumber = -1; /// @var noteNumber The note number
double value = -1;
bool hasBeenProcessed = false;
}ctlMessage;
#endif // DATATYPES_H
#include <iostream>
#include "midi_sine_example.h"
using std::cout;
using std::endl;
int main(int argc, char *argv[]){
// process command line arguments
int id;
int n;
for (int i = 1; i < argc; i++)
{
if (i + 1 != argc)
{
if (strcmp(argv[i], "-ID") == 0)
{
id = atoi(argv[i + 1]);
i++;
}
if (strcmp(argv[i], "-n") == 0)
{
n = atoi(argv[i + 1]);
i++;
}
}
}
MidiSineExample * m = new MidiSineExample(id, n);
}
/**
*
* \file midi_sine_example.cpp
* \class MidiSineExample
*
* \brief
*
* \author Henrik von Coler
*
* \date $Date: 2019/03/23 $
*
*/
#include"midi_sine_example.h"
using std::cout;
using std::endl;
MidiSineExample::MidiSineExample(int ID, int nPart )
{
nPartials = nPart;
this->client = jack_client_open("MIDI_Sine_Example", JackNullOption, &status, NULL);
fs = jack_get_sample_rate(client);
// allocate array
sines = new Sinusoid[nPartials];
// set initial values
for (int i=0; i<nPartials; i++)
sines[i].init(432 * (double) (i+1),0.1,1,fs);
// create a ne grain player
//grainer = new GrainPlayer(filename, fs, win_size, nWindows);
nChannels = 2;
/// allocate a new midi manager
midiMan = new MidiMan(ID);
// -----------------------------------------------------------------------
// standard JACK startup:
// -----------------------------------------------------------------------
cout << "Starting Jack Client! " << endl;
jack_set_process_callback(this->client, this->callback_process, this);
output_port = new jack_port_t*[nChannels];
for (int i=0; i<nOutputs; 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);
}
jack_activate(this->client);
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 MidiSineExample::process (jack_nframes_t nframes)
{
// allocate output buffer array
jack_default_audio_sample_t **out = new jack_default_audio_sample_t*[nChannels];
for ( int i=0 ; i<nChannels; i++)
{
// buffer size can change
out[i] = (jack_default_audio_sample_t *) jack_port_get_buffer(this->output_port[i], jack_get_buffer_size(client));
}
// process midi messages
MidiMan::midiMessage m = midiMan->get_rtmidi();
// if a valid MIDI message is received
if(m.byte3>=0)
{
double f0 = 0;
// if it is a note message, use first data byte
if(m.byte1 == 144)
f0 = 440.0 * std::pow(2, ((double) m.byte2-69) / 12.0) ;
// if it is a control message, use second data byte
if(m.byte1 == 176)
f0 = 440.0 * std::pow(2, ((double) m.byte3-69) / 12.0) ;
// flush all messages
midiMan->flushProcessedMessages();
// set alll partial frequencies and amplitudes
for (int i=0; i<nPartials; i++)
{
sines[i].amplitude(0.1 * 1/(i+1));
sines[i].frequency(f0* (double) (i+1));
}
}
// loop over all samples of output buffer
for(int sampCNT=0; sampCNT<nframes; sampCNT++)
{
// initialize samples
out[0][sampCNT] = 0;
out[1][sampCNT] = 0;
// loop over all partials
for (int i=0; i<nPartials; i++)
{
double tmpVal = sines[i].getNextSample();
// take care of nyquist frequency
if (sines[i].frequency()<fs/2)
{
out[0][sampCNT] += tmpVal;
out[1][sampCNT] += tmpVal;
}
}
}
return 0;
}
int MidiSineExample::callback_process(jack_nframes_t x, void* object)
{
return static_cast<MidiSineExample*>(object)->process(x);
}
/**
* \file wav_example.h
* \class WavExample
*
* \brief Simple example, passing the input to the output
* with gain modification through OSC.
*
* \author Henrik von Coler
*
* \date $Date: 2019/03/18 $
*
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<jack/jack.h>
#include "oscman.h"
#include "midiman.h"
#include "sinusoid.h"
using std::cout;
using std::endl;
class MidiSineExample{
private:
int nPartials;
///
/// \brief fs
/// sample rate of the jack server
int fs = 0;
///
/// \brief nOutputs
/// number off jack output ports
int nOutputs = 2;
///
/// \brief nChannels
/// number of channels in the sample
int nChannels;
///
/// \brief ports
/// the jack output ports
const char **ports;
jack_client_t *client;
jack_status_t status;
jack_port_t **output_port;
/// The OSC manager object
OscMan *oscman;
/// an array of sinusoids
Sinusoid *sines;
MidiMan *midiMan;
///
/// \brief process
/// get the next buffer from the sample and playback
/// \param nframes
/// \return
///
int process(jack_nframes_t nframes);
///
/// \brief callback_process
/// \param x
/// \param object
/// \return
///
static int callback_process(jack_nframes_t x, void* object);
public:
/// \brief GainExample
/// Constructor!
MidiSineExample(int ID, int nPart);
};
#include "midiman.h"
bool MidiMan::done;
MidiMan::MidiMan(int ID)
{
// rtmidid intit
midiin = new RtMidiIn(RtMidiIn::Api::UNSPECIFIED ,std::string("RtMidi Input Client"),(unsigned int) 100);
midiin->openPort(ID);
// // Don't ignore sysex, timing, or active sensing messages.
midiin->ignoreTypes( false, false, false );
done = false;
}
void MidiMan::setVerbose()
{
isVerbose = true;
}
MidiMan::midiMessage MidiMan::get_rtmidi()
{
MidiMan::midiMessage mm;
std::vector<unsigned char> a;
int nBytes = 1;
/// this is kind of a dirty workaroud -
/// we loop over all in-massages and take the last one:
while(nBytes>0)
{
midiin->getMessage(&a);
nBytes = a.size();
/// only do something if bytes are received
if(nBytes!=0)
{
/// only give feedback if 'verbose-mode' is active
if(isVerbose == true )
{
std::cout << "received " << nBytes << "Bytes: " ;
for (int i=0; i<nBytes; i++ )
std::cout << i << " = " << (int)a[i] << " -- " ;
std::cout << std::endl;
}
mm.byte1 = a[0];
mm.byte2 = a[1];
mm.byte3 = a[2];
}
}
return mm;
}
//////////////////////////////////////////////////////////////////
// FLUSH
//////////////////////////////////////////////////////////////////
void MidiMan::flushProcessedMessages()
{
val.clear();
}
int MidiMan::getNumFaderMessages()
{
int v = (int) val.size();
return v;
}
/**
* \class MidiMan
*
*
* \brief Class which parses and stores the incoming MIDI messages.
*
*
* \author Henrik von Coler
*
* \version $Revision: 0.5 $
*
* \date $Date: 2005/04/14 14:16:20 $
*
* Contact: von_coler@tu-berlin.de
*
*
*/
#ifndef MIDIMAN_H
#define MIDIMAN_H
#include <iostream>
#include <cstdlib>
#include <signal.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <iostream>
#include <jack/midiport.h>
#include <rtmidi/RtMidi.h>
#include "datatypes.h"
class MidiMan
{
public:
typedef struct {
int byte1 = -1;
int byte2 = -1;
double byte3 = -1;
bool hasBeenProcessed = false;
}midiMessage;
MidiMan(int ID);
~MidiMan();
std::vector<std::string> returnAllNames();
void updateMidiMessages(void *port_buf);
void parseMidiMessages();
void addNoteOnMessage(int in[3]);
std::vector<noteMessage> getNoteOnMessages();
void clearNoteOnMessages();
void addNoteOffMessage(int in[3]);
std::vector<noteMessage> getNoteOffMessages();
void clearNoteOffMessages();
void eraseNoteOnMessage(int position);
void addFaderMessage(ctlMessage m);
void markOnMessageProcessed(int pos);
void markOffMessageProcessed(int pos);
void flushProcessedMessages();
ctlMessage getLastFaderMessage();
int getNumFaderMessages();
static void finish(int ignore);
midiMessage get_rtmidi();
void setVerbose();
private:
// rtmidi
static bool done;
RtMidiIn *midiin;
int nBytes, i;
double stamp;
bool isVerbose = false;
std::vector<int> val;
noteMessage *tmpNote;
void mycallback( double deltatime, std::vector< unsigned char > *message, void *userData );
};
#endif // MIDIMAN_H
/**
* \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(int p)
{
port = p;
speed = 0.05;
st = new lo::ServerThread(port);
if (st->is_valid())
{
// Add the example handler to the server!
st->add_method("/speed", "f", speed_callback, this);
// start, obviously
st->start();
std::cout << "Started OSC Server!" << std::endl;
}
else
throw std::invalid_argument("OSC server not started - possibly a bad port!");
}
int OscMan::speed_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 playback speed to: " << argv[0]->f << std::endl;
statCast->speed = argv[0]->f;
}
double OscMan::get_speed()
{
return speed;
}
/**
* \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<iostream>
#include<vector>
#include<string>
#include <stdexcept>
class OscMan
{
private:
/// the port to be opened
int port;
lo::ServerThread *st;
double speed;
///
////// \brief OscMan::speed_callback
////// \param path
////// \param types
////// \param argv
////// \param argc
////// \param data
////// \param user_data
////// \return
static int speed_callback(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data);
public:
///
/// \brief OscMan::OscMan
/// \param p
///
OscMan(int p);
///
/// \brief OscMan::get_speed
/// \return
///
double get_speed();
};
#endif
/**
* \class Sinusoid
*
*
* \brief Simple sinusoid handler class.
*
*
*
* \author Henrik von Coler
*
* \version $Revision: 0.5 $
*
* \date $Date: 2016/08/01 14:16:20 $
*
* Contact: von_coler@intelligent-noise-solutions.de
*
*
*/
#include "sinusoid.h"
Sinusoid::Sinusoid()
{
}
void Sinusoid::init(double f, double a, double p, int fS)
{
freq = f;
amp = a;
phi = p;
fs = fS;
}
double Sinusoid