Reputation: 13
For my final year project in college I am working with Wav Files and Python and messing around with them. I would love to be able to play the sound samples from memory rather than write the sound samples out in to a WAV file before I can hear them.
I have been looking for weeks online and have found PyMedia, PySound, PyGame etc and none of them seem to work for me. Every single package gives me errors.
Are there other libraries I am missing that would help me do this ? Or am I just being stupid and can't get the other packages to work.
Exactly what I want to do is along the lines of this:
#open file and get parameters
wavfile = Wave.open("file.wav", "r")
params = wfile.getparams()
nframes = params[3]
#get sound samples in a list
samples = []
for i in range(nframes):
samples.append(wfile.readframes(1))
playsound(samples)
changedSamples = makeChangeTo(samples)
playsound(changedSamples)
And I would like to be able to have this in a loop so I can edit and hear the edits while the program is still runnning without having to write the samples to a wav file before being able to hear it as that takes too long.
Any suggestions ? Cheers !
Upvotes: 1
Views: 5471
Reputation: 4914
You should clearly separate those two concerns:
Reading/writing WAV files (or other audio files)
Playing/recording sounds
There are several questions and answers to both topics here on SO.
This is my personal (and of course biased) recommendation:
You should use NumPy to manipulate sounds, it's much easier than handling plain Python buffers. If for some reason you cannot use NumPy, you can still do all this, but it will be a bit more work.
For reading/writing sound files, I recommend the soundfile module (full disclosure: I'm a co-author).
For playing/recording sounds, I recommend the sounddevice module (full disclosure: I'm its main author).
When using those modules, your example would probably become something like this:
import soundfile as sf
import sounddevice as sd
samples, samplerate = sf.read('file.wav')
sd.play(samples, samplerate)
sd.wait()
changed_samples = make_change_to(samples)
sd.play(changed_samples, samplerate)
sd.wait()
If you work in an interactive Python prompt, you probably don't need the sd.wait()
calls, you can just wait until the playback has finished. Or, if you get bored of listening to it, you can use:
sd.stop()
If you know that you will use the same sampling rate for some time, you can set it as default:
sd.default.samplerate = 48000
After that, you can drop the samplerate
argument when using play()
:
sd.play(samples)
If you want to store the changed sound to a file, you can use something like this:
sf.write('changed_file.wav', changed_samples, samplerate)
Further reading:
Upvotes: 7