├── .gitignore ├── Gemfile ├── README.md ├── config.yml.template ├── lib ├── character.rb ├── pd-connect.rb └── twitter-auth.rb ├── ruby_interact.pd ├── ruby_interact_midi.pd ├── ruby_interact_vanilla.pd ├── scripts ├── github-commits.rb ├── github-realtime.rb ├── manual-input.rb ├── rss-feed.rb ├── string_slicer.rb ├── twitter-search.rb └── twitter-userstream.rb └── twitter.yml.template /.gitignore: -------------------------------------------------------------------------------- 1 | config.yml 2 | twitter.yml -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem "tweetstream" 4 | gem "highline" 5 | gem "twitter_oauth" 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Text to Music 2 | ============= 3 | by Andrew Faraday 4 | 5 | Overview 6 | -------- 7 | 8 | A derivation of my very first Ruby project: reading a string and converting it to control signals for Pure Data. The Pure Data patch receives these via a TCP port and sends them to some short audio chains and the result is heard in sound. 9 | This has also been plugged into the Twitter streaming API, to sonify tweets as they come in. A sort of literal Twitter. 10 | Watch out for rhyming and/or recurring words — you can actually hear that 'how now brown cow' rhymes. You can also get some drum sounds out of ASCII characters: '\_=\_=\_\_\_=\_\!\_=\_\_\+='. 11 | 12 | Requirements 13 | ------------ 14 | 15 | * git 16 | * ruby 17 | * rubygems 18 | * openssl-lib 19 | * Pure Data Extended (from www.puredata.info/downloads/pd-extended) 20 | * Gems: (`bundle install` or `sudo gem install tweetstream highline twitter_oauth`) 21 | * tweetstream 22 | * highline 23 | * twitter_oauth 24 | 25 | Installation 26 | ------------ 27 | 28 | * Make sure you have the above programs and gems 29 | * Clone the git repository (`git clone https://github.com/AJFaraday/Text-to-music.git`) 30 | * Make a copy of the file config.yml.template called config.yml (`cp config.yml.template config.yml`) 31 | * Make a copy of the file twitter.yml.template called twitter.yml (`cp twitter.yml.template twitter.yml`) 32 | * (Optional) Modify config.yml and twitter.yml as required 33 | 34 | Manual Mode 35 | ----------- 36 | 37 | * Open ruby_interact.pd in puredata (make sure 'DSP' is checked) 38 | * Run `ruby scripts/manual-input.rb` 39 | * Input a speed from 1 to 10 40 | * Type some text and listen to the result 41 | * Repeat as required 42 | * Press `ctrl+c` to end the script 43 | 44 | Twitter real-time search sonification 45 | ------------------------------------- 46 | 47 | * Open ruby_interact.pd in puredata (make sure 'DSP' is checked) 48 | * Run `ruby scripts/twitter-search.rb` 49 | * You will be prompted to authorise text-to-music to know who is following you (you should only have to do this once) 50 | * Watch the tweets containing 'fail' rolling in and being sonified 51 | * To stop script press `ctrl+c` (you may have to hold it from there) 52 | * Optionally: 53 | * Change the default search term in config.yml 54 | * Use arguments to change the search terms (e.g. `ruby scripts/twitter-search.rb win` or `ruby scripts/twitter-search.rb right wrong`) 55 | 56 | Twitter user stream sonification 57 | -------------------------------- 58 | 59 | * Open ruby_interact.pd in puredata (make sure 'DSP' is checked) 60 | * Run `ruby scripts/twitter-userstream.rb` 61 | * You will be prompted to authorise text-to-music to know who is following you (you should only have to do this once) 62 | * Listen to tweets from the accounts you follow roll in in real-time 63 | * To stop script press `ctrl+c` (you may have to hold it from there) 64 | 65 | 66 | RSS feed sonification 67 | --------------------- 68 | 69 | By default, the RSS feed will sonify the first 5 items of a feed, then begin again when an item is added. 70 | Initially developed and tested with the BBC News headlines feed, other RSS feeds may be structured differently. 71 | 72 | * Open ruby_interact.pd in puredata (make sure 'DSP' is checked) 73 | * Run `ruby scripts/rss-feed.rb` 74 | * Optionally: 75 | * Set a different RSS feed by changing the default feed in config.yml 76 | * Set a different feed as an argument (e.g. `ruby scripts/rss-feed.rb http://feeds.bbci.co.uk/news/rss.xml`) 77 | 78 | GitHub commit review 79 | -------------------- 80 | 81 | This will sonify all the commits in a GitHub repository starting with the most recent. 82 | 83 | * Open ruby_interact.pd in puredata (make sure 'DSP' is checked) 84 | * Run `ruby scripts/github-commits.rb` 85 | * Optionally: 86 | * Set a different repo (in the style 'username/repository') 87 | * in config.yml (github: repo: ) 88 | * as an argument (e.g. `ruby scripts/github-commits.rb rails/rails`) 89 | * Set a different branch: 90 | * in config.yml (github: branch: ) 91 | * as an argument, after the repo (e.g. `ruby scripts/github-commits.rb rails/rails master`) 92 | 93 | 94 | GitHub live commits 95 | ------------------- 96 | 97 | This will sonify commits of a GitHub repository in real-time. 98 | 99 | * Open ruby_interact.pd in puredata (make sure 'DSP' is checked) 100 | * Run `ruby scripts/github-realtime.rb` 101 | * Optionally: 102 | * Set a different repo (in the style 'username/repository') 103 | * in config.yml (github: repo: ) 104 | * as an argument (e.g. `ruby scripts/github-realtime.rb rails/rails`) 105 | * Set a different branch: 106 | * in config.yml (github: branch: ) 107 | * as an argument, after the repo (e.g. `ruby scripts/github-realtime.rb rails/rails master`) 108 | * Change the time (in seconds) between checks in config.yml (github: polling_time:) 109 | 110 | Limitations 111 | ----------- 112 | 113 | If you can find solutions to these problems, feel free to fix them. 114 | 115 | * If this ran for a long time, there would be a huge array of used commit ids in memory, which could slow your computer down. Perhaps some garbage collection here when unused_ids gets past a given point. 116 | * This is currently making a request for the whole RSS feed every minute. This seems like a lot of traffic. Is there a way to poll for just the feed version or most recent post time? 117 | 118 | Reading a file 119 | -------------- 120 | 121 | * Open ruby_interact.pd in puredata (make sure 'DSP' is checked) 122 | * Run `ruby scripts/manual-input.rb` followed by a file name (e.g. `ruby scripts/manual-input.rb README.md` will read this file) 123 | 124 | Future intentions 125 | ----------------- 126 | 127 | * Connect to Pidgin or IRC, musical chat client. 128 | * Find a library for MIDI output, to feed a hardware synthesizer. 129 | * Use location information from tweets (longitude and latitude) to make repeatable timbral changes to tweets. 130 | * Alternative Pure Data patches, providing a kind of 'audio skinning' (this will require a restructure of the Pure Data patch to put the TCP receive part in an abstraction). 131 | * Find a way to automatically add OAuth credentials to config.yml 132 | * Use other live-streaming text APIs to feed the algorithm: 133 | * National Rail real-time API (https://datafeeds.networkrail.co.uk/ntrod/) 134 | 135 | Contributors 136 | ------------ 137 | 138 | * Andrew Faraday 139 | * Robin Gower 140 | * [Peter Vandenberk](https://www.github.com/pvdb) 141 | * [Abe Stanway](https://www.github.com/astanway) 142 | * [Pat Nakajima](https://www.github.com/nakajima) 143 | * [Jeremy Wentworth](https://www.github.com/jeremywen) 144 | 145 | Testers 146 | ------- 147 | 148 | * Richard Knight 149 | * Peter Shillito 150 | 151 | Notes 152 | ----- 153 | 154 | * The word 'potato' sounds surprisingly pleasant due to the reversed patter, 'ot' and 'to' 155 | * I have added a vanilla mod to the Pure Data patch, requiring no pd-extended libraries. This can be run entirely in the command line with `puredata -nogui ruby_interact_vanilla.pd` 156 | -------------------------------------------------------------------------------- /config.yml.template: -------------------------------------------------------------------------------- 1 | # 2 | # Andrew James Faraday - May 2012 3 | # 4 | # A simple config file to avoid repeat data input and change details as required. 5 | # When you first install the script you will need to make a copy of this file called 'config.yml' 6 | # 7 | 8 | # These attributes will affect the TCP connection from ruby to pure data. 9 | # 127.0.0.1 is the computer that's running the script and 3939 is the default port. 10 | connection: 11 | hostname: '127.0.0.1' 12 | port: 3939 13 | 14 | # Attributes for Twitter have been moved out to twitter.yml (you may need to copy this from twitter.yml.template 15 | 16 | # 17 | # The default feed url for the rss aggregator 18 | # 19 | rss: 20 | default_feed: 'http://feeds.bbci.co.uk/news/rss.xml' 21 | github: 22 | repo: 'AJFaraday/Text-to-music' 23 | branch: 'master' 24 | polling_time: 60 25 | # 26 | # Music settings: 27 | # 28 | # transpose denotes the semitones up or down the letter and number notes will be moved by. 29 | # speed is the time from one note to the next being triggered 30 | # this is only overridden on manual import 31 | music: 32 | transpose: 10 33 | speed: 0.15 34 | 35 | -------------------------------------------------------------------------------- /lib/character.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Andrew James Faraday - May 2012 3 | # 4 | # The Character module handles single characters from a string of text and outputs a command which the pure data patch (ruby_interact.pd) responds to. 5 | # 6 | # 7 | # Letters result in a chromatic scale, each letter being 1 semitone higher than the previous one. 8 | # Character.command('a') #=> "letter 60 ;" 9 | # Character.command('b') => "letter 61 ;" 10 | # 11 | # Upper case letters are the same notes but one octave higher. 12 | # Character.command('A') => "letter 72 ;" 13 | # 14 | # Numbers result in a diminished scale on a different synth. 15 | # Character.command('1') #=> "num 53 ;" 16 | # Character.command('2') #=> "num 56 ;" 17 | # 18 | # Punctuation results in a series of percussive and sliding sounds 19 | # 20 | # Character.command('!') #=> "punct 3 ;" 21 | # 22 | 23 | 24 | module Character 25 | 26 | TRANSPOSE = 10 27 | NUMBERS = [50, 53, 56, 59, 62, 65, 68, 71, 74, 77] 28 | PUNCTUATION = ['.',',',"'",'!','?','(',')','[',']','{','}', '#','=','_','<','>','"','-','+','/', '\\'] 29 | PUNCTUATION_NUMBERS = [46, 44, 39, 33, 63, 40, 41, 91, 93, 123, 125, 35, 61, 95, 60, 62, 34, 45, 43, 47, 92] 30 | 31 | # 32 | # handles input of strings and numbers, converts the first character of a string to it's ascii number 33 | # 34 | def self.get_number(character) 35 | if character.is_a?(Integer) 36 | character 37 | elsif character.is_a?(String) 38 | character.bytes.first 39 | else 40 | raise WrongInput 41 | end 42 | end 43 | 44 | # 45 | # Converts a character (or rather, the first character of a string) and converts it into commands for the pure data patch. 46 | # See above for examples 47 | # 48 | def self.command(character, transpose) 49 | transpose ||= TRANSPOSE 50 | pre = 'letter' 51 | number = get_number(character) 52 | case number 53 | # Upper case 54 | when 65..90 55 | comm = number + transpose 56 | # Lower case 57 | when 97..122 58 | comm = (number-47) + transpose 59 | # space 60 | when 32 61 | comm = 0 62 | when 48..57 63 | pre = 'num' 64 | comm = NUMBERS[character.to_i] + transpose 65 | end 66 | # punctuation 67 | if PUNCTUATION_NUMBERS.include? number 68 | pre = 'punct' 69 | comm = PUNCTUATION.index(character) 70 | end 71 | return "#{pre} #{comm} ;" 72 | end 73 | 74 | end 75 | -------------------------------------------------------------------------------- /lib/pd-connect.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Andrew James Faraday - May 2012 3 | # 4 | # The PureData class handles the connection to the bundled pure data patch. One instance of PureData can be used multiple times. 5 | # 6 | 7 | require 'socket' 8 | require './lib/character' 9 | require 'yaml' 10 | 11 | class PureData 12 | 13 | attr_accessor :connection 14 | attr_accessor :hostname 15 | attr_accessor :port 16 | attr_accessor :music 17 | 18 | # 19 | # Initializing an instance of PureData will set up a connection(TCPSocket) to the pure data patch. 20 | # This should handle the lack of a config file, the patch being closed and an invalid hostname and/or port 21 | # 22 | def initialize 23 | begin 24 | config = YAML.load_file("config.yml") 25 | connection = config['connection'] 26 | self.music = config['music'] 27 | rescue 28 | puts "config.yml not found, please copy it from the template and modify as required. (`cp config.yml.template config.yml`)" 29 | abort 30 | end 31 | hostname = connection['hostname'] 32 | port = connection['port'] 33 | transpose = music['transpose'] 34 | begin 35 | self.connection = TCPSocket.open hostname, port 36 | puts "Connection established on #{hostname}:#{port}" 37 | rescue Errno::ECONNREFUSED 38 | puts "Connection refused! Please ensure ruby_interact.pd is running in puredata and listening on #{hostname}:#{port}" 39 | abort 40 | rescue SocketError 41 | puts "Hostname and port are invalid. Please make sure they're a valid ip address and port number." 42 | abort 43 | end 44 | end 45 | 46 | def reload_music_params 47 | config = YAML.load_file('config.yml') 48 | self.music = config['music'] 49 | end 50 | 51 | # 52 | # Accepts a string and separates it into it's individual characters and a speed (actually a rest time in seconds) 53 | # Outputs characters to the console one by one (typewriter effect) 54 | # Outputs suitable commands to the pure data patch 55 | # 56 | def send_string(string,speed=nil) 57 | reload_music_params 58 | speed ||= music['speed'] 59 | string.chars.each do |c| 60 | print c 61 | connection.puts Character.command(c, music['transpose']) 62 | $stdout.flush 63 | sleep speed 64 | end 65 | end 66 | 67 | # 68 | # accepts the 'place' and 'geo' hashes from a tweet (TweetStream::Hash) and dumps parts of it to puredata 69 | # command will be along the lines of "location GB Guildford 51.24008618 -0.57108614" 70 | # This is intended to be used as timbre control, providing a noticable tone difference based on location. 71 | # 72 | def send_location(place, geo) 73 | if place and !place.nil? 74 | if geo and !geo.nil? 75 | # TODO add an extra case to average the boundary co-ordinates from place in the absence of geo 76 | connection.puts("location #{place[:country_code]} #{place[:name]} #{geo[:coordinates][0]} #{geo[:coordinates][1]};") 77 | end 78 | else 79 | connection.puts("location reset;") 80 | end 81 | end 82 | 83 | end 84 | -------------------------------------------------------------------------------- /lib/twitter-auth.rb: -------------------------------------------------------------------------------- 1 | require 'twitter_oauth' 2 | 3 | def get_twitter_auth(config) 4 | 5 | # Load attributes from the config file 6 | consumer_key = config['consumer_key'] if config['consumer_key'] and !config['consumer_key'].empty? 7 | consumer_secret = config['consumer_secret'] if config['consumer_secret'] and !config['consumer_secret'].empty? 8 | oauth_token = config['oauth_token'] if config['oauth_token'] and !config['oauth_token'].empty? 9 | oauth_token_secret = config['oauth_token_secret'] if config['oauth_token_secret'] and !config['oauth_token_secret'].empty? 10 | 11 | unless oauth_token and oauth_token_secret 12 | client = TwitterOAuth::Client.new(:consumer_key => consumer_key, 13 | :consumer_secret => consumer_secret) 14 | request_token = client.request_token() 15 | puts "go to the browser and open this url to authorise your account: #{request_token.authorize_url}" 16 | puts "What pin did it give you?" 17 | pin = gets.chomp 18 | access_token = client.authorize(request_token.token, 19 | request_token.secret, 20 | :oauth_verifier => pin) 21 | 22 | config['oauth_token'] = oauth_token = access_token.token 23 | config['oauth_token_secret'] = oauth_token_secret = access_token.secret 24 | 25 | #save the new oauth values 26 | File.open("twitter.yml", "w"){ |f| 27 | YAML.dump(config, f) 28 | } 29 | 30 | puts 'You\'ve successfully authorised text-to-music to read your tweets and find out who you follow in order to reproduce your twitter stream with musical accompaniment. ' 31 | end 32 | 33 | return consumer_key, consumer_secret, oauth_token, oauth_token_secret 34 | end 35 | -------------------------------------------------------------------------------- /ruby_interact.pd: -------------------------------------------------------------------------------- 1 | #N canvas 62 129 621 231 10; 2 | #X obj 35 21 netreceive 3939; 3 | #N canvas 474 70 450 300 synth 0; 4 | #X obj 26 64 osc~; 5 | #X obj 26 41 mtof; 6 | #X obj 26 131 *~; 7 | #X obj 67 103 vline~; 8 | #X msg 67 80 1 30 \, 0 100 50; 9 | #X obj 25 185 dac~; 10 | #X obj 26 20 r let; 11 | #X floatatom 94 45 5 0 0 0 - - -; 12 | #X obj 26 159 *~ 0.3; 13 | #X connect 0 0 2 0; 14 | #X connect 1 0 0 0; 15 | #X connect 2 0 8 0; 16 | #X connect 3 0 2 1; 17 | #X connect 4 0 3 0; 18 | #X connect 6 0 1 0; 19 | #X connect 6 0 4 0; 20 | #X connect 6 0 7 0; 21 | #X connect 8 0 5 0; 22 | #X connect 8 0 5 1; 23 | #X restore 520 62 pd synth; 24 | #X text 38 1 tune \, letters; 25 | #N canvas 404 36 589 420 punctuation 0; 26 | #X obj 100 43 r stop; 27 | #X obj 101 67 click~; 28 | #X obj 19 156 dac~; 29 | #X obj 161 70 click~; 30 | #X obj 160 100 dac~; 31 | #X obj 25 96 delwrite~ stopdel 50; 32 | #X obj 19 122 delread~ stopdel 50; 33 | #X obj 59 171 s~ fb; 34 | #X obj 55 144 *~ 0.3; 35 | #X obj 34 57 r~ fb; 36 | #X obj 161 46 r comma; 37 | #X obj 217 44 r exclaim; 38 | #X obj 217 150 osc~; 39 | #X obj 217 108 vline~; 40 | #X obj 228 226 dac~; 41 | #X obj 228 179 *~; 42 | #X obj 276 135 vline~; 43 | #X msg 276 109 1 20 \, 0 100 200; 44 | #X msg 217 83 1000 100 \, 500 200 100; 45 | #X obj 384 155 osc~; 46 | #X obj 384 113 vline~; 47 | #X obj 395 231 dac~; 48 | #X obj 395 184 *~; 49 | #X obj 443 140 vline~; 50 | #X msg 443 114 1 20 \, 0 100 200; 51 | #X obj 384 48 r question; 52 | #X msg 385 88 500 100 \, 1000 200 100; 53 | #X obj 163 231 noise~; 54 | #X obj 48 274 *~; 55 | #X obj 53 300 dac~; 56 | #X obj 22 252 vline~; 57 | #X msg 11 226 1 100 \, 0 100 100; 58 | #X obj 163 256 bp~ 1000 2; 59 | #X obj 313 395 dac~; 60 | #X obj 312 372 *~; 61 | #X obj 394 365 vline~; 62 | #X msg 394 345 1 50 \, 0 100 50; 63 | #X obj 398 269 r =; 64 | #X obj 410 297 del 100; 65 | #X obj 290 309 noise~; 66 | #X obj 287 335 bp~ 2000 20; 67 | #X obj 207 310 noise~; 68 | #X obj 111 378 *~; 69 | #X obj 116 404 dac~; 70 | #X obj 85 355 vline~; 71 | #X obj 207 335 bp~ 100 2; 72 | #X obj 86 307 r _; 73 | #X obj 23 204 r hash; 74 | #X obj 228 201 *~ 0.4; 75 | #X obj 395 207 *~ 0.3; 76 | #X msg 74 330 2 100 \, 0 100 100; 77 | #X connect 0 0 1 0; 78 | #X connect 1 0 5 0; 79 | #X connect 3 0 4 0; 80 | #X connect 3 0 4 1; 81 | #X connect 6 0 2 0; 82 | #X connect 6 0 2 1; 83 | #X connect 6 0 8 0; 84 | #X connect 8 0 7 0; 85 | #X connect 9 0 5 0; 86 | #X connect 10 0 3 0; 87 | #X connect 11 0 18 0; 88 | #X connect 11 0 17 0; 89 | #X connect 12 0 15 0; 90 | #X connect 13 0 12 0; 91 | #X connect 15 0 48 0; 92 | #X connect 16 0 15 1; 93 | #X connect 17 0 16 0; 94 | #X connect 18 0 13 0; 95 | #X connect 19 0 22 0; 96 | #X connect 20 0 19 0; 97 | #X connect 22 0 49 0; 98 | #X connect 23 0 22 1; 99 | #X connect 24 0 23 0; 100 | #X connect 25 0 26 0; 101 | #X connect 25 0 24 0; 102 | #X connect 26 0 20 0; 103 | #X connect 27 0 32 0; 104 | #X connect 28 0 29 0; 105 | #X connect 28 0 29 1; 106 | #X connect 30 0 28 0; 107 | #X connect 31 0 30 0; 108 | #X connect 32 0 28 1; 109 | #X connect 34 0 33 0; 110 | #X connect 34 0 33 1; 111 | #X connect 35 0 34 1; 112 | #X connect 36 0 35 0; 113 | #X connect 37 0 36 0; 114 | #X connect 37 0 38 0; 115 | #X connect 38 0 36 0; 116 | #X connect 39 0 40 0; 117 | #X connect 40 0 34 0; 118 | #X connect 41 0 45 0; 119 | #X connect 42 0 43 0; 120 | #X connect 42 0 43 1; 121 | #X connect 44 0 42 0; 122 | #X connect 45 0 42 1; 123 | #X connect 46 0 50 0; 124 | #X connect 47 0 31 0; 125 | #X connect 48 0 14 0; 126 | #X connect 48 0 14 1; 127 | #X connect 49 0 21 0; 128 | #X connect 49 0 21 1; 129 | #X connect 50 0 44 0; 130 | #X restore 482 2 pd punctuation; 131 | #N canvas 264 25 750 513 brackets 0; 132 | #X obj 148 39 r opb; 133 | #X obj 156 71 r clb; 134 | #X obj 65 143 vline~; 135 | #X obj 14 169 *~; 136 | #X obj 13 194 *~ 0.2; 137 | #X msg 65 119 1 100 \, 0 100 200; 138 | #X obj 9 142 osc~; 139 | #X obj 13 216 dac~; 140 | #X obj 10 119 vline~; 141 | #X msg 10 72 440 \, 880 400; 142 | #X msg 21 92 880 \, 440 400; 143 | #X obj 332 129 vline~; 144 | #X obj 209 215 *~; 145 | #X obj 208 240 *~ 0.2; 146 | #X msg 332 105 1 100 \, 0 100 200; 147 | #X obj 208 262 dac~; 148 | #X obj 206 107 vline~; 149 | #X msg 206 60 440 \, 880 400; 150 | #X msg 217 80 880 \, 440 400; 151 | #X obj 344 27 r ops; 152 | #X obj 352 59 r cls; 153 | #X obj 556 158 vline~; 154 | #X obj 505 184 *~; 155 | #X obj 504 209 *~ 0.2; 156 | #X msg 556 134 1 100 \, 0 100 200; 157 | #X obj 500 157 osc~; 158 | #X obj 504 231 dac~; 159 | #X obj 501 88 vline~; 160 | #X msg 501 41 440 \, 880 400; 161 | #X msg 512 61 880 \, 440 400; 162 | #X obj 501 135 +~; 163 | #X obj 639 54 r opc; 164 | #X obj 647 86 r clc; 165 | #X obj 455 114 *~ 100; 166 | #X obj 454 88 osc~ 5; 167 | #X obj 205 130 osc~; 168 | #X obj 200 162 expr~ $v1 > 0; 169 | #X connect 0 0 9 0; 170 | #X connect 0 0 5 0; 171 | #X connect 1 0 10 0; 172 | #X connect 1 0 5 0; 173 | #X connect 2 0 3 1; 174 | #X connect 3 0 4 0; 175 | #X connect 4 0 7 0; 176 | #X connect 4 0 7 1; 177 | #X connect 5 0 2 0; 178 | #X connect 6 0 3 0; 179 | #X connect 8 0 6 0; 180 | #X connect 9 0 8 0; 181 | #X connect 10 0 8 0; 182 | #X connect 11 0 12 1; 183 | #X connect 12 0 13 0; 184 | #X connect 13 0 15 0; 185 | #X connect 13 0 15 1; 186 | #X connect 14 0 11 0; 187 | #X connect 16 0 35 0; 188 | #X connect 17 0 16 0; 189 | #X connect 18 0 16 0; 190 | #X connect 19 0 17 0; 191 | #X connect 19 0 14 0; 192 | #X connect 20 0 18 0; 193 | #X connect 20 0 14 0; 194 | #X connect 21 0 22 1; 195 | #X connect 22 0 23 0; 196 | #X connect 23 0 26 0; 197 | #X connect 23 0 26 1; 198 | #X connect 24 0 21 0; 199 | #X connect 25 0 22 0; 200 | #X connect 27 0 30 1; 201 | #X connect 28 0 27 0; 202 | #X connect 29 0 27 0; 203 | #X connect 30 0 25 0; 204 | #X connect 31 0 28 0; 205 | #X connect 31 0 24 0; 206 | #X connect 32 0 29 0; 207 | #X connect 32 0 24 0; 208 | #X connect 33 0 30 0; 209 | #X connect 34 0 33 0; 210 | #X connect 35 0 36 0; 211 | #X connect 36 0 12 0; 212 | #X restore 502 42 pd brackets; 213 | #N canvas 474 70 450 300 numbsynth 0; 214 | #X obj 26 41 mtof; 215 | #X obj 27 166 *~; 216 | #X obj 198 113 vline~; 217 | #X obj 26 212 dac~; 218 | #X obj 27 68 phasor~; 219 | #X obj 28 139 moog~; 220 | #X obj 100 58 +~ 1; 221 | #X obj 100 78 *~ 2000; 222 | #X obj 100 99 +~ 300; 223 | #X obj 26 19 r num; 224 | #X obj 197 51 r num; 225 | #X floatatom 247 59 5 0 0 0 - - -; 226 | #X obj 100 36 osc~ 10; 227 | #X msg 198 88 1 30 \, 0 200 100; 228 | #X obj 27 186 *~ 0.4; 229 | #X connect 0 0 4 0; 230 | #X connect 1 0 14 0; 231 | #X connect 2 0 1 1; 232 | #X connect 4 0 5 0; 233 | #X connect 5 0 1 0; 234 | #X connect 6 0 7 0; 235 | #X connect 7 0 8 0; 236 | #X connect 8 0 5 1; 237 | #X connect 9 0 0 0; 238 | #X connect 10 0 13 0; 239 | #X connect 10 0 11 0; 240 | #X connect 12 0 6 0; 241 | #X connect 13 0 2 0; 242 | #X connect 14 0 3 0; 243 | #X connect 14 0 3 1; 244 | #X restore 496 84 pd numbsynth; 245 | #N canvas 104 35 860 501 punctuation2 0; 246 | #X obj 24 140 osc~; 247 | #X obj 24 118 line~; 248 | #X obj 69 140 osc~; 249 | #X obj 69 118 line~; 250 | #X obj 66 214 *~; 251 | #X msg 8 63 440 \, 880 100; 252 | #X msg 32 82 440 \, 220 100; 253 | #X obj 65 236 dac~; 254 | #X obj 13 28 r <; 255 | #X obj 63 34 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 256 | -1; 257 | #X obj 119 188 vline~; 258 | #X msg 114 161 1 10 \, 0 200 10; 259 | #X obj 244 136 osc~; 260 | #X obj 244 114 line~; 261 | #X obj 282 136 osc~; 262 | #X obj 282 114 line~; 263 | #X obj 310 195 *~; 264 | #X obj 311 219 dac~; 265 | #X obj 321 27 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 266 | -1; 267 | #X obj 316 137 vline~; 268 | #X msg 319 114 1 10 \, 0 200 10; 269 | #X obj 254 30 r >; 270 | #X msg 233 62 220 \, 440 100; 271 | #X msg 250 85 880 \, 440 100; 272 | #X obj 457 35 r "; 273 | #X obj 427 167 osc~; 274 | #X obj 427 145 line~; 275 | #X obj 458 241 *~; 276 | #X obj 459 265 dac~; 277 | #X obj 464 183 vline~; 278 | #X msg 423 110 10000 \, 5000 100; 279 | #X obj 462 57 del 100; 280 | #X msg 467 160 1 10 \, 0 50 10; 281 | #X obj 36 281 r -; 282 | #X obj 12 363 osc~; 283 | #X obj 43 437 *~; 284 | #X obj 44 461 dac~; 285 | #X obj 49 379 vline~; 286 | #X obj 150 355 osc~; 287 | #X obj 150 333 line~; 288 | #X obj 181 429 *~; 289 | #X obj 182 453 dac~; 290 | #X obj 187 371 vline~; 291 | #X msg 190 348 1 10 \, 0 300 10; 292 | #X obj 174 273 r +; 293 | #X msg 147 298 50 \, 1000 300; 294 | #X obj 288 349 osc~; 295 | #X obj 288 327 line~; 296 | #X obj 319 423 *~; 297 | #X obj 320 447 dac~; 298 | #X obj 325 365 vline~; 299 | #X msg 329 342 1 10 \, 0 300 10; 300 | #X obj 312 267 r /; 301 | #X msg 285 292 440 \, 880 1000; 302 | #X obj 660 254 r &; 303 | #X obj 717 418 dac~; 304 | #X obj 722 338 vline~; 305 | #X obj 719 398 *~; 306 | #X msg 726 315 1 10 \, 0 400 10; 307 | #X obj 646 314 random 10000; 308 | #X obj 644 340 osc~; 309 | #X obj 471 356 osc~; 310 | #X obj 471 334 line~; 311 | #X obj 502 430 *~; 312 | #X obj 503 454 dac~; 313 | #X obj 508 372 vline~; 314 | #X msg 512 349 1 10 \, 0 300 10; 315 | #X obj 495 274 r backslash; 316 | #X msg 468 299 880 \, 440 1000; 317 | #X obj 66 188 *~ 0.3; 318 | #X obj 312 174 *~ 0.3; 319 | #X obj 461 221 *~ 0.3; 320 | #X obj 45 417 *~ 0.3; 321 | #X msg 9 306 1000; 322 | #X obj 183 408 *~ 0.3; 323 | #X obj 321 402 *~ 0.3; 324 | #X obj 504 408 *~ 0.3; 325 | #X obj 718 375 *~ 0.3; 326 | #X msg 51 358 1 10 \, 0 400 10; 327 | #X obj 649 287 bang; 328 | #X connect 0 0 69 0; 329 | #X connect 1 0 0 0; 330 | #X connect 2 0 69 0; 331 | #X connect 3 0 2 0; 332 | #X connect 4 0 7 0; 333 | #X connect 4 0 7 1; 334 | #X connect 5 0 1 0; 335 | #X connect 6 0 3 0; 336 | #X connect 8 0 5 0; 337 | #X connect 8 0 6 0; 338 | #X connect 8 0 11 0; 339 | #X connect 9 0 5 0; 340 | #X connect 9 0 6 0; 341 | #X connect 9 0 11 0; 342 | #X connect 10 0 4 1; 343 | #X connect 11 0 10 0; 344 | #X connect 12 0 70 0; 345 | #X connect 13 0 12 0; 346 | #X connect 14 0 70 0; 347 | #X connect 15 0 14 0; 348 | #X connect 16 0 17 0; 349 | #X connect 16 0 17 1; 350 | #X connect 18 0 22 0; 351 | #X connect 18 0 23 0; 352 | #X connect 18 0 20 0; 353 | #X connect 19 0 16 1; 354 | #X connect 20 0 19 0; 355 | #X connect 21 0 22 0; 356 | #X connect 21 0 23 0; 357 | #X connect 21 0 20 0; 358 | #X connect 22 0 13 0; 359 | #X connect 23 0 15 0; 360 | #X connect 24 0 31 0; 361 | #X connect 24 0 32 0; 362 | #X connect 25 0 71 0; 363 | #X connect 26 0 25 0; 364 | #X connect 27 0 28 0; 365 | #X connect 27 0 28 1; 366 | #X connect 29 0 27 1; 367 | #X connect 30 0 26 0; 368 | #X connect 31 0 32 0; 369 | #X connect 31 0 30 0; 370 | #X connect 32 0 29 0; 371 | #X connect 33 0 73 0; 372 | #X connect 33 0 78 0; 373 | #X connect 34 0 72 0; 374 | #X connect 35 0 36 0; 375 | #X connect 35 0 36 1; 376 | #X connect 37 0 35 1; 377 | #X connect 38 0 74 0; 378 | #X connect 39 0 38 0; 379 | #X connect 40 0 41 0; 380 | #X connect 40 0 41 1; 381 | #X connect 42 0 40 1; 382 | #X connect 43 0 42 0; 383 | #X connect 44 0 45 0; 384 | #X connect 44 0 43 0; 385 | #X connect 45 0 39 0; 386 | #X connect 46 0 75 0; 387 | #X connect 47 0 46 0; 388 | #X connect 48 0 49 0; 389 | #X connect 48 0 49 1; 390 | #X connect 50 0 48 1; 391 | #X connect 51 0 50 0; 392 | #X connect 52 0 53 0; 393 | #X connect 52 0 51 0; 394 | #X connect 53 0 47 0; 395 | #X connect 54 0 58 0; 396 | #X connect 54 0 79 0; 397 | #X connect 56 0 57 1; 398 | #X connect 57 0 55 0; 399 | #X connect 57 0 55 1; 400 | #X connect 58 0 56 0; 401 | #X connect 59 0 60 0; 402 | #X connect 60 0 77 0; 403 | #X connect 61 0 76 0; 404 | #X connect 62 0 61 0; 405 | #X connect 63 0 64 0; 406 | #X connect 63 0 64 1; 407 | #X connect 65 0 63 1; 408 | #X connect 66 0 65 0; 409 | #X connect 67 0 68 0; 410 | #X connect 67 0 66 0; 411 | #X connect 68 0 62 0; 412 | #X connect 69 0 4 0; 413 | #X connect 70 0 16 0; 414 | #X connect 71 0 27 0; 415 | #X connect 72 0 35 0; 416 | #X connect 73 0 34 0; 417 | #X connect 74 0 40 0; 418 | #X connect 75 0 48 0; 419 | #X connect 76 0 63 0; 420 | #X connect 77 0 57 0; 421 | #X connect 78 0 37 0; 422 | #X connect 79 0 59 0; 423 | #X restore 482 23 pd punctuation2; 424 | #X obj 34 152 s let; 425 | #X obj 79 153 s num; 426 | #X obj 72 46 print; 427 | #N canvas 0 0 733 336 punctuation-route 0; 428 | #X obj 57 27 inlet; 429 | #X obj 57 78 s stop; 430 | #X obj 74 101 s comma; 431 | #X obj 89 129 s "; 432 | #X obj 106 153 s exclaim; 433 | #X obj 122 73 s question; 434 | #X obj 138 97 s <; 435 | #X obj 155 118 s >; 436 | #X obj 171 146 s <; 437 | #X obj 187 169 s >; 438 | #X obj 204 72 s <; 439 | #X obj 220 95 s >; 440 | #X obj 236 117 s hash; 441 | #X obj 253 140 s =; 442 | #X obj 269 164 s _; 443 | #X obj 285 73 s <; 444 | #X obj 301 96 s >; 445 | #X obj 318 118 s "; 446 | #X obj 334 145 s -; 447 | #X obj 351 73 s +; 448 | #X obj 367 98 s /; 449 | #X obj 385 124 s backslash; 450 | #X obj 57 52 route 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 451 | 20; 452 | #X connect 0 0 22 0; 453 | #X connect 22 0 1 0; 454 | #X connect 22 1 2 0; 455 | #X connect 22 2 3 0; 456 | #X connect 22 3 4 0; 457 | #X connect 22 4 5 0; 458 | #X connect 22 5 6 0; 459 | #X connect 22 6 7 0; 460 | #X connect 22 7 8 0; 461 | #X connect 22 8 9 0; 462 | #X connect 22 9 10 0; 463 | #X connect 22 10 11 0; 464 | #X connect 22 11 12 0; 465 | #X connect 22 12 13 0; 466 | #X connect 22 13 14 0; 467 | #X connect 22 14 15 0; 468 | #X connect 22 15 16 0; 469 | #X connect 22 16 17 0; 470 | #X connect 22 17 18 0; 471 | #X connect 22 18 19 0; 472 | #X connect 22 19 20 0; 473 | #X connect 22 20 21 0; 474 | #X restore 125 154 pd punctuation-route; 475 | #X obj 34 65 route letter num punct location; 476 | #N canvas 0 0 450 300 location 0; 477 | #X obj 59 66 inlet; 478 | #X obj 59 109 unpack s s f f; 479 | #X symbolatom 59 140 10 0 0 0 - - -; 480 | #X symbolatom 86 166 10 0 0 0 - - -; 481 | #X floatatom 113 197 5 0 0 0 - - -; 482 | #X floatatom 140 225 5 0 0 0 - - -; 483 | #X connect 0 0 1 0; 484 | #X connect 1 0 2 0; 485 | #X connect 1 1 3 0; 486 | #X connect 1 2 4 0; 487 | #X connect 1 3 5 0; 488 | #X restore 171 125 pd location; 489 | #X text 243 1 Text to music synthesis patch; 490 | #X text 238 18 Andrew James Faraday - May 2012; 491 | #X text 231 182 Note: this patch must be open for the ruby text to 492 | music scripts to work.; 493 | #X connect 0 0 9 0; 494 | #X connect 0 0 11 0; 495 | #X connect 11 0 7 0; 496 | #X connect 11 1 8 0; 497 | #X connect 11 2 10 0; 498 | #X connect 11 3 12 0; 499 | -------------------------------------------------------------------------------- /ruby_interact_midi.pd: -------------------------------------------------------------------------------- 1 | #N canvas 62 131 621 231 10; 2 | #X obj 35 21 netreceive 3939; 3 | #X text 38 1 tune \, letters; 4 | #X obj 34 99 s let; 5 | #X obj 77 100 s num; 6 | #X obj 72 46 print; 7 | #N canvas 691 236 450 300 letter-midi 0; 8 | #X obj 32 25 r let; 9 | #X obj 32 53 makenote 100 150; 10 | #X obj 32 138 noteout 1; 11 | #X connect 0 0 1 0; 12 | #X connect 1 0 2 0; 13 | #X connect 1 1 2 1; 14 | #X restore 493 11 pd letter-midi; 15 | #N canvas 691 237 450 300 number-midi 0; 16 | #X obj 32 53 makenote 100 150; 17 | #X obj 32 25 r num; 18 | #X obj 32 138 noteout 2; 19 | #X connect 0 0 2 0; 20 | #X connect 0 1 2 1; 21 | #X connect 1 0 0 0; 22 | #X restore 493 33 pd number-midi; 23 | #N canvas 479 93 705 293 punct-midi 1; 24 | #X obj 53 30 r punct; 25 | #X obj 53 54 makenote 100 10; 26 | #X obj 53 130 noteout 10; 27 | #X connect 0 0 1 0; 28 | #X connect 1 0 2 0; 29 | #X connect 1 1 2 1; 30 | #X restore 493 58 pd punct-midi; 31 | #X obj 120 100 s punct; 32 | #X text 243 1 Text to music MIDI Routing Patch; 33 | #X text 245 18 Andrew James Faraday - October 2013; 34 | #X text 243 61 Letters - Midi Channel 1; 35 | #X text 243 75 Numbers - Midi Channel 2; 36 | #X text 242 89 Puctuation - Midi Channel 10 (0 - 20); 37 | #X text 231 182 Note: this patch or another like it must be open for 38 | the ruby text to music scripts to work.; 39 | #X obj 34 66 route letter num punct; 40 | #X connect 0 0 4 0; 41 | #X connect 0 0 15 0; 42 | #X connect 15 0 2 0; 43 | #X connect 15 1 3 0; 44 | #X connect 15 2 8 0; 45 | -------------------------------------------------------------------------------- /ruby_interact_vanilla.pd: -------------------------------------------------------------------------------- 1 | #N canvas 255 205 592 224 10; 2 | #X obj 35 21 netreceive 3939; 3 | #N canvas 474 70 450 300 synth 0; 4 | #X obj 26 64 osc~; 5 | #X obj 26 41 mtof; 6 | #X obj 26 131 *~; 7 | #X obj 67 103 vline~; 8 | #X msg 67 80 1 30 \, 0 100 50; 9 | #X obj 25 185 dac~; 10 | #X obj 26 20 r let; 11 | #X floatatom 94 45 5 0 0 0 - - -; 12 | #X obj 26 159 *~ 0.3; 13 | #X connect 0 0 2 0; 14 | #X connect 1 0 0 0; 15 | #X connect 2 0 8 0; 16 | #X connect 3 0 2 1; 17 | #X connect 4 0 3 0; 18 | #X connect 6 0 1 0; 19 | #X connect 6 0 4 0; 20 | #X connect 6 0 7 0; 21 | #X connect 8 0 5 0; 22 | #X connect 8 0 5 1; 23 | #X restore 520 62 pd synth; 24 | #X text 38 1 tune \, letters; 25 | #N canvas 404 36 589 420 punctuation 0; 26 | #X obj 100 44 r stop; 27 | #X obj 19 156 dac~; 28 | #X obj 160 100 dac~; 29 | #X obj 25 96 delwrite~ stopdel 50; 30 | #X obj 19 122 delread~ stopdel 50; 31 | #X obj 59 171 s~ fb; 32 | #X obj 55 144 *~ 0.3; 33 | #X obj 34 57 r~ fb; 34 | #X obj 161 46 r comma; 35 | #X obj 217 44 r exclaim; 36 | #X obj 217 150 osc~; 37 | #X obj 217 108 vline~; 38 | #X obj 228 226 dac~; 39 | #X obj 228 179 *~; 40 | #X obj 276 135 vline~; 41 | #X msg 276 109 1 20 \, 0 100 200; 42 | #X msg 217 83 1000 100 \, 500 200 100; 43 | #X obj 384 155 osc~; 44 | #X obj 384 113 vline~; 45 | #X obj 395 231 dac~; 46 | #X obj 395 184 *~; 47 | #X obj 443 140 vline~; 48 | #X msg 443 114 1 20 \, 0 100 200; 49 | #X obj 384 48 r question; 50 | #X msg 385 88 500 100 \, 1000 200 100; 51 | #X obj 163 231 noise~; 52 | #X obj 48 274 *~; 53 | #X obj 53 300 dac~; 54 | #X obj 22 252 vline~; 55 | #X msg 11 226 1 100 \, 0 100 100; 56 | #X obj 163 256 bp~ 1000 2; 57 | #X obj 313 395 dac~; 58 | #X obj 312 372 *~; 59 | #X obj 394 365 vline~; 60 | #X msg 394 345 1 50 \, 0 100 50; 61 | #X obj 398 269 r =; 62 | #X obj 410 297 del 100; 63 | #X obj 290 309 noise~; 64 | #X obj 287 335 bp~ 2000 20; 65 | #X obj 207 310 noise~; 66 | #X obj 111 378 *~; 67 | #X obj 116 404 dac~; 68 | #X obj 85 355 vline~; 69 | #X obj 207 335 bp~ 100 2; 70 | #X obj 86 307 r _; 71 | #X obj 23 204 r hash; 72 | #X obj 228 201 *~ 0.4; 73 | #X obj 395 207 *~ 0.3; 74 | #X msg 74 330 2 100 \, 0 100 100; 75 | #N canvas 0 0 450 300 click 0; 76 | #X msg 65 39 1 \, 0 10; 77 | #X obj 65 60 line~; 78 | #X obj 64 80 outlet~; 79 | #X obj 65 18 inlet; 80 | #X connect 0 0 1 0; 81 | #X connect 1 0 2 0; 82 | #X connect 3 0 0 0; 83 | #X restore 89 69 pd click; 84 | #N canvas 0 0 450 300 click 0; 85 | #X msg 65 39 1 \, 0 10; 86 | #X obj 65 60 line~; 87 | #X obj 64 80 outlet~; 88 | #X obj 65 18 inlet; 89 | #X connect 0 0 1 0; 90 | #X connect 1 0 2 0; 91 | #X connect 3 0 0 0; 92 | #X restore 158 68 pd click; 93 | #X connect 0 0 49 0; 94 | #X connect 4 0 1 0; 95 | #X connect 4 0 1 1; 96 | #X connect 4 0 6 0; 97 | #X connect 6 0 5 0; 98 | #X connect 7 0 3 0; 99 | #X connect 9 0 16 0; 100 | #X connect 9 0 15 0; 101 | #X connect 10 0 13 0; 102 | #X connect 11 0 10 0; 103 | #X connect 13 0 46 0; 104 | #X connect 14 0 13 1; 105 | #X connect 15 0 14 0; 106 | #X connect 16 0 11 0; 107 | #X connect 17 0 20 0; 108 | #X connect 18 0 17 0; 109 | #X connect 20 0 47 0; 110 | #X connect 21 0 20 1; 111 | #X connect 22 0 21 0; 112 | #X connect 23 0 24 0; 113 | #X connect 23 0 22 0; 114 | #X connect 24 0 18 0; 115 | #X connect 25 0 30 0; 116 | #X connect 26 0 27 0; 117 | #X connect 26 0 27 1; 118 | #X connect 28 0 26 0; 119 | #X connect 29 0 28 0; 120 | #X connect 30 0 26 1; 121 | #X connect 32 0 31 0; 122 | #X connect 32 0 31 1; 123 | #X connect 33 0 32 1; 124 | #X connect 34 0 33 0; 125 | #X connect 35 0 34 0; 126 | #X connect 35 0 36 0; 127 | #X connect 36 0 34 0; 128 | #X connect 37 0 38 0; 129 | #X connect 38 0 32 0; 130 | #X connect 39 0 43 0; 131 | #X connect 40 0 41 0; 132 | #X connect 40 0 41 1; 133 | #X connect 42 0 40 0; 134 | #X connect 43 0 40 1; 135 | #X connect 44 0 48 0; 136 | #X connect 45 0 29 0; 137 | #X connect 46 0 12 0; 138 | #X connect 46 0 12 1; 139 | #X connect 47 0 19 0; 140 | #X connect 47 0 19 1; 141 | #X connect 48 0 42 0; 142 | #X connect 49 0 3 0; 143 | #X connect 50 0 2 0; 144 | #X connect 50 0 2 1; 145 | #X restore 482 2 pd punctuation; 146 | #N canvas 264 25 750 513 brackets 0; 147 | #X obj 148 39 r opb; 148 | #X obj 156 71 r clb; 149 | #X obj 65 143 vline~; 150 | #X obj 14 169 *~; 151 | #X obj 13 194 *~ 0.2; 152 | #X msg 65 119 1 100 \, 0 100 200; 153 | #X obj 9 142 osc~; 154 | #X obj 13 216 dac~; 155 | #X obj 10 119 vline~; 156 | #X msg 10 72 440 \, 880 400; 157 | #X msg 21 92 880 \, 440 400; 158 | #X obj 332 129 vline~; 159 | #X obj 209 215 *~; 160 | #X obj 208 240 *~ 0.2; 161 | #X msg 332 105 1 100 \, 0 100 200; 162 | #X obj 208 262 dac~; 163 | #X obj 206 107 vline~; 164 | #X msg 206 60 440 \, 880 400; 165 | #X msg 217 80 880 \, 440 400; 166 | #X obj 344 27 r ops; 167 | #X obj 352 59 r cls; 168 | #X obj 556 158 vline~; 169 | #X obj 505 184 *~; 170 | #X obj 504 209 *~ 0.2; 171 | #X msg 556 134 1 100 \, 0 100 200; 172 | #X obj 500 157 osc~; 173 | #X obj 504 231 dac~; 174 | #X obj 501 88 vline~; 175 | #X msg 501 41 440 \, 880 400; 176 | #X msg 512 61 880 \, 440 400; 177 | #X obj 501 135 +~; 178 | #X obj 639 54 r opc; 179 | #X obj 647 86 r clc; 180 | #X obj 455 114 *~ 100; 181 | #X obj 454 88 osc~ 5; 182 | #X obj 205 130 osc~; 183 | #X obj 200 162 expr~ $v1 > 0; 184 | #X connect 0 0 9 0; 185 | #X connect 0 0 5 0; 186 | #X connect 1 0 10 0; 187 | #X connect 1 0 5 0; 188 | #X connect 2 0 3 1; 189 | #X connect 3 0 4 0; 190 | #X connect 4 0 7 0; 191 | #X connect 4 0 7 1; 192 | #X connect 5 0 2 0; 193 | #X connect 6 0 3 0; 194 | #X connect 8 0 6 0; 195 | #X connect 9 0 8 0; 196 | #X connect 10 0 8 0; 197 | #X connect 11 0 12 1; 198 | #X connect 12 0 13 0; 199 | #X connect 13 0 15 0; 200 | #X connect 13 0 15 1; 201 | #X connect 14 0 11 0; 202 | #X connect 16 0 35 0; 203 | #X connect 17 0 16 0; 204 | #X connect 18 0 16 0; 205 | #X connect 19 0 17 0; 206 | #X connect 19 0 14 0; 207 | #X connect 20 0 18 0; 208 | #X connect 20 0 14 0; 209 | #X connect 21 0 22 1; 210 | #X connect 22 0 23 0; 211 | #X connect 23 0 26 0; 212 | #X connect 23 0 26 1; 213 | #X connect 24 0 21 0; 214 | #X connect 25 0 22 0; 215 | #X connect 27 0 30 1; 216 | #X connect 28 0 27 0; 217 | #X connect 29 0 27 0; 218 | #X connect 30 0 25 0; 219 | #X connect 31 0 28 0; 220 | #X connect 31 0 24 0; 221 | #X connect 32 0 29 0; 222 | #X connect 32 0 24 0; 223 | #X connect 33 0 30 0; 224 | #X connect 34 0 33 0; 225 | #X connect 35 0 36 0; 226 | #X connect 36 0 12 0; 227 | #X restore 502 42 pd brackets; 228 | #N canvas 474 70 450 300 numbsynth 0; 229 | #X obj 26 41 mtof; 230 | #X obj 27 166 *~; 231 | #X obj 198 113 vline~; 232 | #X obj 26 212 dac~; 233 | #X obj 27 68 phasor~; 234 | #X obj 26 19 r num; 235 | #X obj 197 51 r num; 236 | #X floatatom 247 59 5 0 0 0 - - -; 237 | #X msg 198 88 1 30 \, 0 200 100; 238 | #X obj 27 186 *~ 0.4; 239 | #X msg 96 69 \$1 100; 240 | #X obj 88 89 line; 241 | #X obj 27 138 bp~ 100 5; 242 | #X connect 0 0 4 0; 243 | #X connect 0 0 10 0; 244 | #X connect 1 0 9 0; 245 | #X connect 2 0 1 1; 246 | #X connect 4 0 12 0; 247 | #X connect 5 0 0 0; 248 | #X connect 6 0 8 0; 249 | #X connect 6 0 7 0; 250 | #X connect 8 0 2 0; 251 | #X connect 9 0 3 0; 252 | #X connect 9 0 3 1; 253 | #X connect 10 0 11 0; 254 | #X connect 11 0 12 1; 255 | #X connect 12 0 1 0; 256 | #X restore 496 84 pd numbsynth; 257 | #N canvas 104 35 860 501 punctuation2 0; 258 | #X obj 24 140 osc~; 259 | #X obj 24 118 line~; 260 | #X obj 69 140 osc~; 261 | #X obj 69 118 line~; 262 | #X obj 66 214 *~; 263 | #X msg 8 63 440 \, 880 100; 264 | #X msg 32 82 440 \, 220 100; 265 | #X obj 65 236 dac~; 266 | #X obj 13 28 r <; 267 | #X obj 63 34 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 268 | -1; 269 | #X obj 119 188 vline~; 270 | #X msg 114 161 1 10 \, 0 200 10; 271 | #X obj 244 136 osc~; 272 | #X obj 244 114 line~; 273 | #X obj 282 136 osc~; 274 | #X obj 282 114 line~; 275 | #X obj 310 195 *~; 276 | #X obj 311 219 dac~; 277 | #X obj 321 27 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 278 | -1; 279 | #X obj 316 137 vline~; 280 | #X msg 319 114 1 10 \, 0 200 10; 281 | #X obj 254 30 r >; 282 | #X msg 233 62 220 \, 440 100; 283 | #X msg 250 85 880 \, 440 100; 284 | #X obj 457 35 r "; 285 | #X obj 427 167 osc~; 286 | #X obj 427 145 line~; 287 | #X obj 458 241 *~; 288 | #X obj 459 265 dac~; 289 | #X obj 464 183 vline~; 290 | #X msg 423 110 10000 \, 5000 100; 291 | #X obj 462 57 del 100; 292 | #X msg 467 160 1 10 \, 0 50 10; 293 | #X obj 36 281 r -; 294 | #X obj 12 363 osc~; 295 | #X obj 43 437 *~; 296 | #X obj 44 461 dac~; 297 | #X obj 49 379 vline~; 298 | #X obj 150 355 osc~; 299 | #X obj 150 333 line~; 300 | #X obj 181 429 *~; 301 | #X obj 182 453 dac~; 302 | #X obj 187 371 vline~; 303 | #X msg 190 348 1 10 \, 0 300 10; 304 | #X obj 174 273 r +; 305 | #X msg 147 298 50 \, 1000 300; 306 | #X obj 288 349 osc~; 307 | #X obj 288 327 line~; 308 | #X obj 319 423 *~; 309 | #X obj 320 447 dac~; 310 | #X obj 325 365 vline~; 311 | #X msg 329 342 1 10 \, 0 300 10; 312 | #X obj 312 267 r /; 313 | #X msg 285 292 440 \, 880 1000; 314 | #X obj 660 254 r &; 315 | #X obj 717 418 dac~; 316 | #X obj 722 338 vline~; 317 | #X obj 719 398 *~; 318 | #X msg 726 315 1 10 \, 0 400 10; 319 | #X obj 646 314 random 10000; 320 | #X obj 644 340 osc~; 321 | #X obj 471 356 osc~; 322 | #X obj 471 334 line~; 323 | #X obj 502 430 *~; 324 | #X obj 503 454 dac~; 325 | #X obj 508 372 vline~; 326 | #X msg 512 349 1 10 \, 0 300 10; 327 | #X obj 495 274 r backslash; 328 | #X msg 468 299 880 \, 440 1000; 329 | #X obj 66 188 *~ 0.3; 330 | #X obj 312 174 *~ 0.3; 331 | #X obj 461 221 *~ 0.3; 332 | #X obj 45 417 *~ 0.3; 333 | #X msg 9 306 1000; 334 | #X obj 183 408 *~ 0.3; 335 | #X obj 321 402 *~ 0.3; 336 | #X obj 504 408 *~ 0.3; 337 | #X obj 718 375 *~ 0.3; 338 | #X msg 51 358 1 10 \, 0 400 10; 339 | #X obj 649 287 bang; 340 | #X connect 0 0 69 0; 341 | #X connect 1 0 0 0; 342 | #X connect 2 0 69 0; 343 | #X connect 3 0 2 0; 344 | #X connect 4 0 7 0; 345 | #X connect 4 0 7 1; 346 | #X connect 5 0 1 0; 347 | #X connect 6 0 3 0; 348 | #X connect 8 0 5 0; 349 | #X connect 8 0 6 0; 350 | #X connect 8 0 11 0; 351 | #X connect 9 0 5 0; 352 | #X connect 9 0 6 0; 353 | #X connect 9 0 11 0; 354 | #X connect 10 0 4 1; 355 | #X connect 11 0 10 0; 356 | #X connect 12 0 70 0; 357 | #X connect 13 0 12 0; 358 | #X connect 14 0 70 0; 359 | #X connect 15 0 14 0; 360 | #X connect 16 0 17 0; 361 | #X connect 16 0 17 1; 362 | #X connect 18 0 22 0; 363 | #X connect 18 0 23 0; 364 | #X connect 18 0 20 0; 365 | #X connect 19 0 16 1; 366 | #X connect 20 0 19 0; 367 | #X connect 21 0 22 0; 368 | #X connect 21 0 23 0; 369 | #X connect 21 0 20 0; 370 | #X connect 22 0 13 0; 371 | #X connect 23 0 15 0; 372 | #X connect 24 0 31 0; 373 | #X connect 24 0 32 0; 374 | #X connect 25 0 71 0; 375 | #X connect 26 0 25 0; 376 | #X connect 27 0 28 0; 377 | #X connect 27 0 28 1; 378 | #X connect 29 0 27 1; 379 | #X connect 30 0 26 0; 380 | #X connect 31 0 32 0; 381 | #X connect 31 0 30 0; 382 | #X connect 32 0 29 0; 383 | #X connect 33 0 73 0; 384 | #X connect 33 0 78 0; 385 | #X connect 34 0 72 0; 386 | #X connect 35 0 36 0; 387 | #X connect 35 0 36 1; 388 | #X connect 37 0 35 1; 389 | #X connect 38 0 74 0; 390 | #X connect 39 0 38 0; 391 | #X connect 40 0 41 0; 392 | #X connect 40 0 41 1; 393 | #X connect 42 0 40 1; 394 | #X connect 43 0 42 0; 395 | #X connect 44 0 45 0; 396 | #X connect 44 0 43 0; 397 | #X connect 45 0 39 0; 398 | #X connect 46 0 75 0; 399 | #X connect 47 0 46 0; 400 | #X connect 48 0 49 0; 401 | #X connect 48 0 49 1; 402 | #X connect 50 0 48 1; 403 | #X connect 51 0 50 0; 404 | #X connect 52 0 53 0; 405 | #X connect 52 0 51 0; 406 | #X connect 53 0 47 0; 407 | #X connect 54 0 58 0; 408 | #X connect 54 0 79 0; 409 | #X connect 56 0 57 1; 410 | #X connect 57 0 55 0; 411 | #X connect 57 0 55 1; 412 | #X connect 58 0 56 0; 413 | #X connect 59 0 60 0; 414 | #X connect 60 0 77 0; 415 | #X connect 61 0 76 0; 416 | #X connect 62 0 61 0; 417 | #X connect 63 0 64 0; 418 | #X connect 63 0 64 1; 419 | #X connect 65 0 63 1; 420 | #X connect 66 0 65 0; 421 | #X connect 67 0 68 0; 422 | #X connect 67 0 66 0; 423 | #X connect 68 0 62 0; 424 | #X connect 69 0 4 0; 425 | #X connect 70 0 16 0; 426 | #X connect 71 0 27 0; 427 | #X connect 72 0 35 0; 428 | #X connect 73 0 34 0; 429 | #X connect 74 0 40 0; 430 | #X connect 75 0 48 0; 431 | #X connect 76 0 63 0; 432 | #X connect 77 0 57 0; 433 | #X connect 78 0 37 0; 434 | #X connect 79 0 59 0; 435 | #X restore 482 23 pd punctuation2; 436 | #X obj 34 152 s let; 437 | #X obj 79 153 s num; 438 | #X obj 72 46 print; 439 | #N canvas 0 0 733 336 punctuation-route 0; 440 | #X obj 57 27 inlet; 441 | #X obj 57 78 s stop; 442 | #X obj 74 101 s comma; 443 | #X obj 89 129 s "; 444 | #X obj 106 153 s exclaim; 445 | #X obj 122 73 s question; 446 | #X obj 138 97 s <; 447 | #X obj 155 118 s >; 448 | #X obj 171 146 s <; 449 | #X obj 187 169 s >; 450 | #X obj 204 72 s <; 451 | #X obj 220 95 s >; 452 | #X obj 236 117 s hash; 453 | #X obj 253 140 s =; 454 | #X obj 269 164 s _; 455 | #X obj 285 73 s <; 456 | #X obj 301 96 s >; 457 | #X obj 318 118 s "; 458 | #X obj 334 145 s -; 459 | #X obj 351 73 s +; 460 | #X obj 367 98 s /; 461 | #X obj 385 124 s backslash; 462 | #X obj 57 52 route 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 463 | 20; 464 | #X connect 0 0 22 0; 465 | #X connect 22 0 1 0; 466 | #X connect 22 1 2 0; 467 | #X connect 22 2 3 0; 468 | #X connect 22 3 4 0; 469 | #X connect 22 4 5 0; 470 | #X connect 22 5 6 0; 471 | #X connect 22 6 7 0; 472 | #X connect 22 7 8 0; 473 | #X connect 22 8 9 0; 474 | #X connect 22 9 10 0; 475 | #X connect 22 10 11 0; 476 | #X connect 22 11 12 0; 477 | #X connect 22 12 13 0; 478 | #X connect 22 13 14 0; 479 | #X connect 22 14 15 0; 480 | #X connect 22 15 16 0; 481 | #X connect 22 16 17 0; 482 | #X connect 22 17 18 0; 483 | #X connect 22 18 19 0; 484 | #X connect 22 19 20 0; 485 | #X connect 22 20 21 0; 486 | #X restore 125 154 pd punctuation-route; 487 | #X obj 34 65 route letter num punct location; 488 | #N canvas 0 0 450 300 location 0; 489 | #X obj 59 66 inlet; 490 | #X obj 59 109 unpack s s f f; 491 | #X symbolatom 59 140 10 0 0 0 - - -; 492 | #X symbolatom 86 166 10 0 0 0 - - -; 493 | #X floatatom 113 197 5 0 0 0 - - -; 494 | #X floatatom 140 225 5 0 0 0 - - -; 495 | #X connect 0 0 1 0; 496 | #X connect 1 0 2 0; 497 | #X connect 1 1 3 0; 498 | #X connect 1 2 4 0; 499 | #X connect 1 3 5 0; 500 | #X restore 171 125 pd location; 501 | #X text 243 1 Text to music synthesis patch; 502 | #X text 244 12 Andrew James Faraday - May 2012; 503 | #X text 231 182 Note: this patch must be open for the ruby text to 504 | music scripts to work.; 505 | #X obj 493 106 loadbang; 506 | #X msg 493 127 dsp 1; 507 | #X obj 495 149 s pd; 508 | #X text 314 128 compute audio as standard -->; 509 | #X connect 0 0 9 0; 510 | #X connect 0 0 11 0; 511 | #X connect 11 0 7 0; 512 | #X connect 11 1 8 0; 513 | #X connect 11 2 10 0; 514 | #X connect 11 3 12 0; 515 | #X connect 16 0 17 0; 516 | #X connect 17 0 18 0; 517 | -------------------------------------------------------------------------------- /scripts/github-commits.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Andrew James Faraday - May 2013 3 | # 4 | # This is an attempt to review github commits. 5 | # 6 | 7 | require './lib/pd-connect' 8 | require 'yaml' 9 | require 'rss' 10 | 11 | # Set up a port into pd 12 | pd = PureData.new 13 | 14 | # Get rss feed url 15 | # default feed is set if arguments are empty, otherwise, the first argument is used 16 | if ARGV.empty? 17 | repo = YAML.load_file("config.yml")['rss']['github']['repo'] 18 | branch = YAML.load_file("config.yml")['rss']['github']['branch'] 19 | else 20 | repo = ARGV[0] 21 | branch = ARGV[1] 22 | branch ||= YAML.load_file("config.yml")['rss']['github']['branch'] 23 | end 24 | puts "Sonifying repo: #{repo} branch: #{branch}" 25 | url = "https://www.github.com/#{repo}/commits/#{branch}.atom" 26 | 27 | # an array of used ids, to avoid repeats 28 | used_ids = [] 29 | 30 | # the actual script, will find the most recent headline, 31 | # if it's changed, the headline and description will be sent to pure data 32 | 33 | 34 | loop do 35 | feed = RSS::Parser.parse(open(url).read, false) 36 | feed.items.each do |item| 37 | unless used_ids.include? item.id.content 38 | used_ids << item.id.content 39 | # Selecting content from feed item 40 | title = item.title.content.strip 41 | author = item.author.name.content 42 | date = item.updated.content.strftime('%Y %b %d') 43 | content = item.content.content.gsub(/(<[^>]*>)|\n|\t/s) {" "}.strip 44 | # Constructing commit string 45 | puts("#{author}(#{date})") 46 | pd.send_string(content) 47 | 2.times{puts ''} 48 | sleep 1 49 | end 50 | end 51 | sleep 60 52 | end 53 | 54 | -------------------------------------------------------------------------------- /scripts/github-realtime.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Andrew James Faraday - May 2013 3 | # 4 | # This is an attempt to sonify github commits in real time 5 | # 6 | 7 | require './lib/pd-connect' 8 | require 'yaml' 9 | require 'rss' 10 | 11 | # Set up a port into pd 12 | pd = PureData.new 13 | 14 | # Get rss feed url 15 | # default feed is set if arguments are empty, otherwise, the first argument is used 16 | if ARGV.empty? 17 | repo = YAML.load_file("config.yml")['rss']['github']['repo'] 18 | branch = YAML.load_file("config.yml")['rss']['github']['branch'] 19 | else 20 | repo = ARGV[0] 21 | branch = ARGV[1] 22 | branch ||= YAML.load_file("config.yml")['rss']['github']['branch'] 23 | end 24 | polling_time = YAML.load_file("config.yml")['rss']['github']['polling_time'] 25 | puts "Sonifying repo: '#{repo}' branch: '#{branch}' with a delay of #{polling_time} seconds." 26 | url = "https://www.github.com/#{repo}/commits/#{branch}.atom" 27 | # an array of used ids, to avoid repeats 28 | 29 | # the actual script, will find the most recent headline, 30 | # if it's changed, the headline and description will be sent to pure data 31 | 32 | # This collects the last 21 ids and avoids these being sonified 33 | feed = RSS::Parser.parse(open(url).read, false) 34 | used_ids = feed.items.collect{|item| item.id.content} 35 | 36 | # This will check the last 20 commit ids against the used ids array 37 | # And sonify them if they are new 38 | 39 | loop do 40 | puts "Polling commits on '#{repo}' at #{Time.now.strftime('%H:%M:%S')}" 41 | 42 | feed.items.each do |item| 43 | unless used_ids.include? item.id.content 44 | used_ids << item.id.content 45 | # Selecting content from feed item 46 | title = item.title.content.strip 47 | author = item.author.name.content 48 | date = item.updated.content.strftime('%Y %b %d') 49 | content = item.content.content.gsub(/(<[^>]*>)|\n|\t/s) {" "}.strip 50 | # Constructing commit string 51 | puts("#{author}(#{date})") 52 | pd.send_string(content) 53 | 2.times{puts ''} 54 | sleep 1 55 | end 56 | end 57 | # Wait ten seconds, then poll again 58 | sleep polling_time 59 | feed = RSS::Parser.parse(open(url).read, false) 60 | end 61 | 62 | -------------------------------------------------------------------------------- /scripts/manual-input.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Andrew James Faraday - May 2012 3 | # 4 | # This script is to allow direct manual control of the text-to-music algorithm. 5 | # After a simple check of speed (1 divided by numbers 1 to 10 = number of seconds between characters) the user is prompted to provide textual input which is then sonified. 6 | # This is recommended as a first experience of the text-to-music system, so new users can see the correlation between their use of text and the resulting sound. 7 | # press ctrl+c to exit the script 8 | # 9 | 10 | # 11 | # Update, 11 Jun 2012 12 | # 13 | # The script, with a surprisingly simple set of changes, can now be fed a file, which it reads. This opens the rather mind-blowing possibility of running this line: 14 | # 15 | # ruby scripts/manual-input.rb scripts/manual-input.rb 16 | # 17 | # The above command will use this file to read and sonify this file including this comment about reading and sonifying this file. 18 | # 19 | 20 | require './lib/pd-connect' 21 | 22 | # If the first argument is a valid file, place a flag to skip prompts 23 | begin 24 | file = File.new(ARGV[0]) 25 | puts "Reading file: #{file.path}" 26 | rescue 27 | # a convenience rescue to keep the process silent when a file is not present. 28 | end 29 | 30 | # Set up a port into pd 31 | pd = PureData.new 32 | 33 | if file and file.is_a? File 34 | # Automatically set the playback speed 35 | speed = 0.15 36 | show_prompt = false 37 | else 38 | # Manually set the playback speed 39 | puts "what speed? (1 to 10)" 40 | onetoten = gets.to_f 41 | unless onetoten && onetoten >= 1 && onetoten <= 10 42 | onetoten = 10.0 43 | puts "defaulted to 10!" 44 | end 45 | speed = (1 / onetoten) 46 | show_prompt = true 47 | end 48 | 49 | # Repeatedly prompt the user to provide some text to sonify. 50 | phrase = '' 51 | until phrase.nil? do 52 | puts 'Phrase:' if show_prompt 53 | phrase = nil 54 | phrase = gets 55 | pd.send_string(phrase.chomp, speed) if phrase 56 | puts '' 57 | end 58 | -------------------------------------------------------------------------------- /scripts/rss-feed.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Andrew James Faraday - May 2012 3 | # 4 | 5 | require './lib/pd-connect' 6 | require 'yaml' 7 | require 'rss' 8 | 9 | # Set up a port into pd 10 | pd = PureData.new 11 | 12 | # Get rss feed url 13 | # default feed is set if arguments are empty, otherwise, the first argument is used 14 | if ARGV.empty? 15 | url = YAML.load_file("config.yml")['rss']['default_feed'] 16 | else 17 | url = ARGV[0] 18 | end 19 | # an array of used titles, to avoid repeats 20 | used_titles = [] 21 | 22 | # the actual script, will find the most recent headline, 23 | # if it's changed, the headline and description will be sent to pure data 24 | 25 | puts url 26 | 27 | loop do 28 | feed = RSS::Parser.parse(open(url).read, false) 29 | feed.items[0..9].each do |item| 30 | unless used_titles.include? item.title 31 | used_titles << item.title 32 | string = "#{item.title}! - #{item.description}" 33 | pd.send_string(string) 34 | 2.times{puts ''} 35 | sleep 1 36 | end 37 | end 38 | sleep 10 39 | end 40 | 41 | -------------------------------------------------------------------------------- /scripts/string_slicer.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Andrew James Faraday - April 2013 3 | # 4 | # This script is an attempt to progressively vary and change a string over 5 | # time allowing the user to hear a provess of string transforms taking 6 | # place with the text-to-music algorithm. 7 | # 8 | # It's a string slicer, which will take an opening string and a number, 9 | # then divide the string into groups of that number and increase the 10 | # last character of the string. 11 | # 12 | # Every 8 instances the slicing factor will increase 13 | # 14 | 15 | # A string transform method 16 | class String 17 | # Increases one character in the middle of a string 18 | def slice_and_increase(groups_of) 19 | self.scan(/.{1,#{groups_of}}/).collect{|x|x.succ}.join 20 | end 21 | end 22 | 23 | # creates a string of a given length with hashes at given intervals 24 | def demo_string(length,interval) 25 | result = '' 26 | until result.length >= length 27 | (interval - 1).times{result << ' '} 28 | result << '#' 29 | end 30 | result[0...length] 31 | end 32 | 33 | 34 | 35 | # Add TTM library 36 | require './lib/pd-connect' 37 | 38 | # Set up port into pure data 39 | pd = PureData.new 40 | 41 | # Acquire a string from the user 42 | puts 'Phrase:' 43 | string = gets 44 | string = string.chomp 45 | 46 | puts "Choose a number:" 47 | number = gets.to_i 48 | 49 | 50 | puts demo_string(string.length, number) 51 | i = 1 52 | loop do 53 | # Send the string to PD 54 | pd.send_string(string, 0.1) 55 | puts '' 56 | # Every 8 instances increase the slicing factor 57 | if i % 8 == 0 58 | number = number+1 59 | puts "Slice increased to #{number}" 60 | puts demo_string(string.length, number) 61 | end 62 | if number > string.length 63 | puts "Slices are bigger than your string." 64 | puts "Let's just say it came to a natural ending." 65 | break 66 | end 67 | # every time. perform the transform 68 | string = string.slice_and_increase(number) 69 | i += 1 70 | end 71 | 72 | -------------------------------------------------------------------------------- /scripts/twitter-search.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Andrew James Faraday - May 2012 3 | # 4 | # The twitter stream script is a way to automatically feed the text-to-music algorithm from the twitter streaming api. 5 | # A search, either default (from config.yml) or manually (from the command line) will be returned in real-time as tweets are posted and then sonified or kept in a queue (deal with by the twitter streaming api) to be sonified in turn. 6 | # 7 | 8 | require 'rubygems' 9 | require 'highline/import' 10 | require 'tweetstream' 11 | require './lib/pd-connect' 12 | require './lib/twitter-auth' 13 | 14 | # Set up a port to PureData 15 | pd = PureData.new 16 | 17 | # Load attributes from the config file 18 | config = YAML.load_file("twitter.yml") 19 | 20 | search = config['default_search'].split(' ') 21 | # default search is set if arguments are empty 22 | if ARGV.empty? 23 | search = search 24 | else 25 | search = ARGV.join ' ' 26 | end 27 | 28 | consumer_key, consumer_secret, oauth_token, oauth_token_secret = get_twitter_auth(config) 29 | 30 | # Configure TweetStream 31 | TweetStream.configure do |config| 32 | config.consumer_key = consumer_key 33 | config.consumer_secret = consumer_secret 34 | config.oauth_token = oauth_token 35 | config.oauth_token_secret = oauth_token_secret 36 | config.auth_method = :oauth 37 | end 38 | 39 | 40 | # Set up new TweetStream client 41 | ts = TweetStream::Client.new 42 | # Last bits of information 43 | #TODO catch incorrect username/password at this stage 44 | puts 'initialization finished' 45 | puts "search: #{search}" 46 | 47 | ts.on_error do |error| 48 | puts "ERROR: #{error}" 49 | end 50 | 51 | # Code to be run on finding a tweet matching search term. 52 | ts.track(search) do |status| 53 | begin 54 | # Output user and source to the console 55 | puts '' 56 | puts "[#{status.user.screen_name}] - #{status.source}" 57 | # Send location to console and pure data if present 58 | puts "location: #{status.place.country} - #{status.place.name}" if status.place 59 | pd.send_location(status.place, status.geo) 60 | # Set and sonify tweet text, format => "[mr_bloke] this is a tweet #fail #win #woot!" 61 | string = "[#{status.user.screen_name}] #{status.text}" 62 | pd.send_string(string) 63 | puts '' 64 | rescue => er 65 | # display any errors that occur while keeping the stream open. 66 | puts er.message 67 | puts er.backtrace 68 | end 69 | end 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /scripts/twitter-userstream.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Andrew James Faraday - May 2012 3 | # 4 | # The twitter stream script is a way to automatically feed the text-to-music algorithm from the twitter userstream api. 5 | # A users stream will be returned in real-time as tweets are posted and then sonified or kept in a queue (deal with by the twitter streaming api) to be sonified in turn. 6 | # 7 | 8 | require 'rubygems' 9 | require 'tweetstream' 10 | require './lib/pd-connect' 11 | require './lib/twitter-auth' 12 | 13 | config = YAML.load_file("twitter.yml") 14 | 15 | # Set up a port to PureData 16 | pd = PureData.new 17 | 18 | consumer_key, consumer_secret, oauth_token, oauth_token_secret = get_twitter_auth(config) 19 | 20 | # Configure TweetStream 21 | TweetStream.configure do |config| 22 | config.consumer_key = consumer_key 23 | config.consumer_secret = consumer_secret 24 | config.oauth_token = oauth_token 25 | config.oauth_token_secret = oauth_token_secret 26 | config.auth_method = :oauth 27 | end 28 | 29 | # Set up new TweetStream client 30 | ts = TweetStream::Client.new 31 | # Last bits of information 32 | puts 'initialization finished' 33 | 34 | # Code to be run on finding a tweet matching search term. 35 | ts.on_timeline_status do |status| 36 | begin 37 | # Output user and source to the console 38 | puts '' 39 | puts "[#{status.user.screen_name}] - #{status.source}" 40 | # Send location to console and pure data if present 41 | puts "location: #{status.place.country} - #{status.place.name}" if status.place 42 | pd.send_location(status.place, status.geo) 43 | # Set and sonify tweet text in this format: "[mr_bloke] this is a tweet #fail #win #woot!" 44 | string = "[#{status.user.screen_name}] #{status.text}" 45 | pd.send_string(string) 46 | puts '' 47 | rescue => er 48 | # display any errors that occur while keeping the stream open. 49 | puts er.message 50 | puts er.backtrace 51 | end 52 | end 53 | 54 | ts.on_error do |error| 55 | puts "ERROR: #{error}" 56 | end 57 | 58 | ts.userstream 59 | 60 | -------------------------------------------------------------------------------- /twitter.yml.template: -------------------------------------------------------------------------------- 1 | --- 2 | consumer_key: I9bnoRdRPzhAdxdlAy7Qw 3 | consumer_secret: t1a6rX1bza1lZuN1ARIrwraRvzpDFIhhL94mdNhtFY 4 | default_search: fail 5 | oauth_token: 6 | oauth_token_secret: 7 | --------------------------------------------------------------------------------