fixing cent deviation sign bug and adding path finder for rising version and other tweaks
This commit is contained in:
parent
433678463f
commit
edc2f1b3a0
|
|
@ -2,7 +2,7 @@
|
||||||
"cells": [
|
"cells": [
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 1,
|
"execution_count": 89,
|
||||||
"id": "806f6f69-1e0b-4d34-aac9-695c8531cdb1",
|
"id": "806f6f69-1e0b-4d34-aac9-695c8531cdb1",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
|
|
@ -79,7 +79,7 @@
|
||||||
"def edges(chords, min_symdiff, max_symdiff, max_chord_size): \n",
|
"def edges(chords, min_symdiff, max_symdiff, max_chord_size): \n",
|
||||||
"\n",
|
"\n",
|
||||||
" def reverse_movements(movements):\n",
|
" def reverse_movements(movements):\n",
|
||||||
" return {value['destination']:{'destination':key, 'cent_difference':value['cent_difference']} for key, value in movements.items()}\n",
|
" return {value['destination']:{'destination':key, 'cent_difference':value['cent_difference'] * -1} for key, value in movements.items()}\n",
|
||||||
"\n",
|
"\n",
|
||||||
" def is_directly_tunable(intersection, diff):\n",
|
" def is_directly_tunable(intersection, diff):\n",
|
||||||
" # this only works for now when intersection if one element - need to fix that\n",
|
" # this only works for now when intersection if one element - need to fix that\n",
|
||||||
|
|
@ -166,7 +166,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 2,
|
"execution_count": 214,
|
||||||
"id": "4e3ef738-7f64-47c3-9129-0450fd031375",
|
"id": "4e3ef738-7f64-47c3-9129-0450fd031375",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
|
|
@ -180,17 +180,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 7,
|
"execution_count": 215,
|
||||||
"id": "aea5215c-8551-4685-b761-11c2dc74cf22",
|
"id": "aea5215c-8551-4685-b761-11c2dc74cf22",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"144"
|
"260"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 7,
|
"execution_count": 215,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
|
@ -198,6 +198,7 @@
|
||||||
"source": [
|
"source": [
|
||||||
"from random import choice, choices\n",
|
"from random import choice, choices\n",
|
||||||
"\n",
|
"\n",
|
||||||
|
"# This is for the static version\n",
|
||||||
"def stochastic_hamiltonian(graph):\n",
|
"def stochastic_hamiltonian(graph):\n",
|
||||||
" \n",
|
" \n",
|
||||||
" def movement_size_weights(edges):\n",
|
" def movement_size_weights(edges):\n",
|
||||||
|
|
@ -246,9 +247,11 @@
|
||||||
" for e in edges:\n",
|
" for e in edges:\n",
|
||||||
" yield 10 if not has_voice_crossing(e) else 0\n",
|
" yield 10 if not has_voice_crossing(e) else 0\n",
|
||||||
"\n",
|
"\n",
|
||||||
|
" def is_bass_rooted(chord):\n",
|
||||||
|
" return max([sum(abs(p) for p in collapse_pitch(pitch_difference(chord[0], p))) for p in chord[1:]]) == 1\n",
|
||||||
|
" \n",
|
||||||
" check_graph = graph.copy()\n",
|
" check_graph = graph.copy()\n",
|
||||||
" #next_node = choice(list(graph.nodes()))\n",
|
" next_node = choice([node for node in graph.nodes() if is_bass_rooted(node)])\n",
|
||||||
" next_node = list(graph.nodes())[0]\n",
|
|
||||||
" check_graph.remove_node(next_node)\n",
|
" check_graph.remove_node(next_node)\n",
|
||||||
" for node in graph.nodes(data=True):\n",
|
" for node in graph.nodes(data=True):\n",
|
||||||
" node[1]['count'] = 1\n",
|
" node[1]['count'] = 1\n",
|
||||||
|
|
@ -280,6 +283,30 @@
|
||||||
"len(path)"
|
"len(path)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 25,
|
||||||
|
"id": "ac9e15be-5495-405c-9ce4-ae40d97c7814",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"[]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 25,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"def is_super_compact(chord):\n",
|
||||||
|
" return max([sum(abs(p) for p in collapse_pitch(pitch_difference(c[0], c[1]))) for c in combinations(chord, 2)]) == 1\n",
|
||||||
|
" \n",
|
||||||
|
"[node for node in graph.nodes() if is_super_compact(node)]"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 11,
|
"execution_count": 11,
|
||||||
|
|
@ -372,6 +399,189 @@
|
||||||
"source": [
|
"source": [
|
||||||
"lprun -f edge_data edges(chord_set, 3, 3, 4)"
|
"lprun -f edge_data edges(chord_set, 3, 3, 4)"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 180,
|
||||||
|
"id": "a76dc0f3-02e2-4739-9014-b53d3a590e3d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"dims = (2, 3, 5, 7, 11)\n",
|
||||||
|
"root = (0, 0, 0, 0, 0)\n",
|
||||||
|
"chord = (root,)\n",
|
||||||
|
"chord_set = chords(chord, root, 3, 3)\n",
|
||||||
|
"graph = generate_graph(chord_set, 2, 2, 3)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 213,
|
||||||
|
"id": "6e4ecb10-344b-4721-b2f4-68de91d712db",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"((4, 0, 0, 0, -1), (3, 0, -1, 0, 0), (0, 0, 0, 0, 0))\n",
|
||||||
|
"0\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"144"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 213,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"from random import choice, choices\n",
|
||||||
|
"\n",
|
||||||
|
"# This is for the rising version / yitgadal\n",
|
||||||
|
"def stochastic_hamiltonian(graph):\n",
|
||||||
|
" \n",
|
||||||
|
" def movement_size_weights(edges):\n",
|
||||||
|
" \n",
|
||||||
|
" def max_cent_diff(edge):\n",
|
||||||
|
" res = max([v for val in edge[2]['movements'].values() if (v:=val['cent_difference']) is not None])\n",
|
||||||
|
" return res\n",
|
||||||
|
" \n",
|
||||||
|
" def min_cent_diff(edge):\n",
|
||||||
|
" res = [v for val in edge[2]['movements'].values() if (v:=val['cent_difference']) is not None]\n",
|
||||||
|
" res.remove(0)\n",
|
||||||
|
" return min(res)\n",
|
||||||
|
" \n",
|
||||||
|
" for e in edges:\n",
|
||||||
|
" yield 1000 if ((max_cent_diff(e) < 175) and (min_cent_diff(e)) >= 0) else 1\n",
|
||||||
|
"\n",
|
||||||
|
" def hamiltonian_weights(edges):\n",
|
||||||
|
" for e in edges:\n",
|
||||||
|
" yield 10 if e[1] not in [path_edge[0] for path_edge in path] else 1 / graph.nodes[e[1]]['count']\n",
|
||||||
|
" \n",
|
||||||
|
" def contrary_motion_weights(edges):\n",
|
||||||
|
"\n",
|
||||||
|
" def is_contrary(edge):\n",
|
||||||
|
" cent_diffs = [v for val in edge[2]['movements'].values() if (v:=val['cent_difference']) is not None]\n",
|
||||||
|
" cent_diffs.sort()\n",
|
||||||
|
" return (cent_diffs[0] < 0) and (cent_diffs[1] == 0) and (cent_diffs[2] > 0)\n",
|
||||||
|
"\n",
|
||||||
|
" for e in edges:\n",
|
||||||
|
" yield 2 if is_contrary(e) else 1\n",
|
||||||
|
" \n",
|
||||||
|
" def is_directly_tunable_weights(edges):\n",
|
||||||
|
" for e in edges:\n",
|
||||||
|
" yield 10 if e[2]['is_directly_tunable'] else 0\n",
|
||||||
|
"\n",
|
||||||
|
" def transposition_weight(edges):\n",
|
||||||
|
" for e in edges:\n",
|
||||||
|
" yield 1000 if 0 <= hs_array_to_cents(e[2]['transposition']) < 100 else 0\n",
|
||||||
|
"\n",
|
||||||
|
" def is_sustained_voice(edges, voice):\n",
|
||||||
|
" \n",
|
||||||
|
" def is_sustained(edge):\n",
|
||||||
|
" source = list(edge[0])\n",
|
||||||
|
" ordered_source = sorted(source, key=hs_array_to_fr) \n",
|
||||||
|
" destination = [transpose_pitch(edge[2]['movements'][p]['destination'], edge[2]['transposition']) for p in source]\n",
|
||||||
|
" ordered_destination = sorted(destination, key=hs_array_to_fr)\n",
|
||||||
|
" return ordered_source[voice] == ordered_destination[voice]\n",
|
||||||
|
"\n",
|
||||||
|
" for e in edges:\n",
|
||||||
|
" yield 10 if is_sustained(e) else 0\n",
|
||||||
|
"\n",
|
||||||
|
" def voice_crossing_weights(edges):\n",
|
||||||
|
" \n",
|
||||||
|
" def has_voice_crossing(edge):\n",
|
||||||
|
" source = list(edge[0])\n",
|
||||||
|
" ordered_source = sorted(source, key=hs_array_to_fr) \n",
|
||||||
|
" source_order = [ordered_source.index(p) for p in source]\n",
|
||||||
|
" destination = [transpose_pitch(edge[2]['movements'][p]['destination'], edge[2]['transposition']) for p in source]\n",
|
||||||
|
" ordered_destination = sorted(destination, key=hs_array_to_fr)\n",
|
||||||
|
" destination_order = [ordered_destination.index(p) for p in destination]\n",
|
||||||
|
" return source_order != destination_order\n",
|
||||||
|
"\n",
|
||||||
|
" for e in edges:\n",
|
||||||
|
" yield 10 if not has_voice_crossing(e) else 0\n",
|
||||||
|
"\n",
|
||||||
|
" def is_bass_rooted(chord):\n",
|
||||||
|
" return max([sum(abs(p) for p in collapse_pitch(pitch_difference(chord[0], p))) for p in chord[1:]]) == 1\n",
|
||||||
|
" \n",
|
||||||
|
" check_graph = graph.copy()\n",
|
||||||
|
" #next_node = choice([node for node in graph.nodes() if is_bass_rooted(node)])\n",
|
||||||
|
" next_node = choice(list(graph.nodes()))\n",
|
||||||
|
" print(next_node)\n",
|
||||||
|
" check_graph.remove_node(next_node)\n",
|
||||||
|
" for node in graph.nodes(data=True):\n",
|
||||||
|
" node[1]['count'] = 1\n",
|
||||||
|
" path = []\n",
|
||||||
|
" while (nx.number_of_nodes(check_graph) > 0) and (len(path) < 500):\n",
|
||||||
|
" out_edges = list(graph.out_edges(next_node, data=True))\n",
|
||||||
|
" #print([l for l in zip(movement_size_weights(out_edges), hamiltonian_weights(out_edges))])\n",
|
||||||
|
" factors = [\n",
|
||||||
|
" movement_size_weights(out_edges), \n",
|
||||||
|
" hamiltonian_weights(out_edges), \n",
|
||||||
|
" #contrary_motion_weights(out_edges), \n",
|
||||||
|
" #is_directly_tunable_weights(out_edges),\n",
|
||||||
|
" voice_crossing_weights(out_edges),\n",
|
||||||
|
" #transposition_weight(out_edges)\n",
|
||||||
|
" #is_sustained_voice(out_edges, 0)\n",
|
||||||
|
" ]\n",
|
||||||
|
" weights = [prod(a) for a in zip(*factors)]\n",
|
||||||
|
" #print(weights)\n",
|
||||||
|
" edge = choices(out_edges, weights=weights)[0]\n",
|
||||||
|
" #print(edge)\n",
|
||||||
|
" #edge = random.choice(out_edges)\n",
|
||||||
|
" next_node = edge[1]\n",
|
||||||
|
" node[1]['count'] += 1\n",
|
||||||
|
" path.append(edge)\n",
|
||||||
|
" if next_node in check_graph.nodes:\n",
|
||||||
|
" check_graph.remove_node(next_node)\n",
|
||||||
|
" print(len(check_graph.nodes()))\n",
|
||||||
|
" return path\n",
|
||||||
|
" \n",
|
||||||
|
"path = stochastic_hamiltonian(graph)\n",
|
||||||
|
"#for edge in path:\n",
|
||||||
|
"# print(edge)\n",
|
||||||
|
"write_chord_sequence(path_to_chords(path, root))\n",
|
||||||
|
"len(path)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 212,
|
||||||
|
"id": "7b76d848-fe53-4b60-b414-46cfe570f78b",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"((4, 0, 0, 0, -1), (2, -1, 0, 0, 0), (0, 0, 0, 0, 0))\n",
|
||||||
|
"0\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"219"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 212,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"path = stochastic_hamiltonian(graph)\n",
|
||||||
|
"#for edge in path:\n",
|
||||||
|
"# print(edge)\n",
|
||||||
|
"write_chord_sequence(path_to_chords(path, root))\n",
|
||||||
|
"len(path)"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
# In[1]:
|
# In[89]:
|
||||||
|
|
||||||
|
|
||||||
from itertools import chain, combinations, permutations, product
|
from itertools import chain, combinations, permutations, product
|
||||||
|
|
@ -76,7 +76,7 @@ def chords(chord, root, min_chord_size, max_chord_size):
|
||||||
def edges(chords, min_symdiff, max_symdiff, max_chord_size):
|
def edges(chords, min_symdiff, max_symdiff, max_chord_size):
|
||||||
|
|
||||||
def reverse_movements(movements):
|
def reverse_movements(movements):
|
||||||
return {value['destination']:{'destination':key, 'cent_difference':value['cent_difference']} for key, value in movements.items()}
|
return {value['destination']:{'destination':key, 'cent_difference':value['cent_difference'] * -1} for key, value in movements.items()}
|
||||||
|
|
||||||
def is_directly_tunable(intersection, diff):
|
def is_directly_tunable(intersection, diff):
|
||||||
# this only works for now when intersection if one element - need to fix that
|
# this only works for now when intersection if one element - need to fix that
|
||||||
|
|
@ -161,7 +161,7 @@ def write_chord_sequence(path):
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
|
|
||||||
# In[2]:
|
# In[214]:
|
||||||
|
|
||||||
|
|
||||||
dims = (2, 3, 5, 7, 11)
|
dims = (2, 3, 5, 7, 11)
|
||||||
|
|
@ -171,11 +171,12 @@ chord_set = chords(chord, root, 3, 3)
|
||||||
graph = generate_graph(chord_set, 4, 4, 3)
|
graph = generate_graph(chord_set, 4, 4, 3)
|
||||||
|
|
||||||
|
|
||||||
# In[7]:
|
# In[215]:
|
||||||
|
|
||||||
|
|
||||||
from random import choice, choices
|
from random import choice, choices
|
||||||
|
|
||||||
|
# This is for the static version
|
||||||
def stochastic_hamiltonian(graph):
|
def stochastic_hamiltonian(graph):
|
||||||
|
|
||||||
def movement_size_weights(edges):
|
def movement_size_weights(edges):
|
||||||
|
|
@ -224,9 +225,11 @@ def stochastic_hamiltonian(graph):
|
||||||
for e in edges:
|
for e in edges:
|
||||||
yield 10 if not has_voice_crossing(e) else 0
|
yield 10 if not has_voice_crossing(e) else 0
|
||||||
|
|
||||||
|
def is_bass_rooted(chord):
|
||||||
|
return max([sum(abs(p) for p in collapse_pitch(pitch_difference(chord[0], p))) for p in chord[1:]]) == 1
|
||||||
|
|
||||||
check_graph = graph.copy()
|
check_graph = graph.copy()
|
||||||
#next_node = choice(list(graph.nodes()))
|
next_node = choice([node for node in graph.nodes() if is_bass_rooted(node)])
|
||||||
next_node = list(graph.nodes())[0]
|
|
||||||
check_graph.remove_node(next_node)
|
check_graph.remove_node(next_node)
|
||||||
for node in graph.nodes(data=True):
|
for node in graph.nodes(data=True):
|
||||||
node[1]['count'] = 1
|
node[1]['count'] = 1
|
||||||
|
|
@ -258,6 +261,15 @@ write_chord_sequence(path_to_chords(path, root))
|
||||||
len(path)
|
len(path)
|
||||||
|
|
||||||
|
|
||||||
|
# In[25]:
|
||||||
|
|
||||||
|
|
||||||
|
def is_super_compact(chord):
|
||||||
|
return max([sum(abs(p) for p in collapse_pitch(pitch_difference(c[0], c[1]))) for c in combinations(chord, 2)]) == 1
|
||||||
|
|
||||||
|
[node for node in graph.nodes() if is_super_compact(node)]
|
||||||
|
|
||||||
|
|
||||||
# In[11]:
|
# In[11]:
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -275,3 +287,136 @@ chord_set = chords(chord, root, 3, 3)
|
||||||
|
|
||||||
lprun -f edge_data edges(chord_set, 3, 3, 4)
|
lprun -f edge_data edges(chord_set, 3, 3, 4)
|
||||||
|
|
||||||
|
|
||||||
|
# In[180]:
|
||||||
|
|
||||||
|
|
||||||
|
dims = (2, 3, 5, 7, 11)
|
||||||
|
root = (0, 0, 0, 0, 0)
|
||||||
|
chord = (root,)
|
||||||
|
chord_set = chords(chord, root, 3, 3)
|
||||||
|
graph = generate_graph(chord_set, 2, 2, 3)
|
||||||
|
|
||||||
|
|
||||||
|
# In[213]:
|
||||||
|
|
||||||
|
|
||||||
|
from random import choice, choices
|
||||||
|
|
||||||
|
# This is for the rising version / yitgadal
|
||||||
|
def stochastic_hamiltonian(graph):
|
||||||
|
|
||||||
|
def movement_size_weights(edges):
|
||||||
|
|
||||||
|
def max_cent_diff(edge):
|
||||||
|
res = max([v for val in edge[2]['movements'].values() if (v:=val['cent_difference']) is not None])
|
||||||
|
return res
|
||||||
|
|
||||||
|
def min_cent_diff(edge):
|
||||||
|
res = [v for val in edge[2]['movements'].values() if (v:=val['cent_difference']) is not None]
|
||||||
|
res.remove(0)
|
||||||
|
return min(res)
|
||||||
|
|
||||||
|
for e in edges:
|
||||||
|
yield 1000 if ((max_cent_diff(e) < 175) and (min_cent_diff(e)) >= 0) else 1
|
||||||
|
|
||||||
|
def hamiltonian_weights(edges):
|
||||||
|
for e in edges:
|
||||||
|
yield 10 if e[1] not in [path_edge[0] for path_edge in path] else 1 / graph.nodes[e[1]]['count']
|
||||||
|
|
||||||
|
def contrary_motion_weights(edges):
|
||||||
|
|
||||||
|
def is_contrary(edge):
|
||||||
|
cent_diffs = [v for val in edge[2]['movements'].values() if (v:=val['cent_difference']) is not None]
|
||||||
|
cent_diffs.sort()
|
||||||
|
return (cent_diffs[0] < 0) and (cent_diffs[1] == 0) and (cent_diffs[2] > 0)
|
||||||
|
|
||||||
|
for e in edges:
|
||||||
|
yield 2 if is_contrary(e) else 1
|
||||||
|
|
||||||
|
def is_directly_tunable_weights(edges):
|
||||||
|
for e in edges:
|
||||||
|
yield 10 if e[2]['is_directly_tunable'] else 0
|
||||||
|
|
||||||
|
def transposition_weight(edges):
|
||||||
|
for e in edges:
|
||||||
|
yield 1000 if 0 <= hs_array_to_cents(e[2]['transposition']) < 100 else 0
|
||||||
|
|
||||||
|
def is_sustained_voice(edges, voice):
|
||||||
|
|
||||||
|
def is_sustained(edge):
|
||||||
|
source = list(edge[0])
|
||||||
|
ordered_source = sorted(source, key=hs_array_to_fr)
|
||||||
|
destination = [transpose_pitch(edge[2]['movements'][p]['destination'], edge[2]['transposition']) for p in source]
|
||||||
|
ordered_destination = sorted(destination, key=hs_array_to_fr)
|
||||||
|
return ordered_source[voice] == ordered_destination[voice]
|
||||||
|
|
||||||
|
for e in edges:
|
||||||
|
yield 10 if is_sustained(e) else 0
|
||||||
|
|
||||||
|
def voice_crossing_weights(edges):
|
||||||
|
|
||||||
|
def has_voice_crossing(edge):
|
||||||
|
source = list(edge[0])
|
||||||
|
ordered_source = sorted(source, key=hs_array_to_fr)
|
||||||
|
source_order = [ordered_source.index(p) for p in source]
|
||||||
|
destination = [transpose_pitch(edge[2]['movements'][p]['destination'], edge[2]['transposition']) for p in source]
|
||||||
|
ordered_destination = sorted(destination, key=hs_array_to_fr)
|
||||||
|
destination_order = [ordered_destination.index(p) for p in destination]
|
||||||
|
return source_order != destination_order
|
||||||
|
|
||||||
|
for e in edges:
|
||||||
|
yield 10 if not has_voice_crossing(e) else 0
|
||||||
|
|
||||||
|
def is_bass_rooted(chord):
|
||||||
|
return max([sum(abs(p) for p in collapse_pitch(pitch_difference(chord[0], p))) for p in chord[1:]]) == 1
|
||||||
|
|
||||||
|
check_graph = graph.copy()
|
||||||
|
#next_node = choice([node for node in graph.nodes() if is_bass_rooted(node)])
|
||||||
|
next_node = choice(list(graph.nodes()))
|
||||||
|
print(next_node)
|
||||||
|
check_graph.remove_node(next_node)
|
||||||
|
for node in graph.nodes(data=True):
|
||||||
|
node[1]['count'] = 1
|
||||||
|
path = []
|
||||||
|
while (nx.number_of_nodes(check_graph) > 0) and (len(path) < 500):
|
||||||
|
out_edges = list(graph.out_edges(next_node, data=True))
|
||||||
|
#print([l for l in zip(movement_size_weights(out_edges), hamiltonian_weights(out_edges))])
|
||||||
|
factors = [
|
||||||
|
movement_size_weights(out_edges),
|
||||||
|
hamiltonian_weights(out_edges),
|
||||||
|
#contrary_motion_weights(out_edges),
|
||||||
|
#is_directly_tunable_weights(out_edges),
|
||||||
|
voice_crossing_weights(out_edges),
|
||||||
|
#transposition_weight(out_edges)
|
||||||
|
#is_sustained_voice(out_edges, 0)
|
||||||
|
]
|
||||||
|
weights = [prod(a) for a in zip(*factors)]
|
||||||
|
#print(weights)
|
||||||
|
edge = choices(out_edges, weights=weights)[0]
|
||||||
|
#print(edge)
|
||||||
|
#edge = random.choice(out_edges)
|
||||||
|
next_node = edge[1]
|
||||||
|
node[1]['count'] += 1
|
||||||
|
path.append(edge)
|
||||||
|
if next_node in check_graph.nodes:
|
||||||
|
check_graph.remove_node(next_node)
|
||||||
|
print(len(check_graph.nodes()))
|
||||||
|
return path
|
||||||
|
|
||||||
|
path = stochastic_hamiltonian(graph)
|
||||||
|
#for edge in path:
|
||||||
|
# print(edge)
|
||||||
|
write_chord_sequence(path_to_chords(path, root))
|
||||||
|
len(path)
|
||||||
|
|
||||||
|
|
||||||
|
# In[212]:
|
||||||
|
|
||||||
|
|
||||||
|
path = stochastic_hamiltonian(graph)
|
||||||
|
#for edge in path:
|
||||||
|
# print(edge)
|
||||||
|
write_chord_sequence(path_to_chords(path, root))
|
||||||
|
len(path)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ SynthDef(\string_model, {arg freq, gate = 1, del, sustain, amp, dur, attack, rel
|
||||||
sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq),
|
sig1 = (Klank.ar(`[ Array.series(noHarms, freq, freq),
|
||||||
Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}),
|
Array.geom(noHarms, 1, 0.2) + Array.fill(noHarms, {rrand(0.01, 0.03)}),
|
||||||
Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip;
|
Array.fill(noHarms, {rrand(1, 2)}) ], exc) * 0.8).softclip;
|
||||||
|
//note that the delay cuts into the sustain portion of the tone!!!
|
||||||
Out.ar([0, 1], 0.75 * sig1 * amp * EnvGen.kr(Env.dadsr(del, attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2));
|
Out.ar([0, 1], 0.75 * sig1 * amp * EnvGen.kr(Env.dadsr(del, attack, 0.3, 0.9, release, 0.9, -3), gate, doneAction: 2));
|
||||||
}).add;
|
}).add;
|
||||||
)
|
)
|
||||||
|
|
@ -13,7 +14,7 @@ SynthDef(\string_model, {arg freq, gate = 1, del, sustain, amp, dur, attack, rel
|
||||||
(
|
(
|
||||||
var primes, hsArrayToFreq, hsArrayDimDiff, file, seq, phraseLengths, musicData, patterns;
|
var primes, hsArrayToFreq, hsArrayDimDiff, file, seq, phraseLengths, musicData, patterns;
|
||||||
|
|
||||||
thisThread.randSeed = 1923;
|
thisThread.randSeed = 83924874938;
|
||||||
|
|
||||||
primes = [2, 3, 5, 7, 11];
|
primes = [2, 3, 5, 7, 11];
|
||||||
|
|
||||||
|
|
@ -35,14 +36,25 @@ seq = file.readAllString.interpret;
|
||||||
//seq = seq.collect({arg item; item.sort});
|
//seq = seq.collect({arg item; item.sort});
|
||||||
seq = seq.collect({arg chord, index;
|
seq = seq.collect({arg chord, index;
|
||||||
var ref_ins;
|
var ref_ins;
|
||||||
ref_ins = if(index == 0, {0}, {[seq[index - 1], chord].flop.collect({arg pair; pair[0] == pair[1]}).indexOf(true)});
|
ref_ins = if(index == 0, {
|
||||||
|
[0] // this should actually check which is the 'centered' pitch
|
||||||
|
}, {
|
||||||
|
[seq[index - 1], chord].postln.flop.collect({arg pair, p; if(pair[0] == pair[1], {p}, {-1})}).postln.removeEvery([-1])
|
||||||
|
});
|
||||||
chord.collect({arg pitch;
|
chord.collect({arg pitch;
|
||||||
var dimDiff;
|
var dimDiff;
|
||||||
[pitch, [ref_ins, hsArrayDimDiff.value(chord[ref_ins], pitch)]]
|
ref_ins.postln;
|
||||||
|
if(ref_ins.size == 1, {
|
||||||
|
[pitch, [ref_ins[0], hsArrayDimDiff.value(chord[ref_ins[0]], pitch)]]
|
||||||
|
}, {
|
||||||
|
var min_ref_ins;
|
||||||
|
min_ref_ins = ref_ins.minItem({arg ins; (chord[ins].drop(1) - pitch.drop(1)).abs.sum});
|
||||||
|
[pitch, [min_ref_ins.postln, hsArrayDimDiff.value(chord[min_ref_ins], pitch)]]
|
||||||
|
});
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
seq.do({arg chord; chord; chord.collect({arg pitch; hsArrayToFreq.value(pitch[0])})});
|
seq.do({arg chord; chord; chord.collect({arg pitch; hsArrayToFreq.value(pitch[0])}).postln});
|
||||||
//seq.postln;
|
//seq.postln;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -51,28 +63,33 @@ while({phraseLengths.sum < seq.size}, {phraseLengths = phraseLengths ++ [rrand(1
|
||||||
//phraseLengths.postln;
|
//phraseLengths.postln;
|
||||||
|
|
||||||
musicData = seq.clumps(phraseLengths).collect({arg subSeq, seqIndex;
|
musicData = seq.clumps(phraseLengths).collect({arg subSeq, seqIndex;
|
||||||
var baseRound, baseDurs, baseDelay, baseSubtract;
|
var baseRound, baseDurs, minDelay, maxDelay, baseSubtract;
|
||||||
baseRound = 0.5;
|
baseRound = 0.5;
|
||||||
//baseDurs = subSeq.size.collect({arg subSeqIndex; if(subSeqIndex != (subSeq.size - 1), {rrand(7.0, 10.0)}, {rrand(10.0, 15.0)})}).round(baseRound);
|
|
||||||
baseDurs = subSeq.size.collect({arg subSeqIndex; if(subSeqIndex != (subSeq.size - 1), {rrand(5.0, 7.0)}, {rrand(10.0, 15.0)})}).round(baseRound);
|
baseDurs = subSeq.size.collect({arg subSeqIndex; if(subSeqIndex != (subSeq.size - 1), {rrand(5.0, 7.0)}, {rrand(10.0, 15.0)})}).round(baseRound);
|
||||||
baseDelay = rrand(1.0, 2.0);
|
//baseDurs = subSeq.size.collect({arg subSeqIndex; if(subSeqIndex != (subSeq.size - 1), {rrand(5.0, 7.0)}, {rrand(15.0, 20.0)})}).round(baseRound);
|
||||||
baseSubtract = rrand(2.0, 4.0);
|
//maxDelay = rrand(1.0, 3.0);
|
||||||
|
//maxDelay = 5;
|
||||||
|
minDelay = 0;
|
||||||
|
maxDelay = 0;
|
||||||
|
baseDurs[0] = baseDurs[0] + maxDelay;
|
||||||
|
baseSubtract = rrand(0.0, 3.0);
|
||||||
subSeq.flop.collect({arg voice, v;
|
subSeq.flop.collect({arg voice, v;
|
||||||
var phrases, freqs, durs, delays, attacks, rels, sustains, amps, refs;
|
var phrases, freqs, durs, delays, attacks, rels, sustains, amps, refs;
|
||||||
phrases = voice.separate({arg a, b; a[0] != b[0]});
|
phrases = voice.separate({arg a, b; a[0] != b[0]});
|
||||||
freqs = phrases.collect({arg phrase; if(phrase[0][0] != ["Rest"], {48.midicps * pow(2, (v * 2).clip(0, 1)) * hsArrayToFreq.value(phrase[0][0])}, {Rest(0)})});
|
freqs = phrases.collect({arg phrase; if(phrase[0][0] != ["Rest"], {45.midicps * pow(2, (v * 2).clip(0, 1)) * hsArrayToFreq.value(phrase[0][0])}, {Rest(0)})});
|
||||||
refs = phrases.collect({arg phrase; if(phrase[0][0] != ["Rest"], {phrase[0][1]}, {Rest(0)})});
|
refs = phrases.collect({arg phrase; if(phrase[0][0] != ["Rest"], {phrase[0][1]}, {Rest(0)})});
|
||||||
durs = baseDurs.clumps(phrases.collect({arg phrase; phrase.size})).collect({arg c; c.sum});
|
durs = baseDurs.clumps(phrases.collect({arg phrase; phrase.size})).collect({arg c; c.sum});
|
||||||
delays = durs.collect({arg dur; rrand(0.0, 0.0)}).round(baseRound);
|
delays = durs.collect({arg dur, d; if((d == 0) && (refs[d][0] != v), {[rrand(minDelay, maxDelay), 0].wchoose([1, 1].normalizeSum)}, {0})}).round(baseRound);
|
||||||
//delays = durs.collect({arg dur, d; if((d == 0) && (refs[d][0] != v), {[baseDelay, rrand(2.0, 3.0)].wchoose([2, 1].normalizeSum)}, {0})}).round(baseRound);
|
//delays = durs.collect({0}}).round(baseRound);
|
||||||
//delays = durs.collect({arg dur, d; if((d == 0) && (refs[d][0] != v), {baseDelay}, {0})}).round(baseRound);
|
|
||||||
//durs = durs + delays;
|
|
||||||
attacks = durs.collect({arg dur, d; if(d == 0, {rrand(3.0, 5.0)}, {rrand(1.0, 3.0)})}).round(baseRound);
|
attacks = durs.collect({arg dur, d; if(d == 0, {rrand(3.0, 5.0)}, {rrand(1.0, 3.0)})}).round(baseRound);
|
||||||
rels = durs.collect({arg dur, d; if(d != (durs.size - 1), {rrand(1.0, 2.0)}, {rrand(3.0, 5.0)})}).round(baseRound);
|
rels = durs.collect({arg dur, d; if(d != (durs.size - 1), {rrand(0.5, 1.0)}, {rrand(3.0, 5.0)})}).round(baseRound);
|
||||||
//sustains = durs.collect({arg dur, d; if(d != (durs.size - 1), {dur - rels[d] - delays[d]}, {dur - rels[d] - delays[d]})}).round(baseRound);
|
sustains = durs.collect({arg dur, d;
|
||||||
//sustains = durs.collect({arg dur, d; if(d != (durs.size - 1), {dur}, {dur - rrand(3.0, 5.0)})}).round(baseRound);
|
if(d != (durs.size - 1), {
|
||||||
sustains = durs.collect({arg dur, d; if(d != (durs.size - 1), {dur - rels[d] - delays[d] - 0.5}, {dur - rels[d] - delays[d] - baseSubtract - rrand(0.0, 2.0)})}).round(baseRound);
|
dur - rels[d]
|
||||||
amps = freqs.collect({rrand(0.6, 0.7) / [1, 2, 2][v]});
|
}, {
|
||||||
|
dur - rels[d] - baseSubtract - rrand(0.0, 1.0)})
|
||||||
|
}).round(baseRound);
|
||||||
|
amps = freqs.collect({rrand(0.6, 0.7) / [1, 2, 2, 2][v]});
|
||||||
[freqs, durs, attacks, delays, sustains, rels, amps, refs].flop;
|
[freqs, durs, attacks, delays, sustains, rels, amps, refs].flop;
|
||||||
});
|
});
|
||||||
}).flop.collect({arg voice; voice.flatten});
|
}).flop.collect({arg voice; voice.flatten});
|
||||||
|
|
@ -80,7 +97,7 @@ musicData = seq.clumps(phraseLengths).collect({arg subSeq, seqIndex;
|
||||||
musicData = musicData.collect({arg voice, v;
|
musicData = musicData.collect({arg voice, v;
|
||||||
var clumps;
|
var clumps;
|
||||||
//(v + "~~~~~~~~~~").postln;
|
//(v + "~~~~~~~~~~").postln;
|
||||||
clumps = voice.separate({arg a, b; [true, a[0] != b[0]].wchoose([1, 1].normalizeSum)});
|
clumps = voice.separate({arg a, b; [true, a[0] != b[0]].wchoose([1, 2].normalizeSum)});
|
||||||
clumps = clumps.collect({arg clump;
|
clumps = clumps.collect({arg clump;
|
||||||
if(clump.size == 1, {clump[0]}, {
|
if(clump.size == 1, {clump[0]}, {
|
||||||
var mergedClump;
|
var mergedClump;
|
||||||
|
|
@ -99,6 +116,7 @@ musicData = musicData.collect({arg voice, v;
|
||||||
musicData.collect({arg voice, v;
|
musicData.collect({arg voice, v;
|
||||||
var freqs, durs, attacks, delays, sustains, rels, amps;
|
var freqs, durs, attacks, delays, sustains, rels, amps;
|
||||||
# freqs, durs, attacks, delays, sustains, rels, amps = voice.flop;
|
# freqs, durs, attacks, delays, sustains, rels, amps = voice.flop;
|
||||||
|
//# durs, attacks, delays, sustains, rels = [durs, attacks, delays, sustains, rels].collect({arg data; data / 16});
|
||||||
Pbind(
|
Pbind(
|
||||||
\instrument, \string_model,
|
\instrument, \string_model,
|
||||||
\freq, Pseq(freqs, 1),
|
\freq, Pseq(freqs, 1),
|
||||||
|
|
@ -116,4 +134,4 @@ musicData = musicData.collect({arg voice, v;
|
||||||
~patterns.play
|
~patterns.play
|
||||||
)
|
)
|
||||||
|
|
||||||
~patterns.play
|
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,13 @@ formatMusicData = {arg seq;
|
||||||
var freqs, durs, attacks, delays, sustains, rels, amps, refs, res;
|
var freqs, durs, attacks, delays, sustains, rels, amps, refs, res;
|
||||||
# freqs, durs, attacks, delays, sustains, rels, amps, refs = partData.flop;
|
# freqs, durs, attacks, delays, sustains, rels, amps, refs = partData.flop;
|
||||||
durs = (durs / 0.5).round.asInteger;
|
durs = (durs / 0.5).round.asInteger;
|
||||||
sustains = ((sustains + delays + rels) / 0.5).round.asInteger;
|
sustains = ((sustains + rels - 0.5) / 0.5).round.asInteger;
|
||||||
//sustains = (sustains / 0.5).round.asInteger;
|
delays = (delays / 0.5).round.asInteger;
|
||||||
//[durs, sustains, delays, rels].flop.do({arg item; if(item[0] < item[1], {item.postln})});
|
res = [freqs, durs, delays, sustains, refs].flop.collect({arg data, i;
|
||||||
res = [freqs, durs, sustains, refs].flop.collect({arg data, i;
|
var freq, dur, del, sus, ref;
|
||||||
var freq, dur, sus, ref;
|
# freq, dur, del, sus, ref = data;
|
||||||
# freq, dur, sus, ref = data;
|
del.collect({[-1, ref, i]}) ++ (sus - del).collect({[freq, ref, i]}) ++ (dur - sus).collect({[-1, ref, i]})
|
||||||
sus.collect({[freq, ref, i]}) ++ (dur - sus).collect({[-1, ref, i]})
|
//sus.collect({[freq, ref, i]}) ++ (dur - sus).collect({[-1, ref, i]})
|
||||||
}).flatten;
|
}).flatten;
|
||||||
if(res.size > maxSize, {maxSize = res.size});
|
if(res.size > maxSize, {maxSize = res.size});
|
||||||
res
|
res
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue