Re: LPCM Downmix Algorithm problem
Re: LPCM Downmix Algorithm problem
- Subject: Re: LPCM Downmix Algorithm problem
- From: uɐıʇəqɐz pnoqɥɒɯ <email@hidden>
- Date: Mon, 16 Aug 2010 08:04:03 -0700
On Aug 14, 2010, at 8:00 PM, Steve Bird wrote:
>
> On Aug 14, 2010, at 10:48 PM, Bob Ingraham wrote:
>
>> Ok, so one last time, because code is fairly simple, like my brain:
>>
>> To mix two 16-bit-signed samples:
>>
>> MixedSample = Sample1 + Sample2 - (Sample1 * Sample2);
>
> ---- I don't know where you got that algorithm, but apply a little brainpower to it:
> If Sample1 is 10000 and Sample2 is 10000 then you're going to subtract 100,000,000 from the sum?
> That will have a hard time fitting into a 16-bit word.
Since I was the one who presented that faulty algorithm, then let me try to explain how I got to it. Now keep in mind that after testing it and verifying that it SEEMED to work, I abandoned it and went with using the iPhone's AU mixers, so I didn't know that there were any real issues beyond listening to it for a few tries and deciding that it didn't work as well as Core Audio.
On this list, I had many posters tell me that to mix, I should do the following:
totalSample = (sampleA + sampleB + sampleC + ...) / number of samples.
However, this didn't sit well for me. Imagine the situation where you have two samples, one that has an amplitude of 0.8 and the other has the amplitude of 0.05. (Both on scale of −1.0 to 1.0). Why should the totalSample be 0.425? Why not 0.85? Or even 0.7? Why should I degrade my louder signal, if a softer one is also playing? I am not mixing with the intention to make sure both signals are heard; I am mixing to make sure each signal gets its own representation, with the caveat that I don't want to exceed |1.0| and get distortion.
Thus, I thought another algorithm was needed. One that only came into play as the total of the two signals began to encroach on abs(1.0), and left the signals alone if they were well away from the maximum points at either end,
> If Sample1 is 10000 and Sample2 is 10000 then you're going to subtract 100,000,000 from the sum?
Think of it this way:
If sample1 is 1.0 and sample2 is 1.0, then you're going to subtract 1.0 from the sum, and get, 1.0.
If sample1 is 0.6 and sample2 is 0.5, then you are going to subtract 0.3 from the sum of 1.1 and get 0.8.
If sample1 is 0.4 and sample2 is 0.2, then you will subtract 0.08 from the total of 0.6 and get 0.52.
If sample1 is 0.8 and sample2 is 0.9, then you will subtract 0.72 from the total of 1.7 and get 0.98.
Now, to get here, you have to provide normalized data within 0-1.0. Not −1.0 to 1.0. Not −32767-32768. If you are working with floats, and you have a −1.0 to 1.0 range, then you add 1 and divide by 2. If you are using 16bit −32767-32767 then you use a 32 bit temp, add 2^16 and divide by 2.
After you've mixed as above, then you have to turn it back into the appropriate format.
Doesn't this all sound too perfect, simple and straightforward?
Nope. I see one big flaw in how two non-normalised negative signals would add up. Normally, the negative numbers would add up pushing the signal further down into the negatives. Normalizing as above would mean that those two signals would actually add up towards the midpoint:
if sample1 is −0.8 and sample2 is −0.7, then when normalized, the two samples would be 0.1 and 0.15, added together are 0.25 minus the product would be 0.235, and un-normalized, we'd end up with −0.53. Without any kind of clipping protection, these two signals would have been added up to −1.5. With my ideal anticlipping, I'd want it at −0.94. Not good.
What if we normalized to −1.0 to 1.0 and used: totalSample = (sample1 + sample2) - (sign(sample1+ sample2) * (sample1 * sample2))
Let's see:
If sample1 is 1.0 and sample2 is 1.0, then you're going to subtract 1.0 from the sum, and get, 1.0.
If sample1 is 0.6 and sample2 is 0.5, then you are going to subtract 0.3 from the sum of 1.1 and get 0.8.
If sample1 is 0.4 and sample2 is 0.2, then you will subtract 0.08 from the total of 0.6 and get 0.52.
If sample1 is -0.8 and sample2 is −0.7, then you will add 0.56 to the total of −1.5 and get -0.94.
If sample1 is -0.5 and sample2 is -0.9, then you will add 0.45 to the total of -1.4 and get −0.95.
Cool!? Nope:
If sample1 is −1.0 and sample2 is 1.0, then you will subtract 1.0 from the total of 0 and get −1. Should be 0.
If sample1 is −0.5 and sample2 is 0.5, then you will subtract 0.25 to the total of 0 and get -0.25. Should be 0.
Now, given that I found the AU mixer to be adequate for my needs, I haven't delved into this any more. But it seems to me that there must be a simple, yet better alternative to mix = (sampleA + sampleB) / 2.
Maybe once I have my new apps released and my consulting project over with, I can delve into it. OR at least when I've had more sleep.
BTW, a really cool tool for visualization of all this is Graphing Calculator:
https://files.me.com/mahboud/3cnd84
the blue is sample1 and sample2.
Teal is (sample1+sample2) - (sample1*sample2) see how well it performs above the line?
Green is (sample1+sample2)/2.
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden