📄 audbri_utils.c
字号:
#ident "@(#)audbri_utils.c 1.1 92/07/30 SMI"/* * Copyright (C) 1992 by Sun Microsystems, Inc. *//* * Utility routines for DBRI/MMCODEC audio tests. */#include <stdio.h>#include <fcntl.h>#include <stropts.h>#include <errno.h>#include <math.h>#include <sys/types.h>#include <sys/file.h>#include <sys/ioctl.h>#include <sys/asynch.h>#include <sys/stat.h>#include <sys/mman.h>#include <sys/time.h>/* #include <sun/audioio.h> ...not there yet... */#include "audioio.h"#include "sdrtns.h"#include "../../../lib/include/libonline.h"#include "audbri.h"#include "audbri_msg.h"#include "audbri_g711.h"extern int bin_sel;extern double lbins[],rbins[],lrms,rrms;/* * Calculate calibration and loopback offset (in shorts) into signal. */intcalc_offset(auptr)au_data_t *auptr;{ int chancnt, offset; func_name = "calc_offset"; TRACE_IN if (auptr->channels == MONO) { chancnt = 1; } else { chancnt = 2; } offset = .75 * (chancnt * auptr->sample_rate); TRACE_OUT return(offset);}/* * Calculate signal's RMS value. */doublermscalc(sigptr, sample_cnt)short *sigptr;int sample_cnt;{ int i; double sum; func_name = "rmscalc"; TRACE_IN /* * Calculate RMS */ for (i = 0, sum = 0; i < sample_cnt; sigptr++, i++) { sum = sum + ((double) *sigptr) * ((double) *sigptr); } sum = sum / sample_cnt; sum = sqrt(sum); /* * Convert to db. */ sum = 20 * log10(sum); TRACE_OUT return(sum);}/* * Returns the maximum fft magnitude for a given frequency range */doublebandrms(magp, fsize, size, start, end, sr)double *magp;int fsize;int size;int start;int end;int sr;{ int i, lower_slot, upper_slot, tmp_slot; double sum, tmp, save; func_name = "bandrms"; 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)); } /* * Determine the RMS for this band. */ if (lower_slot > upper_slot) { tmp_slot = upper_slot; upper_slot = lower_slot; lower_slot = tmp_slot; } sum = 0; for (i = lower_slot; i <= upper_slot; i++) { tmp = exp10(magp[i]/20); sum = sum + (tmp * tmp); } sum = sum / (upper_slot - lower_slot + 1); sum = sqrt(sum); /* * Convert to db. */ sum = 20 * log10(sum); TRACE_OUT return(sum);}/* * Generate a sine wave of given frequency, sample_rate and duration * allocated for the signal (an array of doubles) and pointed to by * 'signal'. The signal produced will be scaled to the range * specified by the value 'maxval'. 'maxval' is the maximum value * the signal have. */intgensine(freq, srate, dur, sigptr, maxval)int freq; /* Hz */int srate; /* Hz */int dur; /* seconds */short **sigptr;int maxval;{ int i, sample_cnt; short *sptr; double radians, samples_per_cycle; func_name = "gensine"; TRACE_IN if (freq != 0) { samples_per_cycle = (double) srate / (double) freq; } sample_cnt = srate * dur; /* * get space for the signal */ if ((*sigptr = (short *) calloc(sample_cnt, sizeof(short))) == NULL) { send_message(ERSYS, ERROR, er_mem, (sizeof(short)*sample_cnt), SYSMSG); } /* * make the signal */ for (i = 0, sptr=*sigptr; i < sample_cnt;) { if (freq == 0) { *sptr++ = 0; i++; } else { for (radians = 0; radians < (2*M_PI), i < sample_cnt; i++, radians += (2*M_PI)/samples_per_cycle ) { *sptr++ = (short) (sin(radians) * (double) maxval); } } } TRACE_OUT return(sample_cnt);}/* * Generate a stereo (2 channel) signal from 2 mono signals. If a NULL * is passed for either channel then that channel is filled with zeros. */intgenstereo(lsigptr, rsigptr, ssigptr, sample_cnt)short *lsigptr, *rsigptr;short **ssigptr;int sample_cnt;{ int i, st_sample_cnt; short *sptr; func_name = "genstereo"; TRACE_IN st_sample_cnt = 2*sample_cnt; /* * get space for the signal */ if ((*ssigptr = (short *) calloc(st_sample_cnt, sizeof(short))) == NULL) { send_message(ERSYS, ERROR, er_mem, (sizeof(short)*st_sample_cnt), SYSMSG); } /* * make the signal */ for (i = 0, sptr=*ssigptr; i < sample_cnt; i++) { *sptr++ = (lsigptr ? *lsigptr++ : 0); *sptr++ = (rsigptr ? *rsigptr++ : 0); } TRACE_OUT return(st_sample_cnt);}/* * Generate a signal to play, either mono or stereo depending upon * the contents of the au_data_t structure. */intgensig(auptr, sigptr, duration)au_data_t *auptr;short **sigptr;int duration;{ short *lsig, *rsig; int sample_cnt; func_name = "gensig"; TRACE_IN /* * Generate left channel signal. */ sample_cnt = gensine(auptr->lfreq, auptr->sample_rate, duration, &lsig, MAXPCM); /* * MONO signals just use left channel data from the au_data_t. */ if (auptr->channels == MONO) { *sigptr = lsig; } /* * Generate right side also if this is STEREO */ else { (void) gensine(auptr->rfreq, auptr->sample_rate, duration, &rsig, MAXPCM); sample_cnt = genstereo(lsig, rsig, sigptr, sample_cnt); } TRACE_OUT return(sample_cnt);}/* * Split a stereo (2 channel) signal into 2 mono signals. */voidsplitstereo(lsigptr, rsigptr, ssigptr, sample_cnt)short **lsigptr, **rsigptr;short *ssigptr;int sample_cnt;{ int i; short *lptr, *rptr; func_name = "splitstereo"; TRACE_IN sample_cnt = sample_cnt / 2; /* * get space for mono signals */ if ((*lsigptr = (short *) calloc(sample_cnt, sizeof(short))) == NULL) { send_message(ERSYS, ERROR, er_mem, (sizeof(short)*sample_cnt), SYSMSG); } if ((*rsigptr = (short *) calloc(sample_cnt, sizeof(short))) == NULL) { send_message(ERSYS, ERROR, er_mem, (sizeof(short)*sample_cnt), SYSMSG); } /* * split the signal */ for (i = 0, lptr=*lsigptr, rptr=*rsigptr; i < sample_cnt; i++) { *lptr++ = *ssigptr++; *rptr++ = *ssigptr++; } TRACE_OUT}/* * Play data. Doesn't return until the play is completed. */intplay(psig, sample_cnt, precision)caddr_t psig;int sample_cnt;int precision;{ int i, err, wcnt, write_size, size, count; audio_info_t info; struct timeval begin_tp, end_tp; long time; func_name = "play"; TRACE_IN if (precision == 16) { size = sample_cnt * sizeof(short); /* we're writing shorts */ } else { size = sample_cnt; } /* * unpause */ AUDIO_INITINFO(&info); info.play.pause = 0; if (ioctl(audiofd, AUDIO_SETINFO, &info) < 0) { send_message(ERSYS, ERROR, er_ioctl, "AUDIO_SETINFO", SYSMSG); } /* * play, continue on EINTR */ (void) gettimeofday(&begin_tp, NULL); count = 0; while (count < size && dc_flag != 4) { if (play_size > size - count) { write_size = size - count; } else { write_size = play_size; } /* * Restart write if error in EINTR. */ do { wcnt = write(audiofd, psig, write_size); if (wcnt == -1 && errno != EINTR) { send_message(ERSYS, ERROR, er_write, SYSMSG); } } while(wcnt == -1); count += wcnt; psig += wcnt; } /* * wait for completion or controls test completion (dc_flag), * continue on EINTR */ while (dc_flag != 4 && (err = ioctl(audiofd, AUDIO_DRAIN, NULL)) != 0) { if (err == -1 && errno != EINTR) { send_message(ERSYS, ERROR, er_ioctl, "AUDIO_DRAIN", SYSMSG); } } (void) gettimeofday(&end_tp, NULL); time = (long) intervalcalc(&begin_tp, &end_tp); /* * pause play */ AUDIO_INITINFO(&info); info.play.pause = 1; if (ioctl(audiofd, AUDIO_SETINFO, &info) < 0) { send_message(ERSYS, ERROR, er_ioctl, "AUDIO_SETINFO", SYSMSG); } /* * flush the audio stream */ if (ioctl(audiofd, I_FLUSH, FLUSHW) < 0) { send_message(ERSYS, ERROR, er_ioctl, "I_FLUSH", SYSMSG); } TRACE_OUT return((int) time);}/* * Play and record data at the same time. This routine is used * for loopback tests. This routine expects psig to point to a 16 bit * PCM signal and returns a pointer to a 16 bit PCM signal in *rsig. * * The variable auptr->encoding determines what type of signal is * actually played and recorded. */voidplayrecord(psig, rsig, sample_cnt, dur, auptr)short *psig;short **rsig;int sample_cnt;int dur;au_data_t *auptr;{ aio_result_t aw_result, ar_result; struct timeval timeout; int i, sample_size; audio_info_t info; u_char *play_sig, *record_sig, *tmptr; short *sptr; func_name = "playrecord"; TRACE_IN /* * Convert play signal to encoding indicated by auptr->encoding */ switch (auptr->encoding) { case AUDIO_ENCODING_ULAW: /* * Make sure precision is 8. */ if (auptr->precision != 8) { send_message(ERAUDIO, ERROR, er_precision); } /* * get space for the signal */ sample_size = sizeof(char); if ((play_sig = (u_char *) calloc(sample_cnt, sample_size)) == NULL) { send_message(ERSYS, ERROR, er_mem, sample_cnt, SYSMSG); } /* * Convert play signal to ulaw. */ tmptr = play_sig; for (i = 0; i < sample_cnt; i++) { *tmptr++ = audio_s2u(*psig++); } break; case AUDIO_ENCODING_ALAW: /* * Make sure precision is 8. */ if (auptr->precision != 8) { send_message(ERAUDIO, ERROR, er_precision); } /* * get space for the signal */ sample_size = sizeof(char); if ((play_sig = (u_char *) calloc(sample_cnt, sample_size)) == NULL) { send_message(ERSYS, ERROR, er_mem, sample_cnt, SYSMSG); } /* * Convert play signal to alaw. */ tmptr = play_sig; for (i = 0; i < sample_cnt; i++) { *tmptr++ = audio_s2a(*psig++); } break; case AUDIO_ENCODING_LINEAR: play_sig = (u_char *) psig; sample_size = sizeof(short); break; default: send_message(ERAUDIO, ERROR, er_encoding); break; } /* * get space for the recorded signal */ if ((record_sig = (u_char *) calloc(sample_cnt, sample_size)) == NULL) { send_message(ERSYS, ERROR, er_mem, (sample_size*sample_cnt), SYSMSG); } /* * set up unpause */ AUDIO_INITINFO(&info); info.play.pause = 0; info.record.pause = 0; /* * initialize aio results */ aw_result.aio_return = ar_result.aio_return = AIO_INPROGRESS; /* * start play */ if (aiowrite(audiofd, play_sig, sample_size*sample_cnt, 0, 0, &aw_result) == -1) { send_message(ERSYS, ERROR, er_aiowrite, SYSMSG); } /* * unpause record and play */ if (ioctl(audiofd, AUDIO_SETINFO, &info) < 0) { send_message(ERSYS, ERROR, er_ioctl, "AUDIO_SETINFO", SYSMSG); } /* * start record */ if (aioread(audiofd, record_sig, sample_size*sample_cnt, 0, 0, &ar_result) == -1) { send_message(ERSYS, ERROR, er_aioread, SYSMSG); } /* * wait for completion */ i = 0; do { timeout.tv_sec = dur; timeout.tv_usec = 0; if (aiowait(&timeout) == -1) { if (errno == EINVAL) { /* nothing to wait for */ break; } send_message(ERSYS, ERROR, er_aiowait, SYSMSG); } i++; } while ((i<aioto_cnt) && (aw_result.aio_return == AIO_INPROGRESS || ar_result.aio_return == AIO_INPROGRESS)); /* * wait for play to "drain" */ if (ioctl(audiofd, AUDIO_DRAIN, NULL) < 0) { send_message(ERSYS, ERROR, er_ioctl, "AUDIO_DRAIN", SYSMSG); } /* * pause record and play */ AUDIO_INITINFO(&info); info.play.pause = 1; info.record.pause = 1; if (ioctl(audiofd, AUDIO_SETINFO, &info) < 0) { send_message(ERSYS, ERROR, er_ioctl, "AUDIO_SETINFO", SYSMSG); } /* * see if aiowrite and aioread completed ok */ if (aw_result.aio_return == AIO_INPROGRESS || aw_result.aio_return == -1) { (void) aiocancel(&aw_result); send_message(ERSYS, ERROR, er_aiowrite, SYSMSG); } if (ar_result.aio_return == AIO_INPROGRESS || ar_result.aio_return == -1) { (void) aiocancel(&ar_result); send_message(ERSYS, ERROR, er_aioread, SYSMSG); } /* * See if all data was written */ if (aw_result.aio_return != sample_cnt*sample_size) { send_message(ERAUDIO, ERROR, er_aiowritep, aw_result.aio_return, sample_cnt*sample_size); } /* * See if all data was read */ if (ar_result.aio_return != sample_cnt*sample_size) { send_message(ERAUDIO, ERROR, er_aioreadp, ar_result.aio_return, sample_cnt*sample_size); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -