Browse Source

PD: revert to PD v.0.50-2, implements knob send, lights receive and audio through, displays multi instance warning

tags/v1.3.0
clwe 4 years ago
parent
commit
c769b1b1aa
2 changed files with 187 additions and 69 deletions
  1. +52
    -9
      examples/audio-trough.pd
  2. +135
    -60
      src/LibPDEngine.cpp

+ 52
- 9
examples/audio-trough.pd View File

@@ -1,9 +1,52 @@
#N canvas 653 457 450 300 12;
#X obj 151 125 adc~ 1 2 3 4 5 6;
#X obj 152 184 dac~ 1 2 3 4 5 6;
#X connect 0 0 1 0;
#X connect 0 1 1 1;
#X connect 0 2 1 2;
#X connect 0 3 1 3;
#X connect 0 4 1 4;
#X connect 0 5 1 5;
#N canvas 2220 331 802 519 12;
#X obj 112 43 adc~ 1 2 3 4 5 6, f 47;
#X obj 113 199 dac~ 1 2 3 4 5 6, f 47;
#X obj 112 127 *~ 1;
#X obj 137 94 r K1;
#X obj 178 126 *~ 1;
#X obj 242 128 *~ 1;
#X obj 308 127 *~ 1;
#X obj 372 127 *~ 1;
#X obj 438 126 *~ 1;
#X obj 203 93 r K2;
#X obj 267 93 r K3;
#X obj 333 94 r K4;
#X obj 397 93 r K5;
#X obj 463 93 r K6;
#X obj 290 416 print toVCV;
#X msg 267 278 L3 \$1 0 0;
#X msg 333 310 L4 \$1 0 0;
#X msg 463 311 L6 \$1 0 0;
#X msg 136 277 L1 \$1 0 0;
#X msg 203 309 L2 \$1 0 0;
#X msg 397 280 L5 \$1 0 0;
#X connect 0 0 2 0;
#X connect 0 1 4 0;
#X connect 0 2 5 0;
#X connect 0 3 6 0;
#X connect 0 4 7 0;
#X connect 0 5 8 0;
#X connect 2 0 1 0;
#X connect 3 0 2 1;
#X connect 3 0 18 0;
#X connect 4 0 1 1;
#X connect 5 0 1 2;
#X connect 6 0 1 3;
#X connect 7 0 1 4;
#X connect 8 0 1 5;
#X connect 9 0 4 1;
#X connect 9 0 19 0;
#X connect 10 0 5 1;
#X connect 10 0 15 0;
#X connect 11 0 6 1;
#X connect 11 0 16 0;
#X connect 12 0 7 1;
#X connect 12 0 20 0;
#X connect 13 0 8 1;
#X connect 13 0 17 0;
#X connect 15 0 14 0;
#X connect 16 0 14 0;
#X connect 17 0 14 0;
#X connect 18 0 14 0;
#X connect 19 0 14 0;
#X connect 20 0 14 0;

+ 135
- 60
src/LibPDEngine.cpp View File

@@ -1,45 +1,54 @@
#include "ScriptEngine.hpp"
#include "z_libpd.h"
#include <iostream>
#include <fstream>
using namespace std;
#include "util/z_print_util.h"
using namespace rack;

#define BUFFERSIZE MAX_BUFFER_SIZE * NUM_ROWS

void chair_write_patch_to_file(const string &patch, const string &path, const string &name )
{
ofstream myfile;
cout << "file to write: " << path + "/" + name << endl;
myfile.open (path + "/" + name);
myfile << patch;
myfile.close();
}

