user_78361084
user_78361084

Reputation: 3908

How do I write a multi-frequency audio file?

I am trying to write an audio file with tones from 440hz to 600hz. The file should start at 440hz and then play each frequency (in increasing order) for 1 second, ending at 600hz. I've come up with python's wave module, but am doing something wrong here, as I end up with a file with no sound. (If someone has a better suggestion, I really don't care if it's in python or not. I am using Linux and anything that will work on that platform will do fine. I just need to create an audio file with the above specs. thx!)

frequencies = range(440,600)
data_size = len(frequencies)
fname = "WaveTest.wav"
frate = 11025.0  # framerate as a float
amp = 64000.0     # multiplier for amplitude

sine_list_x = []
for f in frequencies:
    for x in range(data_size):
        sine_list_x.append(math.sin(2*math.pi*f*(x/frate)))

wav_file = wave.open(fname, "w")

nchannels = 1
sampwidth = 2
framerate = int(frate)
nframes = data_size
comptype = "NONE"
compname = "not compressed"

wav_file.setparams((nchannels, sampwidth, framerate, nframes,
    comptype, compname))

for s in sine_list_x:
    # write the audio frames to file
    wav_file.writeframes(struct.pack('h', int(s*amp/2)))

wav_file.close()

Upvotes: 2

Views: 1210

Answers (2)

lucasg
lucasg

Reputation: 11002

It seems to works fine for me on a Windows plateform :

start of the signal at 440 Hz

end of the signal at 600 Hz

The sampling is respected and the frequencies are just right (from 440 to 600 Hz). However, in your code the frequencies does not stay for one second, but for len(frequencies)/frate-th of second. If you want to have a full second for every frequency, data_size should be equal to frate.

import math
import wave
import struct

frequencies = range(440,600)
duration = 1 #in second
fname = "WaveTest.wav"
frate = 11025.0  # framerate as a float
amp = 64000.0     # multiplier for amplitude

sine_list_x = []
for f in frequencies:
    for x in range(duration*frate)  :
        sine_list_x.append(math.sin(2*math.pi*f*(x/frate)))

wav_file = wave.open(fname, "w")

nchannels = 1
sampwidth = 2
framerate = int(frate)
nframes = data_size
comptype = "NONE"
compname = "not compressed"

wav_file.setparams((nchannels, sampwidth, framerate, nframes,
    comptype, compname))

for s in sine_list_x:
    # write the audio frames to file
    wav_file.writeframes(struct.pack('h', int(s*amp/2)))

wav_file.close()

Upvotes: 1

IamAlexAlright
IamAlexAlright

Reputation: 1500

Something like this should work: hopefully its at least a good starting point for you to continue.

import numpy as N
import wave

towrite = ''
for freq in xrange(440,600):
     duration = 1
     samplerate = 44100
     samples = duration*samplerate
     period = samplerate / float(freq) # in sample points
     omega = N.pi * 2 / period

     xaxis = N.arange(samples,dtype = N.float)
     ydata = 16384 * N.sin(xaxis*omega)

     signal = N.resize(ydata, (samples,))

     towrite += ''.join([wave.struct.pack('h',s) for s in signal])

 f = wave.open('freqs.wav', 'wb')
 f.setparams((1,2,44100, 44100*4, 'NONE', 'noncompressed'))
 f.writeframes(towrite)
 f.close()

Reference

Upvotes: 1

Related Questions