e6fbaa2ffd
Due to the fact that we cut the sound at n seconds and not at the end of the period. Sidenote : dropped numpy part in sound4python, not happy with it.
101 lines
3.6 KiB
Python
101 lines
3.6 KiB
Python
|
|
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
|
|
# Not satisfied by the numpy implementation, buzzing and so...
|
|
#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)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|