Many thanks in advance...
You need to keep a short running buffer that is always playing (do this
with the DSP auto-init DMA transfer). Each time the soundblaster
generates an interrupt, you fill the buffer with whatever is supposed to
be played next. The mixing part is simple. Convert the sounds to signed
format and add them together. (Do not divide!)
This is the technique I used in my sound freeware sound library, Varmint's
Audio Tools. (http://www.rt66.com/smeagol/html/vat.html)
-e
--------------- My WEB page: http://www.rt66.com/smeagol/ --------------------
--------- Ground Up: http://www.rt66.com/smeagol/html/groundup.html ----------
PC mod players usually do something like this:
1) Allocate one chunk of memory that can store 1/4 or so worth of
sound. This buffer is split into two chunks during playback. While one
is playing your program will fill the other with sound data (same
technique as double buffering).
2) Set up the DMA controller so that it plays both chunks in a
continuous loop, but generates an interrupt at the end of each chunk
(ie two interrupts for each complete playback of the entire buffer).
Info on how to set up the DMA chip like this is in the PCGPE
(x2ftp.oulu.fi /pub/msdos/programming/gpe).
3) Fill chunks 0 and 1 with some sound and start DMA. When a DMA
interrupt is generated you will know that chunk 1 is now playing and
that you can fill chunk 0 with the next block of sound. The next
interrupt will indicate that chunk 0 is playing so you can load chunk
1, and so on.
As fas as actually mixing the sound goes you should simply do this:
1) I assume your sample values are in the range 0->255 with a bias (ie
middle) point at 128 (the soundblaster uses this format with 8 bit
sound).
2) Convert each sample to a signed integer by subtracting 128, thus
putting them in the range -128->127.
3) Add all your samples together.
4) Clip the result to -128 and 127.
5) Convert back to an unsigned integer by adding 128. Store this value.
One of the quickest ways to do all this is to use the following
formula:
new_sample = (sum of all samples) - (number of samples - 1) * 128;
if (newsample < 0) newsample = 0;
if (newsample > 255) newsample = 255;
Clipping can of course be quickly performed using a lookup table. The
size of the lookup table would depend on the maximum number of samples
to mix. And make sure you cast the samples to type WORD when you sum
them so that you don't get overflow errors (it's an easy mistake to
make!).
Whatever you do don't simply take the average of all the samples. This
drops the volume level of all samples and makes it sound like crap.
Hope this helps,
Mark Feldman
:> to mix two samples together, you just add the values together of each
:> bit after dividing them by the number of samples
:> eg :- (sample1[x]/2) + (sample2[x]/2) to mix two samples
You do not need to do any division. Just add them together. If you
divide, the volume gets way too small when you mix more than a couple
samples. If you don't divide, the only side effect is a small ammount of
harmonic distortion which is virtually undetectable.
to mix two samples together, you just add the values together of each
bit after dividing them by the number of samples
eg :- (sample1[x]/2) + (sample2[x]/2) to mix two samples
sean.
--
-------------------------------------------------------------------------------
___ Sean Douch ___ (Vornskr) _ |
/ __| ___ __ _ _ _ | \ ___ _ _ __| |_ |
sh...@ecs.soton.ac.uk
\__ \/ -_) _` | ' \ | |) / _ \ || / _| ' \ | Computer Science
Student
|___/\___\__,_|_||_| |___/\___/\_,_\__|_||_| | Southampton
University
|
'Strong am I with the Force, But not that strong'
----------------- http://whirligig.ecs.soton.ac.uk:80/~shd94/
-----------------
>to mix two samples together, you just add the values together of each
>bit after dividing them by the number of samples
>
>eg :- (sample1[x]/2) + (sample2[x]/2) to mix two samples
>
>sean.
Um, this doesn't make much sense to me. For example, take two sin waves. If
one has an amplitude of 6 and the other has an amplitude of 0.5 and both have
the same frequency, using your equation they'd have a combined amplitude of:
6/2 + 0.5/2 = 3.25
Which means that your sin wave has a lower volume when two waves of equal
frequency are combined. Now did I misunderstand the point? I'm somewhat
confused. It seems to make more sense (from a logical standpoint) to add the
samples and then perform some technique to prevent distortion or whatever.
bko...@ucsd.edu
http://psy.ucsd.edu/~bkoike
: >to mix two samples together, you just add the values together of each
: >bit after dividing them by the number of samples
: >eg :- (sample1[x]/2) + (sample2[x]/2) to mix two samples
: Um, this doesn't make much sense to me. For example, take two sin waves. If
: one has an amplitude of 6 and the other has an amplitude of 0.5 and both have
: the same frequency, using your equation they'd have a combined amplitude of:
: 6/2 + 0.5/2 = 3.25
: Which means that your sin wave has a lower volume when two waves of equal
: frequency are combined. Now did I misunderstand the point? I'm somewhat
: confused. It seems to make more sense (from a logical standpoint) to add the
: samples and then perform some technique to prevent distortion or whatever.
Someone said that you should just add the samples together as signed
data and then clip them to the range... But there is a problem too.
If you are mixing 16 sinewaves, all of amplitude 128 and all at the
same frequency, you'll get values from -2048 to 2048. If you clip
that data to range -127 to 128... You're in trouble. The sinewaves
are not sinewaves anymore, they are starting to look like square
wave... And when you mix sounds with software, you'll always get
somewhat lower volume. But that can be taken care of by multiplying
the values with some number that doesn't cause much distortion.
And to those persons who suggested the clipping; Tell me how you
can do it with 'small amount of harmonic distortion that human
ears can't detect'... Or was that just for mixing two samples?
Because when you use more samples, the distortion becomes VERY
detectable!
-Feenix/Epical-
--
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/
Sami Kuhmonen, Department of Computer Science,_/ You could have it all
Tampere University of Technology_/ My empire of dirt
eMail: k15...@cc.tut.fi _/ I would let you down
Phone: + 40-5540 198 _/ I would make you hurt!
Snail: Nayttelijankatu 21 B 2 _/
FIN-33720 Tampere _/ - Trent Reznor
http://proffa.cc.tut.fi/~k153616 _/
The first thing to understand about sound in nature is that it is
_additive_. When your ears hear multiple sounds, they aren't being
multiplied of divided by any factors... your ear just adds them up. The
best approximation for a digital mixer is to add the sounds together and
clip. If you want to minimize the ammount that you clip, then you should
normalize the maximum volume of all your samples to be around 60% of their
possible maximum.
The other thing to consider is that in a game, you aren't going to be
playing 16 coherent sine waves on top of each other. In fact, as you
increase the number of samples you are mixing, the ammount of clipping
goes down because the average amplitude of any sample is around 0 (128
unsigned).
:> And to those persons who suggested the clipping; Tell me how you
:> can do it with 'small amount of harmonic distortion that human
:> ears can't detect'... Or was that just for mixing two samples?
:> Because when you use more samples, the distortion becomes VERY
:> detectable!
I can only guess that something is going wrong with your clipping
algorythms. Download Varmint's Audio Tools and listen to the demo:
http://www.rt66.com/smeagol/html/vat.html
ftp://mack.rt66.com/users/smeagol/vat061.zip
The demo allows up to 20 simultaneous digital channels (4 MOD tracks and
16 samples) and the distortion is really unnoticeable when they are all
active.
If you want to convince yourself further, Take a regular sample and
gradually clip off the extremes more and more and stop when the
distortion becomes noticeable. You'll have to clip off quite a bit
before you hear the reduction in bit depth.
If you just add and clip as suggested, yes you may be adding
distortion but it won't be that noticeable. If you have 8-bit
samples as in your suggestion, you already have a pretty
miserable signal to noise ratio - the extra distortion won't be
much worse.
Mixing 16 full-amplitude, in-phase sine waves is not a realistic
example. Grab some real WAV files, add them together, and see
how much actual clipping occurs. You'll be surprised.
--
Brent Burley br...@aimla.com
Dividing by the current number of samples is just plain wrong unless
the number of samples is fixed or unless you somehow manage to increase
the volume correspondingly through the mixer chip. However, when
adding lots of samples, there is quite a lot of distortion if the
samples go up to the maximum level (255). The best thing to do is
probably to pre-divide all samples by 2 or 4 to create 7 or 6 bit
samples. This lowers the volume, but does so consistently so you
can simply crank up the master volume to compensate. It also lowers
the resolution, but that happens with all software mixing. The best
solution to that problem would be to go 16 bits. By creating 6 bit
samples you can add up to four of them without any clipping, and you
should be able to get pretty good results by mixing up to 16 of them
with clipping.
--
+------------------------------------------------------+
| "Fumbling in frustration, inside soul torn apart |
| Feel the loss of paradise, leave an empty heart |
| Closing eyes will shut out, the warm light of a life |
| Grip is fading slowly, for each day passing by" |
| - Desultory, "A Closing Eye" |
+------------------------------------------------------+
| Rainer Deyke (rai...@mdddhd.fc.hp.com) |
+------------------------------------------------------+
: samples go up to the maximum level (255). The best thing to do is
: probably to pre-divide all samples by 2 or 4 to create 7 or 6 bit
No. Add first (to a variable capable of holding the result without
overflowing), THEN divide. This gives better precision. Consider adding
1 and 1. Pre-dividing: (1/2=0) + (1/2=0) = 0; post-dividing: (1 + 1)/2 = 1.
Besides, if you are scaling at run time, post-dividing saves divisions.
--
Tommy Anderberg
Tommy.A...@abc.se
The point is that you can pre-divide before running the program and thus
increase speed.
Or you can process the mixed data with a lookup table. Dividing is a
lousy algorithm, as it reduces amplitude, forcing you to increase the
volume and noise. The best algorithm, in my opinion, is a form of
clipping. It isn't likely that all the sound will be in phase, so
they will mostly cancel output, resulting in fairly rare clipping.
So, when clipping occurs, it usually cutting off the top of all the
waves and resulting in massive distortion. In my new music engine,
I am using curved "clipping." For most (-96 - 96) of the range, it
is linear, but the top is logrithmic, begining with 1:1 mapping, but
ending in flat line. This minimizes distortion in most situations
(two or three peaks in phase) without much distortion on the standard
range (when one sample is being played). It only adds one extra
step to the mixing algorithm, which isn't much, considering it already
does panning and volume control. (also with lookup tables)
Ethan Brodsky
--
<A HREF=http://www.pobox.com/~ebrodsky/> Ethan Brodsky </A>
>If you just add and clip as suggested, yes you may be adding
>distortion but it won't be that noticeable. If you have 8-bit
>samples as in your suggestion, you already have a pretty
>miserable signal to noise ratio - the extra distortion won't be
>much worse.
Its still pretty bad. We are talking about clipping a wave with a
potential range -256 to 255 , down to -128 to 127. That kind of
distortion has the potential to be VERY noticable, and WILL be very
noticable in average mixing applications where the full bandwidth of
the wave is being used for the sound (the way sound SHOULD be stored).
Clay