wtaudiorecord.c

来自「MCF5249的音频驱动程序,可以实现PCM的实时播放和采集」· C语言 代码 · 共 984 行 · 第 1/2 页

C
984
字号
    337, 371, 408, 449, 494, 544, 598, 658, 724, 796,    876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,    2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,    5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,    15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767};typedef struct adpcm_state{	int index;	int valprev;}_ADPCM,*pADPCM;voidadpcm_coder(short *indata, unsigned char *outdata, int len, struct adpcm_state *state){    short *inp;			/* Input buffer pointer */    signed char *outp;		/* output buffer pointer */    int val;			/* Current input sample value */    int sign;			/* Current adpcm sign bit */    int delta;			/* Current adpcm output value */    int diff;			/* Difference between val and valprev */    int step;			/* Stepsize */    int valpred;		/* Predicted output value */    int vpdiff;			/* Current change to valpred */    int index;			/* Current step change index */    int outputbuffer;		/* place to keep previous 4-bit value */    int bufferstep;		/* toggle between outputbuffer/output */    outp = (signed char *)outdata;    inp = indata;    valpred = state->valprev;    index = state->index;    step = stepsizeTable[index];        bufferstep = 1;        for ( ; len > 0 ; len-- ) {	val = *inp++;	/* Step 1 - compute difference with previous value */	diff = val - valpred;	sign = (diff < 0) ? 8 : 0;	if ( sign ) diff = (-diff);	/* Step 2 - Divide and clamp */	/* Note:	** This code *approximately* computes:	**    delta = diff*4/step;	**    vpdiff = (delta+0.5)*step/4;	** but in shift step bits are dropped. The net result of this is	** that even if you have fast mul/div hardware you cannot put it to	** good use since the fixup would be too expensive.	*/	delta = 0;	vpdiff = (step >> 3);		if ( diff >= step ) {	    delta = 4;	    diff -= step;	    vpdiff += step;	}	step >>= 1;	if ( diff >= step  ) {	    delta |= 2;	    diff -= step;	    vpdiff += step;	}	step >>= 1;	if ( diff >= step ) {	    delta |= 1;	    vpdiff += step;	}	/* Step 3 - Update previous value */	if ( sign )	  valpred -= vpdiff;	else	  valpred += vpdiff;	/* Step 4 - Clamp previous value to 16 bits */	if ( valpred > 32767 )	  valpred = 32767;	else if ( valpred < -32768 )	  valpred = -32768;	/* Step 5 - Assemble value, update index and step values */	delta |= sign;		index += indexTable[delta];	if ( index < 0 ) index = 0;	if ( index > 88 ) index = 88;	step = stepsizeTable[index];	/* Step 6 - Output value */	if ( bufferstep ) {	    outputbuffer = (delta & 0x0f) ; 	} else {	    *outp++ = ((delta << 4) & 0xf0) | outputbuffer;	}	bufferstep = !bufferstep;    }    /* Output last step, if needed */    if ( !bufferstep )      *outp++ = outputbuffer;        state->valprev = valpred;    state->index = index;}voidadpcm_decoder(char *indata, short *outdata,int len, struct adpcm_state* state)    {    signed char *inp;		/* Input buffer pointer */    short *outp;		/* output buffer pointer */    int sign;			/* Current adpcm sign bit */    int delta;			/* Current adpcm output value */    int step;			/* Stepsize */    int valpred;		/* Predicted value */    int vpdiff;			/* Current change to valpred */    int index;			/* Current step change index */    int inputbuffer;		/* place to keep next 4-bit value */    int bufferstep;		/* toggle between inputbuffer/input */    outp = outdata;    inp = (signed char *)indata;    valpred = state->valprev;    index = state->index;    step = stepsizeTable[index];    bufferstep = 0;        for ( ; len > 0 ; len-- ) {		/* Step 1 - get the delta value */	if ( bufferstep ) {	    delta = inputbuffer & 0xf;	} else {	    inputbuffer = *inp++;	    delta = (inputbuffer >> 4) & 0xf;	}	bufferstep = !bufferstep;	/* Step 2 - Find new index value (for later) */	index += indexTable[delta];	if ( index < 0 ) index = 0;	if ( index > 88 ) index = 88;	/* Step 3 - Separate sign and magnitude */	sign = delta & 8;	delta = delta & 7;	/* Step 4 - Compute difference and new predicted value */	/*	** Computes 'vpdiff = (delta+0.5)*step/4', but see comment	** in adpcm_coder.	*/	vpdiff = step >> 3;	if ( delta & 4 ) vpdiff += step;	if ( delta & 2 ) vpdiff += step>>1;	if ( delta & 1 ) vpdiff += step>>2;	if ( sign )	  valpred -= vpdiff;	else	  valpred += vpdiff;	/* Step 5 - clamp output value */	if ( valpred > 32767 )	  valpred = 32767;	else if ( valpred < -32768 )	  valpred = -32768;	/* Step 6 - Update step value */	step = stepsizeTable[index];	/* Step 7 - Output value */	*outp++ = valpred;    }    state->valprev = valpred;    state->index = index;}void upcm_encode(unsigned char *indata, unsigned char * outdata, int len){	unsigned int i=0;	unsigned short *src = (unsigned short *)indata;		for(;i<(len/2);i++)		outdata[i] = linear2ulaw(src[i]);}void a2u_encode(unsigned char *indata, unsigned char *outdata, int len){	int i=0;	for(;i<len;i++)		outdata[i] = alaw2ulaw(indata[i]);}static inline short adpcm_ima_expand_nibble(char nibble,pADPCM state){	int index;	int valprev;	int sign, delta, diff, step;	step = stepsizeTable[state->index];	index = state->index + indexTable[(unsigned)nibble];	if (index < 0) index = 0;	else if (index > 88) index = 88;	sign = nibble & 8;	delta = nibble & 7;	/* perform direct multiplication instead of series of jumps proposed by	* the reference ADPCM implementation since modern CPUs can do the mults	* quickly enough */	diff = ((2 * delta + 1) * step) >> 3;	/*		diff = step >> 3;	if ( delta & 4 ) diff += step;	if ( delta & 2 ) diff += step>>1;	if ( delta & 1 ) diff += step>>2;	*/	valprev = state->valprev;	if (sign) valprev -= diff;	else valprev += diff;	CLAMP_TO_SHORT(valprev);	state->valprev = valprev;	state->index = index;	return (short)valprev;}void ad2u_Send(void* indata, OUTDATA_T* outdata, int nSrcSize, BYTE* private ){	//short *samples;	long *samples;	unsigned char *src;	pADPCM state;	short tmp;	state = (pADPCM)private;	samples = (long *)outdata; //dest	src = (unsigned char *)indata;      //src    	state->valprev = (*src++) & 0x0FF;	state->valprev |= ((*src++) << 8) & 0x0FF00;	if(state->valprev & 0x8000)		state->valprev -= 0x10000;	CLAMP_TO_SHORT(state->valprev);	//*samples++ = state->valprev;		*samples++ = (linear2ulaw(state->valprev)<<24)&0xff000000;	state->index = *src++;	if (state->index < 0) state->index = 0;	if (state->index > 88) state->index = 88;	*src++;	//if (*src++) fprintf(stderr, "unused byte should be null !!\n"); 		for(; src < ((unsigned char *)indata + nSrcSize);) 	{		//*samples++ = adpcm_ima_expand_nibble(src[0] & 0x0F,state);						*samples++ = (linear2ulaw(adpcm_ima_expand_nibble(src[0] & 0x0F,state))<<24)&0xff000000;		//*samples++ = adpcm_ima_expand_nibble((src[0] >> 4) & 0x0F,state);		 				*samples++ = (linear2ulaw(adpcm_ima_expand_nibble((src[0] >> 4) & 0x0F,state))<<24)&0xff000000;				src++;	}	//*pDestSize = (unsigned char *)samples - (unsigned char *)outdata;	return;}void ulaw_Send(void* indata, OUTDATA_T* outdata, int nSrcSize, BYTE* private ){	unsigned char* src = (unsigned char *)indata;	while(nSrcSize--){		*outdata++ = (*src<<24);		src++;			}}unsigned long ad2ulaw(short indata, struct adpcm_state *state){	int sign;			/* Current adpcm sign bit */    	int delta;			/* Current adpcm output value */    	int step;			/* Stepsize */    	int valpred;		/* Predicted value */    	int vpdiff;			/* Current change to valpred */    	int index;			/* Current step change index */  //unsigned char Intmp[4],Outtmp[4];	int i;	unsigned long outdata=0; 	valpred = state->valprev; 	 index = state->index;  	for(i=3; i>=0; i--){				//delta = (indata>>4*i)&0x0f;		if(i == 3)			delta = indata>>8;		else if(i == 2)			delta = indata>>12;		else if(i == 0)			delta = indata>>4;		else			delta = indata;		delta &= 0x0f;		//printf("delta[%d] = 0x%02x\n",i,delta);		    step = stepsizeTable[index];		index += indexTable[delta];		if ( index < 0 ) index = 0;		if ( index > 88 ) index = 88;		sign = delta & 8;		delta = delta & 7;		vpdiff = step >> 3;		if ( delta & 4 ) vpdiff += step;		if ( delta & 2 ) vpdiff += step>>1;		if ( delta & 1 ) vpdiff += step>>2;		if ( sign )	  		valpred -= vpdiff;		else	  		valpred += vpdiff;		if ( valpred > 32767 )	  		valpred = 32767;		else if ( valpred < -32768 )	  		valpred = -32768;		//printf("valpred = 0x%04x\n",valpred);		outdata |= (linear2ulaw(valpred)<<(8*i));		//printf("outdata =0x%04x\n",outdata);	}	//printf("outdata =0x%04x\n",outdata);	state->valprev = valpred;    	state->index = index;	return outdata;	}int Audio_encode(unsigned char *indata, unsigned char * outdata, int len, int coding_type,struct adpcm_state *state){	unsigned char *pBuf;	int i;	unsigned short * pInData;	unsigned long *pOutData;	pInData = (unsigned short *)indata;	pOutData = (unsigned long *)outdata;	switch(coding_type) {	case AUDIO_ENCODING_ADPCM:		for(i=0; i<len; i++){						*pOutData ++ = ad2ulaw(*pInData++,state);					}		//adpcm_decoder(indata,(short *)pBuf,len,&state);		//upcm_encode(pBuf,outdata,len*4);		//free(pBuf);		break;	case AUDIO_ENCODING_LINEAR:		upcm_encode(indata,outdata,len);		break;	case AUDIO_ENCODING_ALAW:		a2u_encode(indata, outdata, len);	case AUDIO_ENCODING_ULAW:		while (len--){ 			*outdata++ = *indata++;			//printf("%x ",*outdata);		}	default:		return -1; 			}	return 0;}void mySig(void (*fun)(int)){	struct sigaction act;   	act.sa_handler = fun;   	sigemptyset(&act.sa_mask);   	act.sa_flags=0;	sigaction(SIGTERM,&act,NULL);    	sigaction(SIGHUP,&act,NULL);    	sigaction(SIGINT,&act,NULL);    	sigaction(SIGQUIT,&act,NULL);    	sigaction(SIGUSR1,&act,NULL);    	sigaction(SIGUSR2,&act,NULL); 	}void myExit(int signo){	//I6400WriteMem(0x2000,0x2);//Stop	//munmap(VBuffer,VIDEOBUFSIZE);	//munmap(ABuffer,AUDIOBUFSIZE);		//munmap(VU_Stream.srcBuffer,VIDEOBUFSIZE);	//munmap(VU_Stream.srcBuffer,APACKCOUNT*AU_Stream.nOutPSize);		//	AudioDelay(1);		//close(VideoIN);	close(AudioID);		printf("exit()_signo[%d]\n",signo);	//alarm(0);	//raise(signo);	exit(1);}/************************************************//* Example too the audio playback*/int main(){	BYTE *pDataIN; //input  audio data		DWORD *pDataOUT;	_ADPCM state;	int coding;		int nSaveFile;	int nr,nw;			mySig(myExit);  //safe exit	state.index = 0;	state.valprev = 0;	AudioID = open("/dev/WTAUDIO",O_RDWR );	if(AudioID  == -1)	{		printf("Can not open /dev/WTAUDIO .\n");		exit(0);	}		nSaveFile = open("../audio.raw",O_RDWR |O_CREAT);	if(nSaveFile == -1)	{			printf("Can't creat ../audio.raw\n");		exit(0);	}	pDataOUT = (DWORD*)malloc(sizeof(int)*508);	 	while(1)	{#ifdef AUDIO_RECODE	nr = read(AudioID, pDataOUT, sizeof(int)*508);	if(nr != 508)		printf("read error\n");	nw = write(nSaveFile, pDataOUT, sizeof(int)*508);	if(nw != 508)		printf("read error\n");	#endif		}		close(AudioID);		return 0;}

⌨️ 快捷键说明

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