Some patches won't open. (was: Why Vanilla fails at reading some Purr Data patches?)
@lacuna said:
So these patches starting with
#N canvas 2802 562 675 300 12;
or
#N canvas 785 1198 794 777 12;
appear blank.
If (I'm guessing) the canvas parameters are "left-X top-Y width height" (and I guess 12 is a zoom factor but I'm not sure), then X = 2802 is very, very far to the right, and 1198 is very, very far down. On my laptop, I've got 1366x768; a window positioned 2802 pixels away from screen left would far, far out of bounds.
The window manager that I use in Linux will "fix" offscreen window coordinates, so when I open the js-help patch, it appears flush against the right and bottom screen borders. The stated coordinates are out of bounds on my system; the window manager shifts them to be on screen. The problem is technically there, but masked by the window manager.
I have seen Windows not adjust out of bounds window coordinates -- i.e., open a subpatch within a student's patch, and couldn't see the window at all.
I'm not 100% certain that's the problem here -- but I'll observe that the action you took, which resolved the problem, was to change the upper-left window coordinates to be much closer to the top left of the screen.
hjh
CPU usage of idle patches, tabread4~?
Hi zigmhount!
This is a copy paste of a message I (hopefully) sent via chat as well:
I figured I’d tell you a bit more about my patch so we can see if there’s overlap. Switch is definitely an overlap. I’m not using a metronome at all on mine. The inspiration was two loopers I love: the line 6 DL4 and the EHX 45000. It’s going to be 4 foot switches. Record, play, previous and next. Record and play function the way they do in the DL4. Record to start a new loop, record again to set length and start overdubbing or play to simply set length and start looping. From there record works like overdub on/ off toggle and play stop or restarts the loop. Previous and next are where it gets interesting.
There’s a 7 segment display (meaning a 1 digit number read out) that tells you what loop you’re “focused” on. It starts on 0. You can’t change focus until you have a loop going. Once you do, prev or next change focus. If you change focus while recording, it closes the loop you’re on and starts playing it, then immediately starts recording the next loop. The next loop though can be as long as you want. However, silence gets added to the end of the loop when you are done so that it matches up with a multiple of “loop 0”
In other words, loop 0, acts as a measure length and all other loops are set to a multiple of that measure length.
But...they can start anywhere you want. To the person playing the looper, it will feel like individual loops are all overdubs of the first loop, just at any length you want. I don’t know if I’m explaining this so well, but the point is, you don’t have to worry about timing or a metronome with this. You don’t have to wait for the beginning of measures to start or end loops. Once you have the timing of the first loop down there’s no waiting... you start recording and playing whenever you want as long as you want t and if it’s in time when you play it it will be i the recording.
So far I have recording and overdubbing down on loop 0 WITHOUT CLICKS. this took a lot of work and messing. Sounds like you are struggling with that now. Hardware is important yes.
I’m running it on a rasberry pi 4b 4 gig memory but with a pi sound audio interface. It’s more expensive than the pi but the latency and sound quality are GREAT. I also wanted to make the hardware all independent eventually and have the whole thing fit i it’s own box. The foot pedals run on an arduino that talks through comport to the pi and pure data.
In pure data I’m timing the loops and recording them via tabwrite. I’m then playing them with tabplay with a 0 $1 message box where 0 is start and $1 is the length, rounded to block size, of the recording. I record and play the same arrays for each loop at the same time while overdubbing, but delay the recording so it’s a few blocks back from the tabplay. The delay on the recording seemed to help elimate clocks as well. So did using tabplay instead of tabread 4. I think the phasor is CPU expensive or something. I don’t know. When I start / stop recording I use a line ramp on the volume going into the recording of 5 msecs. This is also necessary to eliminate clicks. Also, I had to stop resizing or clearing arrays as both cause clicks. Now I just overwrite what I need and don’t read from what I didn’t overwrite (If that makes sense).
If you are getting clicking I would try upping block size, buffer size and just delaying the actual recording (delay the audio in the same amount) giving the computer time to think avoids drop outs. Also you don’t want monitoring if you can avoid it. I don’t know if you are using a mic or what.
Hopefully some of this made sense.
looking for links to info on Canvas/ GUI
@liamorourke Yes, probably best to start simple.
Here is an example using "graph on parent"...... GOP.
cart.pd
The patch itself will only work in extended. Many objects will be missing.... but that is not important.
Right click the window with the controls and click open and you will see what is inside.
The window is actually a sub-patch called [pd guts]
Once it is open you can right click anywhere on its background and a properties window can be opened.
The properties control the GOP..... whether its name is shown........ whether the GOP is active...... the size and the position of the GOP window in the sub-patch (the red box).
The size is reflected in the mother patch [cart] but the position is the position of the window through which you are looking into [pd guts]
"size" is obvious. "margin" sets the position of the box relative to the top left of the window.
Nothing outside that window is shown through the GOP, and no connections are shown even within the window.
David.
[sigmund~] creation arguments/parameters setup
@cfry Those sorts of sounds can be gotten as well and a more sensitive mic will pick them up. The problem you are having is the mic is just getting noise, everything of the same volume, so nothing distinct for [sigmund~] to pick out, remember all those discrete sources add together. By wind noise I meant the sound of wind hitting a microphone directly, this creates a constant sound which will over power all those other sounds, not the sound of wind rustling the leaves in a tree. A good wind screen will be very helpful for you here, but you need to remember, a windscreen does reduce mic sensitivity, so there is a trade off, increase mic sensitivity and the more wind noise it picks up, put on a denser wind screen and you loose some of that sensitivity. A pop screen could work better since it can be placed between the wind and the mic, the other sides of the mic are left open, but if the wind shifts you could end up with wind noise overpowering everything and have to reposition the screen. If you limit yourself to days with nothing more than light winds, you should be able to get by with just a light windscreen and not suffer much loss in sensitivity.
My knowledge of windscreens and pop screens and the like is fairly limited and largely theoretical, I have little hands on use of these things as I mostly record in more controlled environments or in situations where I have more leeway than your needs allow. Seeking out people or sites dedicated to making field recordings would likely be your best path on finding a good mic/pre setup for your needs.
[pix_share_read] and [pix_share_write] under windows
@whale-av, here is a log running pd with -lib Gem -verbose.
tried both 32bit and 64bit pd 0.48-1...
tried ./Gem.m_i386 and failed
tried ./Gem.dll and failed
tried ./Gem/Gem.m_i386 and failed
tried ./Gem/Gem.dll and failed
tried ./Gem.pd and failed
tried ./Gem.pat and failed
tried ./Gem/Gem.pd and failed
tried C:/Users/Raphael Isdant/Documents/Pd/externals/Gem.m_i386 and failed
tried C:/Users/Raphael Isdant/Documents/Pd/externals/Gem.dll and failed
tried C:/Users/Raphael Isdant/Documents/Pd/externals/Gem/Gem.m_i386 and failed
tried C:/Users/Raphael Isdant/Documents/Pd/externals/Gem/Gem.dll and failed
tried C:/Users/Raphael Isdant/Documents/Pd/externals/Gem.pd and failed
tried C:/Users/Raphael Isdant/Documents/Pd/externals/Gem.pat and failed
tried C:/Users/Raphael Isdant/Documents/Pd/externals/Gem/Gem.pd and failed
tried C:/Users/Raphael Isdant/AppData/Roaming/Pd/Gem.m_i386 and failed
tried C:/Users/Raphael Isdant/AppData/Roaming/Pd/Gem.dll and failed
tried C:/Users/Raphael Isdant/AppData/Roaming/Pd/Gem/Gem.m_i386 and failed
tried C:/Users/Raphael Isdant/AppData/Roaming/Pd/Gem/Gem.dll and failed
tried C:/Users/Raphael Isdant/AppData/Roaming/Pd/Gem.pd and failed
tried C:/Users/Raphael Isdant/AppData/Roaming/Pd/Gem.pat and failed
tried C:/Users/Raphael Isdant/AppData/Roaming/Pd/Gem/Gem.pd and failed
tried C:/Program Files/Common Files/Pd/Gem.m_i386 and failed
tried C:/Program Files/Common Files/Pd/Gem.dll and failed
tried C:/Program Files/Common Files/Pd/Gem/Gem.m_i386 and failed
tried C:/Program Files/Common Files/Pd/Gem/Gem.dll and failed
tried C:/Program Files/Common Files/Pd/Gem.pd and failed
tried C:/Program Files/Common Files/Pd/Gem.pat and failed
tried C:/Program Files/Common Files/Pd/Gem/Gem.pd and failed
tried D:/pd-0.48-1.windows.64bit/extra/Gem.m_i386 and failed
tried D:/pd-0.48-1.windows.64bit/extra/Gem.dll and failed
tried D:/pd-0.48-1.windows.64bit/extra/Gem/Gem.m_i386 and failed
tried D:/pd-0.48-1.windows.64bit/extra/Gem/Gem.dll and succeeded
D:\\pd-0.48-1.windows.64bit\\extra\\Gem\\Gem.dll: couldn't load
tried D:/pd-0.48-1.windows.64bit/extra/Gem.pd and failed
tried D:/pd-0.48-1.windows.64bit/extra/Gem.pat and failed
tried D:/pd-0.48-1.windows.64bit/extra/Gem/Gem.pd and failed
tried D:/pd-0.48-1.windows.64bit/doc/5.reference/Gem.m_i386 and failed
tried D:/pd-0.48-1.windows.64bit/doc/5.reference/Gem.dll and failed
tried D:/pd-0.48-1.windows.64bit/doc/5.reference/Gem/Gem.m_i386 and failed
tried D:/pd-0.48-1.windows.64bit/doc/5.reference/Gem/Gem.dll and failed
tried D:/pd-0.48-1.windows.64bit/doc/5.reference/Gem.pd and failed
tried D:/pd-0.48-1.windows.64bit/doc/5.reference/Gem.pat and failed
tried D:/pd-0.48-1.windows.64bit/doc/5.reference/Gem/Gem.pd and failed
Gem: can't load library```
ofelia: deque class
i am not sure if it is the best solution, but it works now (with setFromPixels) it is a variable framebuffer and the example buffers the last 300 frames from a video.
;
if type(window) ~= "userdata" then;
window = ofWindow();
end;
;
local canvas = pdCanvas(this);
local clock = pdClock(this, "setup");
local videoPlayer = ofVideoPlayer();
local outputList = {};
local frames = {};
local images = {};
local N = 300;
for i = 1, N do;
images[i] = ofImage();
end;
;
function ofelia.new();
ofWindow.addListener("setup", this);
ofWindow.addListener("update", this);
ofWindow.addListener("draw", this);
ofWindow.addListener("exit", this);
window:setPosition(50, 100);
window:setSize(800 + 40, 600 + 40);
if type(window) ~= "userdata" then;
window = ofWindow();
end;
;
window:create();
if ofWindow.exists then;
clock:delay(0);
end;
end;
;
function ofelia.free();
window:destroy();
ofWindow.removeListener("setup", this);
ofWindow.removeListener("update", this);
ofWindow.removeListener("draw", this);
ofWindow.removeListener("exit", this);
end;
;
function ofelia.setup();
ofSetWindowTitle("Video Player");
ofBackground(0, 0, 0, 255);
end;
;
function ofelia.moviefile(path);
videoPlayer:load(path);
videoPlayer:setLoopState(OF_LOOP_NORMAL);
videoPlayer:setPaused(true);
end;
;
function ofelia.setSpeed(f);
videoPlayer:setSpeed(f / 100);
end;
;
function ofelia.play();
videoPlayer:play();
end;
;
function ofelia.stop();
videoPlayer:setFrame(0);
videoPlayer:setPaused(true);
end;
;
function ofelia.setPaused(f);
if f == 1 then pause = true;
else pause = false;
end;
videoPlayer:setPaused(pause);
end;
;
function ofelia.setFrame(f);
videoPlayer:setFrame(f);
end;
;
function ofelia.setPosition(f);
videoPlayer:setPosition(f);
end;
;
function ofelia.setVolume(f);
videoPlayer:setVolume(f / 100);
end;
;
local number = 0;
function ofelia.update();
videoPlayer:update();
if videoPlayer:isFrameNew() then;
number = (number + 1) % N;
print(number + 1);
images[number + 1]:setFromPixels(videoPlayer:getPixels());
table.insert(frames, 1, images[number + 1]);
if #frames > N then;
table.remove(frames);
end;
end;
outputList[1] = videoPlayer:getPosition();
outputList[2] = videoPlayer:getCurrentFrame();
outputList[3] = videoPlayer:getTotalNumFrames();
return outputList;
end;
;
function ofelia.draw();
videoPlayer:draw(420, 20, 400, 600);
if #frames == N then;
frames[ofelia.frame]:draw(20, 20, 400, 600);
end;
end;
;
function ofelia.exit();
videoPlayer:close();
for i = 1, N do;
images[i]:clear();
end;
end;
;
ofelia: deque class
@Cuinjune I tried to create a video frame table ("circular video buffer").
It is possible to read (draw) video from the table but somehow only the current frame is stored at every position of the table.
Here is an example patch. "frames" is the frame table. "N" is the table size. At the left is the texture from the table, at the right the original video. Do you know what I do wrong?
I also tried ofPixels instead of ofTexture with the same result.
And I tried to store several images (jpg´s) instead of video to the frame buffer, which does probably work because each image has its own source.
;
if type(window) ~= "userdata" then;
window = ofWindow();
end;
;
local canvas = pdCanvas(this);
local clock = pdClock(this, "setup");
local videoPlayer = ofVideoPlayer();
local outputList = {};
local frames = {};
local N = 150;
;
function ofelia.bang();
ofWindow.addListener("setup", this);
ofWindow.addListener("update", this);
ofWindow.addListener("draw", this);
ofWindow.addListener("exit", this);
window:setPosition(50, 100);
window:setSize(800 + 40, 600 + 40);
if type(window) ~= "userdata" then;
window = ofWindow();
end;
;
window:create();
if ofWindow.exists then;
clock:delay(0);
end;
end;
;
function ofelia.free();
window:destroy();
ofWindow.removeListener("setup", this);
ofWindow.removeListener("update", this);
ofWindow.removeListener("draw", this);
ofWindow.removeListener("exit", this);
end;
;
function ofelia.setup();
ofSetWindowTitle("Video Player");
ofBackground(0, 0, 0, 255);
end;
;
function ofelia.moviefile(path);
videoPlayer:load(path);
videoPlayer:setLoopState(OF_LOOP_NORMAL);
videoPlayer:setPaused(true);
end;
;
function ofelia.setSpeed(f);
videoPlayer:setSpeed(f / 100);
end;
;
function ofelia.play();
videoPlayer:play();
end;
;
function ofelia.stop();
videoPlayer:setFrame(0);
videoPlayer:setPaused(true);
end;
;
function ofelia.setPaused(f);
if f == 1 then pause = true;
else pause = false;
end;
videoPlayer:setPaused(pause);
end;
;
function ofelia.setFrame(f);
videoPlayer:setFrame(f);
end;
;
function ofelia.setPosition(f);
videoPlayer:setPosition(f);
end;
;
function ofelia.setVolume(f);
videoPlayer:setVolume(f / 100);
end;
;
function ofelia.update();
videoPlayer:update();
if videoPlayer:isFrameNew() then;
table.insert(frames, 1, videoPlayer:getTexture());
if #frames > N then;
table.remove(frames, N + 1);
end;
end;
end;
;
function ofelia.draw();
videoPlayer:draw(420, 20, 400, 600);
if #frames == N then;
frames[ofelia.frame]:draw(20, 20, 400, 600);
end;
outputList[1] = videoPlayer:getPosition();
outputList[2] = videoPlayer:getCurrentFrame();
outputList[3] = videoPlayer:getTotalNumFrames();
return outputList;
end;
;
function ofelia.exit();
videoPlayer:close();
end;
;
Ofelia - videoPlayer and GLSL Effects
i think it is possible after trying a bit.
what seems important:
-use photo JPG (or something similar) as the codec for the video. a good program for converting is http://www.squared5.com/
-use setPosition and not setFrame for scrubbing or playing reverse through the video (it is much faster)
-playing with setPosition is without sound
-for playing with setPosition the video needs to be paused
it is adapted from the video example and can be optimized a lot to work like the [pixfilm] object...
video4.pd
if type(window) ~= "userdata" then;
window = ofWindow();
end;
;
local canvas = pdCanvas(this);
local clock = pdClock(this, "setup");
local videoPlayer = ofVideoPlayer();
;
function ofelia.bang();
ofWindow.addListener("setup", this);
ofWindow.addListener("update", this);
ofWindow.addListener("draw", this);
ofWindow.addListener("exit", this);
window:setPosition(50, 100);
window:setSize(800 + 40, 600 + 40);
if type(window) ~= "userdata" then;
window = ofWindow();
end;
;
window:create();
if ofWindow.exists then;
clock:delay(0);
end;
end;
;
function ofelia.free();
window:destroy();
ofWindow.removeListener("setup", this);
ofWindow.removeListener("update", this);
ofWindow.removeListener("draw", this);
ofWindow.removeListener("exit", this);
end;
;
function ofelia.setup();
ofSetWindowTitle("Video Player");
ofBackground(0, 0, 0, 255);
end;
;
function ofelia.moviefile(path);
videoPlayer:load(path);
videoPlayer:setLoopState(OF_LOOP_NORMAL);
videoPlayer:setPaused(true);
end;
;
function ofelia.setSpeed(f);
videoPlayer:setSpeed(f / 100);
end;
;
function ofelia.play();
videoPlayer:play();
end;
;
function ofelia.stop();
videoPlayer:setFrame(0);
videoPlayer:setPaused(true);
end;
;
function ofelia.setPaused(f);
if f == 1 then pause = true;
else pause = false;
end;
videoPlayer:setPaused(pause);
end;
;
function ofelia.setFrame(f);
videoPlayer:setFrame(f);
end;
;
function ofelia.setPosition(f);
videoPlayer:setPosition(f);
end;
;
function ofelia.setVolume(f);
videoPlayer:setVolume(f / 100);
end;
;
function ofelia.update();
videoPlayer:update();
end;
;
function ofelia.draw();
ofSetHexColor(0xFFFFFF);
videoPlayer:draw(20, 20, 800, 600);
local outputList = {};
outputList[1] = videoPlayer:getPosition();
outputList[2] = videoPlayer:getCurrentFrame();
outputList[3] = videoPlayer:getTotalNumFrames();
return outputList;
end;
;
function ofelia.exit();
videoPlayer:close();
end;
i/o-errors in pd
@JackPD Ok, looking at sndfiler. Let me see if I understand it correctly.
Take the following test patch:
[table foo 128]
[nbx]
|
[; A bang; B resize foo $1; C bang(
[receive B]
|
[sndfiler]
|
[bang]
|
[send SNDFILER_OUT]
[r A] [r SNDFILER_OUT]
| |
[timer]
|
[print first]
[r C]
|
[print last]
Is it true that I would get output printed in the order "last" then "first"? If so then sndfiler breaks Pd's depth-first message passing rule.
Is it true that [timer] here will output different values depending on the size of the float provided to [nbx]? If so then [sndfiler] breaks Pd's deterministic scheduling rule.
Also, it appears a "resize" message with no arguments would crash Pd. That's a bit alarming given that I just happened upon it while scrolling through the source. Threading issues are extremely difficult to debug so I'm a bit cautious about exploring much further. (Also there's a threading wrapper library dependency by yet another author...)
Just for a thought-experiment: imagine a set of "delay" externals that try to do computation on a separate thread in the time allotted:
[resize foo 256(
|
[sndfiler 50]
In this case "50" would mean to delay output for 50 milliseconds from the time the object receives an input. So you send the resize message, sndfiler does the work in a separate thread, and after 50ms the object gets a callback to send output.
Now, if the thread has finished its work the output would be sent deterministically. If not the object would block until the thread has finished, send the output, then display an error to the console that it missed a deadline.
That's basically just mapping Pd's system scheduling to control objects. I think that would be a very clunky design that would be hard for users to maintain and reason about. But it's still preferable to breaking determinism as sndfiler apparently does.
Btw-- even after sndfiler finishes its threaded array resizing, it still must rebuild the dsp graph for the reasons I mentioned in my last message. So for patches with lots of signal objects you'd probably still generate dropouts.
Hm... here's an idea:
- Require every class that deals with garrays to have a "set" method
- Require the "set" method of these classes to bind the object to a symbol that concatenates the array name with something like "_setter". So [set foo(--[tabread] would bind that object to symbol "foo_setter"
- When array "foo" gets resized, send a message "set foo" to "foo_setter"
Now every table-related object that uses array "foo" will have an updated reference to the newly resized array before the next dsp tick. This is because when you send a message to a receiver symbol in Pd it will dispatch the message to every object that shares this name.
On the other hand, the "set" methods of table-related classes in Pd weren't designed to be realtime safe. For example, some resize values may trigger an runtime error condition that requires rebuilding the graph. I guess the algorithm above could call some kind of "slim-lined" version of "set" that does size-based checks but excludes things like array name lookups, etc. But that would require splitting out every single "set" into a set of two methods.
A combination of that and the delay-based sndfiler could get you array resizing without dropouts. But that's a very clunky interface which is difficult to debug for a lot of work upfront just to get it running.
Pd-extended 0.40.3 released, dedicated to Jamie Tittle
@hans said:
Finally, it's done! The most polished release of Pd yet. We are further refining Pd into a truly powerful and usable programming platform.
http://puredata.org/downloads/
This release is dedicated to Jamie Tittle, aka tigital, who recently died of cancer. He was a long time and key contributor to Gem and Pd in general, even while he was in the hospital undergoing treatment. He is sorely missed in this community, and I am sure by many others.
Some highlights of this release:
* more functional namespace tools ([declare] and [import])
* new appearance designed to enhance readability
* GLSL shader support in Gem
* usability improvements
* on Mac OS X, you can now build "standalone" applications
* standard locations for user-installed externals
* many bug fixesHere's the rough changelog:
next visual appearance designed for readability
default locations for user-installed externals, helpfiles, etc.
GNU/Linux: /usr/local/lib/pd-externals and ~/pd-externals
Mac OS X: /Library/Pd and ~/Library/Pd
Windows: %ProgramFiles%/Common Files/Pd and %UserProfile%/Application Data/Pdlots of standard key bindings added:
Enter/Return for OK
Escape for Cancel
Ctrl/Cmd-W closes all windows
on Mac OS X, Cmd-` cycles thru open windows
on Mac OS X, Cmd-m minimizes windows
Ctrl/Cmd-R raises/lowers Pd window
Ctrl/Cmd-Shift-R shrinks/grows Pd window
Ctrl/Cmd-Shift-L clears Pd window's text console
Ctrl/Cmd-B opens the Help Browseryou can now use "~" in all paths to mean home folder, and on Windows you can use environment variables, lie %UserProfile% in paths
improved Cut/Copy/Paste support for working in object and message boxes
fixed Cut/Copy/Paste for the Pd window's console
[declare] and [import] now sorted out for loading (but much work needs to be done before there namespace support is complete)
"File -> Save As" defaults to the Home folder (~/) on Mac OSX
new patches default to the folder last saved in
included pgp_opengl aka 3dp on GNU/Linux and Mac OS X
'hardware' and 'deprecated' removed from libraries loaded by default
On Debian/Ubuntu, the packages now install into /usr rather than /usr/local
On Mac OS X, you can now build "standalone" applications from the File menu.
bug fixes and clean up of [hid] and mapping externals
included config in Info.plist for the Spotlight Importer
KNOWN BUGS
check http://puredata.info/dev/bugtracker before reporting bugs
Escape, Enter, and Ctrl/Cmd-W don't close the Path and Startup preferences
pdp_opengl is alpha and will definitely crash Pd
loading pdp_opengl will crash Pd if X11 is not open before trying to load it
the GUI runs slower in some situations
The new visual style is very nice indeed,