Comments (12)
from cl-patterns.
from cl-patterns.
Hi!
For example, using this script, if I change 7 to some other integer while the pattern is playing and eval the expression, the pattern doesn't change. How do I do this?
All patterns will repeat infinitely by default, and any changes made to a pattern definition (i.e. pdef
or pb
in this case) will only apply once the pattern ends and loops.
In the case of pbjorklund
, the :dur
argument is effectively just a duration multiplier and doesn't actually set a "total duration" before the pattern ends. Since the pattern is repeating forever, it never ends and never has the chance to restart and take the new parameters into effect. There are at least two things you can do to change that in this case:
- Add a
:repeats 1
argument topbjorklund
, so it only plays once before ending. Then any changes you make will take effect when next loop of pbjorklund starts. - Add a
:end-quant 4
argument to thepb
, which will tell thepb
that it can end (and thus restart the loop) at any beat that is a multiple of4
.
Thinking about it now, having :dur
be only a duration multiplier is probably not the most intuitive behavior. I should probably change the name of that argument to :dur-mul
or similar so it's more clear, and then maybe make a new :dur
argument that acts as if setting :dur-mul
to the specified value and :repeats
to 1
simultaneously, so :dur
sets the pattern's total duration just like it does with pfindur
and the like.
Also, I was reading your tutorial and found a function that changes the pitch by moving the mouse/trackpad up and down, similar to a knob. Is it possible to do the same, but changing the steps instead in the pbjorklund function?
Unfortunately, it's not super convenient to do that--at least, not yet.
Mainly, mouse-y
and mouse-x
are SuperCollider UGens that run on the SuperCollider server, so the only way you can use them in regular Lisp functions would be to set up some kind of synth that is playing on the server, and regularly polling those UGens to send their values back to the Lisp side. This would have to be done with the send-reply
UGen and the cl-collider:add-reply-responder
function, like so:
(defparameter *mouse-x-value* 0)
(cl-collider:add-reply-responder
"/mouse-x"
(lambda (node trig &rest value)
(declare (ignorable node trig))
(setf *mouse-x-value* (car value))))
(proxy :mouse-x-value-poller
(let ((mouse-x (mouse-x.kr 0 1 :linear 0)))
(send-reply.kr (impulse.kr 10) "/mouse-x" (list mouse-x))))
The proxy will start a synth on the server that polls mouse-x.kr
10 times per second (thanks to the (impulse.kr 10)
) and sends its value back to the Lisp side. The reply-responder receives the value and sets *mouse-x-value*
to its value.
The proxy
and reply-responder can both be changed while they're running, and the old versions will be replaced with the new versions, as long as you keep their names the same, similar to how pdef
and pb
work.
Normally at this point I would say "now you can simply use something like (pf (round (* 16 *mouse-x-value*)))
for pbjorklund's pulses
parameter and you're good to go", but actually, it looks like pbjorklund wasn't written to accept patterns for most of its parameters, pulses
and steps
included. I've fixed that just now, so you can either copy and eval the new definition of that method to get the changes, or do a git pull
and restart your Lisp and recompile/reload cl-patterns. Or just wait until the next Quicklisp update if you're very patient O:)
I should also note that even with this change, pbjorklund
will only take into account changes at the start of each "loop". So if pulses
is changed in the middle of the pattern, the change won't be heard until the stop-quant
is reached, or the end of the specified number of repeats
in pbjorklund
. It would be a little more complex to implement it so that pbjorklund changes immediately even in the middle of the pattern, so I can't guarantee when that will be ready. But I do intend to look into that sort of thing more in the future, for all patterns in the library, not just that one (it will of course be customizable when implemented, rather than forcing all patterns to always behave that way).
Here's the full version of the code for you:
(defparameter *mouse-x-value* 0)
(cl-collider:add-reply-responder
"/mouse-x"
(lambda (node trig &rest value)
(declare (ignorable node trig))
(setf *mouse-x-value* (car value))))
(proxy :mouse-x-value-poller
(let ((mouse-x (mouse-x.kr 0 1 :linear 0)))
(send-reply.kr (impulse.kr 10) "/mouse-x" (list mouse-x))))
(pb :pattern
:instrument :block
:embed (pbjorklund (pf (let ((v (round (* 16 *mouse-x-value*))))
(format t "~&~s~%" v)
v))
16
:dur 4
:repeats 1))
(play :pattern)
In any case, let me know if any of this doesn't work for you, or is unclear. In the meantime I'll leave this issue open so I remember to look at making pbjorklund's :dur
parameter more intuitive, and also possibly implementing some kind of pattern or function to get the mouse positioning directly from the Lisp side.
from cl-patterns.
from cl-patterns.
If you're just using the code snippet I posted, the 0
is probably from the format
expression, which is printing the value of *mouse-x-value*
every time the pattern restarts. If it's not changing even when you move your mouse, it sounds like either the proxy
or the reply-responder is not working properly. Try changing the reply responder to this to see if it's actually getting any values from the server:
(cl-collider:add-reply-responder
"/mouse-x"
(lambda (node trig &rest value)
(declare (ignorable node trig))
(format t "~&Got value ~s from the server.~%" (car value))
(setf *mouse-x-value* (car value))))
If you run that and you don't see any messages like Got value X from the server
then it means either the proxy isn't running, the server itself isn't running, or maybe there is a typo in your code somewhere.
As for not hearing any sound, I'm guessing you restarted your Lisp, and maybe you forgot to start the SuperCollider server again (or connect it via JACK) after doing that. Are you sure you ran these?
(setf *s* (make-external-server "localhost" :port 4444))
(server-boot *s*)
(jack-connect)
If so, it could also be that you didn't re-send the defsynth
for your block
synthdef. I think by default, cl-collider doesn't store synthdefs permanently, so you have to re-evaluate them when you reboot the server and/or your Lisp.
Let me know if you're still having any issues after trying those suggestions.
from cl-patterns.
I see the "Got value 0.11145834 from the server" messages and the number changes as I move the mouse. Now with the original function, when I evaluate the pb function I see:
; in: PB :PATTERN
; (* 16 CL-PATTERNS::*MOUSE-X-VALUE*)
;
; caught WARNING:
; undefined variable: CL-PATTERNS::*MOUSE-X-VALUE*
;
; compilation unit finished
; Undefined variable:
; *MOUSE-X-VALUE*
; caught 1 WARNING condition
from cl-patterns.
Looks like you're evaluating the pb
in the CL-PATTERNS
package, but evaluated the defparameter
in another package. If you put some in the REPL, they will be evaluated in the package shown by the REPL prompt. So maybe you evaluated them in the CL-USER
or SC-USER
package but then evaluated the pb
in CL-PATTERNS
.
from cl-patterns.
Probably the best solution would be to define your own package, and make it :use
cl-collider
and cl-patterns
, so you have the symbols from both available in it. Then do (in-package #:your-package-name)
to ensure any code evaluated after that is within the defined package. For example:
(defpackage #:my-cool-package
(:use #:cl
#:cl-collider
#:cl-patterns)
(:shadowing-import-from #:cl-patterns
#:play
#:stop
#:quant))
(in-package #:my-cool-package)
;; your code goes here
The :shadowing-import-from
is needed because cl-patterns
exports some symbols that have the same name as symbols that cl-collider
exports. That clause tells defpackage
that we want the ones from cl-patterns
.
Alternatively, this is shorter and works just as well, as long as you have uiop
(which you should if you have a recent-enough version of asdf
):
(uiop:define-package #:my-cooler-package
(:mix #:cl
#:cl-patterns
#:cl-collider))
(in-package #:my-cooler-package)
;; your code goes here
from cl-patterns.
Let's take a step back. What's wrong with the script I'm using, and how do I fix it?
(ql:quickload :cl-collider)
(in-package :sc-user)
(setf *s* (make-external-server "localhost" :port 4444))
(server-boot *s*)
(jack-connect)
(in-package :cl-collider)
(defsynth block ((gain 1))
(let* ((env (line.kr 4 0 .03 :act :free))
(sig (sin-osc.ar 500 0 env)))
(out.ar 0 (pan2.ar sig 0 gain))))
(defparameter *mouse-x-value* 0)
(cl-collider:add-reply-responder
"/mouse-x"
(lambda (node trig &rest value)
(declare (ignorable node trig))
(setf *mouse-x-value* (car value))))
(proxy :mouse-x-value-poller
(let ((mouse-x (mouse-x.kr 0 1 :linear 0)))
(send-reply.kr (impulse.kr 10) "/mouse-x" (list mouse-x))))
(ql:quickload :cl-patterns/supercollider)
(cl-patterns:start-backend :supercollider)
(in-package #:cl-patterns)
(start-clock-loop :tempo 130/60)
;; This one plays
;; (pb :pattern
;; :instrument :block
;; :embed (pbjorklund 7 16 :dur 4 :repeats 1))
;; This one fails
(pb :pattern
:instrument :block
:embed (pbjorklund (pf (let ((v (round (* 16 *mouse-x-value*))))
(format t "~&~s~%" v)
v))
16
:dur 4
:repeats 1))
(play :pattern)
;; (stop t)
from cl-patterns.
Because you have (pb :pattern ...)
under (in-package #:cl-patterns)
, it will look for all symbols (including the symbol *mouse-x-value*
) in the cl-patterns
package. The reason you get that warning is because the symbol *mouse-x-value*
doesn't exist in cl-patterns
; it exists in cl-collider
, because you did (defparameter *mouse-x-value* 0)
under (in-package #:cl-collider)
.
If you do the following instead, it should work (I just tested it from a fresh restart of SBCL):
(ql:quickload '(:cl-collider :cl-patterns/supercollider))
(in-package :sc-user)
(setf *s* (make-external-server "localhost" :port 4444))
(server-boot *s*)
(jack-connect)
(uiop:define-package #:cl-patterns-scratch
(:mix #:cl
#:cl-patterns
#:cl-collider))
(in-package #:cl-patterns-scratch)
(cl-patterns:enable-backend :supercollider)
(start-clock-loop :tempo 130/60)
(defsynth block ((gain 1))
(let* ((env (line.kr 4 0 .03 :act :free))
(sig (sin-osc.ar 500 0 env)))
(out.ar 0 (pan2.ar sig 0 gain))))
;; this symbol's full name is cl-patterns-scratch::*mouse-x-value* here:
(defparameter *mouse-x-value* 0)
;; ...whereas in your previous reply, its full name was cl-collider::*mouse-x-value*
(cl-collider:add-reply-responder
"/mouse-x"
(lambda (node trig &rest value)
(declare (ignorable node trig))
(setf *mouse-x-value* (car value))))
(proxy :mouse-x-value-poller
(let ((mouse-x (mouse-x.kr 0 1 :linear 0)))
(send-reply.kr (impulse.kr 10) "/mouse-x" (list mouse-x))))
(pb :pattern
:instrument :block
:embed (pbjorklund (pf (let ((v (round (* 16 *mouse-x-value*))))
(format t "~&~s~%" v)
v))
16
:dur 4
:repeats 1))
(play :pattern)
The reason this works is because we make a new package, #:cl-patterns-scratch
, which includes all the symbols from #:cl
, #:cl-patterns
, and #:cl-collider
together. Then when we define *mouse-x-value*
it's in the #:cl-patterns-scratch
package, same as the rest of the code, so Lisp knows exactly which symbol you're trying to reference.
So basically, the problem you're facing is due to the way symbols work in Common Lisp; each symbol belongs to a package, and when you're in one package, you won't be able to access the symbols of another package unless you either prefix the symbol name with the name of the package (i.e. package-name::symbol-name
), switch to the correct package with in-package
, or use-package
the package containing the desired symbol from the package you want to use it from.
If you're unfamiliar with how symbols and packages interact in Common Lisp, I would recommend reading a guide like this one or similar to familiarize yourself with them, since you basically can't use CL without using symbols (and thus packages). Otherwise you're likely to run into similar problems in the future.
Hope that clarifies things a bit, let me know if not.
from cl-patterns.
No problem, happy to be of help :)
from cl-patterns.
Related Issues (20)
- Sync MIDI and SuperCollider backends HOT 6
- Support NamedControl for cl-collider HOT 1
- Can't use list with a single value as midinote HOT 6
- [Feature Request] Allow CC only patterns HOT 2
- About *alsa-midi-instrument-map* HOT 3
- Error "There is no class named COMMON-LISP-USER::PBIND-PSTREAM." HOT 2
- Set default quant to 1
- pnary doesn't work with prest HOT 1
- stretch doesn't work HOT 2
- The lock in ipstream-stream is made a non-recursive, but is used as recursive
- Add 12-tone matrix generator HOT 16
- :tempo key HOT 1
- Plazy fails with repeats=1 HOT 1
- Some systems failed to build for Quicklisp dist HOT 1
- Some systems failed to build for Quicklisp dist HOT 2
- Instantaneous tempo changes HOT 3
- Saving output to file HOT 2
- Using print representation of symbols HOT 5
- Can't change tempo of running clock loop HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cl-patterns.