Induction Examples

The following audio examples demonstrate some of the sonic possibilities available through the use of the Induction Connection. The files were initially generated for a presentation I gave at the IRCAM Forum Workshop in Santiago de Chile in 2017.

In all of the examples below, a bichord is created, attached to a cello bridge, and tuned to 55 Hz (set-pitch ‘tension). The bichord corresponds to a group of 2 strings in the lower range of a piano, normally struck by a single piano hammer. These strings are tuned to the same frequency, with a slight random discrepancy introduced (between .4 and 20 cents).

In the first set of examples (1-4), white noise is used as the control signal for the electromagnet.

Example 1: Generic white noise.

Example 2: White noise, with a gap setting such that there is intermittent contact between electromagnet and string.

Example 3: White noise, with a gap setting such that there is fairly heavy contact between electromagnet and string.

Example 4: White noise, with a gap that changes over time. An initially wide gap (0.001 m) gradually narrows until the string is crushed against the electromagnet (0.0001 m), then widens again to its original distance.

In the next set (5-9), the control signal is a recording of a narrator reading from Camus’ novel The Plague.

Example 5: Voice.

Example 6: Voice, with a gap size (0.0009 m) such that heavy contact occurs between electromagnet and string (watch out for volume).

These last couple of examples take advantage of the ability to create fantastic physical parameters, such as strings that are impossibly short or thin.

Example 7 (short string): Again using the voice audio file as input, string length is reduced from initial length of 2m to .5 m, while maintaining pitch of 55 Hz.

Example 8 (short string with strike): Same as above (voice input, string length=0.5m), with a gap size allowing for contact between objects. Note the variation in the timbre of the resulting strikes due to string length.

Example 9 (thin string): Voice input, normal length (2m), with string radius (as set in string object) reduced from 0.004m to 0.002m.

Example 10: Original recording of narrator, used as the control signal for examples 5-9 above.

Code

The above examples were all generated from the base code below. Note that both horizontal and vertical string motion are controlled and audible. Download.


;;;-*-Mode: Lisp; Package: MODALYS -*-

;;;----------------------------------------------------------------------
;;; Induction example.
;;; single bichord (2 strings at nearly the same frequency) connected to 
;;; a cello bridge, vibrated through induction
;;;----------------------------------------------------------------------

(new)

;; output - 1=output audio file/input from sine, 2=output audio file/input from audio-file, 3=generate mlys script
(defparameter *env* 3)

;; parameter defaults
(setf *default-string1-freq* 55)
(setq *detune-range* (list .4 20)); (min max) detune in cents

;; access-locations on strings
(setf *action-point* .1)
(setf *bridge-point* .95)
(setf *listen-point* .75)

; induction settings - power vertical and power horizontal
(setf *power-vert* 380)
(setf *power-horiz* 38)
(setq *gap-init* .005)

;;;
;;; create objects
;;;

;; make bridge
(setq bridge (make-object 'cello-bridge
                          (m1-mass .0046)
                          (m2-mass .0059)
                          (m12-mass .0024)
                          (d-distance .032)
                          (d20-distance .011)
                          (h1-distance .052)
                          (a-distance .035)
                          (i20-distance .026)
                          (d2-stiffness 1); 716.8)
                          (s1-stiffness 360000)
                          (freq-loss 10)
                          (const-loss 10)
                          ))

;; make strings

