SoundTouch is a very useful set of audio manipulation tools, with three powerful features:
- Adjusting the pitch of a segment, without changing its tempo
- Adjusting the tempo of a segment, without changing its pitch
- Detecting the tempo of a segment, using beat detection
I used SoundTouch when I was developing CantoVario under the direction of Diana Dabby and using her algorithms for generating new music from existing music, using Lorenz attractors.  SoundTouch is a C++ library, but CantoVario was in python, so I built a wrapper for it.
Now you can use it too!  PySoundTouch, a python wrapper for the SoundTouch library is available on github!  It’s easy to use, especially with the super-cool AudioReader abstraction that I made with it.
AudioReader provides a single interface to any audio file (currently MP3, WAV, AIF, and AU files are supported). Â Here’s an example of using AudioReader with the SoundTouch library:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | # Open the file and convert it to have SoundTouch's required 2-byte samples reader = AudioReader. open (srcpath) reader2 = ConvertReader(reader, set_raw_width = 2 ) # Create the SoundTouch object and set the given shift st = soundtouch.SoundTouch(reader2.sampling_rate(), reader2.channels()) st.set_pitch_shift(shift) # Create the .WAV file to write the result to writer = wave. open (dstpath, 'w' ) writer.setnchannels(reader2.channels()) writer.setframerate(reader2.sampling_rate()) writer.setsampwidth(reader2.raw_width()) # Read values and feed them into SoundTouch while True : data = reader2.raw_read() if not data: break print len (data) st.put_samples(data) while st.ready_count() > 0 : writer.writeframes(st.get_samples( 11025 )) # Flush any remaining samples waiting = st.waiting_count() ready = st.ready_count() flushed = "" # Add silence until another chunk is pushed out silence = array( 'h' , [ 0 ] * 64 ) while st.ready_count() = = ready: st.put_samples(silence) # Get all of the additional samples while st.ready_count() > 0 : flushed + = st.get_samples( 4000 ) st.clear() if len (flushed) > 2 * reader2.getnchannels() * waiting: flushed = flushed[ 0 :( 2 * reader2.getnchannels() * waiting)] writer.writeframes(flushed) # Clean up writer.close() reader2.close() |
0 responses so far ↓
There are no comments yet...Kick things off by filling out the form below.