delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1999/08/16/22:56:59

Date: Tue, 17 Aug 1999 02:19:54 +0700
From: Batchex <thedark1 AT Phreaker DOT net>
X-Mailer: The Bat! (v1.32) S/N E34104EF
X-Priority: 3 (Normal)
Message-ID: <1097.990817@Phreaker.net>
To: Sahab Yazdani <djgpp AT delorie DOT com>
Subject: Re: 8-Bit Clipping
In-reply-To: <37B46FE9.87C3B20D@geocities.com>
References: <37B46FE9 DOT 87C3B20D AT geocities DOT com>
Mime-Version: 1.0
Reply-To: djgpp AT delorie DOT com
X-Mailing-List: djgpp AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

Saturday, August 14, 1999, 2:20:09 AM, you wrote:

SY> Well I fixed the Mixing problem.  (THanks everybody).
SY> Now I have a problem with 8-bit clipping (It gives a little "wick" at
SY> the end of every wirte).  I have no clue how to fix this.  And the
SY> Allegro code simply made my head spin.  Any hints, web-sites, info???

Do you mean that after you transfer the memory sound buffer contents
to the soundcard, when the sound starts playing it gives a little
"wick"? If so, maybe after you mix the sounds, in the resulting sound
buffer, the data starts with a "spike" (samples that is abruptly have
a high values while the samples immediately before and after them have a
relatively low values). Check the data in the beginning of the buffer
(around 100 samples or so) and see if there is a spike. The samples
should change gradually to sound "smooth".

Another possibility is, the soundcard isn't initialized to play sound
(in a hardware sense) before you transfer the buffer, so, after the
transfer is finished, the soundcard initialized and then play the
sound. Initializing the soundcard does produce a "whack" sometimes.

I don't know if this relate to this problem, but maybe the mixed sound
itself may be clipped. If I'm not mistaken, I've read somewhere in
this mailing list that suggest that mixing two sounds can be achieved
by simply adding their inividual samples together and clip the result
if it is higher than the max value. While this is true, the sound of
the clipped samples can be annoying sometimes (at least for me), and
produce a "wick" or a "whack". For that reason, I listed a few ways to
mix sounds and prevent clipping (theoretically, note that I haven't
got the time to test these approaches yet, so tell me if it works).

Assuming 8 bit, signed data format. Length is the length of the
longest sound file that is to be mixed.

1. Scale each samples with a certain values before adding them
together. The sum of all scale values must be 1.
ex.1 : two channels (sound files), each channels is weighted 0.5 (the
sum of all weights is 0.5 + 0.5 =1).

    for(i=0;i<length;i++)
        mixed[i] = (channel1[i]*0.5) + (channel2[i]*0.5) + 0.5;


2. Add the samples from each channels together, scan the min and max
values of the resulting buffer, then scale the all the samples
resulted from the mixing with the ratio of the max (or abs(min), which
ever the greater) of the scanned sample values and the max value the
data format supports.
ex.2: data format is 8 bit signed, so the min value the data format
supports is -128, and the max is 127.

         int buffer[length];
         int sampleMax, sampleMin;
         float scale;

         sampleMin = 2147483647;
         sampleMax = -2147483678;

         for(i=0;i<length;i++)
         {
          buffer[i] = channel1[i] + channel2[i];
          if(buffer[i] < sampleMin) sampleMin = buffer[i];
          if(buffer[i] > sampleMax) sampleMax = buffer[i];
         }

         if((sampleMax+sampleMin) >= 0) scale = sampleMax / 127;
         else scale = sampleMin / 128;

         for(i=0;i<length;i++)
             buffer[i] = (int)((buffer[i] * scale) + .5);


3. The approach no 2 can be simplified if there is a fixed number of
channels to be mixed. The result of the addition of each samples from
each channels is scaled by 1/number of channels.
ex.3: number of channels is 4, so the scale value is 1/4 or 0.25.

      for(i=0;i<length;i++)
      {
          buffer[i] = channel1[i] + channel2[i] + channel3[i] +
                      channel4[i];
          buffer[i] = (int)((buffer[i] * 0.25) + 0.5);
      }


Hope that helps.

Batchex
mailto:thedark1 AT Phreaker DOT net


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019