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