⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abplay.c

📁 LPC 2.4kbps codec meeting Federal Standard 1016 CELP implementation
💻 C
字号:
#include <unistd.h>#include <fcntl.h>#include <stropts.h>#include <errno.h>#include <values.h>#include "abplay.h"#include <multimedia/libaudio.h>#include <multimedia/audio_device.h>#include <xview/notify.h>#define AUDIO_DEV	"/dev/audio"#define AUDIO_CTLDEV	"/dev/audioctl"static int device_fd = 0;	/* Audio device fd */static int devctl_fd = 0;	/* Audioctl device fd (for status changes) */#define SIG_SIZE 	4096	/* Audio output buffer size (>= STEPMAX!) */static char ptbuf[SIG_SIZE];	/* Signal translation buffer */static int event_posted = FALSE; /* Synchronous notifier client called */static struct {		/* State of background audio stream */	int state;	/* IDLE, DRAIN, or PLAY */	int id;		/* ID of currently (or most recently) playing data */	char *segstart;	/* Pointer to beginning of segment */	char *segend;	/* Pointer to end of segment */	char *posn;	/* Current I/O location in signal file */	char *bp;	/* Current I/O location in translation buffer */	int nb;		/* Unsent bytes left in translation buffer */	int trans;	/* Audio file translation code */	int nmax;	/* Max input to avoid translation buffer overflow */} audio;static struct {	int id;		/* File ID of request (-1 if none) */	float start;	/* Starting point of segment (seconds) */	float end;	/* Ending point of segment */} request;Notify_value sigpoll_handler();abp_open_device(int dtype){	int flags;	char *dev = AUDIO_DEV;	if (device_fd <= 0) {	    audio.state = IDLE;	    if ((device_fd = open(dev, O_WRONLY | O_NDELAY)) < 0) {	        perror(dev);	        if ((errno==EINTR) || (errno==EBUSY)) device_fd = -2;	    } else {	        flags = fcntl(device_fd, F_GETFL, 0) | O_NONBLOCK;	        if (fcntl(device_fd, F_SETFL, flags) < 0)	            perror("audio device F_SETFL fcntl"); /* Set non-blocking */	        if (ioctl(device_fd, I_SETSIG, S_OUTPUT | S_MSG) < 0)	            perror("audio device I_SETSIG");	/*Enable play SIGPOLL*/	        if ((devctl_fd = open(AUDIO_CTLDEV, O_RDWR)) < 0)	            perror(AUDIO_CTLDEV);	        if (ioctl(devctl_fd, I_SETSIG, S_MSG) < 0)	            perror("audio_ctl I_SETSIG");   /* Enable status SIGPOLL */         /* Set up to catch SIGPOLL asynchronously to service audio stream  */         /* Notifier client id is meaningless, but must be unique, so use the              virtual memory address of something random that we own.       */	        (void) notify_set_signal_func((int)&audio,	            (Notify_func)sigpoll_handler, SIGPOLL, NOTIFY_ASYNC);	    }	}	return device_fd;	/* -1 = error, -2 = try again */}abp_close_device(){	if (device_fd > 0) close(device_fd);	if (devctl_fd > 0) close(devctl_fd);	device_fd = devctl_fd = 0;}abp_start_play(int id, int segnum){	struct segstate sg;	if (abp_open_device(0) < 0) return;	sg = abp_get_segstate();	request.id = id;	request.start = request.end = 0.0;	if (segnum > 0 && segnum <= sg.nsegs) {	    request.start = sg.segs[segnum-1].start;	    request.end   = sg.segs[segnum-1].end;	}	audio.state = DRAIN;	kill(getpid(), SIGPOLL);	/* kick SIGPOLL to start play */}abp_stop_play(){	audio.state = DRAIN;	audio_play_eof(device_fd);   /* EOF will SIGPOLL after buffer drains */}abp_abort_play(){	audio.state = DRAIN;	audio_flush_play(device_fd);	kill(getpid(), SIGPOLL);	/* Quit immediately */}abp_get_audio_status(struct audio_status *status){	status->id = audio.id;	status->state = audio.state;	event_posted = FALSE;}/************************* End of public interface *********************//*********************** The rest is implementation ********************/play_setup(){	int i;	int id, n1, n2;	struct abfile *abf;	Audio_hdr dev_hdr, f_hdr;	char *base;	id = request.id;	request.id = -1;	if ((abf = abp_get_abfile(id)) == (struct abfile *)0) {	    fprintf(stderr, "play: invalid file (%d)\n", id);	    return -1;	}	f_hdr = abf->h;	if (request.end <= 0.0) {	    n1 = 0;	    n2 = MAXINT;	} else {	    n1 = audio_secs_to_bytes(&f_hdr, request.start + abf->p.delay);	    n2 = audio_secs_to_bytes(&f_hdr, request.end + abf->p.delay) - 1;	}	if (n1 >= n2) return -1;	audio.trans = audio_set_play_translate(device_fd, &f_hdr, &dev_hdr);	if (audio.trans >= 0) {	    audio.state = PLAY;	    audio.nb = 0;	    audio.id = id;	    base = abf->data + abf->hsize;	    audio.segstart = base + MAX(0, n1);	    audio.segend  =  base + MIN(f_hdr.data_size-1, n2);	    audio.posn = audio.segstart;	    audio.nmax = (SIG_SIZE * f_hdr.bytes_per_unit) /	                            dev_hdr.bytes_per_unit;	}	return audio.trans;}play_service(){	int outcnt, n;	outcnt = audio.segend + 1 - audio.posn;	while (outcnt > 0 || audio.nb > 0) {	   if (audio.nb == 0) {	      if (audio.trans == 0) {	         audio.bp = audio.posn;	         audio.nb = n = outcnt;	      } else {	         audio.bp = ptbuf;	         n = MIN(outcnt, audio.nmax);	         audio.nb = audio_translate(audio.trans, audio.posn, ptbuf, n);	      }	      audio.posn += n;	      outcnt -= n;	   }	   n = write(device_fd, audio.bp, audio.nb);	   if (n < 0 && errno != EWOULDBLOCK) {	      perror("audio device write err");	      audio_flush_play(device_fd);	   }	   if (n <= 0) break;	   audio.nb -= n;	   audio.bp += n;	   if (outcnt == 0 && audio.nb == 0) abp_stop_play();	}}/* Asynchronous SIGPOLL handler.  Service audio device */Notify_valuesigpoll_handler(Notify_client client, int sig, Notify_signal_mode when){	int n;	unsigned active = 0;	static char *sttr[] = {"IDLE", "DRAIN", "PLAY"};/*	fprintf(stderr, "APOLL in:  %d (%s), req id=%d\n",	    audio.state, sttr[audio.state], request.id);*/	if (audio.state == DRAIN) {	    audio_get_play_active(device_fd, &active);	    if (active == 0) audio.state = IDLE;	}	if (audio.state == IDLE && request.id >= 0) {	    play_setup();	}	if (audio.state == PLAY) play_service();/* Post a synchronous notifier event to client "SIGPOLL", to notify * display code that something may have happened. */	if (!event_posted) {	    event_posted = TRUE;	    notify_post_event(SIGPOLL, NULL, NOTIFY_SAFE);	}/*	fprintf(stderr, "APOLL out: %d (%s), %d %d\n",	    audio.state, sttr[audio.state], audio.id, active);*/	return NOTIFY_DONE;}audio_set_play_translate(int fd, Audio_hdr *f_hdr, Audio_hdr *d_hdr){/* * Set up audio file translation *  fd = audio device file descriptor  *  f_hdr = file encoding *  d_hdr = audio device encoding (returned) *  Return value: *  < 0: File is not compatible with audio device *  = 0: Audio device is configured to match file *  > 0: File can be translated to match device */	int i;	char str[AUDIO_MAX_ENCODE_INFO];/* Try to set audio device to match file */	if (fd > 0) {	    *d_hdr = *f_hdr;	    i = audio_set_play_config(fd, d_hdr);	    if (i == AUDIO_SUCCESS)	        return 0;	    else if (i != AUDIO_ERR_NOEFFECT) {	        printf("status %d, fd = %d\n", i, fd);	        perror("audio_set_play_config");	        audio_enc_to_str(f_hdr, str);	        fprintf(stderr,"Can't convert: %s\n", str);	        audio_enc_to_str(d_hdr, str);	        fprintf(stderr,"           to: %s\n", str);	        return -1;	    }	}/*   Can't set device to match file -      see if we can convert file to match device */	return audio_setup_translate(*f_hdr, *d_hdr, 1);}

⌨️ 快捷键说明

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