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 + -
显示快捷键?