[samphold~] noise, [phasor~] noise, round-off error, or ?
@jameslo yes, @ddw_music was correct. It's a combination of double and single precision (and I edited my last comment, this prediction is consistent w/ the 1st patch at least). The value "conv" in the source code is stored in a t_float, which is generally a 32-bit float these days (though maybe that will change soon..). This is set to 1/samplerate. every sample conv is multiplied by the input frequency (which is also a 32-bit float) and then added as a double to the current phase, which is a double with value 1572864 + actual phase, (1572864 is 3^19, a float value that makes bit 32 of the entire 64-bit double value the 1s place, leaving the remaining 32 bits as the fractional part). Every sample the top 32 bits of the phase are set to the top 32 bits of 1572864, and when the phase is output, 1572864 is subtracted from it.
tldr: the phase accumulator is basically 32-bit fixed-point
[samphold~] noise, [phasor~] noise, round-off error, or ?
@jameslo the phasor~ source was a bit confusing to me at first, it works by setting the upper 32 bits of a double (including the exponent) such that bit 32 of the double represents the "1s" place value, so all of the lower 32 bits represent the fractional part. Then after the correct phase accumulation is added, the magnitude that was added to make all lower 32 bits the fractional part is subtracted from the double in order to output just the fractional part. (and then the upper 32 bits are again set to that value, destroying the non-fractional part)
All of this is done to avoid cpu branching so it can pipeline instructions better (so instead of having to check if the phase > 1, each sample you just set bits to a certain value)
Recommended Pitch Detection Object?
If @jancsika has a moment maybe he can explain where things stand.
In Purr Data you can do [floatsize(---[pdinfo]
to tell whether floats are single or double precision. The current possible outputs from that message would be "32" for single precision or "64" for double precision.
Pd and the externals you use have to be compiled for one or the other-- you can't mix the two floatsizes. Currently Purr Data is able to build itself and most externals with floatsize=64, but some libraries need to be revised so that they work. So atm we're shipping floatsize=64 Purr Data with just the core and a few convenience libraries. I named these builds "purr-double-trouble" since they don't yet ship with all the externals.
That is all a separate issue from the arch for which a piece of software is compiled. "Arch" means chip architecture and uses nicknames like "i32", "x86_64", "arm64". For general purpose computers these generally divide into two broad categories-- the ones which the hardware shuttles data around in groups of 64 bits, and hardware that shuttles data in groups of 32 bits. Some 64-bit platforms even let you run old stuff built for a 32-bit hardware in a special compatibility mode.
So to clarify: you can have:
- single-precision Pd built for a 32-bit arch
- single-precision Pd built for a 64-bit arch
- double-precision Pd built for a 32-bit arch
- double-precision Pd built for a 64-bit arch
Recommended Pitch Detection Object?
If I may weigh in (on both the pitch detection & 32/64 topics):
I have tried all three of the aforementioned objects, and personally found [helmholtz~] to work best for my uses. I can't say I was extremely scientific in my comparisons, but I generally got the sense that it performs a bit better than [sigmund~].
When I first began migration from extended to 64-bit vanilla, all of the 32-bit externals I was using needed to be replaced, and [helmholtz~] was the one I missed the most. I replaced it for a while with [sigmund~], but eventually I went & compiled a new [helmholtz~] from source against 64-bit vanilla, which is working fine.
Now, as for comparing performance of 32 vs 64 bit Pd in general (very much FWIW... I'm on MacOS, not Windows, and I have no technical knowledge to back these observations up): a couple years ago I did test my most CPU-intensive patch in both 32 and 64 bit vanilla, and found a modest ~15-20% CPU performance boost (according to the load meter) when using 64-bit. I remember seeing some discussion of this on the Pd-list a while back, it might have been this thread. I did not compare memory usage between versions, so I can't speak to that.
Purr Data 2.5.0
@alfonso.santimone Oh wow, a Windows 10 VM can't even run on my build machine! It's eating the entire system's memory-- I couldn't even ssh into it and had to reboot.
I could probably cross-compile on the Windows 7 VM. But I wouldn't be able to run tests so that isn't ideal.
Anyway, if you want to try compiling yourself, you can use the instructions from the 32-bit build as a guide:
https://git.purrdata.net/jwilkes/purr-data#windows-32-bit-using-msys2
You'll have to change some of the instructions and download the corresponding msys2 64-bit packages. You'll also certainly run into crashers because the Makefile for windows currently installs some 32-bit dependencies manually into the Purr Data installer package. But if you get that far I can guide you through the solutions to most of those problems.
The good news is that you don't need Lucas' preprocessor flag because we already have an ifdef for Windows 64 big in our build system.
If you can get through all that it would help the project: I could add instructions for a 64-bit Windows build and fix up the windows Makefile so it works for 64-bit. (The GUI we ship on Windows is already 64-bit so that's ready to go.)
Cyclone library stopped suddenly loading (PD Vanilla/Windows 10)
@ilpoj It could be a widows10 update.
tcl ........ pd_guiprefs.tcl performs the read/writes through the "registry" object.
On a 64-bit system 32-bit apps write to the "VirtualStore" in the registry.
What is 64-bit and what is 32-bit in Pd and Tcl/Tk?
Maybe it's writing to one and reading from the other?
Tcl........ Tcl 8.6 recommended........
https://stackoverflow.com/questions/31432958/tcl-unable-to-read-variables-of-32-bit-registry-hierarchy-on-a-64-bit-machine
Widows........ Microsoft intend to bin VirtualStore and force app compatibility.....
...... have they just started this process?
https://msdn.microsoft.com/en-us/library/windows/desktop/aa965884(v=vs.85).aspx
Other software identical problem.......
http://knowledgebase.progress.com/articles/Article/UACvirtualisation
Pd_guiprefs.tcl on-going work....... 16 days ago.... maybe time to post a bug?
https://github.com/pure-data/pure-data/tree/master/tcl
Again..... Tcl 8.6 recommended.......
https://community.activestate.com/node/11350
and....
http://www.tcl.tk/cgi-bin/tct/tip/362.html
David.
Purr Data rc5
Purr Data release candidate 5!
- small fixes to OSX app bundle name and build instructions
- fixed OSX app bundle name
- fixed GUI errors with some GUI objects on GOP
- use cat icon for patches
- fixed a [grid] crasher with binding symbol leak
- fixed [grid] line drawing bug and GOP xlet display
- added dialog and scale handle for [grid]
- ported moonlib/knob
- get rid of some extraneous debugging messages
- allow to install Purr Data alongside Pd-l2ork
- Scope~ code cleanup
- fixes for arm build
- added some OSX app bundle dependencies for [fluid~] and others
- fix saving preferences under OSX
- added startup paths and libs to preferences dialog
- use "Purr Data" in OSX menu app
- help browser fixes
- fixed MIDI preference saving on OSX and Windows
- added a "Recent Files" menu to the "File" menu
- get consistent behavior for present working directory when opening/saving files
- fix Volume name for OSX dmg installer
- try to standardize a deterministic package name when compiling Purr Data
- add a Pd-l2ork-specific version number
- add command line open args to "Recent Files" list
- fixed crasher with ds "canvas" field
- allow saving the zoom level per canvas
please report lots of bugs to
https://git.purrdata.net/jwilkes/purr-data/issues
Binaries:
Updated below (to include forward or backward option): Beat Looper, record and playback loops in a set pattern
Needed an effect to fill a slot, so set out to make one.
abs_beatlooper~_sv.pd
abs_beatlooper~_sv_help.pd
Synopsis:
The abstraction repeatedly (via [metro]s) records a loop for a set amount of beats, pauses for another number of beats and plays it for yet another number of beats.
FYI: I think it's timing might be a little out-of-whack. So if some/any-one can diagnose and/or remedy the issue (:-) if there actually is one) that would be great! Thanks in advance.
Note:all times are in beats.
Via its controls, the abs_:
off|on: turns a [switch~] on in the subpatch and starts a [timer];
bpm: sets the beats-per-minute rate of the looper;
rec_time : how many beats the looper should record;
pause_time: how many beats the looper should wait until playing the recorded loop;
play_time: how many beats the looper should play the loop for;
feedback: for the side-chained delay line the loop is being written to;
saturation: the gain-mix for the dry and wet lines
Notes: if play_time is less than rec_time it will only play the first x beats, if greater it will repeat the loop as many times as it can up to mod beats of the rec_time. The looper is actually on a side-chained delay line (with 0 delay time, but allowable feedback). The bpm calc is from the DIY2-4tap-delay abs_, the delay line is from DIY-mono-delay-feedback, and I can't remember where I got the looper.
If someone recognizes the looper subpatch by all means Please share who did it below.
I am very very curious if anyone finds this useful and/or intriguing.
Esp. since that feedback may/probably will impact whether i include it in my rack-app.
So if you do check it out, please, provide feedback below. Thanks.
Peace. And merry music making thru us all.
-svanya
p.s. currently, this only plays the segments forward. I will update it when able so the user can toggle whether the loops are played forward or backward.
Purr Data rc4
Edit: Windows binary is now up
Purr Data release candidate 4!
- fixed race when opening pd file in OSX
- partial fix for midi prefs not getting saved under Windows
- fixed #194: saving a loaded abstraction gives errors
- fixed for #201: new subcanvas position isn't saved with patch
- sync the ALSA sequencer port state with the GUI
- reset ALSA MIDI device handles and event buffers when closing
- got rid of more debugging output
- go ahead and allow curly braces in Pd messages
- replace the Pd-extended output~ abstraction with Alexandre Porres' improved version
- report userful value for "dsp-status" method of [pdinfo] by ignorning suspend/resume
- fixed display of dollar signs in properties dialogs
- fixed loading of lyonpotpourri and disis libraries
please report lots of bugs to
https://git.purrdata.net/jwilkes/purr-data/issues
Binaries:
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