1
\$\begingroup\$

The following procedures are an attempt to connect some physical aspects of the sound (frequency and duration) to traditional music theory. It is not an exhaustive treatment of the subject.

THE PROCEDURES ARE WRITTEN IN FMSLogo.

Each procedure is accompanied by one or more examples.

The names of the procedures are in Italian, but thanks to the examples should be understandable to those who have a basic knowledge of music. The procedures are grouped by musical categories.


Example 1 - Arpeggio

make "arpeggio [do3 mi3 sol3 sib3 do4 mi4 sol4 sib4 do5 mi5 sol5 sib5 do6]
make "arpeggioFrequencies map [daAltezzaAFrequenza ?] :arpeggio
show :arpeggioFrequencies
suonaFrequenze :arpeggioFrequencies ; play frequencies
make "chord daListaAltezzeAdAccordo :arpeggio
show :chord

Example 2 - Simple Transposition

make "c4_Hz daAltezzaAFrequenza "do4
show :c4_Hz
make "c_scale_Hz scala :c4_Hz modoMaggiore
show :c_scale_Hz
suonaFrequenzeConDurata 1000 :c_scale_Hz
make "c_sharp_scale_Hz map [? * semitoni 1] :c_scale_Hz
show :c_sharp_scale_Hz
make "c_sharp_scale map [daFrequenzaAdAltezza diapason ?] :c_sharp_scale
show :c_sharp_scale

Standard frequencies: diapason, do4, frequenzeDo0Si8, la4

Audio: suonaFrequenze, suonaFrequenzeConDurata

Note naming: daNotaANotaBase, noteBase, noteConDiesis

Accidentals: daSpostamentoInSemitoniAdAlterazione

Octaves: ottave

Pitches: altezzaPrecedente, altezzaSuccessiva, altezzeDo0Si8, daSpostamentiAscendentiInSemitoniAdAltezze, daSpostamentiDiscendentiInSemitoniAdAltezze, omofone?

Frequencies and pitches: daAltezzaAFrequenza, daFrequenzaAdAltezza

Notes and pitches: daAltezzaANota, daAltezzeAInsiemeDiNote

Intervals: altezzaInSemitoni, daGradiDelModoASpostamentiInSemitoni, daModoARappresentazioneTradizionale, distanzaDiTerza?, semitoni, spostamentoAssolutoInSemitoni, terzaAscendente?, terzaDiscendente?

Frequencies and intervals: daFrequenzaASpostamentoInSemitoniDalDiapason

Modes: baseModo, daModoAModoBase, daModoAModoNomi, daScalaAltezzeAModoNote, gradiModo, modoMaggiore, modoMinoreArmonico, modoMinoreMelodicoAscendente, modoMinoreMelodicoDiscendente, modoMinoreNaturale, modoStranoAscendente, modoStranoDiscendente, numGradiModo

Scales: daModoAScalaAltezze, scala, scala2, scala4, scalaMaggioreLa4La5

Chords: accordoListaAltezze?, accordoListaNote?, daGradoEModoAdAccordo, daListaAltezzeAdAccordo, daListaNoteAdAccordo, notaDellAccordo?, noteDellAccordo?

Examples: esempio1, esempio2, esempio3, esempio4

Musical helper function: °altezzaInSemitoni2, °altezzaPrecedenteScomposta, °altezzaSuccessivaScomposta, °daInteroAToniESemitoni, °parseAlterazione, °parseAltezza, °promuoviCandidate, °rimuoviOttavaDaAltezza, °sequenzaPerGenerareAccordi, °spostamentoInSemitoniDaAlterazione

Generic helper functions: °°concatena, °°logBase, °°posizione, °°predCircolare, °°predCircolareEnnesimo, °°prendi :n, °°prendiSottostringa, °°rimuoviUltimiDuplicati, °°succCircolare, °°succCircolareEnnesimo, °°togliDaStringa


to accordoListaAltezze? :lista_altezze
  localmake "lista_note map [daAltezzaANota ?] :lista_altezze
  OP accordoListaNote? :lista_note
  ; es. accordoListaAltezze? [do4 sol5 mi3 la4] -> true
end

