Audio

From Devipedia

Jump to: navigation, search

I've been wanting the ability to slice up wave files algorithmically for some time and with python, pyaudio, and wave it's not too tricky. With this little program I take a wave file and oscillate the start point using the cos function while playing it back. It's a bit hard to explain the result, so take a listen instead.

The original sample is a sound clip from Baby Got Back that I called shake.wav. I ran jackwave.py (the name I gave the script below), passing shake.wav, a required argument, and an option argument (-o) which is the name of the wave file that gets written. When running this script, you'll always hear the output, but it won't be saved unless you provide an output file name.

dvenable@dvenable-laptop:~/src/py/wave$ python jackwave.py -o default.wav shake.wav 

This is the result, converted to mp3 to save on bandwidth.

http://www.devinvenable.com/static/default.mp3

You can optionally provide a frequency argument that speeds up the rate of oscillation, as I did here.

dvenable@dvenable-laptop:~/src/py/wave$ python jackwave.py -o freq22.wav -f 22 shake.wav 

http://www.devinvenable.com/static/freq22.mp3

Hear the difference?

#!/usr/bin/python

import pyaudio
import wave
import sys
import time
import math
import argparse


def main(args):
    
    chunk = 1024
    wf = wave.open(args.file, 'rb')
    p = pyaudio.PyAudio()

    # open stream
    stream = p.open(format =
                    p.get_format_from_width(wf.getsampwidth()),
                    channels = wf.getnchannels(),
                    rate = wf.getframerate(),
                    output = True)

    # read data
    data = wf.readframes(chunk)
    pos = wf.tell()

    offset = cnt  = 0
    angleStep = math.pi * 2 / chunk 
    out = []

    # play stream
    while data != '':
        stream.write(data)
        if args.outfile: 
            out.append(data)

        data = wf.readframes(chunk)
        pos2 = wf.tell()
        cnt += args.frequency 
        offset = abs(math.sin(cnt * angleStep) * chunk) 
        wf.setpos(pos2 - int(offset)) 

    stream.close()
    p.terminate()

    if args.outfile:
        # write data to WAVE file
        data = ''.join(out)
        wo = wave.open(args.outfile, 'wb')
        wo.setnchannels(wf.getnchannels())
        wo.setsampwidth(wf.getsampwidth())
        wo.setframerate(wf.getframerate())
        wo.writeframes(data)
        wo.close()

if __name__=="__main__":
    parser = argparse.ArgumentParser(description='Jack with a wave file using cosine offset.')
    parser.add_argument('file',   
                   help='Name of a wave file: example.wav')
    parser.add_argument('-f', dest='frequency', action='store', default=1, 
                        type=int,
                        help='Rate of oscillation applied. Defaults to 1. (1,n)')
    parser.add_argument('-o', dest='outfile', action='store', 
                        help='Save resulting audio to this file')

    args = parser.parse_args()
    
    main(args)
Personal tools