Live player in python added

This commit is contained in:
Phyks 2013-12-06 00:44:04 +01:00
parent c43809e021
commit a62759297c
4 changed files with 228 additions and 0 deletions

28
Live player/LICENSE.md Normal file
View 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.

100
Live player/player.py Executable file
View 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()

View File

@ -0,0 +1,99 @@
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"
# BAD : waveWrite.writeframes( struct.pack(len(itr)*"@h",[int(mult*itm) for itm in itr]) )
writeValues = []
for itm in itr:
packed_value = struct.pack('h', int(mult*itm))
waveWrite.writeframes(packed_value)
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)

View File

@ -9,6 +9,7 @@ This is just a simple C code to handle wave files (see files wave_stuf.* for the
* _generateur.c_ which is the main program
* _generateur_musicsheet.py_ which is just a simple program to generate basic music sheet to use with the main program
* _wave_stuff.*_ which are the functions to handle wave files
* _Live_player/*_ : a python script to play music in live, using a, b, c, d, e, f and g keys on your keyboard.
## Usage of the main program