Csound Csound-dev Csound-tekno Search About

pan_equal_power UDO Fix

Date2005-11-18 20:39
FromDavid Akbari
Subjectpan_equal_power UDO Fix
Hi Steven, all,

In the UDO repository I noticed that the pan_equal_power says

/***  BEGIN QUOTED TEXT ***/
pan_equal_power

Equal Power Panning

Download UDO File
Description

Panning User Defined Opcodes
Conversion of Hans Mikelson's examples in the Csound Magazine
Autumn 1999
http://csounds.com/ezine/autumn1999/beginners/

Syntax

a1, a2 pan_equal_power asig, kpan

Code

         opcode pan_equal_power, aa, ak
asig, kpan              xin

kpan    = kpan * 3.14159265359 * .5
krtl    = sqrt(2) / 2 * (cos(iSpace) + sin(iSpace))
krtr    = sqrt(2) / 2 * (cos(iSpace) - sin(iSpace))

         xout asig * kpanl, asig * kpanr
         endop
Credits

Author: Michael Gogins, converted by Steven Yi
/*** END QUOTED TEXT ***/

Now as you can likely see this results in an error of the Csound 
orchestra compiler, because of an undefined iSpace variable. Thus in 
the interest of consistency, after reviewing the source .orc/.sco 
files, I submit the following fix, since I feel this opcode would be 
useful. Also it would be nice if there was a note in the UDO about the 
expected range of input, in this case -0.5 to 0.5. I think it's 
important to leave the scaling up to the user as there is an 
interesting effect going from 0.0 to 1.0 instead of -0.5 to 0.5 
(angle). This example has been tested with Csound 4.23f12 :




sr		=	44100
kr		=	44100
ksmps	=	1
nchnls	=	2

/*--- ---*/

		opcode	pan_equal_power, aa, ak
	setksmps	100
ain, kpan	xin
ipi		=	((4.0)*taninv(1.0))
kangl	=	(kpan*ipi)*0.5
kpanl	=	(sqrt(2.0)/(2.0))*((cos(kangl))+(sin(kangl)))
kpanr	=	(sqrt(2.0)/(2.0))*((cos(kangl))-(sin(kangl)))
aoutL	=	ain*kpanl
aoutR	=	ain*kpanr
	xout	aoutL, aoutR
		endop

/*--- ---*/

		instr	1

;  YOUR SOUNDFILE HERE !
a0	diskin	"/loops/dl_break0.aif", 1, 0, 1
;-----------------------

;  Uncomment to use realtime MIDI control
;kpan	ctrl7	1, 1, 0, 1

;;  else use the default random UGen
kpan	random	0, 1
kpan	port	kpan, 0.08
;;
kpan	=	kpan-0.5

aL, aR	pan_equal_power		a0, kpan

;  MIDI monitor
;	printk2	kpan

	outs	aL, aR

		endin

/*--- ---*/


i1	0	30

e





-David

Date2005-11-19 10:12
FromIstvan Varga
SubjectRe: pan_equal_power UDO Fix
This still fails because of the 'setksmps 100' which I had to comment
out (you can only change the ksmps in an UDO by dividing the ksmps of
the caller by an integer, and 1/100 = 0.01 is not an integer).
Also note that the minimum pan value (-0.5) results in output being
panned to the right, while the maximum value (0.5) pans to the left.

Here is a shorter and faster version of the UDO that sounds the same:

          opcode  pan_equal_power, aa, ak

ain, kpan       xin
kangl   =  1.57079633 * (kpan + 0.5)
         xout    ain * sin(kangl), ain * cos(kangl)

         endop

By the way, in the example, I replaced the lines that calculate
kpan with 'kpan jspline 0.5, 1, 5' so that the panning effect is
more audible (the filtered noise had a very low amplitude).

David Akbari wrote:

