Skip to content

Instantly share code, notes, and snippets.

@ferrihydrite
Created January 5, 2019 01:27
Show Gist options
  • Save ferrihydrite/f431f4aa955d85e1af2b7c76a742d479 to your computer and use it in GitHub Desktop.
Save ferrihydrite/f431f4aa955d85e1af2b7c76a742d479 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
"""
Created on Fri Jan 4 19:52:52 2019
Read an image, and read rows in a simplified grayscale version of an image to generate a wavetable of specified number of tables and wavelength.
Additionally reverse alternating rows of simplified image to prevent sharp changes in resulting wavetable.
"""
import matplotlib.pyplot as plt
import numpy as np
from scipy.io.wavfile import write
def odd_mirror(array):
'''
Flip every other row to avoid sharp changes in flattened array
'''
# work on copy of array (not inplace)
array=array.copy()
array[1::2, :] = array[1::2, ::-1]
return array
def rgb2gray(frame):
"""
Convert an image to grayscale
"""
# MATLAB's colorband-weighting algorithm
r, g, b = frame[:,:,0] , frame[:,:,1], frame[:,:,2]
gray = 0.2989*r + 0.5870*g + 0.1140*b
return gray
def degridize(data):
'''
Take 2D array and then turn it into spatially-referenced column data
'''
x_size, y_size = data.shape[1], data.shape[0]
columns=[(x,y,data[y,x]) for x in range(x_size) for y in range(y_size)]
return np.array(columns)
# read image
arr = plt.imread('image.jpg')
# convert to grayscale
imgr = rgb2gray(arr)
# flatten image to [x,y,intensity]
imfd = degridize(imgr)
# Wavelength [x-axis of image] and Number of tables [y-axis of image]
# [256,64] works for WaveEditOnline (and thus the Synthesis Technology
# wavetable modules), but these can be changed for modules like the Expert
# Sleepers Disting, which have changable wavelength and number of wavetable
# requirements.
wvlen=256
num_wav = 64
# calculate values within boxes across image
intensity, _, _ = np.histogram2d(imfd[:,1],imfd[:,0],bins=(num_wav,wvlen),
weights=imfd[:,2],
normed=False)
count, _, _ = np.histogram2d(imfd[:,1],imfd[:,0],bins=(num_wav,wvlen))
# shift to center at 0 and normalize intensity -1 to 1
norm_inten = ((intensity/count).view() / 255.) - 0.5
norm_inten = norm_inten / 0.5
# convert array to int16 and save wav file (Disting-compatible).
# this flattens array so that each row of the 2D historgram is an entry
# into the resulting wavetable
sc16 = (2**16)/2 -1
data_flip16 = (odd_mirror(norm_inten)*sc16).astype('int16').flatten()
write('wavetable.wav',44100,data_flip16)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment