spwrite.c

来自「speech signal process tools」· C语言 代码 · 共 827 行 · 第 1/2 页

C
827
字号
#include <stdio.h>#define SPHERE_LIBRARY_CODE#include <sp/sphere.h>#include <sp/ulaw.h>#include <sp/alaw.h>#include <sp/shorten/shorten.h>#include <string.h>static int spw_file_init(SP_FILE *sp, char *call_proc);static int spw_process_data(SP_FILE *sp, void *buffer, size_t num_sample, char *call_proc);static void array2interleaved(char **arr_buff, SP_INTEGER arr_offset, char *inter_buff, SP_INTEGER chcnt, SP_INTEGER snb, SP_INTEGER samples);void ulaw2pcm2(unsigned char *ulaw_data, short *pcm_data, enum SP_sample_encoding pcm_sbf, SP_INTEGER samples);void alaw2pcm2(unsigned char *alaw_data, short *pcm_data, enum SP_sample_encoding pcm_sbf, SP_INTEGER samples);void pculaw2pcm2(unsigned char *pculaw_data, short *pcm_data, enum SP_sample_encoding pcm_sbf, SP_INTEGER samples);void pcm22ulaw(short *pcm_data, enum SP_sample_encoding pcm_sbf, unsigned char *ulaw_data, SP_INTEGER samples);void pcm22alaw(short *pcm_data, enum SP_sample_encoding pcm_sbf, unsigned char *alaw_data, SP_INTEGER samples);void pcm22pculaw(short *pcm_data, enum SP_sample_encoding pcm_sbf, unsigned char *pculaw_data, SP_INTEGER samples);/* * *  sp_mc_write_data() * */int sp_mc_write_data(void *buffer, size_t num_sample, SP_FILE *sp){    char *proc="sp_write_data " SPHERE_VERSION_STR;    if (sp_verbose > 10)	fprintf(spfp,	       "Proc %s: file %s, %d bytes/sample, %d channels, %ld samples\n",	       proc,sp->write_spifr->status->external_filename,	       sp->write_spifr->status->user_sample_n_bytes,	       sp->write_spifr->status->user_channel_count,	       num_sample);    if (buffer == (void *)0) 	return_err(proc,100,0,"Null memory buffer");     if (sp == SPNULL)	return_err(proc,101,0,"Null SPFILE structure");    if (sp->open_mode == SP_mode_read)	return_err(proc,104,0,		   "Unable to write data to a file opened for reading");#ifdef isnotansi    if (num_sample < 0)	return_err(proc,103,0,		   rsprintf("Negative sample count %d",num_sample));#endif    /*************************************************************************/    /*     Perform all initializations to the sphere file to begin reading   */    /* set up the FoB Structure for reading */    if (sp->write_spifr->status->write_occured_flag == FALSE) 	if (spw_file_init(sp,proc) != 0)	    return_err(proc,100,0,get_subordinated_message());    return_child(proc,int,spw_process_data(sp,buffer,num_sample,proc));}/* do any sample conversions, and write the data to the FOB */static int spw_process_data(SP_FILE *sp, void *buffer, size_t num_sample, char *call_proc){    char *proc = "spw_process_data";    int samples_written = 0, ret;    int out_samples=0;    int block=0;    void *out_block = (void *)0, *end_of_input_block=(void *)0;    void *out_inter_block = (void *)0;    SP_CHECKSUM checksum=0;    SPIFR *spifr;     SPSTATUS *spstat;     SPWAVEFORM *spwav;    spifr = sp->write_spifr;    spstat = spifr->status;    spwav = spifr->waveform;        while (samples_written < num_sample){	if (sp_verbose > 16)	    fprintf(spfp,"Proc %s: Beginning Block %d\n",proc,block);		/* if conversions are neccessary, restrict the size of the */	/* data to that of the translation buffers   */	if ((spstat->user_encoding != spstat->file_encoding) || 	    (spstat->channels != CHANNELSNULL) ||	    (spstat->user_sbf != spstat->file_sbf) ||	    spstat->user_data_fmt == SP_df_array){	    if ((out_samples = (num_sample - samples_written)) >		TRANSLATION_LEN)		out_samples = TRANSLATION_LEN;	} else	    out_samples = num_sample;		/*  First, un-interleave the data if neccessary */	if (spstat->user_data_fmt == SP_df_array){	    /* convert the data from it's array form */	    /* to an interleaved format              */	    array2interleaved((char **)buffer,samples_written,			      (char *)spwav->interleave_buffer,			      spifr->status->user_channel_count,			      spifr->status->user_sample_n_bytes,			      out_samples);	    out_inter_block = (void *)spwav->interleave_buffer;	} else { /* use the buffer passed to the function */	    if (out_inter_block == (void *)0)		out_inter_block = (void *)buffer;	    else		out_inter_block = end_of_input_block;	    end_of_input_block = 		(void *)((char *)out_inter_block + 			 (out_samples * spifr->status->user_sample_n_bytes *			  spifr->status->user_channel_count));	}		/*  Next do the sample encoding conversions if necessary */	if ((spstat->user_encoding == SP_se_ulaw) &&	    (spstat->file_encoding == SP_se_pcm2)) {	    if (sp_verbose > 15)		fprintf(spfp,"Proc %s: converting ULAW to PCM\n",proc);	    ulaw2pcm2((unsigned char *)out_inter_block,		     (short *)spwav->converted_buffer,		     spstat->file_sbf,		     out_samples*spstat->user_channel_count);	    out_block = (void *)spwav->converted_buffer;	} else if ((spstat->user_encoding == SP_se_pcm2) &&		   (spstat->file_encoding == SP_se_ulaw)) {	    if (sp_verbose > 15)		fprintf(spfp,"Proc %s: converting PCM to ULAW\n",proc);       	    pcm22ulaw((short *)out_inter_block,		      spstat->user_sbf,		      (unsigned char *)spwav->converted_buffer,		      out_samples*spstat->user_channel_count);		    out_block = (void *)spwav->converted_buffer;	} else if ((spstat->user_encoding == SP_se_pculaw) &&		   (spstat->file_encoding == SP_se_pcm2)) {	    if (sp_verbose > 15)		fprintf(spfp,"Proc %s: converting PCULAW to PCM\n",proc);	    	    pculaw2pcm2((unsigned char *)out_inter_block,			(short *)spwav->converted_buffer,			spstat->file_sbf,			out_samples*spstat->user_channel_count);	    	    out_block = (void *)spwav->converted_buffer;	} else if ((spstat->user_encoding == SP_se_pcm2) &&		   (spstat->file_encoding == SP_se_pculaw)) {	    if (sp_verbose > 15)		fprintf(spfp,"Proc %s: converting PCULAW to PCM\n",proc);	    	    pcm22pculaw((short *)out_inter_block,			spstat->user_sbf,			(unsigned char *)spwav->converted_buffer,			out_samples*spstat->user_channel_count);	    	    out_block = (void *)spwav->converted_buffer;	} else if ((spstat->user_encoding == SP_se_alaw) &&		   (spstat->file_encoding == SP_se_pcm2)) {	    if (sp_verbose > 15)		fprintf(spfp,"Proc %s: converting ALAW to PCM\n",proc);	    	    alaw2pcm2((unsigned char *)out_inter_block,		     (short *)spwav->converted_buffer,		     spstat->file_sbf,		     out_samples*spstat->user_channel_count);	    out_block = (void *)spwav->converted_buffer;	} else if ((spstat->user_encoding == SP_se_pcm2) &&		   (spstat->file_encoding == SP_se_alaw)) {	    if (sp_verbose > 15)		fprintf(spfp,"Proc %s: converting ALAW to PCM\n",proc);	    pcm22alaw((short *)out_inter_block,		      spstat->user_sbf,		      (unsigned char *)spwav->converted_buffer,		      out_samples*spstat->user_channel_count);	    	    out_block = (void *)spwav->converted_buffer;	} else if (((spstat->user_encoding == SP_se_pcm2) &&		    (spstat->file_encoding == SP_se_pcm2)) &&		   (spstat->user_sbf != spstat->file_sbf)){	    /* swap them bytes now */	    char *tp = (char *)spwav->byteswap_buffer;	    char *p=(char *)out_inter_block;	    int nn = out_samples*spstat->user_channel_count, n;	    for (n = 0; n < nn; n++, p+=2, tp+=2){		*tp= *(p+1); *(tp+1) = *p;	    }	    out_block = spwav->byteswap_buffer;	} else { /* use the buffer passed to the function */	    out_block = out_inter_block;	}		/*****************************************************/	/****             INVARIANT ASSERTION:            ****/	/****  out_block points to the file_encoded data  ****/	/****  and file_sbf, but the same channel count   ****/	/****  as the user's input.                       ****/	/*****************************************************/		/* do the channel modifications */	if (spstat->channels != CHANNELSNULL){		    int in_recsize, out_recsize, in_chancnt, out_chancnt, out_snb;	    int oc, s;	    void *eod;	    	    if (sp_verbose > 15)		fprintf(spfp,"Proc %s: Converting channels\n",proc);	    	    in_chancnt = spstat->user_channel_count;	    in_recsize = spstat->file_sample_n_bytes *  in_chancnt;	    out_chancnt = spstat->file_channel_count;	    out_snb = spstat->file_sample_n_bytes;	    out_recsize = spstat->file_sample_n_bytes * out_chancnt;	    	    /*  process each requested channel */	    for (oc=0; oc<spifr->status->channels->num_chan; oc++)		if (spifr->status->channels->ochan[oc].num_origin == 1){		    char *in_ptr, *out_ptr;		    in_ptr = (char *)out_block + 			((spstat->channels->ochan[oc].orig_channel[0]-1)*			 spstat->file_sample_n_bytes);		    out_ptr = (char *)spwav->file_data_buffer + 			(oc * spifr->status->file_sample_n_bytes);		    /*		       fprintf(spfp,		       " %x  %x  %x  %x\n",in_ptr,in_conversion_block,		       out_ptr , out_block);		       fprintf(spfp,"  %d   %d\n",in_recsize, out_recsize);		       */		    		    for (s=0; s<out_samples; s++){			memcpy(out_ptr,in_ptr,out_snb);			in_ptr += in_recsize;			out_ptr += out_recsize;		    }		    in_ptr-=((spstat->channels->ochan[oc].orig_channel[0]-1)*			     spstat->file_sample_n_bytes);		    eod = (void *)in_ptr;		} else { /* Channels need to be added together */		    if (spstat->file_encoding == SP_se_pcm2) {			/* do a straight add */			ORIGINATION_CHAN *ochn;			short *in_ptr, *out_ptr;			int sum, ch;			if (sp_verbose > 15)			    fprintf(spfp,				    "Proc %s: Adding PCM data %s %d\n",				    proc, "channel",oc);			in_ptr = (short *)out_block;			out_ptr = (short *)spwav->file_data_buffer;			ochn = &(spstat->channels->ochan[oc]);						if (spstat->file_sbf== get_natural_sbf(2)){			    for (s=0; s<out_samples; s++){				for (ch=0, sum=0; ch <ochn->num_origin;ch++){				    sum +=*(in_ptr+ochn->orig_channel[ch]-1);				}				if (sum > 32767) sum = 32767;				else if (sum < -32768) sum = -32768;				*(out_ptr + oc) = (short)sum;				in_ptr += in_chancnt;				out_ptr += out_chancnt;			    }			    eod = in_ptr;			} else {			    short x;			    if (sp_verbose > 15)				fprintf(spfp,"Proc %s: %s %d\n", proc,					"Adding Swapped PCM data channel",oc);			    for (s=0; s<out_samples; s++){				/*				   fprintf(spfp,"sample %d\n",s);  */				for (ch=0, sum=0; ch <ochn->num_origin;ch++){				    x = *(in_ptr+ochn->orig_channel[ch]-1);				    swap_bytes(x);				    sum += x;				    /*				       fprintf(spfp,"   %d  =  %d\n",x,sum); */				}				if (sum > 32767) x = 32767;				else if (sum < -32768) x = -32768;				else x = sum;				swap_bytes(x);				*(out_ptr + oc) = (short)x;				in_ptr += in_chancnt;				out_ptr += out_chancnt;			    }			    eod = in_ptr;			}		    } else if (spifr->status->file_encoding == SP_se_ulaw){			/* do an add on ulaw data */			ORIGINATION_CHAN *ochn;			unsigned char *in_ptr, *out_ptr;			int sum, ch;			if (sp_verbose > 15)			    fprintf(spfp,				    "Proc %s: Adding ULAW data %s %d\n",				    proc, "channel",oc);			in_ptr = (unsigned char *)out_block;			out_ptr = (unsigned char *)spwav->file_data_buffer;			ochn = &(spifr->status->channels->ochan[oc]);						for (s=0; s<out_samples; s++){			    for (ch=0, sum=0; ch <ochn->num_origin;ch++){				sum +=				    ulaw2linear_10_sbf_lut[							   *(in_ptr+ochn->orig_channel[ch]-1)];			    }			    if (sum > 32767) sum = 32767;			    else if (sum < -32768) sum = -32768;			    *(out_ptr + oc) =  linear2ulaw(sum);			    in_ptr += in_chancnt;			    out_ptr += out_chancnt;			}			eod = in_ptr;		    } else if (spifr->status->file_encoding == SP_se_pculaw){			/* do an add on ulaw data */			ORIGINATION_CHAN *ochn;			unsigned char *in_ptr, *out_ptr;			int sum, ch;			if (sp_verbose > 15)			    fprintf(spfp,				    "Proc %s: Adding PCULAW data %s %d\n",				    proc, "channel",oc);			in_ptr = (unsigned char *)out_block;			out_ptr = (unsigned char *)spwav->file_data_buffer;			ochn = &(spifr->status->channels->ochan[oc]);						for (s=0; s<out_samples; s++){			    for (ch=0, sum=0; ch <ochn->num_origin;ch++){				sum +=				    ulaw2linear_10_sbf_lut[							   uchar_bitreverse_lut[										*(in_ptr+ochn->orig_channel[ch]-1)]];			    }			    if (sum > 32767) sum = 32767;			    else if (sum < -32768) sum = -32768;			    *(out_ptr + oc) = uchar_bitreverse_lut[								   linear2ulaw(sum)];			    in_ptr += in_chancnt;			    out_ptr += out_chancnt;			}			eod = in_ptr;		    } else if (spifr->status->file_encoding == SP_se_alaw){			/* do an add on alaw data */			ORIGINATION_CHAN *ochn;			unsigned char *in_ptr, *out_ptr;			int sum, ch;			if (sp_verbose > 15)			    fprintf(spfp,				    "Proc %s: Adding ALAW data %s %d\n",				    proc, "channel",oc);			in_ptr = (unsigned char *)out_block;			out_ptr = (unsigned char *)spwav->file_data_buffer;			ochn = &(spifr->status->channels->ochan[oc]);						for (s=0; s<out_samples; s++){			    for (ch=0, sum=0; ch <ochn->num_origin;ch++){				sum +=				    alaw2linear_10_sbf_lut[							   *(in_ptr+ochn->orig_channel[ch]-1)];			    }			    if (sum > 32767) sum = 32767;			    else if (sum < -32768) sum = -32768;			    *(out_ptr + oc) =  linear2alaw(sum);			    in_ptr += in_chancnt;			    out_ptr += out_chancnt;			}			eod = in_ptr;		    }		}	    /**** in_ptr MUST point to the next input block of data ***/	    	    out_block = spwav->file_data_buffer;	}		ret = fob_fwrite(out_block, spstat->file_sample_n_bytes*			 spstat->file_channel_count,			 out_samples, spwav->sp_fob);	if (ret != out_samples){	    return_err(proc,306,0,		       rsprintf("Unable to write data %d written, not %d",				ret,out_samples));	}	   	samples_written += ret;		/* Perform the checksum computation */	switch (spstat->file_encoding){	  case SP_se_pcm2:	    if (spstat->file_sbf != get_natural_sbf(2)){		if (sp_verbose > 16)		    fprintf(spfp,"Proc %s: Swapping for checksum\n",proc);		checksum = sp_compute_short_checksum(out_block, out_samples*						     spstat->file_channel_count, TRUE);	    } else {		if (sp_verbose > 16)		    fprintf(spfp,			    "Proc %s: Not Swapping for checksum\n",proc);		checksum = sp_compute_short_checksum(out_block, out_samples*						     spstat->file_channel_count, FALSE);	    }	    	    if (sp_verbose > 16)		fprintf(spfp,"Proc %s: short checksum = %d\n",proc,checksum);	    spwav->checksum =		sp_add_checksum(spwav->checksum,checksum);	    spwav->samples_written += ret;

⌨️ 快捷键说明

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