to accordoListaNote? :lista_note
  localmake "note remdup :lista_note
  if (count :note) < 3 [OP "false]
  localmake "buone (list (first :note))
  localmake "candidate butfirst :note
  localmake "risultato °promuoviCandidate (list :buone :candidate) (count :candidate)
  OP empty? (last :risultato)
  ; es. accordoListaNote? [do sol mi la] -> true
end

to altezzaInSemitoni :altezza
  localmake  "lista_nota °parseAltezza :altezza
  localmake "notaBase first :lista_nota
  localmake "alterazione item 2 :lista_nota
  localmake "ottava last :lista_nota
  OP °altezzaInSemitoni2 :notaBase :alterazione :ottava
  ; es. altezzaInSemitoni "do0  -> 0
  ; es. altezzaInSemitoni "do#0 -> 1
  ; es. altezzaInSemitoni "do#1 -> 13
  ; es. altezzaInSemitoni "lab4 -> 56
end

to altezzaPrecedente :notaBase :alterazione :ottava :spostamento_in_semitoni ; semitoni < 0
  OP reduce [word ?1 ?2] (°altezzaPrecedenteScomposta :notaBase :alterazione :ottava :spostamento_in_semitoni)
  ; es. altezzaPrecedente "do "# 4 -2  -> si3
  ; es. altezzaPrecedente "do "# 4 -1  -> si#3
  ; es. altezzaPrecedente "do "b 4 -1  -> sib3
  ; es. altezzaPrecedente "do "  4 -1  -> si3
end

to altezzaSuccessiva :notaBase :alterazione :ottava :spostamento_in_semitoni ; semitoni > 0
  OP reduce [word ?1 ?2] (°altezzaSuccessivaScomposta :notaBase :alterazione :ottava :spostamento_in_semitoni)
  ; es. altezzaSuccessiva "do "# 4 1  -> re4
  ; es. altezzaSuccessiva "do "# 4 2  -> re#4
  ; es. altezzaSuccessiva "do "b 4 1  -> rebb4
  ; es. altezzaSuccessiva "do "  4 2  -> re4
end

to altezzeDo0Si8
  OP (crossmap [word ?2 ?1] ottave noteConDiesis)
  ; altezzeDo0Si8  -> [do0 do#0 .. la#8 si8]
end

to baseModo :modo
  OP butlast :modo
  ; es. baseModo modoMaggiore           -> [0  2  4 5 7 9 11]
  ; es. baseModo (reverse modoMaggiore) -> [12 11 9 7 5 4 2 ]
end

to daAltezzaAFrequenza :altezza
  OP la4 * semitoni ((altezzaInSemitoni :altezza) - (altezzaInSemitoni "la4))
  ; alternativa: OP item (°°posizione :alt altezzeDo0Si8) frequenzeDo0Si8
  ; es. daAltezzaAFrequenza "la4   -> 440
  ; es. daAltezzaAFrequenza "la#4  -> 466.16376151809
  ; es. daAltezzaAFrequenza "la3   -> 220
  ; es. daAltezzaAFrequenza "solx4 -> 440
end

to daAltezzaANota :altezza
  OP °rimuoviOttavaDaAltezza :altezza
  ; es. daAltezzaANota "la4   -> la
  ; es. daAltezzaANota "la#4  -> la#
  ; es. daAltezzaANota "labb4 -> labb
end

to daAltezzeAInsiemeDiNote :altezze
  OP remdup (daAltezzeANote :altezze)
  ; es. daAltezzeAInsiemeDiNote [do4 mi5 do3 sol4 mi4 la4 do5 sol5]  -> [mi la do sol]
end

to daFrequenzaAdAltezza :diapason :hz ; approssimazione al semitono più vicino
  localmake "semitoni daFrequenzaASpostamentoInSemitoniDalDiapason :diapason :hz
  OP item (1 + 57 + :semitoni) altezzeDo0Si8
  ; es. daFrequenzaAdAltezza 440 440  -> la4
  ; es. daFrequenzaAdAltezza 440 450  -> la4
  ; es. daFrequenzaAdAltezza 440 455  -> la#4
  ; es. daFrequenzaAdAltezza 440 466  -> la#4
  ; es. daFrequenzaAdAltezza 440 220  -> la3
end

to daFrequenzaASpostamentoInSemitoniDalDiapason :diapason :hz ; approssimazione al semitono più vicino
  localmake "cent round °°logBase (power 2 (1/1200)) (:hz / :diapason)
  localmake "smt int (:cent / 100)
  localmake "mc modulo :cent 100
  localmake "r ifelse :diapason <= :hz [ifelse :mc < 50 [0] [1]] [ifelse (or (:mc = 0) (:mc > 50)) [0] [-1]]
  OP :smt + :r
  ; es. daFrequenzaASpostamentoInSemitoniDalDiapason 440 440  -> 0
  ; es. daFrequenzaASpostamentoInSemitoniDalDiapason 440 455  -> 1
  ; es. daFrequenzaASpostamentoInSemitoniDalDiapason 440 466  -> 1
  ; es. daFrequenzaASpostamentoInSemitoniDalDiapason 440 880  -> 12
  ; es. daFrequenzaASpostamentoInSemitoniDalDiapason 440 220  -> -12
end

to daGradiDelModoASpostamentiInSemitoni :modo
  OP (map [?1 - ?2] (butfirst :modo) (butlast :modo))
  ; es. daGradiDelModoASpostamentiInSemitoni modoMaggiore   -> [2 2 1 2 2 2 1]
  ; es. daGradiDelModoASpostamentiInSemitoni (reverse modoMaggiore)  -> [-1 -2 -2 -2 -1 -2 -2]
end

to daGradoEModoAdAccordo :grado :num_note :modo_note
  localmake "modo_base_note daModoAModoBase :modo_note
  if or (:num_note < 3) (:num_note > 7) [OP [il numero di note deve essere compreso tra 3 e 7]]
  localmake "fondamentale item :grado :modo_base_note
  localmake "seq °°prendi :num_note °sequenzaPerGenerareAccordi
  OP map [°°succCircolareEnnesimo ? :fondamentale :modo_base_note] :seq
  ; es. daGradoEModoAdAccordo 2 5 [sib do re mib fa sol la sib]
  ; es. daGradoEModoAdAccordo 5 4 (daModoAModoNomi "do modoMaggiore)
  ; es. daGradoEModoAdAccordo 2 3 (daModoAModoNomi "do (reverse modoMaggiore))
  ; es. daGradoEModoAdAccordo 5 4 (daModoAModoNomi "sib modoMaggiore)
end

to daListaAltezzeAdAccordo :lista_altezze
  localmake "lista_note map [daAltezzaANota ?] :lista_altezze
  OP daListaNoteAdAccordo :lista_note
  ; es. daListaAltezzeAdAccordo [do4 sol5 mi3 la4]      -> [la do mi sol]
  ; es. daListaAltezzeAdAccordo [dob4 sol#5 mi3 labb4]  -> [labb dob mi sol#]
end

to daListaNoteAdAccordo :lista_note
  localmake "note remdup :lista_note
  if (count :note) < 3 [OP "false]
  localmake "buone (list (first :note))
  localmake "candidate butfirst :note
  localmake "risultato °promuoviCandidate (list :buone :candidate) (count :candidate)
  OP first :risultato
  ; es. daListaNoteAdAccordo [do sol mi la] -> [la do mi sol]
end

to daModoAModoBase :modo
  OP butlast :modo
  ; es. daModoAModoBase modoMaggiore   -> [0 2 4 5 7 9 11]
  ; es. daModoAModoBase (reverse modoMaggiore)  -> [12 11 9 7 5 4 2]
end

to daModoAModoNomi :nomeNota :modo ; ad es. nomeNota può essere re oppure do# oppure la3b
  localmake "scala_altezze daModoAScalaAltezze (word :nomeNota "4) :modo
  OP map [daAltezzaANomeNota ?] :scala_altezze
  ; es. daModoAModoNomi "do modoMaggiore          -> [do re mi fa sol la si do]
  ; es. daModoAModoNomi "la modoMaggiore          -> [la si do# re mi fa# sol# la]
  ; es. daModoAModoNomi "reb (reverse modoMinoreArmonico)  -> [reb do sibb lab solb fab mib reb]
end

to daModoARappresentazioneTradizionale :modo
  OP map [°daInteroAToniESemitoni  ?] (daGradiDelModoASpostamentiInSemitoni :modo)
  ; daModoARappresentazioneTradizionale modoMaggiore   -> [T T S T T T S]
  ; daModoARappresentazioneTradizionale (reverse modoMaggiore)  -> [-S -T -T -T -S -T -T]
end

to daModoAScalaAltezze :altezza :modo
  localmake "lista_altezza °parseAltezza :altezza
  localmake "notaBase first :lista_altezza
  localmake "alterazione item 2 :lista_altezza
  localmake "ottava last :lista_altezza
  localmake "direzione ifelse (first :modo) = 0 ["ascendente] ["discendente]
  localmake "ottava_prima_altezza ifelse :direzione = "ascendente [:ottava] [:ottava + 1]
  localmake "prima_altezza (word :notaBase :alterazione :ottava_prima_altezza)
  localmake "spostamenti_modo daGradiDelModoASpostamentiInSemitoni :modo
  localmake "altezze_successive ifelse :direzione = "ascendente ~
    [daSpostamentiAscendentiInSemitoniAdAltezze  :notaBase :alterazione :ottava_prima_altezza :spostamenti_modo []] ~
    [daSpostamentiDiscendentiInSemitoniAdAltezze :notaBase :alterazione :ottava_prima_altezza :spostamenti_modo []]
  OP sentence :prima_altezza :altezze_successive
  ; es. daModoAModoNomi "do modoMaggiore               -> [do re mi fa sol la si do]
  ; es. daModoAScalaAltezze "la4  modoMaggiore         -> [la4 si4 do#5 re5 mi5 fa#5 sol#5 la5]
  ; es. daModoAScalaAltezze "sib4 (reverse modoMinoreArmonico)  -> [sib5 la5 solb5 fa5 mib5 reb5 do5 sib4]
end

to daNotaANotaBase :nota
  localmake "2car °°prendiSottostringa 2 :nota
  OP ifelse :2car = "so ["sol] [:2car]
  ; es. daNotaANotaBase "do    -> do
  ; es. daNotaANotaBase "do#   -> do
  ; es. daNotaANotaBase "dobb  -> do
end

to daScalaAltezzeAModoNote :scala_altezze
  OP °°rimuoviUltimiDuplicati (daAltezzeANote :scala_altezze)
  ; es. daScalaAltezzeAModoNote [do4 re4 mi4 fa4 sol4 la4 si4 do5 re5 mi5 fa5 sol5 la5 si5 do6]  -> [do re mi fa sol la si]
  ; es. daScalaAltezzeAModoNote [do6 si5 la5 sol5 fa5 mi5 re5 do5 si4 la4 sol4 fa4 mi4 re4 do4]  -> [do si la sol fa mi re]
end

to daSpostamentiAscendentiInSemitoniAdAltezze :notaBase :alterazione :ottava :lista_semitoni :buffer
  if empty? :lista_semitoni [OP :buffer]
  localmake "altezza_successiva °altezzaSuccessivaScomposta :notaBase :alterazione :ottava (first :lista_semitoni)
  localmake "nuovo_buffer SE :buffer (°°concatena :altezza_successiva)
  localmake "nuova_notaBase item 1 :altezza_successiva
  localmake "nuova_alterazione item 2 :altezza_successiva
  localmake "nuova_ottava item 3 :altezza_successiva
  OP daSpostamentiAscendentiInSemitoniAdAltezze :nuova_notaBase :nuova_alterazione :nuova_ottava ~
       (butfirst :lista_semitoni) :nuovo_buffer
  ; es. daSpostamentiAscendentiInSemitoniAdAltezze "do "  "4 [2 2 1 2 2 2 1] []     -> [re4 mi4 fa4 sol4 la4 si4 do5]
  ; es. daSpostamentiAscendentiInSemitoniAdAltezze "do "  "4 [2 2 1 2 2 2 1] [do4]  -> [do4 re4 mi4 fa4 sol4 la4 si4 do5]
  ; es. daSpostamentiAscendentiInSemitoniAdAltezze "do "# "4 [2 2 1 2 2 2 1] []     -> [re#4 mi#4 fa#4 sol#4 la#4 si#4 do#5]
end

to daSpostamentiDiscendentiInSemitoniAdAltezze :notaBase :alterazione :ottava :lista_semitoni :buffer
  if empty? :lista_semitoni [OP :buffer]
  localmake "altezza_precedente °altezzaPrecedenteScomposta :notaBase :alterazione :ottava (first :lista_semitoni)
  localmake "nuovo_buffer SE :buffer (°°concatena :altezza_precedente)
  localmake "nuova_notaBase item 1 :altezza_precedente
  localmake "nuova_alterazione item 2 :altezza_precedente
  localmake "nuova_ottava item 3 :altezza_precedente
  OP daSpostamentiDiscendentiInSemitoniAdAltezze :nuova_notaBase :nuova_alterazione :nuova_ottava ~
       (butfirst :lista_semitoni) :nuovo_buffer
  ; es. daSpostamentiDiscendentiInSemitoniAdAltezze "do "   "5 [-1 -2 -2 -2 -1 -2 -2] []      -> [si4 la4 sol4 fa4 mi4 re4 do4]
  ; es. daSpostamentiDiscendentiInSemitoniAdAltezze "do "   "5 [-1 -2 -2 -2 -1 -2 -2] [do5]   -> [do5 si4 la4 sol4 fa4 mi4 re4 do4]
  ; es. daSpostamentiDiscendentiInSemitoniAdAltezze "re "b  "5 [-1 -2 -2 -2 -1 -2 -2] [reb5]  -> [reb5 do5 sib4 lab4 solb4 fa4 mib4 reb4]
end

to daSpostamentoInSemitoniAdAlterazione :n
  if :n = 0  [OP "]
  if :n = 1  [OP "#]
  if :n = 2  [OP "x]
  if :n > 2  [OP word :n "#]
  if :n = -1 [OP "b]
  if :n = -2 [OP "bb]
  if :n < -2 [OP word (abs :n) "b]
  ; es. daSpostamentoInSemitoniAdAlterazione 1  -> #
  ; es. daSpostamentoInSemitoniAdAlterazione 2  -> x
  ; es. daSpostamentoInSemitoniAdAlterazione -2 -> bb
end

to diapason
  OP 440
end

to distanzaDiTerza? :nota1 :nota2
  localmake "notaBase1 daNotaANotaBase :nota1
  localmake "notaBase2 daNotaANotaBase :nota2
  OP or ((°°succCircolareEnnesimo 2 :notaBase1 noteBase) = :notaBase2) ~
        ((°°predCircolareEnnesimo 2 :notaBase1 noteBase) = :notaBase2)
  ; distanzaDiTerza? "do "la -> true
  ; distanzaDiTerza? "la "do -> true
  ; distanzaDiTerza? "do "fa -> false
end

to do4
  OP la4 * (semitoni -9)  ; do centrale = 261.625565300599 (Hz)
end

to esempio1
  suonaFrequenze (scala la4 modoMaggiore)
end

to esempio2
  suonaFrequenze (scala la4 (reverse modoMaggiore))
end

to esempio3
  suonaFrequenze (scala sib3 modoMinoreMelodicoAscendente)
  suonaFrequenze (scala sib3 modoMinoreMelodicoDiscendente)
end

to esempio4
  suonaFrequenze (scala la4 modoStranoAscendente)
  suonaFrequenze (scala la4 modoStranoDiscendente)
end

to frequenzeDo0Si8
  localmake "num_semitoni 9*12 ; 9 ottave di 12 semitoni
  OP map [la4 * semitoni (? - 57)] (iseq 0 (:num_semitoni - 1)) ; 57 è la distanza in semitoni tra il la4 e il do0
  ; -> [16.3515978312874 17.3239144360545 18.354047994838 .. 7458.62018428944 7902.13282009799]
end

to gradiModo :modo
  OP iseq 1 ((count :modo) - 1)
  ; es. gradiModo modoMaggiore   -> [1 2 3 4 5 6 7]
  ; es. gradiModo (reverse modoMaggiore)  -> [1 2 3 4 5 6 7]
  ; es. gradiModo modoStranoAscendente     -> [1 2 3 4 5]
  ; es. gradiModo modoStranoDiscendente    -> [1 2 3 4 5 6]
end

to la4
  OP diapason  ; = 440 (Hz)
end

to modoMaggiore
  ; sequenza degli "spostamenti" in semitoni dei gradi di una scala maggiore ascendente da una frequenza data
  OP [0 2 4 5 7 9 11 12]
end

to modoMinoreArmonico
  OP [0 2 3 5 7 8 11 12]
end

to modoMinoreMelodicoAscendente
  OP [0 2 3 5 7 9 11 12]
end

to modoMinoreMelodicoDiscendente
  OP reverse modoMinoreNaturale
end

to modoMinoreNaturale
  OP [0 2 3 5 7 8 10 12]
end

to modoStranoAscendente
  OP [0 3 5 6 9 12]
end

to modoStranoDiscendente
  OP [12 9 7 5 3 1 0]
end

to notaDellAccordo? :nota :accordo
  OP memberp :nota :accordo
  ; es. notaDellAccordo? "do [do mi sol]  -> true
  ; es. notaDellAccordo? "do [mi sol do]  -> true
  ; es. notaDellAccordo? "sol# [dob mi sol#]  -> true
end

to noteBase
  OP [do re mi fa sol la si]
end

to noteConDiesis
  OP [do do# re re# mi fa fa# sol sol# la la# si]
end

to noteDellAccordo? :note :accordo
  OP reduce "and (map [notaDellAccordo? ? :accordo] :note)
  ; es. noteDellAccordo? [dox sib] [mi# sib sol dox]  -> true
end

to numGradiModo :modo
  OP count (gradiModo :modo)
  ; es. numGradiModo modoMaggiore      -> 7
  ; es. numGradiModo modoStranoAscendente        -> 5
  ; es. show numGradiModo modoStranoDiscendente  -> 6
end

to omofone? :altezza1 :altezza2
  OP (altezzaInSemitoni :altezza1) = (altezzaInSemitoni :altezza2)
  ; es. omofone? "si#3 "do4    -> true
  ; es. omofone? "la4  "solx4  -> true
end

to ottave
  OP iseq 0 8  ; -> [0 1 2 3 4 5 6 7 8]
end

to scala :freq_base :modo
  OP map [:freq_base * semitoni ? ] :modo
  ; es. scala la4 modoMaggiore = scala 440 modoMaggiore
  ; es. scala 440 modoMaggiore   -> [440 493.883301256124 554.365261953744 587.329535834815 659.25511382574 739.988845423269 830.60939515989 880]
  ; es. scala 440 (reverse modoMaggiore)  -> [880 830.60939515989 739.988845423269 659.25511382574 587.329535834815 554.365261953744 493.883301256124 440]
end

to scala2 :freq_base :modo :ottava
  OP map [:freq_base * semitoni (? + 12 * :ottava)] :modo
  ; es. scala2 440 modoMaggiore 1   -> [880 987.766602512248 1108.73052390749 1174.65907166963 1318.51022765148 1479.97769084654 1661.21879031978 1760]
  ; es. scala2 440 (reverse modoMaggiore) 1  -> [1760 1661.21879031978 1479.97769084654 1318.51022765148 1174.65907166963 1108.73052390749 987.766602512248 880]
end

to scala4 :freq_base :modo :da_ottava :a_ottava
  localmake "scl map.se [butlast (scala2 :freq_base (baseModo :modo) ?)] (iseq :da_ottava (:a_ottava - 1))
  OP SE :scl (scala2 :freq_base :modo :a_ottava)
  ; es. scala4 220 modoMaggiore 1 3
  ; es. scala4 220 (reverse modoMaggiore) 3 1
end

to scalaMaggioreLa4La5
  OP [440 494 554 587 659 740 831 880]
  ;  = OP map [round (la4 * semitoni ?)] [0 2 4 5 7 9 11 12]
end

to semitoni :n
  OP power 2 (:n/12)
  ; es. semitoni 0    -> 1
  ; es. semitoni 1    -> 1.0594630943593
  ; es. semitoni 2    -> 1.12246204830937
  ; es. semitoni 12   -> 2
  ; es. semitoni 24   -> 4
  ; es. semitoni -1   -> 0.943874312681694
  ; es. semitoni -2   -> 0.890898718140339
  ; es. semitoni -12  -> 0.5
  ; es. semitoni -24  -> 0.25
end

to spostamentoAssolutoInSemitoni :notaBase1 :alterazione1 :ottava1 :notaBase2 :alterazione2: :ottava2
  OP (°altezzaInSemitoni2 :notaBase2 :alterazione2: :ottava2) - (°altezzaInSemitoni2 :notaBase1 :alterazione1 :ottava1)
  ; es. spostamentoAssolutoInSemitoni "do "#  4 "re "   4  -> 1
  ; es. spostamentoAssolutoInSemitoni "re "   4 "do "#  4  -> -1
  ; es. spostamentoAssolutoInSemitoni "do "#  4 "re "#  5  -> 14
end

to suonaFrequenze :lhz
  localmake "dms 700
  sound map.se [list (round ?) :dms] :lhz
  ; es. suonaFrequenze [440 466.16376151809 233.081880759045] = suonaFrequenze [la4 la#4 sib3] (solo se altezze definite)
  ; es. suonaFrequenze [220 440 880 1760]
end

to suonaFrequenzeConDurata :dms :lhz ; 1000 ms = 1 s
  sound map.se [list (round ?) :dms] :lhz
  ; es. suonaFrequenzeConDurata 1000 [440 466.16376151809 233.081880759045] = suonaFrequenze [la4 la#4 sib3] (solo se altezze definite)
  ; es. suonaFrequenzeConDurata 1500 [220 440 880 1760]
end

to terzaAscendente? :nota1 :nota2 ; intervallo generico
  localmake "notaBase1 daNotaANotaBase :nota1
  localmake "notaBase2 daNotaANotaBase :nota2
  OP (°°succCircolareEnnesimo 2 :notaBase1 noteBase) = :notaBase2
  ; es. terzaAscendente? "do  "mi   -> true
  ; es. terzaAscendente? "dob "mi#  -> true
  ; es. terzaAscendente? "mi  "do   -> false
  ; es. terzaAscendente? "sib "do   -> false
  ; es. terzaAscendente? "sib "re   -> true
  ; es. terzaAscendente? "re  "sib  -> false
end

to terzaDiscendente? :nota1 :nota2 ; intervallo generico
  OP terzaAscendente? :nota2 :nota1
  ; es. terzaDiscendente? "do  "la   -> true
  ; es. terzaDiscendente? "do# "lab  -> true
  ; es. terzaDiscendente? "la  "do   -> false
  ; es. terzaDiscendente? "do  "mi   -> false
  ; es. terzaDiscendente? "mi  "do   -> true
end

to °altezzaInSemitoni2 :notaBase :alterazione :ottava
  OP ((°°posizione :notaBase noteConDiesis) - 1) + (°spostamentoInSemitoniDaAlterazione :alterazione) + (:ottava * 12)
  ; es. °altezzaInSemitoni2 "do " 0  -> 0
  ; es. °altezzaInSemitoni2 "do "# 0 -> 1
  ; es. °altezzaInSemitoni2 "do "# 1 -> 13
  ; es. °altezzaInSemitoni2 "la "b 4 -> 56
end

to °altezzaPrecedenteScomposta :notaBase :alterazione :ottava :spostamento_in_semitoni ; semitoni < 0
  localmake "notaBase_precedente °°predCircolare :notaBase noteBase
  localmake "nuova_ottava ifelse :notaBase_precedente = "si [:ottava - 1] [:ottava]
  localmake "d1 °altezzaInSemitoni2 :notaBase :alterazione :ottava
  localmake "d2 °altezzaInSemitoni2 :notaBase_precedente "  :nuova_ottava
  localmake "delta :d1 - :d2 + :spostamento_in_semitoni
  localmake "nuova_alterazione daSpostamentoInSemitoniAdAlterazione :delta
  OP (list :notaBase_precedente :nuova_alterazione :nuova_ottava)
  ; es. °altezzaPrecedenteScomposta "do "# 4 -2  -> [si  3]
  ; es. °altezzaPrecedenteScomposta "do "# 4 -1  -> [si # 3]
  ; es. °altezzaPrecedenteScomposta "do "b 4 -1  -> [si b 3]
end

to °altezzaSuccessivaScomposta :notaBase :alterazione :ottava :spostamento_in_semitoni ; semitoni > 0
  localmake "notaBase_successiva °°succCircolare :notaBase noteBase
  localmake "nuova_ottava ifelse :notaBase_successiva = "do [:ottava + 1] [:ottava]
  localmake "d1 °altezzaInSemitoni2 :notaBase :alterazione :ottava
  localmake "d2 °altezzaInSemitoni2 :notaBase_successiva " :nuova_ottava
  localmake "delta :d1 - :d2 + :spostamento_in_semitoni
  localmake "nuova_alterazione daSpostamentoInSemitoniAdAlterazione :delta
  OP (list :notaBase_successiva :nuova_alterazione :nuova_ottava)
  ; es. °altezzaSuccessivaScomposta "do "# 4 1  -> [re  4]
  ; es. °altezzaSuccessivaScomposta "do "# 4 2  -> [re # 4]
end

to °daInteroAToniESemitoni :n ; n <> 0
  if :n =   1 [OP "S]
  if :n =   2 [OP "T]
  if :n =   3 [OP "TS]
  if :n >=  4 [OP word :n "S]
  if :n =  -1 [OP "-S]
  if :n =  -2 [OP "-T]
  if :n =  -3 [OP "-TS]
  if :n <= -4 [OP word :n "S]
  ; es. °daInteroAToniESemitoni 1   -> S
  ; es. °daInteroAToniESemitoni 2   -> T
  ; es. °daInteroAToniESemitoni -3  -> -TS
  ; es. °daInteroAToniESemitoni 4   -> 4S
end

to °parseAlterazione :stringa ; alterazioni "strane" solo se nel formato "d#" oppure "db", dove d = 1 cifra
  localmake "1car first :stringa
  localmake "resto1 butfirst :stringa
  if member? :1car [# x] [OP list :1car :resto1]
  if :1car = "b [ifelse (first :resto1) = "b [OP list "bb bf :resto1]
    [OP list "b :resto1]]
  if (count :stringa) = 1 [OP list " :stringa]
  OP list (°°prendiSottostringa 2 :stringa) (°°togliDaStringa 2 :stringa)
end

to °parseAltezza :alt ; alterazioni "strane" solo se nel formato "d#" oppure "db", dove d = 1 cifra
  localmake "2car °°prendiSottostringa 2 :alt
  ifelse :2car = "so [localmake "notaBase "sol localmake "resto °°togliDaStringa 3 :alt] ~
    [localmake "notaBase :2car localmake "resto °°togliDaStringa 2 :alt]
  localmake "alterazione_e_ottava °parseAlterazione :resto
  OP SE :notaBase :alterazione_e_ottava
  ; es. °parseAltezza "do#4   -> [do # 4]
  ; es. °parseAltezza "dobb2  -> [do bb 2]
  ; es. °parseAltezza "do3#2  -> [do 3# 2]
end

to °promuoviCandidate :buone_candidate :max_tentativi
  if :max_tentativi = 0 [OP :buone_candidate]
  localmake "buone first :buone_candidate
  localmake "candidate last :buone_candidate
  if empty? :candidate [OP :buone_candidate]
  localmake "candidata first :candidate
  if terzaAscendente?  (last :buone) :candidata ~
    [OP °promuoviCandidate  (list (SE :buone :candidata) (butfirst :candidate)) :max_tentativi]
  if terzaDiscendente?  (first :buone) :candidata ~
    [OP °promuoviCandidate  (list (SE :candidata :buone) (butfirst :candidate)) :max_tentativi]
  OP °promuoviCandidate (list :buone (SE (butfirst :candidate) :candidata)) (:max_tentativi - 1)
end

to °rimuoviOttavaDaAltezza :altezza
  ifelse number? (last :altezza) [OP °rimuoviOttavaDaAltezza (butlast :altezza)] [OP :altezza]
  ; es. °rimuoviOttavaDaAltezza "do4    -> do
  ; es. °rimuoviOttavaDaAltezza "dobb2  -> dobb
end

to °sequenzaPerGenerareAccordi ; per un modo di 7 gradi
  OP [0 2 4 6 1 3 5]
end

to °spostamentoInSemitoniDaAlterazione :a
  if :a = "   [OP 0]
  if :a = "#  [OP 1]
  if :a = "x  [OP 2]
  if :a = "b  [OP -1]
  if :a = "bb [OP -2]
  OP (butlast :a) * (ifelse (last :a) = "# [1] [-1])
  ; es. °spostamentoInSemitoniDaAlterazione "#   -> 1
  ; es. °spostamentoInSemitoniDaAlterazione "bb  -> -2
end

to °°concatena :lista
  OP (reduce [word ?1 ?2] :lista)
  ; es. °°concatena [alter azione]  -> "alterazione
end

to °°logBase :b :n
  OP (ln :n) / ln :b
  ; es. °°logBase 2  16  -> 4
  ; es. °°logBase (semitoni 1) (880/440)  -> 12
end

to °°posizione :elemento :lista
  OP 1 + (count :lista) - count (member :elemento :lista)
  ; es. °°posizione "do#3 [re4 mib5 do#3 re4 do#3]  -> 3
end

to °°predCircolare :elem :lista
  localmake "posiz °°posizione :elem :lista
  OP ifelse :posiz = 1 [item (count :lista) :lista] [item (:posiz - 1) :lista]
  ; es. °°predCircolare "si [do re mi fa sol la si]  -> la
  ; es. °°predCircolare "do [do re mi fa sol la si]  -> si
end

to °°predCircolareEnnesimo :n :elem :lista
  OP cascade (modulo :n (count :lista)) [°°predCircolare ? :lista] :elem
  ; es. °°predCircolareEnnesimo 3 "si [do re mi fa sol la si]  -> fa
  ; es. °°predCircolareEnnesimo 1 "do [do re mi fa sol la si]  -> si
end

to °°prendi :n :lista
  if :n = 0 [OP []]
  if empty? :lista [OP []]
  OP (SE (first :lista) (°°prendi (:n - 1) (butfirst :lista)))
  ; es. °°prendi 2 [do4 sol#5 mi3 labb2]  -> [do4 sol#5]
end

to °°prendiSottostringa :n :stringa
  if :n = 0 [OP "]
  if :stringa = " [OP "]
  OP (word (first :stringa) (°°prendiSottostringa (:n - 1) (butfirst :stringa)))
  ; es. °°prendiSottostringa 3 "sol#4  -> sol
end

to °°rimuoviUltimiDuplicati :lista
  OP transfer [] [ifelse member? ?IN ?OUT [?OUT] [lput ?IN ?OUT]] :lista
  ; es. °°rimuoviUltimiDuplicati [1 2 3 1 1 4 6 3 1 2]  -> [1 2 3 4 6]
end

to °°succCircolare :elem :lista
  localmake "posiz °°posizione :elem :lista
  OP ifelse :posiz = count :lista [item 1 :lista] [item (:posiz + 1) :lista]
  ; es. °°succCircolare "do [do re mi fa sol la si]  -> re
  ; es. °°succCircolare "si [do re mi fa sol la si]  -> do
end

to °°succCircolareEnnesimo :n :elem :lista
  OP cascade (modulo :n (count :lista)) [°°succCircolare ? :lista] :elem
  ; es. °°succCircolareEnnesimo 3 "do [do re mi fa sol la si]  -> fa
  ; es. °°succCircolareEnnesimo 1 "si [do re mi fa sol la si]  -> do
end

to °°togliDaStringa :n :stringa
  if :n = 0 [OP :stringa]
  if empty? :stringa [OP "]
  OP °°togliDaStringa (:n - 1) (butfirst :stringa)
  ; es. °°togliDaStringa 5 "alterazione"  -> "azione
end
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.