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.
Http://www.netpd.org/
a few people who have joined Netpd sessions have asked about how to adapt their patches to work within the system...
according to the git page:
- Create your own instrument by typing '/new mysupersynth' into
unpatch's symbol box. A new instrument named 'mysupersynth'
shows up in unpatch's instrument list. Edit mysupersynth.pd and
save it. You might want to check existing instruments to get an
idea of how to cook your own instrument. There will be section
about this topic on http://www.netpd.org/docs .
NOTE: instruments belong to netpd/instruments, their abstractions to
netpd/instruments/abs.
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.
64 bit alternative to [hid]?
@CalBassist If you are using osx or Linux you could try compiling hid from source, although there might be api and memory issues that could be difficult to resolve. At least a quick try will be easy.
For windows.... not so easy. In fact it didn't work in windows as a 32-bit external.
HID Source..... https://github.com/avilleret/hid
or it is in the complete source tarball for extended here.... http://puredata.info/downloads/pd-extended in pd/extra/hid
Or try a different approach......
https://forum.pdpatchrepo.info/topic/11674/hid-mousestate-in-pd-vanilla
David
hanging MIDI notes on a channel split setup
hey folks! looking for some advice here. i have a custom instrument setup where i can switch between timbres based on a certain key range. there are eight ranges of four MIDI notes each and any one of these regions can be assigned to the base instrument, running on MIDI channel 1, or any one of five other instruments (running on channels 2-6). the switching method basically works as it's supposed to, but there are two strange behaviors
-
if i play quickly it can result in stuck notes as i switch between instruments. i have a method where i can send note off data to instruments via the interface, which mostly works to turn notes off, but not 100% of the time.
-
if i hold a note in one region down assigned to one instrument, and then quickly play another assigned to a different instrument, it will sometimes get confused and apply the sound from the first to the second. so if i have a piano timbre in the first region and play a key assigned to a synth timbre the piano will play notes in the second region as well for a time. i've found that if i play notes in a third different region it resets itself properly and the next time i play the second region it will be properly assigned. so in this case somehow the channel switching seems to be happening too late occasionally.
these bugs can sometimes result in interesting happy accidents, but as i work with it more (as well as playing faster or switching quickly between timbres) i want to have it be more consistent in response.
anyway here's my keyrouter object. the active region is set by the inlet. the output is rearranged to put the channel first so i can route it to the correct instrument. there's probably some kind of race condition that behaves properly when the region and timbre switching is clean (playing more staccato or detached) but if notes are held down or the speed of switching increases it starts dropping noteoffs. any input or info appreciated!
[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;