Working on chorizo player, will be there soon
This commit is contained in:
parent
8fd18513ef
commit
de7ae02da0
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*__pycache*
|
28
Chorizo player/LICENSE.md
Normal file
28
Chorizo player/LICENSE.md
Normal file
@ -0,0 +1,28 @@
|
||||
Chorizo.py :
|
||||
====
|
||||
|
||||
This script allows you to play music using a chorizo (or whatever food you
|
||||
like) keyboard ! See README for more info and links.
|
||||
|
||||
As all the other scripts in this repository, I release it under a very
|
||||
permissive license. To make a long story short : do whatever you want with
|
||||
this script (but try to have fun :), I don't mind. It would be cool to quote
|
||||
the origin of the script if you reuse it, but you don't have to. I'd like to
|
||||
be noticed of what you did cool with it (if you think it's worth). :)
|
||||
Ah, I almost forgot : If by chance we ever meet and you think this script is
|
||||
worth, you can buy me a soda :)
|
||||
|
||||
Phyks
|
||||
|
||||
|
||||
Sound4Python.py : https://github.com/standarddeviant/sound4python
|
||||
====
|
||||
Note : The version of sound4python.py in this project is slightly modified (some print statements commented and a bugfix).
|
||||
|
||||
Copyright (C) 2013 dave.crist@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
115
Chorizo player/chorizo.py
Executable file
115
Chorizo player/chorizo.py
Executable file
@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ============================================================================
|
||||
# This script allows you to play music using a chorizo (or whatever food you
|
||||
# like) keyboard ! See README for more info and links.
|
||||
|
||||
# As all the other scripts in this repository, I release it under a very
|
||||
# permissive license. To make a long story short : do whatever you want with
|
||||
# this script (but try to have fun :), I don't mind. It would be cool to quote
|
||||
# the origin of the script if you reuse it, but you don't have to. I'd like to
|
||||
# be noticed of what you did cool with it (if you think it's worth). :)
|
||||
# Ah, I almost forgot : If by chance we ever meet and you think this script is
|
||||
# worth, you can buy me a soda :)
|
||||
#
|
||||
# Phyks
|
||||
# =============================================================================
|
||||
|
||||
from sound4python import sound
|
||||
from multiprocessing oimport Process
|
||||
import math
|
||||
import serial
|
||||
import sys
|
||||
import getopt
|
||||
|
||||
|
||||
def play_wave(frequency=440, nb_secs=1):
|
||||
sine_wave = []
|
||||
for i in range(nb_secs*framerate):
|
||||
sine_wave.append(int(16384*math.sin(2*math.pi*frequency*i/framerate)))
|
||||
|
||||
sound(sine_wave)
|
||||
|
||||
serial_port = "/dev/ttyACM0"
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hs:", ["help", "serial="])
|
||||
|
||||
for opt, arg in opts:
|
||||
if opt in ("-h", "--help"):
|
||||
print("Play music with chorizos !")
|
||||
print("\nUsage : "+sys.argv[0]+" [OPTIONS]")
|
||||
print("\nOptions :")
|
||||
print("\t-h (--help) \t display this help message")
|
||||
print("\t-s (--serial=) \t change serial port (default is " +
|
||||
"/dev/tty/ACM0")
|
||||
sys.exit(0)
|
||||
elif opt in ("-s", "--serial"):
|
||||
serial_port = arg
|
||||
except getopt.GetoptError:
|
||||
pass
|
||||
|
||||
try:
|
||||
ser = serial.Serial(serial_port, 115200)
|
||||
except Exception as e:
|
||||
sys.exit("Error with serial port :"+str(e))
|
||||
|
||||
framerate = 16000
|
||||
frequencies = [440, 600, 880]
|
||||
gap_times = 10
|
||||
p = []
|
||||
for i in range(3):
|
||||
processes.append(Process(target=play_wave, args=(frequencies[i], 1)))
|
||||
processes[-1].start()
|
||||
|
||||
try:
|
||||
ser.open()
|
||||
except Exception as e:
|
||||
sys.exit("Error while opening serial port : "+str(e))
|
||||
|
||||
if ser.isOpen():
|
||||
try:
|
||||
ser.flushInput()
|
||||
ser.flushOutput()
|
||||
|
||||
measures = [[], [], []]
|
||||
|
||||
print("Calibration :")
|
||||
print("Touch each chorizo electrodes before starting")
|
||||
|
||||
for i in range(10000):
|
||||
line = ser.readline()
|
||||
line = line.decode().strip("\r\n")
|
||||
line = line.split(" ")
|
||||
line = [int(j or 0) for j in line]
|
||||
|
||||
for j in range(3):
|
||||
measures[j][i] = line[j]
|
||||
|
||||
|
||||
# Get threshold
|
||||
threshold = [-1, -1, -1]
|
||||
for i in range(3):
|
||||
gap = -1
|
||||
for j in range(1, 10000):
|
||||
if measures[i][j] - measures[i][j-1] > gap:
|
||||
gap = measures[i][j] - measures[i][j-1]
|
||||
threshold[i] = (measures[i][j]+measures[i][j-1])/2
|
||||
|
||||
print("Running...")
|
||||
running = True
|
||||
while running:
|
||||
# Read line from serial
|
||||
line = ser.readline()
|
||||
line = line.decode().strip("\r\n")
|
||||
line = line.split(" ")
|
||||
line = [int(j or 0) for j in line]
|
||||
|
||||
for i in range(3):
|
||||
if line[i] > threshold[i]:
|
||||
print("Playing")
|
||||
p[i].start()
|
||||
|
||||
p[i].join()
|
||||
except Exception as e:
|
||||
sys.exit("Error while handling data from serial : "+str(e))
|
94
Chorizo player/sound4python.py
Normal file
94
Chorizo player/sound4python.py
Normal file
@ -0,0 +1,94 @@
|
||||
|
||||
try: import tempfile, wave, subprocess, os, signal, struct
|
||||
except:
|
||||
print("E: sound4python is unable to import a combination of %s"%
|
||||
("tempfile, wave, subprocess, os, signal, struct"))
|
||||
|
||||
FNULL = open(os.devnull,'w')
|
||||
def launchWithoutConsole(args,output=False):
|
||||
"""Launches args windowless and waits until finished"""
|
||||
startupinfo = None
|
||||
if( 'STARTUPINFO' in dir(subprocess) ):
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
if( output ):
|
||||
return subprocess.Popen(args, stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,startupinfo=startupinfo, )
|
||||
else:
|
||||
return subprocess.Popen(args, stdin=subprocess.PIPE,
|
||||
stdout=FNULL ,stderr=FNULL, startupinfo=startupinfo)
|
||||
|
||||
# sound4python
|
||||
def sound(itr,samprate=16000,autoscale=True,output=False):
|
||||
try: import numpy as np; foundNumpy=True;
|
||||
except:
|
||||
foundNumpy=False;
|
||||
|
||||
#for now, assume 1-D iterable
|
||||
mult = 1
|
||||
if( autoscale ):
|
||||
mult = 32767.0 / max(itr)
|
||||
#mult = 128.0 / max(itr)
|
||||
|
||||
#create file in memory
|
||||
#with tempfile.SpooledTemporaryFile() as memFile:
|
||||
memFile = tempfile.SpooledTemporaryFile()
|
||||
|
||||
#create wave write objection pointing to memFile
|
||||
waveWrite = wave.open(memFile,'wb')
|
||||
waveWrite.setsampwidth(2) # int16 default
|
||||
waveWrite.setnchannels(1) # mono default
|
||||
waveWrite.setframerate(samprate) # 8kHz default
|
||||
|
||||
wroteFrames=False
|
||||
#Let's try to create sound from NumPy vector
|
||||
if( foundNumpy ):
|
||||
if( type(itr)==np.array ):
|
||||
if( itr.ndim == 1 or itr.shape.count(1) == itr.ndim - 1 ):
|
||||
waveWrite.writeframes( (mult*itr.flatten()).astype(np.int16).tostring() )
|
||||
wroteFrames=True
|
||||
else: #we have np, but the iterable isn't a vector
|
||||
waveWrite.writeframes( (mult*np.array(itr)).astype(np.int16).tostring() )
|
||||
wroteFrames=True
|
||||
if( not wroteFrames and not foundNumpy ):
|
||||
#python w/o np doesn't have "short"/"int16", "@h" is "native,aligned short"
|
||||
waveWrite.writeframes( struct.pack(len(itr)*"@h",[int(mult*itm) for itm in itr]) )
|
||||
wroteFrames=True
|
||||
|
||||
if( not wroteFrames ):
|
||||
print("E: Unable to create sound. Only 1D numpy arrays and numerical lists are supported.")
|
||||
waveWrite.close()
|
||||
return None
|
||||
|
||||
#configure the file object, memFile, as if it has just been opened for reading
|
||||
memFile.seek(0)
|
||||
|
||||
try:
|
||||
# getting here means wroteFrames == True
|
||||
#print("\nAttempting to play a mono audio stream of length")
|
||||
#print(" %.2f seconds (%.3f thousand samples at sample rate of %.3f kHz)"%
|
||||
# ( 1.0*len(itr)/samprate , len(itr)/1000. , int(samprate)/1000.) )
|
||||
p=launchWithoutConsole(['sox','-','-d'])
|
||||
except:
|
||||
print("E: Unable to launch sox.")
|
||||
print("E: Please ensure that sox is installed and on the path.")
|
||||
print("E: Try 'sox -h' to test sox installation.")
|
||||
waveWrite.close()
|
||||
return None
|
||||
|
||||
try:
|
||||
p.communicate(memFile.read())
|
||||
p.wait()
|
||||
except:
|
||||
print("E: Unable to send in-memory wave file to stdin of sox subprocess.")
|
||||
waveWrite.close()
|
||||
return None
|
||||
#os.kill(p.pid,signal.CTRL_C_EVENT)
|
||||
#end def sound(itr,samprate=8000,autoscale=True)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
100
Chorizo player/test_player.py
Executable file
100
Chorizo player/test_player.py
Executable file
@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ============================================================================
|
||||
# This script allows you to play music using a chorizo (or whatever food you
|
||||
# like) keyboard ! See README for more info and links.
|
||||
|
||||
# As all the other scripts in this repository, I release it under a very
|
||||
# permissive license. To make a long story short : do whatever you want with
|
||||
# this script (but try to have fun :), I don't mind. It would be cool to quote
|
||||
# the origin of the script if you reuse it, but you don't have to. I'd like to
|
||||
# be noticed of what you did cool with it (if you think it's worth). :)
|
||||
# Ah, I almost forgot : If by chance we ever meet and you think this script is
|
||||
# worth, you can buy me a soda :)
|
||||
#
|
||||
# Phyks
|
||||
# =============================================================================
|
||||
|
||||
from sound4python import sound
|
||||
from multiprocessing import Process
|
||||
import math
|
||||
|
||||
class _Getch:
|
||||
"""Gets a single character from standard input. Does not echo to the
|
||||
screen."""
|
||||
def __init__(self):
|
||||
try:
|
||||
self.impl = _GetchWindows()
|
||||
except ImportError:
|
||||
self.impl = _GetchUnix()
|
||||
|
||||
def __call__(self): return self.impl()
|
||||
|
||||
|
||||
class _GetchUnix:
|
||||
def __init__(self):
|
||||
import tty, sys
|
||||
|
||||
def __call__(self):
|
||||
import sys, tty, termios
|
||||
fd = sys.stdin.fileno()
|
||||
old_settings = termios.tcgetattr(fd)
|
||||
try:
|
||||
tty.setraw(sys.stdin.fileno())
|
||||
ch = sys.stdin.read(1)
|
||||
finally:
|
||||
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
||||
return ch
|
||||
|
||||
|
||||
class _GetchWindows:
|
||||
def __init__(self):
|
||||
import msvcrt
|
||||
|
||||
def __call__(self):
|
||||
import msvcrt
|
||||
return msvcrt.getch()
|
||||
|
||||
getch = _Getch()
|
||||
|
||||
def play_wave(frequency=440, nb_secs=1.):
|
||||
sine_wave = []
|
||||
for i in range(math.ceil(nb_secs*framerate)+1):
|
||||
sine_wave.append(int(16384*math.sin(2*math.pi*frequency*i/framerate)))
|
||||
|
||||
sound(sine_wave)
|
||||
|
||||
framerate = 16000
|
||||
processes = []
|
||||
frequency = 440
|
||||
|
||||
print("Running... Press q to quit.")
|
||||
running = True
|
||||
while running:
|
||||
char = getch()
|
||||
if char == "q":
|
||||
running = False
|
||||
continue
|
||||
elif char == "a":
|
||||
frequency = 440
|
||||
elif char == "b":
|
||||
frequency = 493.88
|
||||
elif char == "c":
|
||||
frequency = 523.25
|
||||
elif char == "d":
|
||||
frequency = 587.33
|
||||
elif char == "e":
|
||||
frequency = 659.26
|
||||
elif char == "f":
|
||||
frequency = 698.46
|
||||
elif char == "g":
|
||||
frequency = 783.99
|
||||
else:
|
||||
continue
|
||||
|
||||
print("Playing "+char.upper())
|
||||
processes.append(Process(target=play_wave, args=(frequency, 0.2)))
|
||||
processes[-1].start()
|
||||
|
||||
for i in processes:
|
||||
i.join()
|
@ -46,14 +46,14 @@ try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hs:", ["help", "serial="])
|
||||
|
||||
for opt, arg in opts:
|
||||
if opt == "-h" or opt == "-help":
|
||||
if opt in ("-h", "--help"):
|
||||
print("Touchless 3D tracking with color mapping")
|
||||
print("\nUsage : "+sys.argv[0]+" [OPTIONS]")
|
||||
print("\nTrack the position of your hand in 3D and map it " +
|
||||
"in RGB space")
|
||||
print("\nOptions :")
|
||||
print("\t-h (--help) \t display this help message")
|
||||
print("\t-s (--serial) \t change serial port (default is " +
|
||||
print("\t-s (--serial=) \t change serial port (default is " +
|
||||
"/dev/tty/ACM0")
|
||||
sys.exit(0)
|
||||
elif opt in ("-s", "--serial"):
|
@ -25,17 +25,17 @@ where `value1`, `value2`, `value3` are values directly proportional to the disch
|
||||
|
||||
You'll also find some basic Python scripts as examples on possible use of the setup.
|
||||
|
||||
### Colors.py
|
||||
### Colors
|
||||
|
||||
This script represents the position of your hand in the RGB space. You can then pick a color by placing your hand at a specific point in the box of the electrodes.
|
||||
|
||||
### Chorizo.py
|
||||
### Chorizo player
|
||||
|
||||
__(working on)__
|
||||
|
||||
A script to play music using chorizo pads as a musical keyboard. See [our website](http://hackens.org/Projets/TouchlessTracking) (french, but vids are available, more coming soon) for infos and demos.
|
||||
|
||||
### 3d_view.py
|
||||
### 3d view
|
||||
|
||||
__(working on)__
|
||||
|
||||
|
61
chorizo.py
61
chorizo.py
@ -1,61 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ============================================================================
|
||||
# This script allows you to play music using a chorizo (or whatever food you
|
||||
# like) keyboard ! See README for more info and links.
|
||||
|
||||
# As all the other scripts in this repository, I release it under a very
|
||||
# permissive license. To make a long story short : do whatever you want with
|
||||
# this script (but try to have fun :), I don't mind. It would be cool to quote
|
||||
# the origin of the script if you reuse it, but you don't have to. I'd like to
|
||||
# be noticed of what you did cool with it (if you think it's worth). :)
|
||||
# Ah, I almost forgot : If by chance we ever meet and you think this script is
|
||||
# worth, you can buy me a soda :)
|
||||
#
|
||||
# Phyks
|
||||
# =============================================================================
|
||||
|
||||
# TODO
|
||||
|
||||
import wave
|
||||
import math
|
||||
import pyaudio
|
||||
import sys
|
||||
|
||||
|
||||
# Params
|
||||
# ======
|
||||
nChannels = 1 # Mono
|
||||
sample_size = 2 # Size of a sample -> 1 = 8 bits
|
||||
framerate = 44100 # Sampling frequency
|
||||
length = 2 # Length in seconds
|
||||
frequency = 440
|
||||
level = 1
|
||||
# =====
|
||||
|
||||
if level < 0.0 or level > 1.0:
|
||||
sys.exit(1)
|
||||
|
||||
filename = "temp"
|
||||
w = wave.open(filename, 'w')
|
||||
|
||||
# Computed params
|
||||
nFrames = int(length*framerate)
|
||||
max_amplitude = int(2**(sample_size * 8 - 1) - 1)
|
||||
amplitude = max_amplitude*level
|
||||
|
||||
w.setparams((nChannels, sample_size, framerate, nFrames,
|
||||
'NONE', 'not compressed'))
|
||||
|
||||
sine_wave = []
|
||||
for i in range(min(framerate, nFrames)):
|
||||
sine_wave.append(int(max_amplitude +
|
||||
amplitude*math.sin(2*math.pi*frequency*i/framerate)))
|
||||
|
||||
for i in range(nFrames):
|
||||
sine_wave = int(amplitude*math.sin(2*math.pi*frequency*i/framerate))
|
||||
data = wave.struct.pack('h', sine_wave)
|
||||
# ^ h is for "short" so each value can go from -2**15 to 2**15
|
||||
w.writeframesraw(data)
|
||||
|
||||
w.close()
|
Loading…
Reference in New Issue
Block a user