;; frequencies
(setq string1-freq (make-controller 'dynamic 1 -1 *default-string1-freq* "string1-freq"))
;(setf string1-freq (make-controller 'arithmetic 1 '* (list string1-freq-raw (const *bridge-point*)))) 
   ;because attaching the string to the bridge shortens it, raises the pitch. this compensates
(defun detune (pitch)
  (let* ((min (float (first *detune-range*)))
         (max (second *detune-range*))
         (range (- max min)))
    (midi-to-freq (+ (freq-to-midi pitch)
                     (/ (+ min 
                           (if (= 0 range) 0 ; if min=max, just add min to freq
                             (random range))) ; otherwise, pick a random # w/in range and add it
                        100)))))


; freq for 2nd slightly detuned string
(setf string2-freq (make-controller 'dynamic 1 -1 (detune *default-string1-freq*) "string2-freq"))
;(setf string2-freq (make-controller 'arithmetic 1 '* (list string2-freq-raw (const *bridge-point*))))

(setf highest-mode (make-controller 'arithmetic 1 '/ (list (const 22050) string1-freq)))

(setf str-len-ctl (make-controller 'dynamic 1 -1 2 "str-len-ctl"))
(setf str-den-ctl (make-controller 'dynamic 1 -1 7850 "str-den-ctl"))
(setf str-rad-ctl (make-controller 'dynamic 1 -1 0.004 "str-rad-ctl"))
(setf str-you-ctl (make-controller 'dynamic 1 -1 1.0 "str-you-ctl"))
(setf str-yo2-ctl (make-controller 'arithmetic 1 '* (list str-you-ctl (const 10000000000))))
;(setf str-yo2-ctl (make-controller 'dynamic 1 -1 1.0e10 "str-you-ctl"))

;; string 1
(setq string1 (make-object 'bi-string
                           (modes      highest-mode)
                           (length      str-len-ctl) ; 1
                           (density str-den-ctl) ; 7700
                           (radius str-rad-ctl) ; 0.0009
                           (young str-yo2-ctl) ; 2.0e10
                           (freq-loss  0.001) ; .01
                           (const-loss  0.3) ; .4
                           ))

;; string 2
(setq string2 (make-object 'bi-string
                           (modes      highest-mode)
                           (length      str-len-ctl) ; 1
                           (density str-den-ctl) ; 7700
                           (radius str-rad-ctl) ; 0.0009
                           (young str-yo2-ctl) ; 2.0e10
                           (freq-loss  0.001) ; .01
                           (const-loss  0.3) ; .4
                           ))


(set-pitch string1 'tension string1-freq)
(set-pitch string2 'tension string2-freq)

;; make electromagnet

(setf magnet (make-object 'mono-two-mass
                          (small-mass 0.1)
                          (large-mass .1)
                          (stiffness0 5000)
                          (freq-loss0 100)
                          (const-loss0 50)))

;;;
;;; make input controllers and gap controllers, one each per bichord 
;;;
(setf *file-name* "/Users/mus/Documents/Data/-in\ progress/ircam-Project/Ircam-Santiago/from-paris/bichord/examples/induction-exploration/everybody-knows.aif")
;(setf *file-name* "/Users/mus/Documents/Data/-in\ progress/ircam-Project/Ircam-Santiago/from-paris/bichord/examples/everything/square-55.aiff")
(defun ctl-gen-file ()
  (make-controller 'sound-file 1 0 (const 44100) *file-name* 0 5 30))

; output - 1=generate audio (sine), 2=generate audio (square), 3=generate mlys scrips
; string 1 vertical is labeled string10, string 1 horizontal is labeled string 11, etc.
(Cond ((= *env* 1)
       (list (setf string10-ctl (make-controller 'arithmetic 1 "*" (const *power-vert*) (make-controller 'sine 1 string1-freq 45)))
             (setf string11-ctl (make-controller 'arithmetic 1 "*" (const *power-horiz*) (make-controller 'sine 1 string1-freq 45)))
             (setf string20-ctl (make-controller 'arithmetic 1 "*" (const *power-vert*) (make-controller 'sine 1 string2-freq 45)))
             (setf string21-ctl (make-controller 'arithmetic 1 "*" (const *power-horiz*) (make-controller 'sine 1 string2-freq 45)))
             (setq gap-ctl (make-controller 'envelope 1 (list (list 0.0 *gap-init*)
                                                              ;(list 2 .0001)
                                                              (list 5 *gap-init*))))))
      ((= *env* 2)
       (list (setf string10-ctl (make-controller 'arithmetic 1 "*" (const *power-vert*) (ctl-gen-file)))
             (setf string11-ctl (make-controller 'arithmetic 1 "*" (const *power-horiz*) (ctl-gen-file)))
             (setf string20-ctl (make-controller 'arithmetic 1 "*" (const *power-vert*) (ctl-gen-file)))
             (setf string21-ctl (make-controller 'arithmetic 1 "*" (const *power-horiz*) (ctl-gen-file)))
             (setq gap-ctl (make-controller 'envelope 1 (list (list 0.0 *gap-init*)
                                                              ;(list 2 .0001)
                                                              (list 5 *gap-init*))))))
      ((= *env* 3)
       (list (setf string10-ctl (make-controller 'signal 1 (make-point-input 0 (const 1))))
             (setf string11-ctl (make-controller 'signal 1 (make-point-input 1 (const 1))))
             (setf string20-ctl (make-controller 'signal 1 (make-point-input 2 (const 1))))
             (setf string21-ctl (make-controller 'signal 1 (make-point-input 3 (const 1))))
             (setf gap-ctl (make-controller 'dynamic 1 0 *gap-init* "gap-ctl"))))
  )


;;;
;;; create all accesses;
;;;

; set interaction point on string
(setq string1-act0 (make-access string1 (const *action-point*) 'trans0)) ; treated as vertical motion
(setq string1-act1 (make-access string1 (const *action-point*) 'trans1)) ; treated as horizontal motion
(setq string2-act0 (make-access string2 (const *action-point*) 'trans0))
(setq string2-act1 (make-access string2 (const *action-point*) 'trans1))
; set point of connection on string with bridge
(setq string1-bridge0 (make-access string1 (const *bridge-point*) 'trans0))
(setq string1-bridge1 (make-access string1 (const *bridge-point*) 'trans1))
(setq string2-bridge0 (make-access string2 (const *bridge-point*) 'trans0))
(setq string2-bridge1 (make-access string2 (const *bridge-point*) 'trans1))
; listening point
(setq string1-out0 (make-access string1 (const *listen-point*) 'trans0))
(setq string1-out1 (make-access string1 (const *listen-point*) 'trans1))
(setq string2-out0 (make-access string2 (const *listen-point*) 'trans0))
(setq string2-out1 (make-access string2 (const *listen-point*) 'trans1))
; graphing points as well
(setq string1-pos0 (make-controller 'access-position 1 string1-out0)) ; for graph
(setq string1-pos1 (make-controller 'access-position 1 string1-out1))
(setq string2-pos0 (make-controller 'access-position 1 string2-out0)) ; for graph
(setq string2-pos1 (make-controller 'access-position 1 string2-out1))
; bridge for strings
(setq bridge-access0 (make-access bridge (const .2) 'top-horizontal))
(setq bridge-access1 (make-access bridge (const .2) 'top-vertical))
(setq bridge-access2 (make-access bridge (const .24) 'top-horizontal))
(setq bridge-access3 (make-access bridge (const .24) 'top-vertical))

; electromagnet
(setf magnet-access (make-access magnet (const 1) 'trans0)) ; small-mass - connected to the strings via induction
(setq magnet-handle (make-access magnet (const 0) 'trans0))  ; large-mass - held in place with position controller


;;;
;;; create connections
;;;

; string to bridge
(make-connection 'adhere string1-bridge0 bridge-access0)
(make-connection 'adhere string1-bridge1 bridge-access1)
(make-connection 'adhere string2-bridge0 bridge-access2)
(make-connection 'adhere string2-bridge1 bridge-access3)
; electromagnet large-mass - held in place with position controller
(make-connection 'position magnet-handle (const 0))

;; induction controllers
(setf em-rad-ctl (make-controller 'dynamic 1 0 0.01 "em-rad-ctl")) ; 0.01
(setf em-len-ctl (make-controller 'dynamic 1 0 0.02 "em-len-ctl")) ; 0.02
(setf em-perm-ctl (make-controller 'dynamic 1 0 8.737434 "em-perm-ctl")) ; 8.737434
(setf em-per2-ctl (make-controller 'arithmetic 1 '/ (list em-perm-ctl (const 10000)))) ; 8.737434e-4
(setf em-str-rad-ctl (make-controller 'dynamic 1 0 0.0004 "em-str-rad-ctl")) 0.0004

; induction connections

(make-connection 'induction string1-act0 magnet-access string10-ctl gap-ctl
                                     em-rad-ctl        ;electromagnet radius
                                     em-len-ctl        ;electromagnet length
                                     em-per2-ctl ;string permeability
                                     em-str-rad-ctl      ;string radius
                                     )
(make-connection 'induction string1-act1 magnet-access string11-ctl gap-ctl
                                     em-rad-ctl        ;electromagnet radius
                                     em-len-ctl        ;electromagnet length
                                     em-per2-ctl ;string permeability
                                     em-str-rad-ctl      ;string radius
                                     )
(make-connection 'induction string2-act0 magnet-access string20-ctl gap-ctl
                                     em-rad-ctl        ;electromagnet radius
                                     em-len-ctl        ;electromagnet length
                                     em-per2-ctl ;string permeability
                                     em-str-rad-ctl      ;string radius
                                     )
(make-connection 'induction string2-act1 magnet-access string21-ctl gap-ctl
                                     em-rad-ctl        ;electromagnet radius
                                     em-len-ctl        ;electromagnet length
                                     em-per2-ctl ;string permeability
                                     em-str-rad-ctl      ;string radius
                                     )

;;;
;;; output points
;;;

; listening to the string
(make-point-output string1-out0 0 1)
(make-point-output string1-out1 0 1)
(make-point-output string2-out0 1 1)
(make-point-output string2-out1 1 1)


;; output - 1=generate audio (sine), 2=generate audio (square), 3=generate mlys scrips
(cond ((= *env* 3)  
       (save-script "/Users/mus/Documents/Data/-in\ progress/ircam-Project/Ircam-Santiago/from-paris/bichord/examples/induction-exploration/bichord.mlys"))
      (t (list (setq graph (make-plot))
               (plot-value graph "string1-v" string2-pos0)
               (plot-value graph "string1-h" string2-pos1)
               ;(plot-value graph "magnet-loc" gap-ctl)
               (run 5)
               (plot graph "My Plotted Controller Data")
               (play))))