Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Glissando Function whose arguments are the extremes of the codomain [closed]

I'm a musician and I am playing with writing a function in Clojure to reproduce a simple glissando between the pitches A4 and A5 (frequencies 440Hz and 880Hz, respectively), with an exponential curve, but I'm running into trouble. Basically I want to use it like this:

(def A4 440)
(def A5 880)
(gliss A4 A5)

which should give me something like:

=>(441 484 529 576 625 676 729 784 841)

except I would eventually like to also give it a sample-rate as a third argument.

This kind of works:

(defn gliss 
  [start-pitch end-pitch s-rate]
  (let [f (fn [x]
            (expt x 2))]
    (remove nil?
      (map 
        (fn [x]
          (when (and 
                  (>= (f x) start-pitch)
                  (<= (f x) end-pitch))
            (f x)))
        (range 0 10000 s-rate)))))

I guess the problem is the way I want to use the function. Instead of saying something like "glissando from x1 to x2 where f(x) = x^2" I'm really trying to say "glissando from f(x) == 440 to f(x) == 880" so I'm not really given a range of x to work with initially, hence why I just hard-coded 0 to 10000 in this case, but that's ugly.

What is a better way to accomplish what I'm trying to do?

Update: I made a mistake in terminology that needs fixing (for all the hordes of people who will come here looking to notate a glissando in Clojure). The third argument isn't really sample-rate, it should be number-of-samples. In other words, the sample rate (which might be 44100Hz or 48000Hz, etc.) determines the number of samples you will need for a particular duration of time. If you needed a glissando with an e exponential curve from A4 to A5 over a duration of 500 milliseconds at a sampling rate of 44100, you might use these functions:

(defn gliss 
  [start end samples]
  (map #(+ start
           (* 
             (math/expt (/ (inc %) samples) 2.718281828)
             (- end start)))
       (range samples)))

(defn ms-to-samps
  [ms s-rate]
  (/ (* ms s-rate) 1000))

like this:

(def A4 440)
(def A5 (* A4 2))
(def s-rate 44100) ;; historic CD quality sample rate
(gliss A4 A5 (ms-to-samps 500 s-rate))
like image 492
tjb1982 Avatar asked May 03 '13 19:05

tjb1982


1 Answers

here's a simple exponential curve distributed over the range of the frequency range with rate samples:

(ns hello.exp 
  (:require [clojure.math.numeric-tower :as math]))

(defn gliss [start end rate]
  (map #(+ start (* (math/expt (/ (inc %) rate) 2.718281828) (- end start)))   
       (range rate)))

This does not exactly fit your gliss curve because im using e as the exponent though I suspect it would sound good if you feed it to overtone ;) I suspect that a proper musical gliss would use an exponent of 1 in this function from what I read in the wikipedia article.

hello.exp> (gliss 440 880 5)                                                    
(445.5393041947095 476.4535293633514 549.7501826896913 679.8965206341077 880.0)

hello.exp> (map int (gliss 440 880 100)) 
(440 440 440 440 441 441 442 442 443 444 445 446 447 448 449
 451 452 454 455 457 459 461 463 465 467 469 472 474 477 479 
 482 485 487 490 493 497 500 503 506 510 513 517 521 525 529 
 533 537 541 545 550 554 558 563 568 573 577 582 588 593 598 
 603 609 614 620 625 631 637 643 649 655 661 668 674 680 687 
 694 700 707 714 721 728 735 743 750 757 765 773 780 788 796 
 804 812 820 828 837 845 853 862 871 880)
like image 198
Arthur Ulfeldt Avatar answered Nov 05 '22 12:11

Arthur Ulfeldt