songleash

generate chansons en laisse
git clone https://a3nm.net/git/songleash/
Log | Files | Refs

commit 1af10c4da687379d5ea75882afeac0bde963c081
parent 322ee37350f05fcd7edda86a31ad555ddd64dbfd
Author: Antoine Amarilli <a3nm@a3nm.net>
Date:   Thu, 27 Aug 2015 02:23:15 +0200

continue

Diffstat:
.gitignore | 7+++++++
3chats.mid | 0
3chats.txt | 24++++++++++++++++++++++++
arrange.py | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
graph2.py | 35++++++++++++++++++++---------------
infersplit.py | 30++++++++++++++++++++++++++++++
print.sh | 15+++++++++++++++
printcycle.py | 52+++++++++++++---------------------------------------
script.sh | 7+++++--
sing.sh | 6++++++
10 files changed, 175 insertions(+), 56 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -6,3 +6,10 @@ lexique.txt lexique3 lexique_full raw_graph +test.raw +test.ogg +song.xml +3chatsrep.txt +lyrics +song +output diff --git a/3chats.mid b/3chats.mid Binary files differ. diff --git a/3chats.txt b/3chats.txt @@ -0,0 +1,24 @@ +0.625 C6 +0.625 D6 +1.25 Ds6 +0.625 D6 +0.625 Ds6 +1.25 C6 +0.625 Ds6 +0.625 F6 +1.25 G6 +1.25 G6 +1.25 G6 +0.625 G6 +0.625 Gs6 +0.625 G6 +0.625 F6 +0.625 F6 +0.625 G6 +0.625 F6 +0.625 Ds6 +0.625 Ds6 +0.625 F6 +1.25 Ds6 +1.25 D6 +1.25 C6 diff --git a/arrange.py b/arrange.py @@ -0,0 +1,55 @@ +#!/usr/bin/python + +import sys + +notes = open(sys.argv[1], "r") +bpm = sys.argv[2] + +def transp(n): + if n[-1] == "4": + n = n[:-1] + "3" + if n[-1] == "5": + n = n[:-1] + "4" + if n[-1] == "6": + n = n[:-1] + "5" + if n[-1] == "7": + n = n[:-1] + "6" + return n + +print """<?xml version="1.0"?> +<!DOCTYPE SINGING PUBLIC "-//SINGING//DTD SINGING mark up//EN" + "Singing.v0_1.dtd" +[]>""" +print '<SINGING BPM="%s">' % bpm + +while True: + note = notes.readline() + note = note.strip().split(" ") + try: + if note[1][0] == "S": + print ("<REST BEATS=\"%s\"></REST>" % note[0]) + continue + except Exception: + break + l = sys.stdin.readline() + if not l: + break + l = l.strip() + nh = len(l.split("-")) + l = "".join(l.split("-")) + n1 = [note[0]] + n2 = [transp(note[1])] + for i in range(nh-1): + note = notes.readline() + note = note.strip().split(" ") + n1.append(note[0]) + n2.append(transp(note[1])) + notes1 = ",".join(n1) + notes2 = ",".join(n2) + print ("<DURATION BEATS=\"%s\"><PITCH NOTE=\"%s\">" + "%s</PITCH></DURATION>" % (notes1, notes2, l)) + + +notes.close() + +print "</SINGING>" diff --git a/graph2.py b/graph2.py @@ -4,7 +4,7 @@ import sys from common import vowels, semivowels, fem, start from collections import defaultdict -g = defaultdict(lambda: defaultdict(lambda: set())) +g = defaultdict(lambda: defaultdict(lambda: [])) def explore(graph, fr): seen = set() @@ -41,21 +41,25 @@ for l in sys.stdin.readlines(): # we are between first vowel included and second vowel excluded fr = (not fems, allp[:i+1]) to = (fems, p[-1]) + if allp.startswith(to[1]): + # loop (e.g., trinitrine), not very pretty + continue #if (w.startswith('mandib')): #print(w, fr, to) - todel = set() - toadd = True - for (ww, syl) in g[fr][to]: - if ww.startswith(w) and w != ww: - # we will kill something longer - todel.add(ww) - elif w.startswith(ww): - # we already have something shorter - toadd = False - break - g[fr][to] -= todel - if toadd: - g[fr][to].add((w, syl)) + g[fr][to].append((w, syl)) +# todel = set() +# toadd = True +# for (ww, syl) in g[fr][to]: +# if ww.startswith(w) and w != ww: +# # we will kill something longer +# todel.add(ww) +# elif w.startswith(ww): +# # we already have something shorter +# toadd = False +# break +# g[fr][to] -= todel +# if toadd: +# g[fr][to].add((w, syl)) # compute reverse graph rg = defaultdict(lambda: defaultdict(lambda: set())) @@ -75,7 +79,8 @@ for f in g.keys(): #print ("HOHOHO", t, start, f in useful, t in useful) if f not in useful or t not in useful: continue - for w in g[f][t]: + # only print the most frequent word, for now + for w in g[f][t][:1]: print ("%s\t%s\t%s\t%s\t%s\t%s" % ('f' if f[0] else 'm', f[1], 'f' if t[0] else 'm', t[1], w[0], w[1])) diff --git a/infersplit.py b/infersplit.py @@ -0,0 +1,30 @@ +# OLD CODE + +def print_word(w, prn): + s = "" + vowels = False + for i in range(len(w)): + p = -(i+1) + s += w[p] + x = strip_accents(w[p])[0] + if not vowels: + if x in vowels_script and (i > 0 or w[-1] != 'e') and (i > 1 or w[-1] != + 's' or w[-2] != 'e') and (i > 2 or (not w.endswith('gue')) + and + not (w.endswith('que'))) and (i > 3 or (not + w.endswith('gues') and (not w.endswith('ques')))): + vowels = True + else: + if x not in vowels_script and x != '-': + if prn[0] in semivowels: + s = s[:-1] + break + # exception + if w[p] == 'h': + s += w[-(i+2)] + break + s = s[::-1] + print ("## %s, %s, %s, %s, %s" % (w, w, w, s, s)) + +print_word(w[0], l[i+1][1]) + diff --git a/print.sh b/print.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +./printcycle.py output 0 < graph > song +./printcycle.py output 1 < graph | tr -d ',' | sed '$d' > lyrics + +N=$(wc -l < lyrics) +echo > 3chatsrep.txt +for i in `seq $(($N/2))` +do + cat 3chats.txt >> 3chatsrep.txt +done +cat lyrics | tr ' ' '\n' | grep -v '^ *$' | + ./arrange.py <(grep -v '^$' 3chatsrep.txt) 120 | + sed 's/Fs/Gb/g;s/As\([1-9]\)/Bb\1/g;s/Cs/Db/g;s/Ds/Eb/g' | + sed 's/"Gs/"Ab/' > song.xml diff --git a/printcycle.py b/printcycle.py @@ -8,32 +8,6 @@ g = defaultdict(lambda: {}) visited = set() -def print_word(w, prn): - s = "" - vowels = False - for i in range(len(w)): - p = -(i+1) - s += w[p] - x = strip_accents(w[p])[0] - if not vowels: - if x in vowels_script and (i > 0 or w[-1] != 'e') and (i > 1 or w[-1] != - 's' or w[-2] != 'e') and (i > 2 or (not w.endswith('gue')) - and - not (w.endswith('que'))) and (i > 3 or (not - w.endswith('gues') and (not w.endswith('ques')))): - vowels = True - else: - if x not in vowels_script and x != '-': - if prn[0] in semivowels: - s = s[:-1] - break - # exception - if w[p] == 'h': - s += w[-(i+2)] - break - s = s[::-1] - print ("## %s, %s, %s, %s, %s" % (w, w, w, s, s)) - def print_list(l): global out if not start[0]: @@ -43,23 +17,23 @@ def print_list(l): w = g[l[i]][l[i+1]] #print(w[0]) fs = w[1].split('-') - if len(w[1]) == 0 or len(fs) < 3: - print_word(w[0], l[i+1][1]) + # remove spaces in syll for singing + for i in range(len(fs)): + fs[i] = ''.join(fs[i].split(' ')) + end = ''.join(fs[2:]) + ssep = ' ' if songmode else '' + spl = ssep.join(fs) + if w[0]: + spl2 = fs[0] + ssep + fs[1] + ssep + ''.join(fs[2:]) else: - # remove spaces in syll for singing - for i in range(len(fs)): - fs[i] = ''.join(fs[i].split(' ')) - end = ''.join(fs[2:]) - spl = ' '.join(fs) - if w[0]: - spl2 = fs[0] + ' ' + fs[1] + ' ' + ''.join(fs[2:]) - else: - spl2 = spl - print (" %s, %s, %s, %s, %s" - % (spl, spl, spl2, end, end)) + spl2 = spl + sep = '' if songmode else ',' + print ("%s%s %s%s %s%s %s%s %s" + % (spl, sep, spl, sep, spl2, sep, end, sep, end)) fname = sys.argv[1] f = open(fname) +songmode = sys.argv[2] == '1' for l in sys.stdin.readlines(): l = l.strip().split('\t') diff --git a/script.sh b/script.sh @@ -5,10 +5,13 @@ #cat Lexique371/Bases+Scripts/Lexique3.txt | # ./lexique_fix.sh| cut -f1,2,4 | grep NOM | uniq > lexique.txt -cat ~/documents/lexique/lexique | cut -f1,2,4,23,24,28 | grep NOM | grep '\s3\s' | cut -f1,4,6 | rev | uniq -f 2 | rev > lexique_full +cat - | sort -k 14,14n -k8,8nr | + grep -vi "zanimaux" | + cut -f1,2,4,23,24,28 | grep NOM | + grep '\s3\s' | cut -f1,4,6 | awk '!a[$1]++' > lexique_full pv lexique_full | ./only3.py > lexique3 cat lexique3 | ./graph2.py > graph -cat graph | ./cycle.py +cat graph | ./cycle.py output # cat <(echo "digraph G {") <(sed 's/\([^ ]*\) \([^ ]*\) \(.*\)/\1 -> \2 # [label="\3"]/g' graph) <(echo "}") | sed 's/#/_/g;s/8/W/g;s/\$/Y/g;s/)/X/g' > diff --git a/sing.sh b/sing.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +echo "(tts \"song.xml\" 'singing)" | festival +# while playing, do cp /tmp/audio* test.raw +# then convert with audacity +