void chair_load_patch(const string &patch, const string &name)
{
// there is no multi-instance support for receiving messages from libpd
// for now, received values for the prototype gui will be stored in global variables

float g_leds[NUM_ROWS][3];

std::vector<std::string> split (const std::string &s, char delim) {
std::vector<std::string> result;
std::stringstream ss (s);
std::string item;

string path = ".";
chair_write_patch_to_file(patch, path, name);
libpd_openfile(name.c_str(), path.c_str());
remove( (path + "/" + name).c_str() );
while (getline (ss, item, delim)) {
result.push_back (item);
}

return result;
}




struct LibPDEngine : ScriptEngine {

~LibPDEngine() {
libpd_free_instance(_lpd);

}
// // variables for libpd

static void receiveLEDs(const char *s);

bool knobChanged(const float* knobs, int idx);

bool switchChanged(const float* knobs, int idx);

t_pdinstance *_lpd;
int _pd_block_size = 64;
int _sampleRate = 0;
int _ticks = 0;
float _old_knobs[NUM_ROWS];
bool _old_switches[NUM_ROWS];
float _output[BUFFERSIZE];
float _input[BUFFERSIZE];// = (float*)malloc(1024*2*sizeof(float));
// end variables for libpd
const static std::map<std::string, int> _led_map;


std::string getEngineName() override {
@@ -49,49 +58,37 @@ struct LibPDEngine : ScriptEngine {
int run(const std::string& path, const std::string& script) override {

ProcessBlock* block = getProcessBlock();

_sampleRate = block->sampleRate;

setBufferSize(_pd_block_size);
setFrameDivider(1);
libpd_init();
_lpd = libpd_new_instance();

libpd_set_instance(_lpd);
libpd_set_printhook((t_libpd_printhook)libpd_print_concatenator);
libpd_set_concatenated_printhook( receiveLEDs );
//libpd_set_printhook(receiveLEDs);
//libpd_bind("L2");
//libpd_bind("foo");
//libpd_set_listhook(receiveList);
//libpd_set_messagehook(receiveMessage);

if(libpd_num_instances()>2)
{
display("Sorry, multi instance support in libpd is under development!");
return -1;
}

//display(std::to_string(libpd_num_instances()));
libpd_init_audio(NUM_ROWS, NUM_ROWS, _sampleRate);
//cout << "_lpd is initialized" << endl;
//cout << "num od pd instances: " << libpd_num_instances() << endl;
// compute audio [; pd dsp 1(

// compute audio [; pd dsp 1(
libpd_start_message(1); // one enstry in list
libpd_add_float(1.0f);
libpd_finish_message("pd", "dsp");
std::string name = "test.pd";
std::string patch = "#N canvas 653 457 450 300 12;\n"
"#X obj 151 125 adc~ 1 2 3 4 5 6;\n"
"#X obj 152 184 dac~ 1 2 3 4 5 6;\n"
"#X connect 0 0 1 0;\n"
"#X connect 0 1 1 1;\n"
"#X connect 0 2 1 2;\n"
"#X connect 0 3 1 3;\n"
"#X connect 0 4 1 4;\n"
"#X connect 0 5 1 5;";





/*"#N canvas 333 425 105 153 10;\n"
"#X obj 32 79 dac~;\n"
"#X obj 32 27 adc~;\n"
"#X connect 1 0 0 0;\n"
"#X connect 1 1 0 1;";*/

//libpd_openfile(patch.c_str(), path.c_str());

chair_load_patch(patch, name);
std::string name = string::filename(path);
std::string dir = string::directory(path);
libpd_openfile(name.c_str(), dir.c_str());
return 0;
}
@@ -100,10 +97,7 @@ struct LibPDEngine : ScriptEngine {
// block
ProcessBlock* block = getProcessBlock();

display(std::to_string(block->bufferSize));

// pass samples to/from libpd
_ticks = 1;//curr_bufSize / 64;
// get samples prototype
int rows = NUM_ROWS;
for (int s = 0; s < _pd_block_size; s++) {
for (int r = 0; r < rows; r++) {
@@ -112,8 +106,33 @@ struct LibPDEngine : ScriptEngine {
}
libpd_set_instance(_lpd);

// knobs
for (int i=0; i<NUM_ROWS; i++){
if( knobChanged(block->knobs, i) ){
std::string knob = "K"+std::to_string(i+1);
libpd_float(knob.c_str(), block->knobs[i]);
}
}
// leds
//display(std::to_string(g_leds[0]));
for(int i=0; i<NUM_ROWS; i++){
block->lights[i][0] = g_leds[i][0];
block->lights[i][1] = g_leds[i][1];
block->lights[i][2] = g_leds[i][2];
}
// switches
for(int i=0; i<NUM_ROWS; i++){
if( switchChanged(block->switches, i) ){
std::string sw = "S"+std::to_string(i+1);
libpd_float(sw.c_str(), block->switches[i]);
}
}
// process samples in libpd
_ticks = 1;
libpd_process_float(_ticks, _input, _output);
//return samples to prototype
for (int s = 0; s < _pd_block_size; s++) {
for (int r = 0; r < rows; r++) {
block->outputs[r][s] = _output[s*rows+r];
@@ -122,8 +141,6 @@ struct LibPDEngine : ScriptEngine {

return 0;
}

};


@@ -131,3 +148,61 @@ __attribute__((constructor(1000)))
static void constructor() {
addScriptEngine<LibPDEngine>("pd");
}


void LibPDEngine::receiveLEDs(const char *s) {
std::string str = std::string(s);
std::vector<std::string> atoms = split (str, ' ');

if(atoms[0]=="toVCV:"){
// led list
bool led_is_valid = true;
int led_idx = -1;
try {
led_idx = _led_map.at(atoms[1]); // map::at throws an out-of-range
}
catch (const std::out_of_range& oor) {
led_is_valid = false;
//display("Warning:"+atoms[1]+" not found!");
}
//std::cout << v[1] << ", " << g_led_map[v[1]] << std::endl;
if(led_is_valid && atoms.size()==5){
g_leds[led_idx][0] = stof(atoms[2]); // red
g_leds[led_idx][1] = stof(atoms[3]); // green
g_leds[led_idx][2] = stof(atoms[4]); // blue
}
else {
}
}
else {
// do nothing
}
}

bool LibPDEngine::knobChanged(const float* knobs, int i){
bool knob_changed = false;
if (_old_knobs[i] != knobs[i]){
knob_changed = true;
_old_knobs[i] = knobs[i];
}
return knob_changed;
}

bool LibPDEngine::switchChanged(const float* switches, int i){
bool switch_changed = false;
if (_old_switches[i] != switches[i]){
switch_changed = true;
_old_switches[i] = switches[i];
}
return switch_changed;
}

const std::map<std::string, int> LibPDEngine::_led_map{
{ "L1", 0 },
{ "L2", 1 },
{ "L3", 2 },
{ "L4", 3 },
{ "L5", 4 },
{ "L6", 5 }
};

Loading…
Cancel
Save