📄 audbri_utils.c
字号:
/* * flush the audio stream */ if (ioctl(audiofd, I_FLUSH, FLUSHRW) < 0) { send_message(ERSYS, ERROR, er_ioctl, "I_FLUSH", SYSMSG); } /* * Convert recorded signal to linear encoding (unless it's * already linear). */ switch (auptr->encoding) { case AUDIO_ENCODING_ULAW: /* * get space for the signal */ if ((*rsig = (short *) calloc(sample_cnt, sizeof(short))) == NULL) { send_message(ERSYS, ERROR, er_mem, sample_cnt*sizeof(short), SYSMSG); } /* * Convert recorded signal to 16 bit PCM. */ tmptr = record_sig; sptr = *rsig; for (i = 0; i < sample_cnt; i++) { *sptr++ = audio_u2s(*tmptr++); } free(play_sig); free(record_sig); break; case AUDIO_ENCODING_ALAW: /* * get space for the signal */ if ((*rsig = (short *) calloc(sample_cnt, sizeof(short))) == NULL) { send_message(ERSYS, ERROR, er_mem, sample_cnt*sizeof(short), SYSMSG); } /* * Convert recorded signal to 16 bit PCM. */ sptr = *rsig; tmptr = record_sig; for (i = 0; i < sample_cnt; i++) { *sptr++ = audio_a2s(*tmptr++); } free(play_sig); free(record_sig); break; case AUDIO_ENCODING_LINEAR: *rsig = (short *) record_sig; break; default: send_message(ERAUDIO, ERROR, er_encoding); break; } TRACE_OUT}/* * Release reference file resources. */unset_ref(){ func_name = "unset_ref"; TRACE_IN (void) munmap(refptr, ref_mapsize); refname = NULL; refptr = NULL; TRACE_OUT}/* * This routine is called if the calibration test is not being * run. It attempts to open the reference file pointed to by * 'refname' if refname is non-NULL, otherwise, the file opened is * derived from the loopback "type". */intset_ref(){ int fd; struct stat statbuf; func_name = "set_ref"; TRACE_IN if (refname[0] < 'A') { strcpy(refname,ldata[ltype].refname); } /* * open the file, get it's size and map it */ if ((fd = open(refname, O_RDONLY)) == -1 ) { send_message(ERSYS, ERROR, er_open, refname, SYSMSG); } if (fstat(fd, &statbuf) == -1) { send_message(ERSYS, ERROR, er_stat, SYSMSG); } ref_mapsize = statbuf.st_size; if ((refptr = (ref_data_t *)mmap((caddr_t) 0, ref_mapsize, PROT_READ, MAP_SHARED, fd, (off_t) 0)) == (ref_data_t *)-1 ) { send_message(ERSYS, ERROR, er_mmap, SYSMSG); } close(fd); TRACE_OUT}/* * Get number of elements in an band_data_t array. */intgetbdsiz(bdptr)band_data_t *bdptr;{ int i=0; while (bdptr->type != NULL) { i++; bdptr++; } return(i);}/* * Get number of elements in an au_data_t array. */intgetausiz(auptr)au_data_t *auptr;{ int i=0; while (auptr->sample_rate != NULL) { i++; auptr++; } return(i);}/* * Determine the size of the reference file, open and map it. */voidmap_ref(fname, auptr)char *fname;au_data_t *auptr;{ int fd, fftsize, rdsize; double rms; func_name = "map_ref"; TRACE_IN /* * open the file */ if ((fd = open(fname, O_CREAT | O_RDWR, 0666)) == -1 ) { send_message(ERSYS, ERROR, er_open, fname, SYSMSG); } /* * The reference file has space for left/right channel data * even if the au_data_t says MONO. This makes coding a bit * easier. */ fftsize = ref_size/2 + 1; rdsize = fftsize * sizeof(double) + sizeof(ref_data_t); ref_mapsize = getausiz(auptr) * rdsize * 2; if (ftruncate(fd, ref_mapsize) == -1 ) { send_message(ERSYS, ERROR, er_truncate, SYSMSG); } /* * map the fft magnitude file */ if ((refptr = (ref_data_t *) mmap ((caddr_t) 0, ref_mapsize, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, (off_t) 0)) == (ref_data_t *)-1 ) { send_message(ERSYS, ERROR, er_mmap, SYSMSG); } close(fd);}/* * Performs RMS and fft calculations and saves RMS, gain and fft * magnitude data in a file as reference data for further tests. */voidcalc_ref(sigptr, size, pgain, rgain, refp)short *sigptr;int size;int pgain;int rgain;ref_data_t *refp;{ int fftsize; double rms; func_name = "calc_ref"; TRACE_IN /* * perform RMS calculation and write rms and gain */ rms = rmscalc(sigptr, size); if (bin_sel == LEFT) lrms = rms; else rrms = rms; refp->rms = rms; refp->play_gain = pgain; refp->record_gain = rgain; /* * perform fft and write magnitude data */ fftsize = size/2+1; bin_sel = LEFT; if (fftmag(sigptr, size, &refp->mag) != fftsize) { send_message(ERAUDIO, ERROR, er_fftmag); } send_message(0, DEBUG, ref_msg, pgain, rgain, rms); TRACE_OUT}/* * Generate reference data and get it into the reference file. */voidgenref(sigptr, sample_cnt, pgain, auptr, aud_index)short *sigptr;int sample_cnt;int pgain;au_data_t *auptr;int aud_index;{ int i, fftsize, rdsize; short *lsig, *rsig; ref_data_t *refp; func_name = "genref"; TRACE_IN /* * Calculate size of reference data (per sample) and * get a pointer into the mapped reference file. */ fftsize = sample_cnt/2 + 1; rdsize = fftsize * sizeof(double) + sizeof(ref_data_t); refp = (ref_data_t *) ((caddr_t) refptr + (rdsize * 2 * aud_index)); if (auptr->channels == MONO) { calc_ref(sigptr, sample_cnt, pgain, auptr->cal_rgain, refp); if (dump_signals) { dump_sig(sigptr, sample_cnt, aufname("ref-rec-mono", auptr)); } } else { splitstereo(&lsig, &rsig, sigptr, 2*sample_cnt); calc_ref(lsig, sample_cnt, pgain, auptr->cal_rgain, refp); if (dump_signals) { dump_sig(lsig, sample_cnt, aufname("ref-rec-left", auptr)); dump_sig(rsig, sample_cnt, aufname("ref-rec-right", auptr)); } refp = (ref_data_t *) ((caddr_t) refptr + (rdsize * 2 * aud_index) + rdsize); calc_ref(rsig, sample_cnt, pgain, auptr->cal_rgain, refp); free(lsig); free(rsig); } TRACE_OUT}/* * Returns the maximum fft magnitude for a given frequency range */doublemaxmag(magp, fsize, size, start, end, sr)double *magp;int fsize;int size;int start;int end;int sr;{ int i, lower_slot, upper_slot; double max; func_name = "maxmag"; TRACE_IN /* * Determine starting and ending fft magnitude slots for * this frequency range. */ if (start == 0) { lower_slot = 0; } else { lower_slot = rint((double) (((double) start * (double) size) / (double) sr)); } if (end == END_FREQ) { upper_slot = fsize; } else { upper_slot = rint((double) (((double) end * (double) size) / (double) sr)); } /* * Find biggest value and return it. */ max = 0; for (i = lower_slot; i <= upper_slot; i++) { if (magp[i] > max) { max = magp[i]; } } TRACE_OUT return(max);}/* * Calculate the thresholds for a given signal and reference data. * We just malloc some space for a bunch of doubles and put all the * threshold values there. */calc_threshold(refp, sample_cnt, auptr, thdata)ref_data_t *refp;int sample_cnt;au_data_t *auptr;thresh_data_t *thdata;{ int i, bcnt, fftsize, rdsize; double *lrefmag, *rrefmag, lref_bandrms, rref_bandrms; double tmp_rms, tmp_mag, ref_bandrms; ref_data_t *lrefp, *rrefp; func_name = "calc_threshold"; TRACE_IN /* * Get some space for the rms limits (upper and lower for * each channel). */ if ((thdata->lrms = (double *) calloc(2, sizeof(double))) == NULL) { send_message(ERSYS, ERROR, er_mem, (sizeof(double)* 2), SYSMSG); } if ((thdata->rrms = (double *) calloc(2, sizeof(double))) == NULL) { send_message(ERSYS, ERROR, er_mem, (sizeof(double)* 2), SYSMSG); } /* * Get some space for FFT band threshold values (number of * bands * 2 channels). */ bcnt = getbdsiz(auptr->bdata); /* number of freq bands */ if ((thdata->lmag = (double *) calloc(bcnt, sizeof(double))) == NULL) { send_message(ERSYS, ERROR, er_mem, (sizeof(double)*bcnt), SYSMSG); } if ((thdata->rmag = (double *) calloc(bcnt, sizeof(double))) == NULL) { send_message(ERSYS, ERROR, er_mem, (sizeof(double)*bcnt), SYSMSG); } fftsize = sample_cnt/2+1; /* offsets for ref data */ rdsize = fftsize * sizeof(double) + sizeof(ref_data_t); lrefp = refp; /* left and right chan ref ptrs */ rrefp = (ref_data_t *) ((caddr_t) refp + rdsize); lrefmag = &lrefp->mag; /* left and right ref fft mags */ rrefmag = &rrefp->mag; /* * RMS limit and fft magnitude threshold calculation for * mono signals. The rms limits and fft magnitude thresholds * for mono signals are placed in the left channel "slot". * Right channel slots are filled with zero. * */ if (auptr->channels == MONO) { /* * set RMS limits */ thdata->lrms[0] = lrefp->rms + aurms_tol; thdata->lrms[1] = lrefp->rms - aurms_tol; thdata->rrms[0] = 0; thdata->rrms[1] = 0; /* * Set FFT magnitude thresholds for each band. */ for (i = 0; i < bcnt; i++) { ref_bandrms = bandrms(lrefmag, fftsize, sample_cnt, auptr->bdata[i].start_freq, auptr->bdata[i].end_freq, auptr->sample_rate); if (auptr->bdata[i].type == BAND_FUND) { thdata->lmag[i] = ref_bandrms - aumag_tol; thdata->rmag[i] = 0; } else { thdata->lmag[i] = ref_bandrms + aumag_tol; thdata->rmag[i] = 0; } } } /* * RMS limit and fft magnitude threshold calculation for * stereo signal with both channels. */ else if (auptr->lfreq && auptr->rfreq) { /* * Set RMS limits, use the average of the left and * right channels as the basis. */ tmp_rms = 20*log10((exp10(lrefp->rms/20) + exp10(rrefp->rms/20))/2); send_message(0, DEBUG, tmprms_msg, tmp_rms); thdata->lrms[0] = tmp_rms + aurms_tol; thdata->lrms[1] = tmp_rms - aurms_tol; thdata->rrms[0] = tmp_rms + aurms_tol; thdata->rrms[1] = tmp_rms - aurms_tol; /* * Set FFT magnitude thresholds for each band. */ for (i = 0; i < bcnt; i++) { lref_bandrms = bandrms(lrefmag, fftsize, sample_cnt, auptr->bdata[i].start_freq, auptr->bdata[i].end_freq, auptr->sample_rate); rref_bandrms = bandrms(rrefmag, fftsize, sample_cnt, auptr->bdata[i].start_freq, auptr->bdata[i].end_freq, auptr->sample_rate); tmp_mag = 20*log10((exp10(lref_bandrms/20) + exp10(rref_bandrms/20))/2); send_message(0, DEBUG, tmpmag_msg, tmp_mag); if (auptr->bdata[i].type == BAND_FUND) { thdata->lmag[i] = tmp_mag - aumag_tol; thdata->rmag[i] = tmp_mag - aumag_tol; } else { thdata->lmag[i] = tmp_mag + aumag_tol; thdata->rmag[i] = tmp_mag + aumag_tol; } } } /* * RMS limit and fft magnitude threshold calculation for * stereo signal with one channel driven. * * If only one channel is driven then the threshold for the * non-driven channel will be the difference between the * the left and right channels in the reference signal * plus some offset. * * In this case, the number calculated below for the non- * driven channel's RMS and FFT mag is not the actual * threshold but a value to subtracted from the test signal's * driven channel RMS or FFT mag. (confused yet?) The * actual threshold will be calculated when when get the * test signal's RMS and SST values in chksig(). * * The idea is that the threshold for the non-driven channel * should be: * D(test) - [D(ref) - ND(ref) - tolerance] * * where D(test) = driven channel from test, D(ref) = * driven channel from reference and ND(ref) = non- * driven channel from reference. * */ else { /* * Set RMS limits. */ if (auptr->lfreq) { thdata->lrms[0] = lrefp->rms + aurms_tol; thdata->lrms[1] = lrefp->rms - aurms_tol; } else { tmp_rms = rrefp->rms - lrefp->rms; send_message(0, DEBUG, tmprms_msg, tmp_rms); thdata->lrms[0] = tmp_rms - aurms_tol; thdata->lrms[1] = 0; } if (auptr->rfreq) { thdata->rrms[0] = rrefp->rms + aurms_tol; thdata->rrms[1] = rrefp->rms - aurms_tol; } else { tmp_rms = lrefp->rms - rrefp->rms; send_message(0, DEBUG, tmprms_msg, tmp_rms); thdata->rrms[0] = tmp_rms - aurms_tol; thdata->rrms[1] = 0; } /* * Set FFT magnitude thresholds for each band. */ for (i = 0; i < bcnt; i++) { lref_bandrms = bandrms(lrefmag, fftsize, sample_cnt, auptr->bdata[i].start_freq, auptr->bdata[i].end_freq, auptr->sample_rate); rref_bandrms = bandrms(rrefmag, fftsize, sample_cnt, auptr->bdata[i].start_freq, auptr->bdata[i].end_freq, auptr->sample_rate); if (auptr->bdata[i].type == BAND_FUND) { if (auptr->lfreq) { thdata->lmag[i] = lref_bandrms - aumag_tol; } else { tmp_mag = rref_bandrms - lref_bandrms; send_message(0, DEBUG, tmpmag_msg, tmp_mag); thdata->lmag[i] = tmp_mag - aumag_tol; } if (auptr->rfreq) { thdata->rmag[i] = rref_bandrms - aumag_tol; } else { tmp_mag = lref_bandrms - rref_bandrms; send_message(0, DEBUG, tmpmag_msg, tmp_mag); thdata->rmag[i] = tmp_mag - aumag_tol; } } else { if (auptr->lfreq) { thdata->lmag[i] = lref_bandrms + aumag_tol; } else { tmp_mag = rref_bandrms - lref_bandrms; send_message(0, DEBUG, tmpmag_msg, tmp_mag); thdata->lmag[i] = tmp_mag - aumag_tol; } if (auptr->rfreq) { thdata->rmag[i] = rref_bandrms + aumag_tol; } else { tmp_mag = lref_bandrms - rref_bandrms; send_message(0, DEBUG, tmpmag_msg, tmp_mag); thdata->rmag[i] = tmp_mag - aumag_tol; } } } } TRACE_OUT}/* * returns whether or not a signal is valid. */intsig_valid(refp, test_sig, sample_cnt, auptr)ref_data_t *refp;short *test_sig;int sample_cnt;au_data_t *auptr;{ int i, fftsize, rdsize; short *lsig, *rsig; double *thptr, *rmsptr, *lmag, *rmag; thresh_data_t thdata; func_name = "sig_valid"; TRACE_IN /* * Calculate RMS and FFT magnitude thresholds. */ calc_threshold(refp, sample_cnt, auptr, &thdata); /* * Check mono signal. */ if (auptr->channels == MONO) { fftsize = sample_cnt/2 + 1; rdsize = fftsize * sizeof(double) + sizeof(ref_data_t); if (dump_signals) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -