Created
January 21, 2017 02:02
-
-
Save Mitame/7722184f2e7abcbbeccfcd0d43444496 to your computer and use it in GitHub Desktop.
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/python | |
import wave | |
import numpy | |
import struct | |
import sys | |
import csv | |
from scikits.samplerate import resample | |
def write_wav(data, filename, framerate, amplitude): | |
wavfile = wave.open(filename, "w") | |
nchannels = 1 | |
sampwidth = 2 | |
framerate = framerate | |
nframes = len(data) | |
comptype = "NONE" | |
compname = "not compressed" | |
wavfile.setparams((nchannels, | |
sampwidth, | |
framerate, | |
nframes, | |
comptype, | |
compname)) | |
print("Please be patient whilst the file is written") | |
frames = [] | |
for s in data: | |
if s < -1: | |
s = -1 | |
elif s > 1: | |
s = 1 | |
mul = int(s * amplitude) | |
#print "s: %f mul: %d" % (s, mul) | |
frames.append(struct.pack('h', mul)) | |
# frames = (struct.pack('h', int(s*self.amp)) for s in sine_list) | |
frames = ''.join(frames) | |
# for x in xrange(0, 7200): | |
# wavfile.writeframes(frames) | |
wavfile.writeframes(frames) | |
wavfile.close() | |
print("%s written" %(filename)) | |
if __name__ == "__main__": | |
if len(sys.argv) <= 1: | |
print "You must supply a filename to generate" | |
exit(-1) | |
for fname in sys.argv[1:]: | |
data = [] | |
for time, value in csv.reader(open(fname, 'U'), delimiter=','): | |
try: | |
data.append(float(value)) | |
except ValueError: | |
pass # Just skip it | |
print "Generating wave file from %d samples" % (len(data),) | |
arr = numpy.array(data) | |
print(arr[0:10]) | |
# Normalize data | |
arr /= numpy.max(numpy.abs(data)) | |
filename_head, extension = fname.rsplit(".", 1) | |
# Resample normalized data to 44.1 kHz | |
# target_samplerate = 44100 | |
# sampled = resample(arr, target_samplerate/100000.0, 'sinc_best') | |
sampled = arr | |
write_wav(sampled, filename_head + ".wav", 44100, 32700) |
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 bash | |
python3 tonedeaf.py && python2 generate.py output.csv |
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
import wave as wav | |
CLOCK_FREQ = 44100 | |
class Note: | |
def __init__(self, freq, amplitude, offset, length): | |
self.freq = freq | |
self.amplitude = amplitude | |
self.offset = offset * CLOCK_FREQ | |
self.length = length * CLOCK_FREQ | |
notes = [ | |
Note(440, 0.1, 0, 1), | |
Note(523.25, 0.1, 1, 1), | |
Note(659.25, 0.1, 1, 1), | |
Note(783.99, 0.1, 1, 2), | |
] | |
def create_wave(notes): | |
wave = [] | |
completed = [] | |
clock = 0 | |
has_ended = False | |
while not has_ended: | |
is_playing = False | |
amp = 0 | |
for note in notes: | |
play_from = note.offset | |
play_until = play_from + note.length | |
# print("Note will start at %i and end at %i" % (play_from, play_until)) | |
if play_from <= clock: | |
# Remove finished notes | |
if clock >= play_until: | |
completed.append(note) | |
continue | |
period = CLOCK_FREQ / note.freq | |
clock_since_start = clock - play_from | |
clock_since_start = (clock_since_start + (period / 4)) % period | |
clock_since_last_wave_start = clock_since_start % period | |
phase = clock_since_last_wave_start / period | |
# print(period, phase) | |
phase *= 4 | |
if phase < 1: | |
raw_amp = phase | |
elif phase < 3: | |
raw_amp = 2 - phase | |
else: | |
raw_amp = phase - 4 | |
amp += raw_amp * note.amplitude | |
is_playing = True | |
# Clipping | |
if amp > 1: | |
amp = 1 | |
elif amp < -1: | |
amp = -1 | |
wave.append(amp) | |
if not is_playing: | |
has_ended = True | |
clock += 1 | |
return wave | |
if __name__ == "__main__": | |
wave = create_wave(notes) | |
f = open("output.csv", "w") | |
f.write("Time,Amplitude\n" + "\n".join("%s,%s" % (i, str(wave[i])) for i in range(len(wave)))) | |
f.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment