Question about Pure Data and decoding a Dx7 sysex patch file....
Hey Seb!
I appreciate the feedback
The routing I am not so concerned about, I already made a nice table based preset system, following pretty strict rules for send/recives for parameter values. So in theory I "just" need to get the data into a table. That side of it I am not so concerned about, I am sure I will find a way.
For me it's more the decoding of the sysex string that I need to research and think a lot about. It's a bit more complicated than the sysex I used for Blofeld.
The 32 voice dump confuses me a bit. I mean most single part(not multitimbral) synths has the same parameter settings for all voices, so I think I can probably do with just decoding 1 voice and send that data to all 16 voices of the synth? The only reason I see one would need to send different data to each voice is if the synth is multitimbral and you can use for example voice 1-8 for part 1, 9-16 for part 2, 17-24 for part 3, 24-32 for part 4. As an example....... Then you would need to set different values for the different voices. I have no plan to make it multitimbral, as it's already pretty heavy on the cpu. Or am I misunderstanding what they mean with voices here?
Blofeld:
What I did for Blofeld was to make an editor, so I can control the synth from Pure Data. Blofeld only has 4 knobs, and 100's of parameters for each part.... And there are 16 parts... So thousand + parameters and only 4 knobs....... You get the idea
It's bit of a nightmare of menu diving, so just wanted to make something a bit more easy editable .
First I simply recorded every single sysex parameter of Blofeld(100's) into Pure data, replaced the parameter value in the parameter value and the channel in the sysex string message with a variable($1+$2), so I can send the data back to Blofeld. I got all parameters working via sysex, but one issue is, that when I change sound/preset in the Pure Data, it sends ALL parameters individually to Blofeld.... Again 100's of parameters sends at once and it does sometimes make Blofeld crash. Still needs a bit of work to be solid and I think learning how to do this decoding/coding of a sysex string can help me get the Blofeld editor working properly too.
I tried several editors for Blofeld, even paid ones and none of them actually works fully they all have different bugs in the parameter assignments or some of them only let's you edit Blofeld in single mode not in multitimbral mode. But good thingis that I actually got ALL parameters working, which is a good start. I just need to find out how to manage the data properly and send it to Blofeld in a manner that does not crash Blofeld, maybe using some smarter approach to sysex.
But anyway, here are some snapshots for the Blofeld editor:
Image of the editor as it is now. Blofeld has is 16 part multitimbral, you chose which part to edit with the top selector:
Here is how I send a single sysex parameter to Blofeld:
If I want to request a sysex dump of the current selected sound of Blofeld(sound dump) I can do this:
I can then send the sound dump to Blofeld at any times to recall the stored preset. For the sound dump, there are the rules I follow:
For the parameters it was pretty easy, I could just record one into PD and then replace the parameter and channel values with $1 & $2.
For sound dumps I had to learn a bit more, cause I couldn't just record the dump and replace values, I actually had to understand what I was doing. When you do a sysex sound dump from the Blofeld, it does not actually send back the sysex string to request the sound dump, it only sends the actual sound dump.
I am not really a programmer, so it took a while understanding it. Not saying i fully understand everything but parameters are working, hehe
So making something in Lua would be a big task, as I don't know Lua at all. I know some C++, from coding Axoloti objects and VCV rack modules, but yeah. It's a hobby/fun thing I think i would prefer to keep it all in Pure Data, as I know Pure Data decently.
So I do see this as a long term project, I need to do it in small steps at a time, learn things step by step.
I do appreciate the feedback a lot and it made me think a bit about some things I can try out. So thanks
Having lots of switches into Pd
@alexandros thanks, it all works!
I merged the codes for in and outs and also changed so you can set up all of the pins with arrays (as you did in the latter code). Then you can set up the pins in any order.
Here is the Arduino code. Do you spot any errors I may have introduced?
//number of elements in array need to match for() cycles
int pinsIn[4] = {2, 7, 10, 11};
int pinsAnalog[3] = {0, 2, 3};
int pin = 0;
int val = 0;
// some random pins
int pinsOut[4] = {3, 4, 5, 6};
void setup()
{
//set up a total of pins for input (has to match number of elements in array)
for(int i = 0; i < 4; i++)
pinMode(pinsIn[i], INPUT);
for (int i = 0; i < 4; i++) {
pinMode(pinsOut[i], OUTPUT);
digitalWrite(pinsOut[i], LOW);
}
Serial.begin(115200); // perhaps use a faster baud rate
}
void loop()
{
Serial.print("knobs"); // use "knobs" as a keyword so you can receive
// the knob values as a list with a [r knobs] in Pd
for(int i = 0; i < 3; i++){
unsigned int knob = analogRead (pinsAnalog[i]);
Serial.print(" "); // first print a white space to separate the "knob" keyword from the values
// and the values from each other
Serial.print(knob); // then print the actual knob value
}
Serial.println(); // finally print a newline character to denote end of data for keyword "knobs"
// the same technique applies to the switches too
// receive the switch values as a list with [r switches]
Serial.print("switches");
for(int i = 0; i < 4; i++) {
int switchVal = digitalRead(pinsIn[i]);
Serial.print(" ");
Serial.print(switchVal);
}
Serial.println();
//handle digital outputs
if (Serial.available()) {
static int temp;
byte in = Serial.read();
if (isDigit(in)) {
temp = temp * 10 + in - '0';
}
else if (in == 'p') {
pin = temp;
temp = 0;
}
else if (in == 'v') {
val = temp;
temp = 0;
digitalWrite(pinsOut[pin], val);
}
}
}
In Pd I was not able to use [r switches] or [r knobs] but had to use [route]. Is this the correct way to use [serial_print]?
And here it is on the breadboard:
Having lots of switches into Pd
I would suggest to not mix the analog values with the digital ones. The first code could be changed to the following (using Serial.print() with the [serial_print] abstraction):
void setup()
{
for(int i = 2; i < 14; i++)
pinMode(i, INPUT);
Serial.begin(115200); // perhaps use a faster baud rate
}
void loop()
{
Serial.print("knobs"); // use "knobs" as a keyword so you can receive
// the knob values as a list with a [r knobs] in Pd
for(int i = 0; i < 6; i++){
unsigned int knob = analogRead (i);
Serial.print(" "); // first print a white space to separate the "knob" keyword from the values
// and the values from each other
Serial.print(knob); // then print the actual knob value
}
Serial.println(); // finally print a newline character to denote end of data for keyword "knobs"
// the same technique applies to the switches too
// receive the switch values as a list with [r switches]
Serial.print("switches");
for(int i = 2; i < 14; i++) {
int switchVal = digitalRead(i);
Serial.print(" ");
Serial.print(switchVal);
}
Serial.println();
}
As for writing to several outputs you need to set which output you want to write to and then the value you want to write. Here's an example that writes to several different digital outputs:
int pin = 0;
int val = 0;
// some random pins
int pins[4] = {3, 4, 5, 6];
void setup() {
for (int i = 0; i < 4; i++) {
pinMode(pins[i], OUTPUT);
digitalWrite(pins[i], LOW);
}
Serial.begin(115200);
}
void loop() {
if (Serial.available()) {
static int temp;
byte in = Serial.read();
if (isDigit(in)) {
temp = temp * 10 + in - '0';
}
else if (in == 'p') {
pin = temp;
temp = 0;
}
else if (in == 'v') {
val = temp;
temp = 0;
digitalWrite(pins[pin], val);
}
}
With the code above you can send messages like this one print $1p$2v
in Pd to the [comport] object. $1 is the number of the pin you want to light up starting from 0 and incrementing by 1 (so the first pin used which is pin 3 in the Arduino code would be 0 in the Pd patch), and $2 is the value, 0 or 1.
Note though that in the first code (and the code you posted), you're using all digital pins as inputs so there's no pin left to use as output. If you want to combine these two chunks of code you'll have to use less pins as inputs and leave some to be used as outputs.
BPM/Pitch calculator
@lead A semitone is 1/12 of an octave, so if you raise the pitch by a semitone, you're raising the tempo by 2 to the power of 1/12 and would multiply the tempo by that.
So if you lower the pitch by 2 semitones you would divide the tempo by 2 to the power of 2/12
The tempo ratio (old to new) would be 1 : (1 / 2 to the power of 0.166666667)
The tempo ratio (new to old) would be (1 / 2^0.166666667) : 1
As sure as I can be...
You can do the math in your patch using [pow]
David.
Http://www.netpd.org/
@beem Nope, just audio and timing.
https://github.com/wahjam/wahjam/wiki/Ninjam-Protocol
*Time is divided into intervals which allow each client to upload audio that other clients will receive and play when the next interval starts. Therefore clients do not play audio together in real-time; audio from remote clients is always delayed by one interval. This design recognizes the fact that latency on the internet is too high for real-time audio collaboration.
The tempo is defined by the Beats Per Minute (bpm) and Beats Per Interval (bpi) session settings. Clients typically offer metronome functionality based on the bpm setting to enable musicians to play in time.*
I added OSC to the ninjam client so that PD can receive the bpm and downbeat (start).
How to implement subdivision of metro value?
@alexandros Thanks very much for your message there. I'm not sure if this works for the specific use I'm going for though? I've included my patch for you to see. Basically, I'm building a little bpm counter for a larger patch I'm working on. By dividing the milliseconds of a minute into my desired bpm for this example (120), I get the 500 I mentioned in my OP. So that is my set tempo 120bpm or 500ms in regards to the bang.. so from there I need to create a signal that will send out to another bang from the same metro but 4 times as quick. So you'll see in the patch, the right bang I would like to bang four times as fast (125ms).
Purr Data 2.5.0
ok dependencies seems to be ok...this is my log
fremen@fremenCPU MINGW64 ~
$ pacman -S autoconf automake git libtool \
make mingw-w64-x86_64-dlfcn mingw-w64-x86_64-fftw
mingw-w64-x86_64-fluidsynth
mingw-w64-x86_64-ftgl mingw-w64-x86_64-fribidi
mingw-w64-x86_64-ladspa-sdk mingw-w64-x86_64-lame
mingw-w64-x86_64-libsndfile mingw-w64-x86_64-libvorbis
mingw-w64-x86_64-lua mingw-w64-x86_64-toolchain
mingw-w64-x86_64-libjpeg-turbo
rsync unzip wget
warning: autoconf-2.69-3 is up to date -- reinstalling
warning: automake-wrapper-10-1 is up to date -- reinstalling
warning: git-2.10.1-1 is up to date -- reinstalling
warning: libtool-2.4.6-2 is up to date -- reinstalling
warning: make-4.2.1-1 is up to date -- reinstalling
:: There are 16 members in group mingw-w64-x86_64-toolchain:
:: Repository mingw64
- mingw-w64-x86_64-binutils 2) mingw-w64-x86_64-crt-git
- mingw-w64-x86_64-gcc 4) mingw-w64-x86_64-gcc-ada
- mingw-w64-x86_64-gcc-fortran 6) mingw-w64-x86_64-gcc-libgfortran
- mingw-w64-x86_64-gcc-libs
mingw-w64-x86_64-gcc-objc
- mingw-w64-x86_64-gdb 10) mingw-w64-x86_64-headers-git
- mingw-w64-x86_64-libmangle-git 12) mingw-w64-x86_64-libwinpthread-git
- mingw-w64-x86_64-make 14) mingw-w64-x86_64-pkg-config
- mingw-w64-x86_64-tools-git 16) mingw-w64-x86_64-winpthreads-git
Enter a selection (default=all):
warning: mingw-w64-x86_64-binutils-2.27-2 is up to date -- reinstalling
warning: mingw-w64-x86_64-crt-git-5.0.0.4745.d2384c2-1 is up to date -- reinstal ling
warning: mingw-w64-x86_64-gcc-6.2.0-2 is up to date -- reinstalling
warning: mingw-w64-x86_64-gcc-libgfortran-6.2.0-2 is up to date -- reinstalling
warning: mingw-w64-x86_64-gcc-libs-6.2.0-2 is up to date -- reinstalling
warning: mingw-w64-x86_64-headers-git-5.0.0.4747.0f8f626-1 is up to date -- rein stalling
warning: mingw-w64-x86_64-libwinpthread-git-5.0.0.4741.2c8939a-1 is up to date - - reinstalling
warning: mingw-w64-x86_64-winpthreads-git-5.0.0.4741.2c8939a-1 is up to date -- reinstalling
warning: unzip-6.0-2 is up to date -- reinstalling
warning: wget-1.18-1 is up to date -- reinstalling
resolving dependencies...
looking for conflicting packages...
warning: dependency cycle detected:
warning: mingw-w64-x86_64-gcc-libgfortran will be installed before its mingw-w64 -x86_64-gcc-libs dependency
warning: dependency cycle detected:
warning: mingw-w64-x86_64-harfbuzz will be installed before its mingw-w64-x86_64 -freetype dependency
warning: dependency cycle detected:
warning: mingw-w64-x86_64-cairo will be installed before its mingw-w64-x86_64-fr eetype dependency
warning: dependency cycle detected:
warning: mingw-w64-x86_64-fontconfig will be installed before its mingw-w64-x86_ 64-freetype dependency
Packages (58) mingw-w64-x86_64-cairo-1.15.2-4 mingw-w64-x86_64-flac-1.3.1-2
mingw-w64-x86_64-fontconfig-2.12.0-2
mingw-w64-x86_64-freetype-2.7-1 mingw-w64-x86_64-gdbm-1.12-1
mingw-w64-x86_64-glib2-2.50.1-2
mingw-w64-x86_64-graphite2-1.3.8-5
mingw-w64-x86_64-harfbuzz-1.3.2-1
mingw-w64-x86_64-libogg-1.3.2-2 mingw-w64-x86_64-libpng-1.6.26-1
mingw-w64-x86_64-ncurses-6.0.20161001-1
mingw-w64-x86_64-pcre-8.38-1 mingw-w64-x86_64-pixman-0.34.0-3
mingw-w64-x86_64-portaudio-19_20140130-2
mingw-w64-x86_64-python2-2.7.12-1
mingw-w64-x86_64-readline-6.3.008-1
mingw-w64-x86_64-speex-1.2rc2-2
mingw-w64-x86_64-speexdsp-1.2rc3-2 mingw-w64-x86_64-tcl-8.6.6-1
mingw-w64-x86_64-termcap-1.3.1-2 mingw-w64-x86_64-tk-8.6.6-1
mingw-w64-x86_64-wineditline-2.101-4 winpty-0.4.0-2
autoconf-2.69-3 automake-wrapper-10-1 git-2.10.1-1
libtool-2.4.6-2 make-4.2.1-1 mingw-w64-x86_64-binutils-2.27-2
mingw-w64-x86_64-crt-git-5.0.0.4745.d2384c2-1
mingw-w64-x86_64-dlfcn-1.0.0-2 mingw-w64-x86_64-fftw-3.3.5-1
mingw-w64-x86_64-fluidsynth-1.1.6-3
mingw-w64-x86_64-fribidi-0.19.7-1
mingw-w64-x86_64-ftgl-2.1.3rc5-2 mingw-w64-x86_64-gcc-6.2.0-2
mingw-w64-x86_64-gcc-ada-6.2.0-2
mingw-w64-x86_64-gcc-fortran-6.2.0-2
mingw-w64-x86_64-gcc-libgfortran-6.2.0-2
mingw-w64-x86_64-gcc-libs-6.2.0-2
mingw-w64-x86_64-gcc-objc-6.2.0-2 mingw-w64-x86_64-gdb-7.12-1
mingw-w64-x86_64-headers-git-5.0.0.4747.0f8f626-1
mingw-w64-x86_64-ladspa-sdk-1.13-2
mingw-w64-x86_64-lame-3.99.5-4
mingw-w64-x86_64-libjpeg-turbo-1.5.1-1
mingw-w64-x86_64-libmangle-git-5.0.0.4669.7de6266-1
mingw-w64-x86_64-libsndfile-1.0.26-1
mingw-w64-x86_64-libvorbis-1.3.5-1
mingw-w64-x86_64-libwinpthread-git-5.0.0.4741.2c8939a-1
mingw-w64-x86_64-lua-5.3.3-1
mingw-w64-x86_64-make-4.1.2351.a80a8b8-1
mingw-w64-x86_64-pkg-config-0.29.1-2
mingw-w64-x86_64-tools-git-5.0.0.4669.7de6266-1
mingw-w64-x86_64-winpthreads-git-5.0.0.4741.2c8939a-1
rsync-3.1.2-2 unzip-6.0-2 wget-1.18-1
Total Download Size: 76.81 MiB
Total Installed Size: 749.00 MiB
Net Upgrade Size: 369.69 MiB
:: Proceed with installation? [Y/n] Y
:: Retrieving packages...
mingw-w64-x86_64-dl... 9.6 KiB 9.41M/s 00:00 [#####################] 100%
mingw-w64-x86_64-ff... 4.0 MiB 1146K/s 00:04 [#####################] 100%
mingw-w64-x86_64-wi... 32.7 KiB 6.39M/s 00:00 [#####################] 100%
mingw-w64-x86_64-pc... 859.1 KiB 1252K/s 00:01 [#####################] 100%
mingw-w64-x86_64-gl... 2.9 MiB 1247K/s 00:02 [#####################] 100%
mingw-w64-x86_64-li... 191.2 KiB 7.18M/s 00:00 [#####################] 100%
mingw-w64-x86_64-fl... 582.7 KiB 1588K/s 00:00 [#####################] 100%
mingw-w64-x86_64-li... 331.2 KiB 1761K/s 00:00 [#####################] 100%
mingw-w64-x86_64-sp... 472.2 KiB 1349K/s 00:00 [#####################] 100%
mingw-w64-x86_64-sp... 519.0 KiB 1458K/s 00:00 [#####################] 100%
mingw-w64-x86_64-li... 359.9 KiB 1874K/s 00:00 [#####################] 100%
mingw-w64-x86_64-po... 143.6 KiB 7.01M/s 00:00 [#####################] 100%
mingw-w64-x86_64-fl... 252.2 KiB 1425K/s 00:00 [#####################] 100%
mingw-w64-x86_64-fo... 220.8 KiB 1284K/s 00:00 [#####################] 100%
mingw-w64-x86_64-pi... 289.5 KiB 1591K/s 00:00 [#####################] 100%
mingw-w64-x86_64-ca... 755.8 KiB 1423K/s 00:01 [#####################] 100%
mingw-w64-x86_64-gr... 167.0 KiB 7.09M/s 00:00 [#####################] 100%
mingw-w64-x86_64-ha... 314.4 KiB 1700K/s 00:00 [#####################] 100%
mingw-w64-x86_64-li... 285.9 KiB 1571K/s 00:00 [#####################] 100%
mingw-w64-x86_64-fr... 503.3 KiB 1422K/s 00:00 [#####################] 100%
mingw-w64-x86_64-ft... 118.8 KiB 7.25M/s 00:00 [#####################] 100%
mingw-w64-x86_64-fr... 93.4 KiB 7.02M/s 00:00 [#####################] 100%
mingw-w64-x86_64-la... 8.3 KiB 8.13M/s 00:00 [#####################] 100%
mingw-w64-x86_64-la... 373.9 KiB 1928K/s 00:00 [#####################] 100%
mingw-w64-x86_64-lu... 269.6 KiB 1506K/s 00:00 [#####################] 100%
mingw-w64-x86_64-gc... 18.0 MiB 1203K/s 00:15 [#####################] 100%
mingw-w64-x86_64-gc... 8.1 MiB 1209K/s 00:07 [#####################] 100%
mingw-w64-x86_64-gc... 13.6 MiB 1202K/s 00:12 [#####################] 100%
mingw-w64-x86_64-gd... 164.1 KiB 6.97M/s 00:00 [#####################] 100%
mingw-w64-x86_64-nc... 1697.2 KiB 1237K/s 00:01 [#####################] 100%
mingw-w64-x86_64-te... 12.6 KiB 12.3M/s 00:00 [#####################] 100%
mingw-w64-x86_64-re... 327.4 KiB 1732K/s 00:00 [#####################] 100%
mingw-w64-x86_64-tc... 2.9 MiB 1242K/s 00:02 [#####################] 100%
mingw-w64-x86_64-tk... 1873.6 KiB 1218K/s 00:02 [#####################] 100%
mingw-w64-x86_64-py... 11.2 MiB 1216K/s 00:09 [#####################] 100%
mingw-w64-x86_64-gd... 2.9 MiB 1234K/s 00:02 [#####################] 100%
mingw-w64-x86_64-li... 26.7 KiB 6.51M/s 00:00 [#####################] 100%
mingw-w64-x86_64-ma... 103.2 KiB 7.20M/s 00:00 [#####################] 100%
mingw-w64-x86_64-pk... 237.5 KiB 1357K/s 00:00 [#####################] 100%
mingw-w64-x86_64-to... 257.4 KiB 1446K/s 00:00 [#####################] 100%
mingw-w64-x86_64-li... 379.7 KiB 1957K/s 00:00 [#####################] 100%
winpty-0.4.0-2-x86_64 495.6 KiB 1404K/s 00:00 [#####################] 100%
rsync-3.1.2-2-x86_64 259.9 KiB 1460K/s 00:00 [#####################] 100%
wget-1.18-1-x86_64 582.1 KiB 1595K/s 00:00 [#####################] 100%
(58/58) checking keys in keyring [#####################] 100%
(58/58) checking package integrity [#####################] 100%
(58/58) loading package files [#####################] 100%
(58/58) checking for file conflicts [#####################] 100%
(58/58) checking available disk space [#####################] 100%
warning: could not get file information for usr/share/man/man3/Git::I18N.3pm.gz
warning: could not get file information for usr/share/man/man3/Git::SVN::Editor. 3pm.gz
warning: could not get file information for usr/share/man/man3/Git::SVN::Fetcher .3pm.gz
warning: could not get file information for usr/share/man/man3/Git::SVN::Memoize ::YAML.3pm.gz
warning: could not get file information for usr/share/man/man3/Git::SVN::Prompt. 3pm.gz
warning: could not get file information for usr/share/man/man3/Git::SVN::Ra.3pm. gz
warning: could not get file information for usr/share/man/man3/Git::SVN::Utils.3 pm.gz
:: Processing package changes...
( 1/58) reinstalling autoconf [#####################] 100%
( 2/58) reinstalling automake-wrapper [#####################] 100%
( 3/58) reinstalling git [#####################] 100%
( 4/58) reinstalling libtool [#####################] 100%
( 5/58) reinstalling make [#####################] 100%
( 6/58) reinstalling mingw-w64-x86_64-libwinpt... [#####################] 100%
( 7/58) reinstalling mingw-w64-x86_64-gcc-libg... [#####################] 100%
( 8/58) reinstalling mingw-w64-x86_64-gcc-libs [#####################] 100%
( 9/58) installing mingw-w64-x86_64-dlfcn [#####################] 100%
(10/58) installing mingw-w64-x86_64-fftw [#####################] 100%
(11/58) installing mingw-w64-x86_64-wineditline [#####################] 100%
(12/58) installing mingw-w64-x86_64-pcre [#####################] 100%
(13/58) installing mingw-w64-x86_64-glib2 [#####################] 100%
No schema files found: doing nothing.
(14/58) installing mingw-w64-x86_64-libogg [#####################] 100%
(15/58) installing mingw-w64-x86_64-flac [#####################] 100%
(16/58) installing mingw-w64-x86_64-libvorbis [#####################] 100%
(17/58) installing mingw-w64-x86_64-speexdsp [#####################] 100%
(18/58) installing mingw-w64-x86_64-speex [#####################] 100%
(19/58) installing mingw-w64-x86_64-libsndfile [#####################] 100%
(20/58) installing mingw-w64-x86_64-portaudio [#####################] 100%
(21/58) installing mingw-w64-x86_64-fluidsynth [#####################] 100%
(22/58) installing mingw-w64-x86_64-fontconfig [#####################] 100%
Fontconfig configuration is done via /mingw64/etc/fonts/conf.avail and conf.d.
Read /mingw64/etc/fonts/conf.d/README for more information.
updating font cache... C:/msys64/mingw64/bin/fc-cache.exe: error while loading s hared libraries: ?: cannot open shared object file: No such file or directory
done.
(23/58) installing mingw-w64-x86_64-pixman [#####################] 100%
(24/58) installing mingw-w64-x86_64-cairo [#####################] 100%
Optional dependencies for mingw-w64-x86_64-cairo
mingw-w64-x86_64-glib2: libcairo-gobject [installed]
(25/58) installing mingw-w64-x86_64-graphite2 [#####################] 100%
(26/58) installing mingw-w64-x86_64-harfbuzz [#####################] 100%
Optional dependencies for mingw-w64-x86_64-harfbuzz
mingw-w64-x86_64-icu: harfbuzz-icu support
(27/58) installing mingw-w64-x86_64-libpng [#####################] 100%
(28/58) installing mingw-w64-x86_64-freetype [#####################] 100%
(29/58) installing mingw-w64-x86_64-ftgl [#####################] 100%
(30/58) installing mingw-w64-x86_64-fribidi [#####################] 100%
(31/58) installing mingw-w64-x86_64-ladspa-sdk [#####################] 100%
(32/58) installing mingw-w64-x86_64-lame [#####################] 100%
(33/58) installing winpty [#####################] 100%
(34/58) installing mingw-w64-x86_64-lua [#####################] 100%
(35/58) reinstalling mingw-w64-x86_64-binutils [#####################] 100%
(36/58) reinstalling mingw-w64-x86_64-headers-git [#####################] 100%
(37/58) reinstalling mingw-w64-x86_64-crt-git [#####################] 100%
(38/58) reinstalling mingw-w64-x86_64-winpthre... [#####################] 100%
(39/58) reinstalling mingw-w64-x86_64-gcc [#####################] 100%
(40/58) installing mingw-w64-x86_64-gcc-ada [#####################] 100%
(41/58) installing mingw-w64-x86_64-gcc-fortran [#####################] 100%
(42/58) installing mingw-w64-x86_64-gcc-objc [#####################] 100%
(43/58) installing mingw-w64-x86_64-gdbm [#####################] 100%
(44/58) installing mingw-w64-x86_64-ncurses [#####################] 100%
(45/58) installing mingw-w64-x86_64-termcap [#####################] 100%
(46/58) installing mingw-w64-x86_64-readline [#####################] 100%
(47/58) installing mingw-w64-x86_64-tcl [#####################] 100%
(48/58) installing mingw-w64-x86_64-tk [#####################] 100%
(49/58) installing mingw-w64-x86_64-python2 [#####################] 100%
(50/58) installing mingw-w64-x86_64-gdb [#####################] 100%
(51/58) installing mingw-w64-x86_64-libmangle-git [#####################] 100%
(52/58) installing mingw-w64-x86_64-make [#####################] 100%
(53/58) installing mingw-w64-x86_64-pkg-config [#####################] 100%
(54/58) installing mingw-w64-x86_64-tools-git [#####################] 100%
(55/58) installing mingw-w64-x86_64-libjpeg-turbo [#####################] 100%
(56/58) installing rsync [#####################] 100%
(57/58) reinstalling unzip [#####################] 100%
(58/58) reinstalling wget [#####################] 100%
ArguScore
Here is an updated version
arguscore-update.zip
and a few Purr Data compatibility replacement objects: purr-data-compatible-replacements.zip
A creation argument only object driven system for instant music making;
Objects so far;
Required;
globaltimer - outputs a 10ms bang to drive all objects;
globalsync - resets all objects to zero or start;
audio~ - dac~ catcher~ for all throws~, output level, mute;
Sound Objects
By default sound objects start playing at the bpm of the first argument
basspump - args - bpm note distortion duration
wood - args - bpm note duration
tremsaw - args - bpm note vibrato distortion duration
tremsine - args - bpm note vibrato noise duration
noisy - args - bpm note vcfq duration
kauplus - args - bpm note string-resonation duration
Effect Objects
sqr - args - 16 required(0 or 1) bpm (starts playing by default)
overides sound objects autoplay
2 optional args for cursor offset and pitch if font different
has 16 outlets to send 0 or 1
echo-delay-bpm - args - bpm feedback(0 to 100) level(0 to 100)
echo-delay-ms - args - millisecs feedback(0 to 100) level(0 to 100)
pan-level - args - pan (-100 to 100) level (0 to 100)
autopan - args - width (0 to 100) frequency (* 0.01) level (0 to 100)
fade - args - millisecs to fade-in pecentage of level to drop to (0 to 100) millisecs to fade-out
filter - args - highpass (midi note to frequency) lowpass (midi note to frequency)
(0 to 135 equates to approx 8Hz to 19912Hz)
start-delay-secs - args - seconds (delays the autostart of the connected object)
start-delay-bpm - args - bpm (delays the autostart of the connected object)
stop-delay-secs - args - seconds (outputs a one at the end of the delay which can connect to a globalsync)
stop-delay-bpm - args - bpm (delays the autostart of the connected object)
isolator - sits between two sqr's and sends a signal to start/stop the receiving sqr
seqnotes - four pairs of note & velocity that receive sqr ones to fire a connected sound object
Notes
Can crash Pd when making lots of edits to arguments, particularly while playing, so save often
There is a [declare -path objects] hiding behind the audio~ object
Fixed missing note and velo message for tremsaw
Two more arguscore patches can be open at the same time providing only one patch contains the globaltimer and audio~ objects (see arguscore-2.pd and arguscore-2-b.pd)
new objects
kauplus, autopan, fade, filter, stop-delay-secs, stop-delay-bpm;
ArguScore
ArguScore
A creation argument only object driven system for instant music making
Objects so far:
Required:
globaltimer - outputs a 10ms bang to drive all objects
globalsync - resets all objects to zero or start
audio~ - dac~ catcher~ for all throws~, output level, mute
Sound Objects
By default sound objects start playing at the bpm of the first argument
basspump - args - bpm note distortion duration
wood - args - bpm note duration
tremsaw - args - bpm note vibrato distortion duration
tremsine - args - bpm note vibrato noise duration
noisy - args - bpm note vcfq duration
Effect Objects
sqr - args - 16 required(0 or 1) bpm (starts playing by default), overides sound objects autoplay, 2 optional args for cursor offset and pitch if font different has 16 outlets to send 0 or 1
echo-delay-bpm args - bpm feedback(0 to 100) level(0 to 100)
echo-delay-ms - args - millisecs feedback(0 to 100) level(0 to 100)
pan-level - args - pan (-100 to 100) level (0 to 100);
start-delay-secs - args - seconds (delays the autostart of the connected object)
start-delay-bpm - args - bpm (delays the autostart of the connected object)
isolator - sits between two sqr's and sends a signal to start/stop the receiving sqr;
seqnotes - four pairs of note & velocity that receive sqr ones to fire a connected sound object
Cheers
Balwyn
arguscore.zip
Matrices and reallocating memory
I tried to find all my errors, corrected them and now it seemes to work.
(The method init_array is still missing a check if allocations failed.)
Do I really have to free the colums before reallocating the rows? Isn't it the other way around?
#include "m_pd.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
static t_class *average_tilde_class;
typedef struct _average_tilde {
t_object x_obj;
t_int len_avg;
t_int block_size;
t_int pos;
t_sample **sampel_arr;
t_sample *avg;
t_inlet* x_in;
t_outlet* x_out;
} t_average_tilde;
void average_tilde_free (t_average_tilde *x)
{
// Deallocate rows
for (int i = 0; i < x->len_avg; ++i)
free(x->sampel_arr[i]);
// Deallocate columns
free(x->sampel_arr);
// Deallocate avg
free(x->avg);
}
t_int *average_tilde_perform(t_int *w)
{
t_average_tilde *x = (t_average_tilde *)(w[1]);
t_sample *in = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
//int block = (int)(w[4]);
t_sample val;
for (int n = 0; n < x->block_size; n++) {
x->avg[n] -= x->sampel_arr[x->pos][n];
val = in[n] / x->block_size;
x->avg[n] += val;
x->sampel_arr[x->pos][n] = val;
*out++ = x->avg[n];
}
x->pos++;
if (x->pos == x->len_avg) x->pos = 0;
return (w + 5);
}
void resize_avg_array(t_average_tilde *x, int len_avg_new)
{
int i,j;
int success = 1;
t_sample **temp = NULL;
t_sample *temp2 = NULL;
do {
success = 1;
// Allocate the columns
temp = realloc(temp, len_avg_new * sizeof(t_sample*));
if (temp == NULL) {
len_avg_new--;
free(temp);
success = 0;
}
else {
// The new column's pointer must be initialised to NULL
for (i = 0; i < len_avg_new; i++)
temp[i] = NULL;
// Allocate the rows
for (i = 0; i < len_avg_new; i++) {
temp[i] = realloc(temp[i], x->block_size * sizeof(t_sample));
if (temp[i] == NULL) {
len_avg_new--;
success = 0;
break;
}
else {
// Initialize the element(s)
for (j = 0; j < x->block_size; j++)
temp[i][j] = 0.0;
}
}
if (success == 1) {
// Initialize avg-array
temp2 = realloc(temp2, x->block_size * sizeof(t_sample));
if (temp2 == NULL) {
len_avg_new--;
success = 0;
free(temp2);
}
else {
// Initialize the element(s)
for (i = 0; i < x->block_size; i++)
temp2[i] = 0.0;
}
if (success == 1) {
// Deallocate rows
for (i = 0; i < x->len_avg; ++i)
free(x->sampel_arr[i]);
// Deallocate columns
free(x->sampel_arr);
// Copy temps to arrays
x->len_avg = len_avg_new;
x->sampel_arr = temp;
free(x->avg);
x->avg = temp2;
x->pos = 0;
}
}
}
} while (success = 0 && len_avg_new > 0);
if (success = 0) {
post("length of avg-vector stayed at %i samples", x->len_avg);
}
}
void average_tilde_dsp(t_average_tilde *x, t_signal **sp)
{
x->block_size = sp[0]->s_n;
float arr_size = sizeof(x->sampel_arr) / sizeof(x->sampel_arr[0][0]);
if (x->block_size * x->len_avg != arr_size)
resize_avg_array(x, 10);
dsp_add(average_tilde_perform, 4,
x,
sp[0]->s_vec,
sp[1]->s_vec,
sp[0]->s_n);
}
void set_len_avg(t_average_tilde *x, t_floatarg f)
{
if ((int)f > 0)
resize_avg_array(x, f);
}
void init_array(t_average_tilde *x)
{
int i = 0, j = 0;
// Allocate the columns
x->sampel_arr = (t_sample**)calloc(x->len_avg, sizeof(t_sample*));
// Allocate the rows
for (i = 0; i < x->len_avg; i++)
x->sampel_arr[i] = (t_sample*)calloc(x->block_size, sizeof(t_sample));
// Initialize the element(s)
for (i = 0; i < x->len_avg; i++)
for (j = 0; j < x->block_size; j++)
x->sampel_arr[i][j] = 0.0;
// Initialize avg-array
x->avg = realloc(x->avg, x->block_size * sizeof(t_sample));
for (j = 0; j < x->block_size; j++)
x->avg[j] = 0.0;
}
void *average_tilde_new(t_floatarg f)
{
t_average_tilde *x = (t_average_tilde *)pd_new(average_tilde_class);
// initialize values with defaults
x->len_avg = ((int)f > 0) ? (int)f : 10;
x->block_size = 64;
x->pos = 0;
init_array(x);
x->x_out = outlet_new(&x->x_obj, &s_signal);
return (void *)x;
}
void init_average(void) {
average_tilde_class = class_new(gensym("r_avg~"),
(t_newmethod)average_tilde_new,
(t_method)average_tilde_free,
sizeof(t_average_tilde),
CLASS_DEFAULT,
A_DEFFLOAT, 0);
class_addmethod(average_tilde_class,
(t_method)average_tilde_dsp, gensym("dsp"), 0);
CLASS_MAINSIGNALIN(average_tilde_class, t_average_tilde, len_avg);
class_addfloat(average_tilde_class, set_len_avg);
}
void helloworld_setup(void) {
init_average();
}
EDIT: Corrected some logical errors in the code.
The variable success has to be set to 1 in each do while loop
The arrays x->sampel_arr and x->avg have to be freed inside the do while loop