#include #include "ysound.h" void YiffMixBuffers( Audio *audio, SoundBuffer *tar_buf, const SoundBuffer *src_buf, YDataLength len, Coefficient volume_left, Coefficient volume_right ); void YiffShortenBuffer16( u_int16_t *buf, int buf_len, /* In u_int8_t (not u_int16_t) units. */ int buf_shoren_len ); void YiffShortenBuffer8( u_int8_t *buf, int buf_len, /* In u_int8_t units. */ int buf_shoren_len ); #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h))) #define ABSOLUTE(x) (((x) < 0) ? ((x) * -1) : (x)) /* * Mixes the source buffer to the target buffer and * compensates for volume. */ void YiffMixBuffers( Audio *audio, SoundBuffer *tar_buf, const SoundBuffer *src_buf, YDataLength len, Coefficient volume_left, Coefficient volume_right ) { int i, b, blocks; SoundBuffer *tp; const SoundBuffer *sp; Coefficient lc, rc; Boolean flip; if((audio == NULL) || (tar_buf == NULL) || (src_buf == NULL) || (len <= 0) ) return; flip = audio->flip_stereo; /* Calculate coefficients. */ if(audio->channels == 2) { /* Stereo. */ blocks = 2; /* Calculate left and right coefficients. */ lc = MAX(MIN(volume_left, 1), 0); rc = MAX(MIN(volume_right, 1), 0); } else { /* Mono. */ blocks = 1; /* Average left and right coefficients. */ lc = (volume_left + volume_right) / 2; rc = MAX(MIN(lc, 1), 0); lc = rc; } /* Begin buffer mixing. */ for(i = 0, b = 0, tp = tar_buf, sp = src_buf; i < len; i++, tp++, sp++ ) { /* Is source byte positive or negative? */ if(*sp < 0) { /* Source byte is negative. */ if(b == 0) (*tp) = MAX((int)(*tp) + ((int)(*sp) * ((flip) ? rc : lc)), (int)-128 ); else (*tp) = MAX((int)(*tp) + ((int)(*sp) * ((flip) ? lc : rc)), (int)-128 ); } else { /* Source byte is positive. */ if(b == 0) (*tp) = MIN((int)(*tp) + ((int)(*sp) * ((flip) ? rc : lc)), (int)127 ); else (*tp) = MIN((int)(*tp) + ((int)(*sp) * ((flip) ? lc : rc)), (int)127 ); } /* Increment block position b. */ b++; if(b >= blocks) b = 0; } } /* * Moves the samples (shortens) from the given buffer length * to the shorten length. * * Inputs assumed valid (not NULL and greater than 0). * * Make sure the buffer is even number when allocated! */ void YiffShortenBuffer16( u_int16_t *buf, int buf_len, /* In u_int8_t (not u_int16_t) units. */ int buf_shoren_len ) { u_int16_t *tar_ptr = buf, *src_ptr = buf, *tar_end = buf + (buf_shoren_len / 2); int src_pos = 0, /* Pos and inc in units of * 256. */ src_inc = 256 * buf_len / buf_shoren_len; /* Target length is assumed to be shorter than source len. */ while(tar_ptr < tar_end) { *tar_ptr++ = src_ptr[(src_pos >> 8)]; src_pos += src_inc; } } /* * Moves the samples (shortens) from the given buffer length * to the shorten length. * * Inputs assumed valid (not NULL and greater than 0). */ void YiffShortenBuffer8( u_int8_t *buf, int buf_len, /* In u_int8_t units. */ int buf_shoren_len ) { u_int8_t *tar_ptr = buf, *src_ptr = buf, *tar_end = buf + buf_shoren_len; int src_pos = 0, /* Pos and inc in units of * 256. */ src_inc = 256 * buf_len / buf_shoren_len; /* Target length is assumed to be shorter than source len. */ while(tar_ptr < tar_end) { *tar_ptr++ = src_ptr[(src_pos >> 8)]; src_pos += src_inc; } }