Quellcode durchsuchen

add argparse to render script, add makefile.

Thomas Buck vor 10 Monaten
Ursprung
Commit
31bd021985
3 geänderte Dateien mit 72 neuen und 32 gelöschten Zeilen
  1. 28
    0
      Makefile
  2. 3
    0
      README.md
  3. 41
    32
      render.py

+ 28
- 0
Makefile Datei anzeigen

@@ -0,0 +1,28 @@
1
+inputs = $(wildcard *.svg)
2
+
3
+outputs = $(inputs:%.svg=output/%_44100.wav)
4
+outputs += $(inputs:%.svg=output/%_48000.wav)
5
+outputs += $(inputs:%.svg=output/%_96000.wav)
6
+outputs += $(inputs:%.svg=output/%_192000.wav)
7
+
8
+.PHONY: all
9
+all: output ${outputs}
10
+
11
+output:
12
+	mkdir output
13
+
14
+output/%_44100.wav: %.svg
15
+	./render.py -s 44100 -o $(@:%.svg=%_44100.wav) $<
16
+
17
+output/%_48000.wav: %.svg
18
+	./render.py -s 48000 -o $(@:%.svg=%_48000.wav) $<
19
+
20
+output/%_96000.wav: %.svg
21
+	./render.py -s 96000 -o $(@:%.svg=%_96000.wav) $<
22
+
23
+output/%_192000.wav: %.svg
24
+	./render.py -s 192000 -o $(@:%.svg=%_192000.wav) $<
25
+
26
+.PHONY: clean
27
+clean:
28
+	rm -rf output

+ 3
- 0
README.md Datei anzeigen

@@ -5,3 +5,6 @@ Please see [my blog post for more details](https://www.xythobuz.de/osci_music_pl
5 5
 Quick start instructions can be found in the top comment of the Python script in this repo.
6 6
 
7 7
     ssh osci-music "sudo systemctl disable --now osci.service" && scp osci-pi.py osci-music:~ && ssh osci-music "sudo systemctl enable --now osci.service"
8
+
9
+Also include a simple script to convert single SVG paths to audio.
10
+Run the included makefile to convert the SVG files in this directory.

+ 41
- 32
render.py Datei anzeigen

@@ -23,15 +23,10 @@
23 23
 
24 24
 import sys
25 25
 import wave
26
+import argparse
26 27
 from svgpathtools import svg2paths
27 28
 
28
-samplerate = 44100 #192000
29
-volume_percent = 70
30
-path_steps = 10
31
-default_duration = 5.0
32
-default_outfile = "out.wav"
33
-
34
-def read_image(filename):
29
+def read_image(filename, path_steps, volume_percent):
35 30
     paths, attributes = svg2paths(filename)
36 31
     path = paths[0]
37 32
     if len(paths) > 1:
@@ -72,16 +67,25 @@ def read_image(filename):
72 67
             p.append(v)
73 68
         return p
74 69
 
70
+    def add_segment(p1, p2, f):
71
+        p = interpolate(p1, p2, f)
72
+        add_point(p)
73
+
75 74
     for n in range(0, len(points) - 1):
76
-        p1 = points[n]
77
-        p2 = points[n + 1]
78 75
         for step in range(0, path_steps):
79
-            p = interpolate(p1, p2, step / path_steps)
80
-            add_point(p)
81
-    add_point(points[len(points) - 1])
76
+            add_segment(points[n], points[n + 1], step / path_steps)
77
+
78
+    #add_point(points[len(points) - 1])
79
+
80
+    for n in range(len(points) - 2, -1, -1):
81
+        for step in range(0, path_steps):
82
+            add_segment(points[n + 1], points[n], step / path_steps)
83
+
84
+    add_point(points[0])
85
+
82 86
     return data
83 87
 
84
-def write_waveform(data, filename):
88
+def write_waveform(data, filename, samplerate):
85 89
     with wave.open(filename, "w") as f:
86 90
         f.setnchannels(2)
87 91
         f.setsampwidth(2)
@@ -89,26 +93,31 @@ def write_waveform(data, filename):
89 93
         f.writeframes(data)
90 94
 
91 95
 def main():
92
-    if len(sys.argv) <= 1:
93
-        print("Usage:")
94
-        print("\t" + sys.argv[0] + " image.png [out.wav] [seconds]")
95
-        sys.exit(1)
96
-
97
-    if len(sys.argv) == 3:
98
-        duration = float(sys.argv[2])
99
-        outfile = default_outfile
100
-    if len(sys.argv) >= 4:
101
-        duration = float(sys.argv[2])
102
-        outfile = sys.argv[3]
103
-    else:
104
-        duration = default_duration
105
-        outfile = default_outfile
106
-
107
-    wave = read_image(sys.argv[1])
96
+    parser = argparse.ArgumentParser(
97
+        prog=sys.argv[0],
98
+        description='Render SVG path to vector XY audio file',
99
+        epilog='Made by Thomas Buck <thomas@xythobuz.de>. Licensed as GPLv3.')
100
+
101
+    parser.add_argument("input", help="Input SVG image file path.")
102
+    parser.add_argument("-o", "--output", dest="output", default="out.wav",
103
+                        help="Output wav sound file path. Defaults to 'out.wav'.")
104
+    parser.add_argument("-t", "--time", dest="time", default=5.0, type=float,
105
+                        help="Length of sound file in seconds. Defaults to 5s.")
106
+    parser.add_argument("-s", "--samplerate", dest="samplerate", default=44100, type=int,
107
+                        help="Samplerate of output file in Hz. Defaults to 44.1kHz.")
108
+    parser.add_argument("-v", "--volume", dest="volume", default=100.0, type=float,
109
+                        help="Volume of output file in percent. Defaults to 100%%.")
110
+    parser.add_argument("-i", "--interpolate", dest="interpolate", default=10, type=int,
111
+                        help="Steps on interpolated paths. Defaults to 10.")
112
+
113
+    args = parser.parse_args()
114
+    print(args)
115
+
116
+    wave = read_image(args.input, args.interpolate, args.volume)
108 117
 
109 118
     samplecount = int(len(wave) / 2 / 2) # stereo, int16
110
-    drawrate = samplerate / samplecount
111
-    drawcount = drawrate * duration
119
+    drawrate = args.samplerate / samplecount
120
+    drawcount = drawrate * args.time
112 121
     print("len={} samples={} drawrate={:.2f} count={:.2f}".format(len(wave), samplecount, drawrate, drawcount))
113 122
 
114 123
     data = bytearray()
@@ -116,7 +125,7 @@ def main():
116 125
         data.extend(wave)
117 126
     print("len={}".format(len(data)))
118 127
 
119
-    write_waveform(bytes(data), outfile)
128
+    write_waveform(bytes(data), args.output, args.samplerate)
120 129
 
121 130
 if __name__ == "__main__":
122 131
     main()

Laden…
Abbrechen
Speichern