I guess I’ll have to install something on my server then. I was hoping to avoid that. But I guess there’s no work-around. I was hoping there might be, but joining wav files is a much easier process than overlaying them.
If you really need it to be in pure php, you could merge raw wav-files, as long as they are unencoded and has the same bit-rate and sample-rate. It’s bound to be horribly slow and memory-expensive though.
Is there a way to do it with PHP? The script wouldn’t even run daily – like once/twice per week.
Just to reiterate:
I need to be able to overlay one .wav file over another and save it (e.g. voice over music)
ffmpeg doesn’t seem capable of doing this? I couldn’t find any support for it - but I did find a couple of posts around the net saying it wouldn’t be possible. I’d prefer to use straight PHP at this time, but if there is a command line program that’d be okay too.
If you want to mix together two tracks that are of the same sample rate, it’s pretty easy. You simply add the two tracks together, sample by sample. However, you need to be aware of clipping, but you can “solve” that by reducing the sample values so that they will not overflow (or underflow) the integer size.
I can’t say that anything you implement in pure PHP will be very fast though.
One of us can explain in more detail what you need to do, but you need to be familiar with how audio is recorded digitally first (samples, sample rate, bit depth, linear quantization, etc.).
I’m guessing this information could be extracted into an array. I’ve taken a look at the wavedit class – I looked at it earlier today as well – I just can’t seem to get the information I want out of the file.
Well, each sample is the smallest possible packet of sound. Samples are stored as your regular binary integers (not ASCII integers), and they can be stored in 8 bits, or 16 bits, etc. To read a WAV file, after you have parsed the WAV header and figured out the bit depth (8, 16, 24, etc.), you proceed to read the data block and start consuming integers. You can use unpack() to convert a binary integer into a PHP nubmer. In a standard stereo WAV file, you will have a sample for each channel, so for each small moment of time, there will be two samples.
After you have extracted the samples, you can simply add them together. However, you can’t just add the samples from two different files together because they can overflow or underflow the size of the integer, so you need to do something about that.
And by the way, as for what each sample means, it represents the amplitude of the sound wave at that precise moment in time. In your PCM wave files, linear quantization is used to store the samples. This means that the non-discrete range of wave amplitudes is all fit into your 8-bit/16-bit/etc. integer in a linear fashion. 50% amplitude is highest value of the signed integer divided in half.
To help you understand, you can check out the wave synthesis code I wrote a few years ago:
That function just generates a regular sine wave. encodeSample() takes the place of pack(). There you can see linear quantization in use (see $volume) and how a sample is generated for each channel.
alright, I took all of your advice and decided to use a command line program. and you’re right - it’s a lot faster.
so I’m using sox. now I’m just going through it all.
I’ve installed it - is it possible to add a codec now? Or did I need to do that first?
e.g. I’d like to work with mp3 files now that I can
All digital audio processing calculations take place using uncompressed raw samples format whether the source file is mp3 or not (mp3 doesn’t store discrete sample values as such). If you start with an mp3, then perform the mix process (the mp3 has to be converted first to raw pcm samples) then output (reconverted) to mp3 you have an extra generation of lossy compression (and quality degradation) than if you start with wavs->mix->output to mp3.