-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaudio_processing.py
More file actions
113 lines (84 loc) · 3.27 KB
/
Copy pathaudio_processing.py
File metadata and controls
113 lines (84 loc) · 3.27 KB
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
103
104
105
106
107
108
109
110
111
112
113
# No Imports Allowed!
def backwards(sound):
raise NotImplementedError
def mix(sound1, sound2, p):
raise NotImplementedError
def echo(sound, num_echoes, delay, scale):
raise NotImplementedError
def pan(sound):
raise NotImplementedError
def remove_vocals(sound):
raise NotImplementedError
# below are helper functions for converting back-and-forth between WAV files
# and our internal dictionary representation for sounds
import io
import wave
import struct
def load_wav(filename, stereo=False):
"""
Given the filename of a WAV file, load the data from that file and return a
Python dictionary representing that sound
"""
f = wave.open(filename, "r")
chan, bd, sr, count, _, _ = f.getparams()
assert bd == 2, "only 16-bit WAV files are supported"
out = {"rate": sr}
if stereo:
left = []
right = []
for i in range(count):
frame = f.readframes(1)
if chan == 2:
left.append(struct.unpack("<h", frame[:2])[0])
right.append(struct.unpack("<h", frame[2:])[0])
else:
datum = struct.unpack("<h", frame)[0]
left.append(datum)
right.append(datum)
out["left"] = [i / (2**15) for i in left]
out["right"] = [i / (2**15) for i in right]
else:
samples = []
for i in range(count):
frame = f.readframes(1)
if chan == 2:
left = struct.unpack("<h", frame[:2])[0]
right = struct.unpack("<h", frame[2:])[0]
samples.append((left + right) / 2)
else:
datum = struct.unpack("<h", frame)[0]
samples.append(datum)
out["samples"] = [i / (2**15) for i in samples]
return out
def write_wav(sound, filename):
"""
Given a dictionary representing a sound, and a filename, convert the given
sound into WAV format and save it as a file with the given filename (which
can then be opened by most audio players)
"""
outfile = wave.open(filename, "w")
if "samples" in sound:
# mono file
outfile.setparams((1, 2, sound["rate"], 0, "NONE", "not compressed"))
out = [int(max(-1, min(1, v)) * (2**15 - 1)) for v in sound["samples"]]
else:
# stereo
outfile.setparams((2, 2, sound["rate"], 0, "NONE", "not compressed"))
out = []
for l, r in zip(sound["left"], sound["right"]):
l = int(max(-1, min(1, l)) * (2**15 - 1))
r = int(max(-1, min(1, r)) * (2**15 - 1))
out.append(l)
out.append(r)
outfile.writeframes(b"".join(struct.pack("<h", frame) for frame in out))
outfile.close()
if __name__ == "__main__":
# code in this block will only be run when you explicitly run your script,
# and not when the tests are being run. this is a good place to put your
# code for generating and saving sounds, or any other code you write for
# testing, etc.
# here is an example of loading a file (note that this is specified as
# sounds/meow.wav, rather than just as meow.wav, to account for the sound
# files being in a different directory than this file)
meow = load_wav("sounds/meow.wav")
# write_wav(backwards(meow), 'meow_reversed.wav')