On Thu, Sep 13, 2012 at 11:48 AM, D.V.N.Sarma డి.వి.ఎన్.శర్మ <dvnsa...@gmail.com> wrote: > > As far as programming volume is concerned winsound.Beep has only frequency > and duration. pyaudio module appears to have provision for volume control.
You should be able to add a wave header to a raw byte string. For example: import wave import winsound from cStringIO import StringIO def get_wave(data): f = StringIO() w = wave.open(f, 'w') w.setnchannels(1) # mono w.setsampwidth(2) # 2 bytes w.setframerate(48000) # samples/second w.writeframes(data) return f.getvalue() Then play the sound like this (_untested_): wave_data = get_wave(data) windsound.PlaySound(wave_data, winsound.SND_MEMORY) I've modified my previous script to add simple polyphonic sound. I included a basic square wave and a sawtooth wave, plus a random polyphonic wave. It's the kind of sound you might hear in a cheesy greeting card. Also, since you're looking to use winsound.PlaySound(), I changed the byte packing to use a little endian signed short (int16). I think that's what Windows wave files use. My demo below still uses pyaudio, which wraps the cross-platform PortAudio library. To me it seems like a better solution than relying on the standard library (e.g. the standard lib uses OSS on Linux; I don't even have that installed). Hopefully it performs OK on your computer. Using NumPy arrays would speed up the number crunching. import pyaudio from math import sin, pi from struct import pack from random import sample, randrange def polywave(freqs, amps, f0, fs): """create a polyphonic waveform freqs: sequence of frequencies (Hz) amps: sequence of amplitudes f0: fundamental frequency (Hz) fs: samples/second output is normalized to the range [-1,1]. """ N = int(fs / f0) rad_step = 2 * pi / fs # radians / (Hz * sample) wave = [0.0] * N for f, a in zip(freqs, amps): for n in xrange(N): wave[n] += a * sin(rad_step * f * n) maxamp = abs(max(wave, key=lambda x: abs(x))) return [samp / maxamp for samp in wave] def packwave(wave, vol=1, duration=None, fs=None): """pack a waveform as bytes (int16) wave: sample sequence, |mag| <= 1 vol: optional volume scale, |mag| <= 1 duration: optional loop time (seconds) fs: samples/second fs is required to set duration. """ scale = min(vol * 32767, 32767) ncycles = 1 if not (duration is None or fs is None): ncycles = int(round(1.0 * duration * fs / len(wave))) data = b''.join(pack('<h', scale * samp) for samp in wave) return data * ncycles def make_square(num, f0, fs): """generate square wave components num: number of harmonics f0: funamental frequency (Hz) fs: samples/second fs/2 is the upper bound. """ stop = min(2*num, int(fs / (2 * f0))) freqs = [n * f0 for n in xrange(1, stop, 2)] amps = [1.0 / n for n in xrange(1, stop, 2)] return freqs, amps def make_saw(num, f0, fs): """generate sawtooth wave components num: number of harmonics f0: funamental frequency (Hz) fs: samples/second fs/2 is the upper bound. """ stop = min(num + 1, int(fs / (2 * f0))) freqs = [n * f0 for n in xrange(1, stop)] amps = [(-1.0) ** (n + 1) / n for n in xrange(1, stop)] return freqs, amps def make_rand(num, f0, fs): """generate wave with random harmonics/amplitudes""" ftop = min(fs // 2, 12000) nmax = int(ftop / f0) num = min(num, nmax) freqs = [n * f0 for n in sample(xrange(1, nmax+1), num)] amps = [randrange(32768)/32767.0 for n in xrange(num)] return freqs, amps def play(data, stream): chunks = (data[i:i+1024] for i in xrange(0, len(data), 1024)) for chunk in chunks: stream.write(chunk) if __name__ == "__main__": from time import sleep fs = 48000 p = pyaudio.PyAudio() stream = p.open( format=pyaudio.paInt16, channels=1, rate=fs, frames_per_buffer=fs//4, output=True) # http://en.wikipedia.org/wiki/ # Equal_temperament#Calculating_absolute_frequencies note = lambda n: 440 * (2**(1/12.)) ** (-21 + n) scale = [note(n) for n in range(12)] rscale = [note(13-n) for n in range(12)] vols = [0.2 + 0.05*n for n in range(len(scale))] rvols = list(reversed(vols)) def play_scale(scale, vols, wave_func, master_vol=1): duration = 0.5 nharmonics = 30 for f0, vol in zip(scale, vols): freqs, amps = wave_func(nharmonics, f0, fs) wave = polywave(freqs, amps, f0, fs) data = packwave(wave, master_vol * vol, duration, fs) play(data, stream) sleep(0.5) play_scale(scale, vols, make_square, 0.5) play_scale(rscale, rvols, make_saw, 0.5) play_scale(scale, vols, make_rand, 0.75) play_scale(rscale, rvols, make_rand, 0.75) stream.close() p.terminate() _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor