mix.c

来自「Windows NT声卡驱动VXD」· C语言 代码 · 共 971 行 · 第 1/2 页

C
971
字号
#include "esd-server.h"#include <limits.h>/*******************************************************************//* ESD_BUF_SIZE is the maximum possible number of samples */signed int mixed_buffer[ ESD_BUF_SIZE ];/* prototype for compiler */;int mix_and_copy( void *dest_buf, int dest_len, 		  int dest_rate, esd_format_t dest_format, 		  void *source_data, int src_len, 		  int src_rate, esd_format_t src_format );int mix_from_stereo_16s( void *dest_buf, unsigned int dest_len, 			 int dest_rate, esd_format_t dest_format, 			 signed short *source_data_ss, int src_len, int src_rate );int mix_from_stereo_8u( void *dest_buf, unsigned int dest_len, 			int dest_rate, esd_format_t dest_format, 			unsigned char *source_data_uc, int src_len, int src_rate );int mix_from_mono_16s( void *dest_buf, unsigned int dest_len, 		       int dest_rate, esd_format_t dest_format, 		       signed short *source_data_ss, int src_len, int src_rate );int mix_from_mono_8u( void *dest_buf, unsigned int dest_len, 		      int dest_rate, esd_format_t dest_format, 		      unsigned char *source_data_uc, int src_len, int src_rate );int mix_mono_8u_to_stereo_32s_sv( esd_player_t *player, int length );int mix_stereo_8u_to_stereo_32s_sv( esd_player_t *player, int length );int mix_mono_16s_to_stereo_32s_sv( esd_player_t *player, int length );int mix_stereo_16s_to_stereo_32s_sv( esd_player_t *player, int length );int mix_mono_8u_to_stereo_32s( esd_player_t *player, int length );int mix_stereo_8u_to_stereo_32s( esd_player_t *player, int length );int mix_mono_16s_to_stereo_32s( esd_player_t *player, int length );int mix_stereo_16s_to_stereo_32s( esd_player_t *player, int length );void clip_mix_to_output_16s( signed short *output, int length );void clip_mix_to_output_8u( signed char *output, int length );/* TODO: straighten out the mix algorithm comment annotations *//* TOTO: i don't think we're in kansas anymore... */mix_func_t *get_mix_func( esd_player_t *player ){    switch ( player->format & ESD_MASK_BITS )    {    case ESD_BITS8:	if ( ( player->format & ESD_MASK_CHAN ) == ESD_MONO )	    if ( ( player->left_vol_scale == ESD_VOLUME_BASE )		 && ( player->right_vol_scale == ESD_VOLUME_BASE ) )		return mix_mono_8u_to_stereo_32s_sv;	    else		return mix_mono_8u_to_stereo_32s;	else if ( ( player->format & ESD_MASK_CHAN ) == ESD_STEREO )	    if ( ( player->left_vol_scale == ESD_VOLUME_BASE )		 && ( player->right_vol_scale == ESD_VOLUME_BASE ) )		return mix_stereo_8u_to_stereo_32s_sv;	    else		return mix_stereo_8u_to_stereo_32s;	else	    return NULL;    case ESD_BITS16:	if ( ( player->format & ESD_MASK_CHAN ) == ESD_MONO )	    if ( ( player->left_vol_scale == ESD_VOLUME_BASE )		 && ( player->right_vol_scale == ESD_VOLUME_BASE ) )		return mix_mono_16s_to_stereo_32s_sv;	    else		return mix_mono_16s_to_stereo_32s;	else if ( ( player->format & ESD_MASK_CHAN ) == ESD_STEREO )	    if ( ( player->left_vol_scale == ESD_VOLUME_BASE )		 && ( player->right_vol_scale == ESD_VOLUME_BASE ) )		return mix_stereo_16s_to_stereo_32s_sv;	    else {printf( "mix_stereo_16s_to_stereo_32s\n" );		return mix_stereo_16s_to_stereo_32s;	    }	else	    return NULL;    default:	return NULL;    }}translate_func_t *get_translate_func( esd_format_t src_fmt, int src_rate, 				      esd_format_t dst_fmt, int dst_rate ){    if ( ( src_fmt & ESD_MASK_CHAN ) == ESD_MONO ) {	if ( (src_fmt & ESD_MASK_BITS) == ESD_BITS16 ) 	    return mix_from_mono_16s;	else	    return mix_from_mono_8u;    } else {	if ( (src_fmt & ESD_MASK_BITS) == ESD_BITS16 ) 	    return mix_from_stereo_16s;	else	    return mix_from_stereo_8u;    }        return 0;}/* decides which of the mix_from_* functions to use, and calls it */int mix_and_copy( void *dest_buf, int dest_len, 		  int dest_rate, esd_format_t dest_format, 		  void *source_data, int src_len, 		  int src_rate, esd_format_t src_format ){    if ( ( src_format & ESD_MASK_CHAN ) == ESD_MONO ) {	if ( (src_format & ESD_MASK_BITS) == ESD_BITS16 ) 	    return mix_from_mono_16s( dest_buf, dest_len, 				      dest_rate, dest_format, 				      source_data, src_len,				      src_rate );	else	    return mix_from_mono_8u( dest_buf, dest_len, 				     dest_rate, dest_format, 				     source_data, src_len,				     src_rate );    } else {	if ( (src_format & ESD_MASK_BITS) == ESD_BITS16 ) 	    return mix_from_stereo_16s( dest_buf, dest_len, 					dest_rate, dest_format, 					source_data, src_len,					src_rate );	else	    return mix_from_stereo_8u( dest_buf, dest_len, 				       dest_rate, dest_format, 				       source_data, src_len,				       src_rate );    }    return 0;}/*******************************************************************//* takes the 16 bit signed source waveform, and mixes to player */int mix_from_stereo_16s( void *dest_buf, unsigned int dest_len, 			 int dest_rate, esd_format_t dest_format, 			 signed short *source_data_ss, int src_len, int src_rate ){    int rd_dat = 0, bytes_written = 0;    unsigned int wr_dat = 0;    register unsigned char *target_data_uc = NULL;    register signed short *target_data_ss = NULL;    signed short lsample, rsample;    ESDBG_MIXER( printf( "mixing from stereo 16s\n" ); );    /* if nothing to mix, just bail */    if ( !src_len ) {	return 0;    }    /* mix it down */    switch ( dest_format & ESD_MASK_BITS )    {    case ESD_BITS8:	target_data_uc = (unsigned char *) dest_buf;	if ( ( dest_format & ESD_MASK_CHAN ) == ESD_MONO ) {	    /* mix mono, 8 bit sound source from stereo, 16 bit */	    while ( wr_dat < dest_len )	    {		rd_dat = wr_dat * src_rate / dest_rate;		rd_dat *= 2;		/* adjust for mono */		/* just multipled by two, it's on an even byte */		/* rd_dat += rd_dat % 2;*/	/* force to left sample */		lsample = source_data_ss[ rd_dat++ ];		rsample = source_data_ss[ rd_dat++ ];		lsample /= 256; lsample += 127;		rsample /= 256; rsample += 127;		target_data_uc[ wr_dat++ ] = (lsample + rsample) / 2;	    }	} else {	    /* mix stereo, 8 bit sound source from stereo, 16 bit */	    while ( wr_dat < dest_len )	    {		rd_dat = wr_dat * src_rate / dest_rate;		lsample = source_data_ss[ rd_dat++ ];		lsample /= 256; lsample += 127;		rsample = source_data_ss[ rd_dat++ ];		rsample /= 256; rsample += 127;		target_data_uc[ wr_dat++ ] = lsample;		target_data_uc[ wr_dat++ ] = rsample;	    }	}	bytes_written = wr_dat * sizeof(unsigned char);	break;    case ESD_BITS16:	target_data_ss = (signed short *) dest_buf;	if ( ( dest_format & ESD_MASK_CHAN ) == ESD_MONO ) {	    /* mix mono, 16 bit sound source from stereo, 16 bit */	    while ( wr_dat < dest_len / sizeof(signed short) )	    {		rd_dat = wr_dat * src_rate / dest_rate;		rd_dat *= 2;		/* adjust for stereo */		lsample = source_data_ss[ rd_dat++ ];		rsample = source_data_ss[ rd_dat++ ];		target_data_ss[ wr_dat++ ] = (lsample + rsample) / 2;	    }	} else {	    /* mix stereo, 16 bit sound source from stereo, 16 bit */	    /* optimize for the case where all settings are the same */	    if ( dest_rate == src_rate ) {		memcpy( target_data_ss, source_data_ss, dest_len );		bytes_written = dest_len;		break;	    }	    /* scale the pointer, and copy the data */	    while ( wr_dat < dest_len / sizeof(signed short) )	    {		rd_dat = wr_dat * src_rate / dest_rate;		lsample = source_data_ss[ rd_dat++ ];		rsample = source_data_ss[ rd_dat++ ];		target_data_ss[ wr_dat++ ] = lsample;		target_data_ss[ wr_dat++ ] = rsample;	    }	}	bytes_written = wr_dat * sizeof(signed short);	break;    default:	fprintf( stderr, "mix from 16s: format 0x%08x not supported\n", 		 dest_format & ESD_MASK_BITS );	break;    }    return bytes_written;}/*******************************************************************//* takes the 8 bit unsigned source waveform, and mixes to player */int mix_from_stereo_8u( void *dest_buf, unsigned int dest_len, 			int dest_rate, esd_format_t dest_format, 			unsigned char *source_data_uc, int src_len, int src_rate ){    int rd_dat = 0, bytes_written = 0;    unsigned int wr_dat = 0;    register unsigned char *target_data_uc = NULL;    register signed short *target_data_ss = NULL;    signed short lsample, rsample;    ESDBG_MIXER( printf( "mixing from stereo 8u\n" ); );    /* if nothing to mix, just bail */    if ( !src_len ) {	return 0;    }    /* mix it down */    switch ( dest_format & ESD_MASK_BITS )    {    case ESD_BITS8:	target_data_uc = (unsigned char *) dest_buf;	if ( ( dest_format & ESD_MASK_CHAN ) == ESD_MONO ) {	    /* mix mono, 8 bit sound source from stereo, 16 bit */	    while ( wr_dat < dest_len )	    {		rd_dat = wr_dat * src_rate / dest_rate;		rd_dat *= 2;		/* adjust for mono */		lsample = source_data_uc[ rd_dat++ ];		rsample = source_data_uc[ rd_dat++ ];		target_data_uc[ wr_dat++ ] = (lsample + rsample) / 2;	    }	} else {	    /* mix stereo, 8 bit sound source from stereo, 16 bit */	    /* optimize for the case where all settings are the same */	    if ( dest_rate == src_rate ) {		memcpy( target_data_uc, source_data_uc, dest_len );		bytes_written = dest_len;		break;	    }	    /* scale the pointer, and copy the data */	    while ( wr_dat < dest_len )	    {		rd_dat = wr_dat * src_rate / dest_rate;		lsample = source_data_uc[ rd_dat++ ];		rsample = source_data_uc[ rd_dat++ ];		target_data_uc[ wr_dat++ ] = lsample;		target_data_uc[ wr_dat++ ] = rsample;	    }	}	bytes_written = wr_dat * sizeof(unsigned char);	break;    case ESD_BITS16:	target_data_ss = (signed short *) dest_buf;	if ( ( dest_format & ESD_MASK_CHAN ) == ESD_MONO ) {	    /* mix mono, 16 bit sound source from stereo, 8 bit */	    while ( wr_dat < dest_len / sizeof(signed short) )	    {		rd_dat = wr_dat * src_rate / dest_rate;		rd_dat *= 2;		/* adjust for stereo */		lsample = source_data_uc[ rd_dat++ ] - 127;		rsample = source_data_uc[ rd_dat++ ] - 127;		target_data_ss[ wr_dat++ ] = (lsample + rsample) * 256 / 2;	    }	} else {	    /* mix stereo, 16 bit sound source from stereo, 8 bit */	    while ( wr_dat < dest_len / sizeof(signed short) )	    {		rd_dat = wr_dat * src_rate / dest_rate;		lsample = source_data_uc[ rd_dat++ ] - 127;		rsample = source_data_uc[ rd_dat++ ] - 127;		target_data_ss[ wr_dat++ ] = lsample * 256;		target_data_ss[ wr_dat++ ] = rsample * 256;	    }	}	bytes_written = wr_dat * sizeof(signed short);	break;    default:	fprintf( stderr, "mix from 8u: format 0x%08x not supported\n", 		 dest_format & ESD_MASK_BITS );	break;    }    return bytes_written;}/*******************************************************************//* takes the 16 bit mono signed source waveform, and mixes to player */int mix_from_mono_16s( void *dest_buf, unsigned int dest_len, 		       int dest_rate, esd_format_t dest_format, 		       signed short *source_data_ss, int src_len, int src_rate ){    int rd_dat = 0, bytes_written = 0;    unsigned int wr_dat = 0;    register unsigned char *target_data_uc = NULL;    register signed short *target_data_ss = NULL;    signed short lsample;    ESDBG_MIXER( printf( "mixing from mono 16s\n" ); );    /* if nothing to mix, just bail */    if ( !src_len ) {	return 0;    }    /* mix it down */    switch ( dest_format & ESD_MASK_BITS )    {    case ESD_BITS8:	target_data_uc = (unsigned char *) dest_buf;	if ( ( dest_format & ESD_MASK_CHAN ) == ESD_MONO ) {	    /* mix mono, 8 bit sound source from mono, 16 bit */	    while ( wr_dat < dest_len )	    {		rd_dat = wr_dat * src_rate / dest_rate;		lsample = source_data_ss[ rd_dat ];		lsample /= 256; lsample += 127;		target_data_uc[ wr_dat++ ] = lsample;	    }	} else {	    /* mix mono, 8 bit sound source from stereo, 8 bit */	    while ( wr_dat < dest_len )	    {		rd_dat = wr_dat * src_rate / dest_rate;		rd_dat /= 2;		lsample = source_data_ss[ rd_dat++ ];		lsample /= 256; lsample += 127;		target_data_uc[ wr_dat++ ] = lsample;		target_data_uc[ wr_dat++ ] = lsample;	    }	}	bytes_written = wr_dat * sizeof(unsigned char);	break;    case ESD_BITS16:	target_data_ss = (signed short *) dest_buf;	if ( ( dest_format & ESD_MASK_CHAN ) == ESD_MONO ) {	    /* mix mono, 16 bit sound source from mono, 16 bit */	    /* optimize for the case where all settings are the same */	    if ( dest_rate == src_rate ) {		memcpy( target_data_ss, source_data_ss, dest_len );		bytes_written = dest_len;		break;	    }	    /* scale the pointer, and copy the data */	    while ( wr_dat < dest_len / sizeof(signed short) )	    {		rd_dat = wr_dat * src_rate / dest_rate;		lsample = source_data_ss[ rd_dat ];		target_data_ss[ wr_dat++ ] = lsample;	    }	} else {	    /* mix stereo, 16 bit sound source from mono, 16 bit */	    while ( wr_dat < dest_len / sizeof(signed short) )	    {		rd_dat = wr_dat * src_rate / dest_rate;		rd_dat /= 2;		lsample = source_data_ss[ rd_dat++ ];		target_data_ss[ wr_dat++ ] = lsample;		target_data_ss[ wr_dat++ ] = lsample;	    }	}	bytes_written = wr_dat * sizeof(signed short);	break;    default:	fprintf( stderr, "mix from 16s: format 0x%08x not supported\n", 		 dest_format & ESD_MASK_BITS );	break;    }    return bytes_written;}/*******************************************************************//* takes the 8 bit mono unsigned source waveform, and mixes to player */int mix_from_mono_8u( void *dest_buf, unsigned int dest_len, 		      int dest_rate, esd_format_t dest_format, 		      unsigned char *source_data_uc, int src_len, int src_rate ){    int rd_dat = 0, bytes_written = 0;    unsigned int wr_dat = 0;    register unsigned char *target_data_uc = NULL;    register signed short *target_data_ss = NULL;    signed short lsample;    ESDBG_MIXER( printf( "mixing from mono 8u\n" ); );    /* if nothing to mix, just bail */    if ( !src_len ) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?