Skip to content

Instantly share code, notes, and snippets.

@Mitame
Created January 21, 2017 02:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mitame/7722184f2e7abcbbeccfcd0d43444496 to your computer and use it in GitHub Desktop.
Save Mitame/7722184f2e7abcbbeccfcd0d43444496 to your computer and use it in GitHub Desktop.
#!/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)
#!/usr/bin/env bash
python3 tonedeaf.py && python2 generate.py output.csv
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