> Now as you can likely see this results in an error of the Csound 
> orchestra compiler, because of an undefined iSpace variable. Thus in the 
> interest of consistency, after reviewing the source .orc/.sco files, I 
> submit the following fix, since I feel this opcode would be useful. Also 
> it would be nice if there was a note in the UDO about the expected range 
> of input, in this case -0.5 to 0.5. I think it's important to leave the 
> scaling up to the user as there is an interesting effect going from 0.0 
> to 1.0 instead of -0.5 to 0.5 (angle). This example has been tested with 
> Csound 4.23f12 :
> 
> 
> 
> 
> sr        =    44100
> kr        =    44100
> ksmps    =    1
> nchnls    =    2
> 
> /*--- ---*/
> 
>         opcode    pan_equal_power, aa, ak
>     setksmps    100
> ain, kpan    xin
> ipi        =    ((4.0)*taninv(1.0))
> kangl    =    (kpan*ipi)*0.5
> kpanl    =    (sqrt(2.0)/(2.0))*((cos(kangl))+(sin(kangl)))
> kpanr    =    (sqrt(2.0)/(2.0))*((cos(kangl))-(sin(kangl)))
> aoutL    =    ain*kpanl
> aoutR    =    ain*kpanr
>     xout    aoutL, aoutR
>         endop
> 
> /*--- ---*/
> 
>         instr    1
> 
> ;  YOUR SOUNDFILE HERE !
> a0    diskin    "/loops/dl_break0.aif", 1, 0, 1
> ;-----------------------
> 
> ;  Uncomment to use realtime MIDI control
> ;kpan    ctrl7    1, 1, 0, 1
> 
> ;;  else use the default random UGen
> kpan    random    0, 1
> kpan    port    kpan, 0.08
> ;;
> kpan    =    kpan-0.5
> 
> aL, aR    pan_equal_power        a0, kpan
> 
> ;  MIDI monitor
> ;    printk2    kpan
> 
>     outs    aL, aR
> 
>         endin
> 
> /*--- ---*/
> 
> 
> i1    0    30
> 
> e
> 
> 
> 
> 
> 
> -David
> 

Date2005-11-19 12:34
Fromluis jure
SubjectRe: pan_equal_power UDO Fix
el 2005-11-19 Istvan Varga escribió:

> This still fails because of the 'setksmps 100' which I had to comment
> out (you can only change the ksmps in an UDO by dividing the ksmps of
> the caller by an integer, and 1/100 = 0.01 is not an integer).

BTW, perhaps the manual page could be more explicit about this. it's true
that you can infer this by reading carefully the note:

"The local ksmps is implemented by splitting up a control period into
smaller sub-kperiods and temporarily modifying internal Csound global
variables."

but IMHO it wouldn't hurt if it were mentioned more explicitly, for example:


Initialization

iksmps -- sets the local ksmps value; must be an integer divisor of the
orchestra level ksmps value.

(or something to that effect but in correct english)

best,

lj


Date2005-11-19 12:49
FromIstvan Varga
SubjectRe: pan_equal_power UDO Fix
luis jure wrote:

> BTW, perhaps the manual page could be more explicit about this. it's true
> that you can infer this by reading carefully the note:

The updated (Oct 2002) manual does mention this (and has many other
corrections as well, and is generally more usable than the original
"draft" version that is unfortunately in all manual distributions).
I kept posting the new manual several times since then, but it was
always ignored; probably I will replace the manual myself eventually.
Anyway, it is included below:

USER DEFINED OPCODES
--------------------

         opcode Name, outtypes, intypes
[xinarg1[, xinarg2[, xinarg3[, ... ]]]  xin]
         [setksmps iksmps]
         [...]
[       xout xoutarg1[, xoutarg2[, xoutarg3[, ... ]]]]
         endop

[xoutarg1[, ... ]]      Name [xinarg1[, ... ]][, iksmps]

DESCRIPTION
-----------

The opcode and endop statements allow defining a new opcode that can
be used the same way as any of the built-in Csound opcodes. These
opcode blocks are very similar to instruments (and are, in fact,
implemented as special instruments), but cannot be called as a normal
instrument e.g. with the "i" score event. An opcode definition must
precede the instrument (or other opcode) from which it is used, but
it is possible to call the opcode from itself, allowing recursion of
any depth that is limited only by available memory. Additionally,
there is an experimental feature that allows running the opcode
definition at a higher control rate than the kr value specified in
the orchestra header.
Similarly to instruments, the variables and labels of an opcode block
are local, and cannot be accessed from the caller instrument (and the
opcode cannot access variables of the caller, either).
Some parameters are automatically copied at initialization, however:
  - all p-fields (including p1)
  - extra time (see also xtratim, linsegr, and related opcodes). This
    may affect the operation of linsegr/expsegr/linenr/envlpxr in the
    opcode definition.
  - MIDI parameters, if there are any
