⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 soundit.c

📁 在linux下多媒体开发实例linux下多媒体开发
💻 C
字号:
/* SoundIt library 0.021   Copyright 1994 Brad Pitzel  pitzel@cs.sfu.ca   Feel free to use/distribute/modify as long as proper credits   are included.*/#include "soundit.h"#include <malloc.h>#include <limits.h>	/* PATH_MAX */#include <stdio.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/time.h>#include <sys/stat.h>#include <fcntl.h>#include <linux/soundcard.h>#include <sys/ioctl.h>#include <sys/wait.h>/*==========================================================================*//* the mix buff, where the channels are mixed into. The mix buffer is then   dumped to the sound device (/dev/dsp). Samples are mixed in   Vunclipbuf (buffer of ints), then the values in Vunclipbuf are clipped to   values between 0 and 255, and stored into Vclippedbuf (buffer of unsigned   chars).*/struct Mix    {    unsigned char *Vclippedbuf;	    int *Vunclipbuf;    int Vsize;    };typedef struct Mix Mix;/*==========================================================================*/struct Channel    {    unsigned char *Vstart,*Vcurrent;	/* ptr's into a playing sample */    int	Vlen;				/* length of sample in bytes */    int	Vleft;				/* bytes left of sample to play */    };typedef struct Channel Channel;/*==========================================================================*//* variables prefixed with S_ are static *//* 0 if mixer isn't initialized or init failed, 1 if mixer is good */static int sampleMixerStatus = 0;	static const Sample 	*S_sounds = NULL; /* ptr to array of samples */static int S_num_sounds = 0;		/* size of 'sounds' array above */static int S_fd_snddev = -1;		/* file # for sound device once open */static int S_fd_pipe[2] = { -1, -1 };	/* pipe to talk to child process */static int S_son_pid = -1;		/* process ID for the forked sound mixer */static const char *S_snddev = NULL;	/* char string for device, ie "/dev/dsp" */static int S_num_channels = 6;		/* number of channels to mix */static int S_playback_freq = 0;		/* playback frequency (in Hz) *//*==========================================================================*//* non-public functions, used only within this file*/int Snd_init_dev();int Snd_restore_dev();void Chan_reset( Channel *chan );	/* init channel structure */	/* start a sample playing on a channel */void Chan_assign( Channel *chan, const Sample *snd );	/* mix all channels together into the 'mix' structure */int  Chan_mixAll( Mix *mix, Channel *ch );	/* used by Chan_mixAll to mix the 1st channel */int  Chan_copyIn( Channel *chan, Mix *mix );	/* used by Chan_mixAll to mix the middle channels */int  Chan_mixIn( Channel *chan, Mix *mix );	/* used by Chan_mixAll to mix the last channel */int  Chan_finalMixIn( Channel *chan, Mix *mix );/* alloc mem for mix buffer, and deallocate function *//* The sound channels are mixed together into the mix buffer   *//* then the mix buffer data is sent directly to the sound device */void Mix_alloc( Mix *mix, int size );void Mix_dealloc( Mix *mix );/*==========================================================================*//* justing for testing, normally not called */void dump_snd_list()	{	int i=0;		for(i=0; i<S_num_sounds; i++)		{		/* printf("snd %d: len = %d \n", i, S_sounds[i].len ); */		}	}	/*==========================================================================*/int Snd_init( int num_snd, const Sample *sa, int frequency,               int channels, const char *dev )	{	int result;	S_num_sounds     = num_snd;	S_sounds         = sa;	/* array of sound samples*/	S_playback_freq  = frequency;	S_num_channels   = channels; 	S_snddev= dev;	/* sound device, eg /dev/dsp*/		if (S_sounds==NULL)		return EXIT_FAILURE;		result=Snd_init_dev();	if (result==EXIT_SUCCESS)		{		sampleMixerStatus=1;		}	else		{		sampleMixerStatus=0;		}	return result;	}/*==========================================================================*/int Snd_restore()	{	int result;	if (!sampleMixerStatus)		return EXIT_FAILURE;		result=Snd_restore_dev();	if (result==EXIT_SUCCESS)		{		sampleMixerStatus=0;		}	else		{		sampleMixerStatus=0;		}	return result;	}/*==========================================================================*//* volume control not implemented yet.*/int Snd_effect( int sound_num, int channel )	{	if(! sampleMixerStatus )		return EXIT_FAILURE;			if(S_sounds[sound_num].data != NULL)		{			write(S_fd_pipe[1], &sound_num, sizeof(sound_num));		write(S_fd_pipe[1], &channel, sizeof(channel));		}	return EXIT_SUCCESS;	}/*============================================================================*/int Snd_init_dev()	{	int whoami;	S_fd_snddev = -1;	S_son_pid = 0;	if(access(S_snddev,W_OK) != 0)		{			return EXIT_FAILURE;		}	S_fd_snddev = open(S_snddev,O_WRONLY);	if(S_fd_snddev < 0)		{			return EXIT_FAILURE;		}			close(S_fd_snddev);	if(pipe(S_fd_pipe) < 0)		{			return EXIT_FAILURE;		}	/* now setup 2nd process for writing the data... */	if((whoami = fork()) < 0)		{			return EXIT_FAILURE;		}			if(whoami != 0)	/* successfully created son */		{			close(S_fd_pipe[0]);	/* close end for reading */		S_son_pid = whoami;		return EXIT_SUCCESS;		}				/* Here is the code for the son... */		{		int sound_num,ch,i;		struct timeval tval = {0L,0L};		fd_set readfds,dsp;		Mix mix;				int frag, fragsize;		Channel *chan = (Channel*)malloc( sizeof(Channel)*S_num_channels );		for (i=0; i<S_num_channels; i++)			Chan_reset( chan+i );					S_fd_snddev = open(S_snddev,O_WRONLY );		if(S_fd_snddev < 0)			{				exit(1);			}		frag = FRAG_SPEC; /*defined in soundIt.h */		 		ioctl(S_fd_snddev, SNDCTL_DSP_SETFRAGMENT, &frag); 		ioctl(S_fd_snddev,SNDCTL_DSP_SPEED, &S_playback_freq);		fragsize=0;		ioctl(S_fd_snddev,SNDCTL_DSP_GETBLKSIZE, &fragsize);					/* init mixer object*/		Mix_alloc( &mix, fragsize );		close(S_fd_pipe[1]);	/* close end for writing */		FD_ZERO(&dsp); 		FD_SET(S_fd_snddev, &dsp);				FD_ZERO(&readfds); 		FD_SET(S_fd_pipe[0], &readfds);				for(;;)			{			FD_ZERO(&readfds); 			FD_SET(S_fd_pipe[0], &readfds);			tval.tv_sec=0L;			tval.tv_usec=0L;			i = select(S_fd_pipe[0]+1, &readfds,NULL,NULL,&tval);			if (i > 0 && FD_ISSET(S_fd_pipe[0], &readfds))			  {			    i = read(S_fd_pipe[0], &sound_num, sizeof(int));			    if (i < sizeof(int)) break;			    i = read(S_fd_pipe[0], &ch, sizeof(int));			    if (i < sizeof(int)) break;			    Chan_assign( &(chan[ch]), &(S_sounds[sound_num]) );						  }			Chan_mixAll(&mix,chan);			write(S_fd_snddev, mix.Vclippedbuf, fragsize );			}		Mix_dealloc( &mix );					close(S_fd_pipe[0]);		close(S_fd_pipe[1]);/* * * Important: call _exit() and not exit() !  Otherwise parent process * files will be closed.  In the case of an X11 based application, the * socket to the X server will be closed!!!! * */		_exit (0);		} /*end of child process */	}/*==========================================================================*/int Snd_restore_dev()	{	close(S_fd_pipe[0]);	close(S_fd_pipe[1]);		/* wait for child process to die*/	waitpid(S_son_pid, 0, 0);	return EXIT_SUCCESS;	}/*==========================================================================*//*   CHANNEL MIXING FUNCTIONS						    *//*==========================================================================*/void Chan_reset( Channel *chan )    {    chan->Vstart=NULL;    chan->Vcurrent=NULL;    chan->Vlen=0;    chan->Vleft=0;    }/*==========================================================================*/void Chan_assign( Channel *chan, const Sample *snd )    {    chan->Vstart  = snd->data;    chan->Vcurrent= chan->Vstart;    chan->Vlen    = snd->len;    chan->Vleft   = snd->len;    } /*==========================================================================*/int Chan_copyIn( Channel *chan, Mix *mix )    {    int    i,*p = mix->Vunclipbuf, result, min;    result = (chan->Vleft>0) ? 1 : 0;    min = (chan->Vleft < mix->Vsize) ? chan->Vleft : mix->Vsize;    for(i=0; i<min; i++)        {        *p++ = (int) *chan->Vcurrent++;        }    chan->Vleft -= i;    /* fill the remaining (if any) part of the mix buffer with silence */    while (i<mix->Vsize)             {             *p++ = 128;             i++;             }    return result;                }/*==========================================================================*/int Chan_mixIn( Channel *chan, Mix *mix )     {    int    i,*p = mix->Vunclipbuf, result, min;    result = (chan->Vleft>0) ? 1 : 0;    min = (chan->Vleft < mix->Vsize) ? chan->Vleft : mix->Vsize;        for(i=0; i<min; i++)        {        *p++ += (int) (*chan->Vcurrent++) - 128;        }    chan->Vleft -= i;    return result;    }/*========================================================================*//* clip an int to a value between 0 and 255 */static inline unsigned char clip(int i)    {    return (i<0) ? 0 : ( (i>255) ? 255 : i );    }    /*==========================================================================*/int Chan_finalMixIn( Channel *chan, Mix *mix )    {    register int    i;    int   *p = mix->Vunclipbuf, result, min;    unsigned char *final = mix->Vclippedbuf;    result = (chan->Vleft>0) ? 1 : 0;    min = (chan->Vleft < mix->Vsize) ? chan->Vleft : mix->Vsize;        for(i=0; i<min; i++)        {        *p += (int) (*chan->Vcurrent++) - 128;        *final++ = clip(*p++);        }    chan->Vleft -= i;    /* copy rest of Vunclipbuf over to Vclippedbuf */    while (i<mix->Vsize)             {            *final++ = clip(*p++);            i++;            }                return result;    }/*==========================================================================*/void Mix_alloc(Mix *mix, int size)    {    mix->Vclippedbuf = (unsigned char *)calloc( sizeof(char), size);    mix->Vunclipbuf = (int *)calloc( sizeof(int), size);    mix->Vsize  = size;        if ((mix->Vclippedbuf==NULL)||(mix->Vunclipbuf==NULL))    	{    	exit(-1);    	}    }/*==========================================================================*/void Mix_dealloc( Mix *mix)    {     if (mix->Vclippedbuf) free(mix->Vclippedbuf);     if (mix->Vunclipbuf) free(mix->Vunclipbuf);     }/*==========================================================================*//* Mixes together the channels into one sound.   Returns # of channels currently playing *any* sound   Therefore, return 0 means to channels have a sample, therefore no   sound is playing*/ int Chan_mixAll( Mix *mix, Channel *chan )    {    int result  = 0,i=0;        result  = Chan_copyIn( chan,  mix);    /* we want to loop for S_num_channels-2 */    for(i=2;i<S_num_channels;i++)    	result += Chan_mixIn( ++chan, mix);    	    result += Chan_finalMixIn( ++chan, mix);        return result;    }/*==========================================================================*//* given the name of a .raw sound file, load it into the Sample struct */ /* pointed to by 'sample'                                              *//* Returns -1 couldn't open/read file				       *//*         -2 couldn't alloc memory)                                   */intSnd_loadRawSample( const char *file, Sample *sample )   {   FILE *fp;   sample->data = NULL;   sample->len  = 0;      fp = fopen(file,"r");         if (fp==NULL) return -1;      /* get length of the file */   sample->len = lseek( fileno(fp), 0, SEEK_END );      /* go back to beginning of file */   lseek( fileno(fp), 0, SEEK_SET );   /* alloc memory for sample */   sample->data = (unsigned char *)malloc( sample->len );      if (sample->data==NULL)   	{   	fclose(fp);   	return -2;   	}      fread( sample->data, 1, sample->len, fp ); 	     fclose(fp);      return 0;   }

⌨️ 快捷键说明

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