Last active
June 17, 2018 15:22
-
-
Save fergusq/16d9805e4f24aef492c74aef53685528 to your computer and use it in GitHub Desktop.
Radio Gem song generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Radio Gem</title> | |
<meta name="description" content="Tekoälyn toimittama radiokanava." /> | |
<meta content="width=device-width, initial-scale=1,maximum-scale=1, user-scalable=no" name="viewport"> | |
<style> | |
html { | |
box-sizing: border-box; | |
} | |
*, *:before, *:after { | |
box-sizing: inherit; | |
} | |
h1 { | |
text-align: center; | |
border-top: 1px solid darkblue; | |
border-bottom: 1px solid darkblue; | |
background-color: #6A6FFA; | |
} | |
body { | |
background-color: lightblue; | |
margin: 0; | |
} | |
.player { | |
text-align: center; | |
font-size: large; | |
} | |
.card { | |
padding: 1em; | |
max-width: 26rem; | |
margin-top: 1rem; | |
margin-left: auto; | |
margin-right: auto; | |
background-color: white; | |
box-shadow: 0px 1px 2px; | |
} | |
.card h2 { | |
margin-top: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Radio Gem</h1> | |
<div class="player"> | |
<audio xmlns="http://www.w3.org/1999/xhtml" controls="controls" preload="none"> | |
<source src="http://kaivos.org:8000/gem.ogg" type="application/ogg"/> | |
</audio> | |
<div id="current_song"></div> | |
</div> | |
<div class="card"> | |
<h2>Mikä on Radio Gem?</h2> | |
<p> | |
Radio Gem on tietokoneen luoma radiokanava, jonka kaikki sisältö on generoitua. | |
Tekoäly on siis säveltänyt musiikit ja keksinyt uutiset. | |
Koska kaikki sisältö on satunnaista ja tuhotaan heti soittamisen jälkeen, | |
kaikki kappaleet ovat olemassa vain pienen hetken. | |
Jokainen hetki Radio Gemin seurassa on siis ainutlaatuinen. | |
</p> | |
<p>Tällä hetkellä Gem perustuu seuraaviin ohjelmiin:</p> | |
<ul> | |
<li><em>Pyco</em>, säveltävä ohjelma. | |
Tekijät <strong>Iikka Hauhio</strong> ja <strong>Lassi Kaimio</strong>.</li> | |
<li><em>Folklaine</em>, säveltävä ohjelma. | |
Tekijä <strong>Pauli Laine</strong>.</li> | |
<li><em>Ylekov</em>, uutisgeneraattori. | |
Tekijä <strong>Mikko Tampio</strong>.</li> | |
</ul> | |
</div> | |
<div class="card"> | |
Jos Radio Gem ei toimi, otathan yhteyttä ylläpitäjä Iikka Hauhioon. | |
</div> | |
<script src="//cdn.jsdelivr.net/jquery/1.9.1/jquery-1.9.1.min.js"></script> | |
<script> | |
"use strict"; | |
$(document).ready(function(){ | |
setInterval(function() { | |
$.ajax({ | |
url: "http://kaivos.org:8000/status-json.xsl", | |
dataType: "json" | |
}).done(function( json ) { | |
$( "#current_song" ).html(json.icestats.source.artist + " - " + json.icestats.source.title); | |
}); | |
}, 5000); | |
}); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env röda | |
{ | |
fileutil := require("fileutil") | |
mv := fileutil.mv | |
rm := fileutil.rm | |
cp := fileutil.cp | |
logExec := fileutil.logExec | |
} | |
rndn a, b { | |
return a+abs(randomInteger()%((b-a)+1)) | |
} | |
function renderOgg midifile, oggfile, artist, songname, wild=FALSE { | |
if [ wild ] do | |
logExec("wildmidi", "-o", midifile..".wav", midifile) | |
else | |
logExec("gst-launch-1.0", | |
"filesrc", "location="..midifile, | |
"!", "decodebin", "!", "audioconvert", "!", "wavenc", | |
"!", "filesink", "location="..midifile..".wav") | |
done | |
logExec("espeak", "-v", "fi", "-s", "130", "-w", "outro.wav", | |
`Se oli $artist-yhtyeen tuore single $songname. Minä olen Espeak ja tämä on Radio Gem.`) | |
logExec("sox", midifile..".wav", "-b", "16", "music.wav", "channels", "1", "rate", "44100") | |
logExec("sox", "outro.wav", "-b", "16", "speak.wav", "channels", "1", "rate", "44100") | |
logExec("sox", "music.wav", "speak.wav", "song.wav") | |
logExec("oggenc", "--utf8", | |
"-q", "4", | |
"-a", artist, "-t", songname, | |
"-o", oggfile, "song.wav") | |
rm midifile..".wav" | |
rm "music.wav" | |
rm "outro.wav" | |
rm "speak.wav" | |
rm "song.wav" | |
} | |
function generateFolklaine songname, filename { | |
logExec "python", "../../3party/folklaine/folklaine.py" | |
renderOgg "folk0.mid", filename, "Folklaine", songname | |
rm "folk0.mid" | |
} | |
function generatePyco songname, filename { | |
randomize songname | |
type := rndn(1,3) | |
scriptfile := filename..".txt" | |
{ | |
print "seed = ", songname | |
print "tempo = ", rndn(40, 220) | |
print "strings\\nonZeroIntervals = 10000" if [ type = 3 ] | |
verses := [] | |
seq(0, rndn(1,3)) | for i do | |
verse := chr(ord("A")+i) | |
letters := [] | |
seq(0, rndn(1,6)) | for j do | |
letters += chr(ord("a")+rndn(0,5))..(push(".") if randomBoolean else push("")) | |
done | |
if [ type = 3 ] do | |
print "*", verse, " = ", letters&" ", " (strings)" | |
else | |
print verse, " = ", letters&" " | |
done | |
verses += verse | |
done | |
struct := [] | |
seq(0, rndn(6,13)) | for _ do | |
struct += verses[rndn(0,#verses-1)] | |
done | |
print struct&" " | |
} | writeStrings scriptfile | |
if [ type = 1 ] do | |
logExec "python3", "../../Python/Sävellys/satunnainen_script.py", "--out", "pyco", scriptfile | |
else | |
instrument := push("--random-instruments") if [ type = 2 ] else push("--strings") | |
logExec "python3", "../../Python/Sävellys/satunnainen_script.py", instrument, "--out", "pyco", scriptfile | |
done | |
renderOgg "sats-pyco.mid", filename, "Pyco", songname | |
rm "sats-pyco.mid" | |
} | |
oneOf s...{[s[rndn(0,#s-1)]]} | |
function generateName { | |
adj := oneOf(*[readLines("words/adjs.txt")]) | |
noun := oneOf(*[readLines("words/nouns.txt")]) | |
song := chr(ord(adj[0:1])-32)..adj[1:].." "..noun | |
return song, adj.."_"..noun | |
} | |
function getnews { | |
return [{}()|bufferedExec("java", "-jar", "ylekov.jar", "generate")][0] | |
} | |
function gettitle { | |
if fileExists("news/news.ogg") do | |
title := [{}()|bufferedExec("vorbiscomment", "-l", "news/news.ogg")][0] | |
return parseInteger(match("(?i)title=(.+)", title)[1]) | |
done | |
return 0 | |
} | |
function generateNews songname, filename { | |
news := getnews() | |
num = gettitle() | |
if [ num > 1000 ] do | |
logExec("java", "-jar", "ylekov.jar", "update") | |
num = 0 | |
done | |
logExec("espeak", "-v", "fi", "-s", "130", "-w", "news.wav", "Sitten seuraa uutinen. "..news) | |
logExec("oggenc", "-q", "4,", "-a", "espeak", "-t", num+1, "-o", "news/news.ogg", "news.wav") | |
rm "news.wav" | |
cp "news/news.ogg", filename | |
} | |
main { | |
rm file for file in [ls(".")] if [ file =~ ".*\\.ogg" ] | |
generateName | pull songname, filename | |
(oneOf(generatePyco, generatePyco, generatePyco, generateFolklaine, generateNews)) songname, filename..".ogg" | |
print filename..".ogg" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0"?> | |
<ices> | |
<!-- run in background --> | |
<background>0</background> | |
<!-- where logs, etc go. --> | |
<logpath>./log</logpath> | |
<logfile>ices.log</logfile> | |
<!-- 1=error,2=warn,3=info,4=debug --> | |
<loglevel>4</loglevel> | |
<!-- set this to 1 to log to the console instead of to the file above --> | |
<consolelog>0</consolelog> | |
<!-- optional filename to write process id to --> | |
<!-- <pidfile>/home/ices/ices.pid</pidfile> --> | |
<stream> | |
<!-- metadata used for stream listing (not currently used) --> | |
<metadata> | |
<name>Radio Gem</name> | |
<genre>Algorithmic</genre> | |
<description>Algorithmic music station</description> | |
</metadata> | |
<!-- input module | |
The module used here is the playlist module - it has | |
'submodules' for different types of playlist. There are | |
two currently implemented, 'basic', which is a simple | |
file-based playlist, and 'script' which invokes a command | |
to returns a filename to start playing. --> | |
<input> | |
<module>playlist</module> | |
<param name="type">script</param> | |
<param name="program">./next_song.röd</param> | |
</input> | |
<!-- Stream instance | |
You may have one or more instances here. This allows you to | |
send the same input data to one or more servers (or to different | |
mountpoints on the same server). Each of them can have different | |
parameters. This is primarily useful for a) relaying to multiple | |
independent servers, and b) encoding/reencoding to multiple | |
bitrates. | |
If one instance fails (for example, the associated server goes | |
down, etc), the others will continue to function correctly. | |
This example defines two instances as two mountpoints on the | |
same server. --> | |
<instance> | |
<!-- Server details: | |
You define hostname and port for the server here, along with | |
the source password and mountpoint. --> | |
<hostname>localhost</hostname> | |
<port>8000</port> | |
<password>PASSWORD HERE</password> | |
<mount>/gem.ogg</mount> | |
<!-- Reconnect parameters: | |
When something goes wrong (e.g. the server crashes, or the | |
network drops) and ices disconnects from the server, these | |
control how often it tries to reconnect, and how many times | |
it tries to reconnect. Delay is in seconds. | |
If you set reconnectattempts to -1, it will continue | |
indefinately. Suggest setting reconnectdelay to a large value | |
if you do this. | |
--> | |
<reconnectdelay>2</reconnectdelay> | |
<reconnectattempts>5</reconnectattempts> | |
<!-- maxqueuelength: | |
This describes how long the internal data queues may be. This | |
basically lets you control how much data gets buffered before | |
ices decides it can't send to the server fast enough, and | |
either shuts down or flushes the queue (dropping the data) | |
and continues. | |
For advanced users only. | |
--> | |
<maxqueuelength>80</maxqueuelength> | |
<!-- Live encoding/reencoding: | |
Currrently, the parameters given here for encoding MUST | |
match the input data for channels and sample rate. That | |
restriction will be relaxed in the future. | |
Remove this section if you don't want your files getting reencoded. | |
--> | |
<encode> | |
<nominal-bitrate>64000</nominal-bitrate> <!-- bps. e.g. 64000 for 64 kbps --> | |
<samplerate>44100</samplerate> | |
<channels>1</channels> | |
</encode> | |
</instance> | |
</stream> | |
</ices> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment