2013-09-22 1 views
3

J'essaie de faire de la musique avec la bibliothèque d'overtones de clojure. Pour produire des sons intéressants, la synthèse additive est utile, c'est-à-dire que je prends des oscillateurs sinusoïdaux de plusieurs fréquences et que je les ajoute simplement. En diphonique, pour créer un synthétiseur, qui se rend compte que, je peux écrire:clojure, le vecteur littéral diffère du résultat de la fonction

(definst myinst [freq 100] 
    (* 0.2 (reduce + (map sin-osc [101.0 100 99.0])))) 

Pour être un peu plus réutilisable, j'écrire une fonction qui prend une fréquence et retourne une liste avec toutes ces fréquences, vous pouvez voir dans l'extrait de code:

(defn split-freq [freq] 
    (apply vector (map #(* freq %) [1.01 1 0.99]))) 

Lors de l'exécution (split-freq 100), le REPL me donne ce qui suit:

[101.0 100 99.0] 

qui est exactement la même que l'entrée, je fourni la fonction de carte ci-dessus. En fait, j'ai copié le résultat. Maintenant, j'essaie ceci:

(definst myinst [freq 100] 
    (* 0.2 (reduce + (map sin-osc (split-freq freq))))) 

Malheureusement, le REPL me dit que je fais mal:

CompilerException java.lang.ClassCastException: 
overtone.sc.machinery.ugen.sc_ugen.ControlProxy cannot be cast to java.lang.Number, 
compiling:(form-init1807789563491679853.clj:1) 

Mais ce code fonctionne très bien:

(definst myinst [freq 100] 
    (* 0.2 (reduce + (map sin-osc (apply vector (map #(* freq %) [1.01 1 0.99])))))) 

bien, je il suffit de mettre dans la définition de la fonction.

Je pense que j'ai un principal manque de compréhension. Je pensais que si l'une de ces versions fonctionnait, les autres devaient aussi fonctionner.

Mes questions sont: Pourquoi ma version 'améliorée' ne fonctionne-t-elle pas? Pourquoi le premier extrait fonctionne-t-il? Comment contourner ce problème?

Clojure 1.3.0 
Overtone 0.8 
(use 'overtone.core) 
+3

Essayez de macroexpanding l'appel à definst. Probablement definst est une macro complexe qui interprète cela et qui est normalement des fonctions (comme '+') dans des définitions de synthé qui additionnent un groupe de signaux, et votre nouvelle forme definst casse la macro. Le code Clojure ne peut pas être exécuté dans le processus du synthétiseur sc, de sorte que vos formulaires doivent être traduits dans des définitions de synthétiseur sc et ne peuvent pas réellement être du vrai code de clojure. – noisesmith

Répondre

1

ups, vous avez raison, je n'ai pas compris le commentaire bruyant.Il est vrai que vous ne pouvez pas utiliser directement cette valeur "freq" dans votre fonction car cette valeur n'est pas liée au moment où votre fonction en a besoin (avant l'exécution de la macro)

Voici donc une solution à ce problème, également en utilisant le formulaire let, il est aussi élégant que de faire votre propre macro mais fonctionne

(defn myinst [inst-name] 
    (let [the-freq 100] 
    (definst inst-name [freq the-freq] (* 0.2 (reduce + (map sin-osc (split-freq the-freq))))))) 

et vous pouvez exécuter en fonction normale

((myinst "my-instrument")) 

J'espère que vous aide

Juan


Commentaire précédent, maintenant pas de réponse valide

peut-être vous faites une erreur avec votre déclaration de valeur d'argument dans votre version améliorée

C'est votre code

(definst myinst [freq 100] 
    (* 0.2 (reduce + (map sin-osc (split-freq freq))))) 

Et, comme dans clojure vous ne pouvez pas assigner la valeur par défaut à la fonction argument, votre version améliorée fonctionnerait si, par exemple, vous utilisez une forme let à signer la valeur par défaut

(definst myinst [] 
    (let [freq 100] 
    (* 0.2 (reduce + (map sin-osc (split-freq freq)))))) 
+0

merci, d'abord. definst est une macro, comme l'a souligné le noisemith. Il attend un nombre pair d'arguments, chaque seconde représente une valeur par défaut. Fait intéressant, votre version compile, mais je ne peux plus appeler 'myinst' avec un argument. Je suis, definst tourne ses arguments dans ces types étranges que j'ai mentionnés ci-dessus. J'ai besoin de les convertir ... – spiehr

+0

Est-ce que cette solution a résolu votre problème? – tangrammer

+0

hmm. pas vraiment. Je veux 'instancier' un instrument (definst) et l'utiliser avec des fréquences différentes. Si je comprends bien votre solution, j'aurais besoin d'instancier un instrument pour chaque fréquence. Je devrais clarifier cela dans ma question. Aussi, je pense que cette question est plus liée à l'overtone qu'à la clojure. J'apprécie ton effort! – spiehr

Questions connexes