Also, the release flag (see release opcode) is copied at performance
time.
Modifying the note duration in the opcode definition by assigning to
p3, or using ihold, turnoff, xtratim, linsegr, or similar opcodes
will also affect the caller instrument. Changes to MIDI controllers
(for example with ctrlinit) will also apply to the instrument from
which the opcode was called.

setksmps sets the local ksmps value (see "iksmps" below).

The xin and xout opcodes copy variables to and from the opcode
definition, allowing communication with the calling instrument.
The types of input and output variables are defined by "intypes" and
"outtypes".
NOTES:
   - xin and xout should be called only once, and xin should precede
     xout, otherwise an init error, and deactivation of the current
     instrument may occur.
   - these opcodes actually run only at i-time, and performance time
     copying is done by the user opcode call. This means that skipping
     xin or xout with kgoto has no effect, while skipping with igoto
     affects both init and performance time operation.

INITIALIZATION
--------------

Name - name of the opcode. It may consist of any combination of
   letters, digits, and underscore (_), but should not begin with a
   digit. If an opcode with the specified name already exists, it is
   redefined (a warning is printed in such cases). Some reserved words
   (like instr and endin) cannot be redefined.
   NOTE: redefinitions do not affect instruments that are defined
   before the new opcode.

intypes - list of input types, any combination of the characters a, k,
   K, i, o, p, and j. A single 0 character can be used if there are no
   input arguments. Double quotes and delimiter characters (e.g. comma)
   are *not* needed. The meaning of the various types is shown in the
   following table:

   +------+-------------------+-------------------------+------------+
   | Type | Description       | Variable types allowed  | Updated at |
   +------+-------------------+-------------------------+------------+
   |  a   | a-rate variable   | a-rate                  | a-rate     |
   +------+-------------------+-------------------------+------------+
   |  k   | k-rate variable   | k- and i-rate, constant | k-rate     |
   +------+-------------------+-------------------------+------------+
   |  K   | k-rate with       | k- and i-rate, constant | i- and     |
   |      | initialization    |                         | k-rate     |
   +------+-------------------+-------------------------+------------+
   |  i   | i-rate variable   | i-rate, constant        | i-rate     |
   +------+-------------------+-------------------------+------------+
   |  o   | optional i-rate,  | i-rate, constant        | i-rate     |
   |      | defaults to zero  |                         |            |
   +------+-------------------+-------------------------+------------+
   |  p   | optional i-rate,  | i-rate, constant        | i-rate     |
   |      | defaults to 1     |                         |            |
   +------+-------------------+-------------------------+------------+
   |  j   | optional i-rate,  | i-rate, constant        | i-rate     |
   |      | defaults to -1    |                         |            |
   +------+-------------------+-------------------------+------------+

   The maximum allowed number of input arguments is 24.
   Additionally to the user specified argument list, one optional
   i-rate input parameter is always added. This defaults to zero, and
   sets the local ksmps value of the opcode call (see "iksmps" below).

outtypes - list of output types. The format is the same as in the case
   of intypes, however, the available types are slightly different:

   +------+-------------------+-------------------------+------------+
   | Type | Description       | Variable types allowed  | Updated at |
   +------+-------------------+-------------------------+------------+
   |  a   | a-rate variable   | a-rate                  | a-rate     |
   +------+-------------------+-------------------------+------------+
   |  k   | k-rate variable   | k-rate                  | k-rate     |
   +------+-------------------+-------------------------+------------+
   |  K   | k-rate with       | k-rate                  | i- and     |
   |      | initialization    |                         | k-rate     |
   +------+-------------------+-------------------------+------------+
   |  i   | i-rate variable   | i-rate                  | i-rate     |
   +------+-------------------+-------------------------+------------+

   The maximum allowed number of output arguments is 24.

iksmps - local ksmps value. Must be a positive integer, and also the
   ksmps of the calling instrument or opcode must be an integer
   multiple of this value. For example, if ksmps is 10 in the
   instrument from which the opcode was called, the allowed values for
   iksmps are 1, 2, 5, and 10.
   If iksmps is set to zero, the ksmps of the caller instrument or
   opcode is used (this is the default behavior).
   NOTE: local ksmps is implmented by splitting up a control period
     into smaller sub-kperiods, and temporarily modifying internal
     Csound global variables. This also requires converting the rate of
     k-rate input and output arguments (input variables receive the
     same value in all sub-kperiods, while outputs are written only in
     the last one).
   WARNING: when the local ksmps is not the same as the orchestra level
     ksmps value (as specified in the orchestra header), global a-rate
     operations must not be used in the opcode definition.
     These include:
       - any access to "ga" variables
       - a-rate zak opcodes (zar, zaw, etc.)
       - tablera and tablewa (these two opcodes may in fact work, but
         caution is needed)
       - in and out opcode family (these read from, and write to global
         a-rate buffers)
     In general, the local ksmps should be used with care, as it is an
     experimental feature, though it works correctly in most cases.

