-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbytebeat.rb
executable file
·102 lines (95 loc) · 3.17 KB
/
bytebeat.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/bin/env ruby
require "optparse"
options = {}
OptionParser.new do |opts|
options[:outputFile] = "music.out"
options[:inputFile] = "main.music"
options[:willRun] = false
options[:defaultCompiler] = "gcc"
options[:keepTemp] = false
options[:noInstrument] = false
options[:willVisualize] = false
opts.banner = "Usage: bytebeat.rb [options] [input file]"
opts.separator "Note: You must have gcc (or a compatible compiler) installed."
opts.separator " You must have aplay installed to use `-r`."
opts.separator ""
opts.on("-o", "--output OUTPUTFILE", "Specify the file to output the compiled binary to (default music.out).") do |out|
options[:outputFile] = out
end
opts.on("-r", "--run-aplay", "Run the music file after compilation, using `aplay`.") do
options[:willRun] = true
end
opts.on("-v", "--visualize", "Open the visualizer and show the bytebeat as it plays.") do
options[:willRun] = false # this opt overrides willRun
options[:willVisualize] = true
end
opts.on("-c", "--compiler COMPILER", "Specify another compiler to use over `gcc`.") do |compiler|
options[:defaultCompiler] = compiler
end
opts.on("-k", "--keep-temp", "Keep the processed files produced before compilation.") do
options[:keepTemp] = true
end
opts.on("--no-instrument", "Don't compile in the `instrument.c` file.") do
options[:noInstrument] = true
end
opts.on_tail("-h", "--help", "Print this message.") do
puts opts
exit
end
end.parse!
# this may or may not be empty. if it's empty, handle it later
options[:inputFile] = ARGV[0]
tempFileName = "~#{options[:outputFile].split(?.).first.split(?/).last}.c"
music = ""
# handle an empty input file
if options[:inputFile].nil?
music = STDIN.read
else
# as long as the input file was supplied, read it
File.open(options[:inputFile], "r") do |inputFile|
music = inputFile.read
end
end
# then generate the temporary C file
File.open(tempFileName, "w") do |tempFile|
processedC = DATA.read.gsub(/REPLACE_ME/, music)
if options[:noInstrument]
processedC = processedC.split(?\n)[1..-1].join(?\n)
else
processedC.gsub!(/PATH_TO_INSTRUMENT_HEADER/, "#{File.expand_path(__dir__)}/c/instrument.h")
end
tempFile.write processedC
end
# and compile the C file(s)
if options[:noInstrument]
puts "#{options[:defaultCompiler]} \"#{tempFileName}\" -o \"#{options[:outputFile]}\""
puts `#{options[:defaultCompiler]} "#{tempFileName}" -o "#{options[:outputFile]}"`
else
puts "#{options[:defaultCompiler]} \"#{tempFileName}\" c/instrument.c -o \"#{options[:outputFile]}\""
puts `#{options[:defaultCompiler]} "#{tempFileName}" c/instrument.c -o "#{options[:outputFile]}"`
end
# delete the C file if the user wants us to
unless options[:keepTemp]
`rm "#{tempFileName}"`
end
puts "chmod +x #{options[:outputFile]}"
`chmod +x #{options[:outputFile]}`
# then run the output file if the user wants us to
if options[:willRun]
puts "./#{options[:outputFile]} | aplay"
puts `./#{options[:outputFile]} | aplay`
end
if options[:willVisualize]
require_relative "visualize.rb"
v = Visualizer.new(options[:outputFile])
v.mainLoop()
end
__END__
#include "PATH_TO_INSTRUMENT_HEADER"
#include <stdio.h>
int main() {
unsigned int t = 0;
for(;;t++){
putchar(REPLACE_ME);
}
}