PERFORMANCE
-----------

xinarg1, xinarg2, ... - input arguments. The number and type of
   variables must agree with the declaration (see also the table at
   "intypes").

xoutarg1, xoutarg2, ... - output arguments. The number and type of
   variables must agree with the declaration (see also the table at
   "outtypes").

NOTE: the opcode call is always executed both at initialization and
   performance time, even if there are no a- or k-rate arguments.
   If there are many user opcode calls that are known to have no
   effect at performance time in an instrument, then it may save some
   CPU time to jump over groups of such opcodes with kgoto.

EXAMPLES
--------

/* ---- opcode_example.orc ---- */

sr      =  44100
ksmps   =  50
nchnls  =  1

/* example opcode 1: simple oscillator */

         opcode Oscillator, a, kk

kamp, kcps      xin             ; read input parameters
a1      vco2 kamp, kcps         ; sawtooth oscillator
         xout a1                 ; write output

         endop

/* example opcode 2: lowpass filter with local ksmps */

         opcode Lowpass, a, akk

         setksmps 1              ; need sr=kr
ain, ka1, ka2   xin             ; read input parameters
aout    init 0                  ; initialize output
aout    =  ain*ka1 + aout*ka2   ; simple tone-like filter
         xout aout               ; write output

         endop

/* example opcode 3: recursive call */

         opcode RecursiveLowpass, a, akkpp

ain, ka1, ka2, idep, icnt       xin     ; read input parameters
         if (icnt >= idep) goto skip1    ; check if max depth reached
ain     RecursiveLowpass ain, ka1, ka2, idep, icnt + 1
skip1:
aout    Lowpass ain, ka1, ka2           ; call filter
         xout aout                       ; write output

         endop

/* example opcode 4: de-click envelope */

         opcode DeClick, a, a

ain     xin
aenv    linseg 0, 0.02, 1, p3 - 0.05, 1, 0.02, 0, 0.01, 0
         xout ain * aenv         ; apply envelope and write output

         endop

/* instr 1 uses the example opcodes */

         instr 1

kamp    =  20000                ; amplitude
kcps    expon 50, p3, 500       ; pitch
a1      Oscillator kamp, kcps                   ; call oscillator
kflt    linseg 0.4, 1.5, 0.4, 1, 0.8, 1.5, 0.8  ; filter envelope
a1      RecursiveLowpass a1, kflt, 1 - kflt, 10 ; 10th order lowpass
a1      DeClick a1
         out a1

         endin

/* ---- opcode_example.sco ---- */

i 1 0 4
e

AUTHOR
------

Istvan Varga, 2002; based on code by Matt J. Ingalls

Date2005-11-19 18:38
FromDavid Akbari
SubjectRe: pan_equal_power UDO Fix
On Nov 19, 2005, at 5:12 AM, Istvan Varga wrote:

> Here is a shorter and faster version of the UDO that sounds the same:
>
>          opcode  pan_equal_power, aa, ak
>
> ain, kpan       xin
> kangl   =  1.57079633 * (kpan + 0.5)
>         xout    ain * sin(kangl), ain * cos(kangl)
>
>         endop
>
> By the way, in the example, I replaced the lines that calculate
> kpan with 'kpan jspline 0.5, 1, 5' so that the panning effect is
> more audible (the filtered noise had a very low amplitude).

wow that is faster! Thanks, Istvan!


-David

Date2005-11-28 21:18
FromSteven Yi
SubjectRe: pan_equal_power UDO Fix
AttachmentsNone  

Date2005-11-28 21:49
FromDavid Akbari
SubjectRe: pan_equal_power UDO Fix
Excellent !

It is quite nice to be having a local UDO repository that is 
synchronous to the canonical repository.

Well done !


-David

On Nov 28, 2005, at 4:18 PM, Steven Yi wrote:

> I just now modified this on the UDO
> database with Istvan's new code, as well as documented him in the
> author's section.  Thanks Istvan