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

📄 pcm86.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    /* Calculate the length of PCM frames. */    cnt = count + tmpbuf.size;    length = pcm_s.bytes << pcm_s.stereo;    r = cnt % length;    cnt -= r;    if (cnt > 0) {	if (pcm_s.stereo)	    fifo_send_stereo(buf, cnt);	else	    fifo_send_monoral(buf, cnt);	/* Carry over extra data which doesn't seem to be a full PCM frame. */	p = (pcm_data *)buf + count - r;	for (i = 0; i < r; i++)	    tmpbuf.buff[i] = *p++;    } else {	/* Carry over extra data which doesn't seem to be a full PCM frame. */	p = (pcm_data *)buf;	for (i = tmpbuf.size; i < r; i++)	    tmpbuf.buff[i] = *p++;    }    tmpbuf.size = r;    rslt = ((cnt / length) * pcm_s.chipspeed / pcm_s.speed) * pcm_s.bytes * 2;#ifdef PCM86_DEBUG    printk("fifo_send(): %d bytes sent\n", rslt);#endif    return rslt;}static voidfifo_sendtrailer(int count){    /* Send trailing zeros to the FIFO buffer. */    int i;    for (i = 0; i < count; i++)	outb(pcm_s.iobase + 12, 0);    pcm_s.intr_trailer = YES;#ifdef PCM86_DEBUG    printk("fifo_sendtrailer(): %d bytes sent\n", count);#endif}static voidfifo_send_stereo(pcm_data *buf, int count){    /* Convert format and sampling speed. */    switch (pcm_s.format) {    case AFMT_MU_LAW:	fifo_send_stereo_ulaw(buf, count);	break;    case AFMT_S8:	fifo_send_stereo_8(buf, count, NO);	break;    case AFMT_U8:	fifo_send_stereo_8(buf, count, YES);	break;    case AFMT_S16_LE:	fifo_send_stereo_16le(buf, count, NO);	break;    case AFMT_U16_LE:	fifo_send_stereo_16le(buf, count, YES);	break;    case AFMT_S16_BE:	fifo_send_stereo_16be(buf, count, NO);	break;    case AFMT_U16_BE:	fifo_send_stereo_16be(buf, count, YES);	break;    }}static voidfifo_send_monoral(pcm_data *buf, int count){    /* Convert format and sampling speed. */    switch (pcm_s.format) {    case AFMT_MU_LAW:	fifo_send_mono_ulaw(buf, count);	break;    case AFMT_S8:	fifo_send_mono_8(buf, count, NO);	break;    case AFMT_U8:	fifo_send_mono_8(buf, count, YES);	break;    case AFMT_S16_LE:	fifo_send_mono_16le(buf, count, NO);	break;    case AFMT_U16_LE:	fifo_send_mono_16le(buf, count, YES);	break;    case AFMT_S16_BE:	fifo_send_mono_16be(buf, count, NO);	break;    case AFMT_U16_BE:	fifo_send_mono_16be(buf, count, YES);	break;    }}static voidfifo_send_stereo_ulaw(pcm_data *buf, int count){    int i;    signed char dl, dl0, dl1, dr, dr0, dr1;    pcm_data t[2];    if (tmpbuf.size > 0)	t[0] = ulaw2linear[tmpbuf.buff[0]];    else	t[0] = ulaw2linear[*buf++];    t[1] = ulaw2linear[*buf++];    if (pcm_s.speed == pcm_s.chipspeed) {	/* No reason to convert the pcm speed. */	outb(pcm_s.iobase + 12, t[0]);	outb(pcm_s.iobase + 12, t[1]);	count -= 2;	for (i = 0; i < count; i++)	    outb(pcm_s.iobase + 12, ulaw2linear[*buf++]);    } else {	/* Speed conversion with linear interpolation method. */	dl0 = pcm_s.last_l;	dr0 = pcm_s.last_r;	dl1 = t[0];	dr1 = t[1];	i = 0;	count /= 2;	while (i < count) {	    while (pcm_s.acc >= pcm_s.chipspeed) {		pcm_s.acc -= pcm_s.chipspeed;		i++;		dl0 = dl1;		dr0 = dr1;		if (i < count) {		    dl1 = ulaw2linear[*buf++];		    dr1 = ulaw2linear[*buf++];		} else		    dl1 = dr1 = 0;	    }	    dl = ((dl0 * (pcm_s.chipspeed - pcm_s.acc)) + (dl1 * pcm_s.acc))		/ pcm_s.chipspeed;	    dr = ((dr0 * (pcm_s.chipspeed - pcm_s.acc)) + (dr1 * pcm_s.acc))		/ pcm_s.chipspeed;	    outb(pcm_s.iobase + 12, dl);	    outb(pcm_s.iobase + 12, dr);	    pcm_s.acc += pcm_s.speed;	}	pcm_s.last_l = dl0;	pcm_s.last_r = dr0;    }}static voidfifo_send_stereo_8(pcm_data *buf, int count, int uflag){    int i;    signed char dl, dl0, dl1, dr, dr0, dr1, zlev;    pcm_data t[2];    zlev = uflag ? -128 : 0;    if (tmpbuf.size > 0)	t[0] = tmpbuf.buff[0] + zlev;    else	t[0] = *buf++ + zlev;    t[1] = *buf++ + zlev;    if (pcm_s.speed == pcm_s.chipspeed) {	/* No reason to convert the pcm speed. */	outb(pcm_s.iobase + 12, t[0]);	outb(pcm_s.iobase + 12, t[1]);	count -= 2;	for (i = 0; i < count; i++)	    outb(pcm_s.iobase + 12, *buf++ + zlev);    } else {	/* Speed conversion with linear interpolation method. */	dl0 = pcm_s.last_l;	dr0 = pcm_s.last_r;	dl1 = t[0];	dr1 = t[1];	i = 0;	count /= 2;	while (i < count) {	    while (pcm_s.acc >= pcm_s.chipspeed) {		pcm_s.acc -= pcm_s.chipspeed;		i++;		dl0 = dl1;		dr0 = dr1;		if (i < count) {		    dl1 = *buf++ + zlev;		    dr1 = *buf++ + zlev;		} else		    dl1 = dr1 = 0;	    }	    dl = ((dl0 * (pcm_s.chipspeed - pcm_s.acc)) + (dl1 * pcm_s.acc))		/ pcm_s.chipspeed;	    dr = ((dr0 * (pcm_s.chipspeed - pcm_s.acc)) + (dr1 * pcm_s.acc))		/ pcm_s.chipspeed;	    outb(pcm_s.iobase + 12, dl);	    outb(pcm_s.iobase + 12, dr);	    pcm_s.acc += pcm_s.speed;	}	pcm_s.last_l = dl0;	pcm_s.last_r = dr0;    }}static voidfifo_send_stereo_16le(pcm_data *buf, int count, int uflag){    int i;    short dl, dl0, dl1, dr, dr0, dr1, zlev;    pcm_data t[4];    zlev = uflag ? -128 : 0;    for (i = 0; i < 4; i++)	t[i] = (tmpbuf.size > i) ? tmpbuf.buff[i] : *buf++;    if (pcm_s.speed == pcm_s.chipspeed) {	/* No reason to convert the pcm speed. */	outb(pcm_s.iobase + 12, t[1] + zlev);	outb(pcm_s.iobase + 12, t[0]);	outb(pcm_s.iobase + 12, t[3] + zlev);	outb(pcm_s.iobase + 12, t[2]);	count = count / 2 - 2;	for (i = 0; i < count; i++) {	    outb(pcm_s.iobase + 12, *(buf + 1) + zlev);	    outb(pcm_s.iobase + 12, *buf);	    buf += 2;	}    } else {	/* Speed conversion with linear interpolation method. */	dl0 = pcm_s.last_l;	dr0 = pcm_s.last_r;	dl1 = t[0] + ((t[1] + zlev) << 8);	dr1 = t[2] + ((t[3] + zlev) << 8);	i = 0;	count /= 4;	while (i < count) {	    while (pcm_s.acc >= pcm_s.chipspeed) {		pcm_s.acc -= pcm_s.chipspeed;		i++;		dl0 = dl1;		dr0 = dr1;		if (i < count) {		    dl1 = *buf + ((*(buf + 1) + zlev) << 8);		    buf += 2;		    dr1 = *buf + ((*(buf + 1) + zlev) << 8);		    buf += 2;		} else		    dl1 = dr1 = 0;	    }	    dl = ((dl0 * (pcm_s.chipspeed - pcm_s.acc)) + (dl1 * pcm_s.acc))		/ pcm_s.chipspeed;	    dr = ((dr0 * (pcm_s.chipspeed - pcm_s.acc)) + (dr1 * pcm_s.acc))		/ pcm_s.chipspeed;	    outb(pcm_s.iobase + 12, (dl >> 8) & 0xff);	    outb(pcm_s.iobase + 12, dl & 0xff);	    outb(pcm_s.iobase + 12, (dr >> 8) & 0xff);	    outb(pcm_s.iobase + 12, dr & 0xff);	    pcm_s.acc += pcm_s.speed;	}	pcm_s.last_l = dl0;	pcm_s.last_r = dr0;    }}static voidfifo_send_stereo_16be(pcm_data *buf, int count, int uflag){    int i;    short dl, dl0, dl1, dr, dr0, dr1, zlev;    pcm_data t[4];    zlev = uflag ? -128 : 0;    for (i = 0; i < 4; i++)	t[i] = (tmpbuf.size > i) ? tmpbuf.buff[i] : *buf++;    if (pcm_s.speed == pcm_s.chipspeed) {	/* No reason to convert the pcm speed. */	outb(pcm_s.iobase + 12, t[0] + zlev);	outb(pcm_s.iobase + 12, t[1]);	outb(pcm_s.iobase + 12, t[2] + zlev);	outb(pcm_s.iobase + 12, t[3]);	count = count / 2 - 2;	for (i = 0; i < count; i++) {	    outb(pcm_s.iobase + 12, *buf + zlev);	    outb(pcm_s.iobase + 12, *(buf + 1));	    buf += 2;	}    } else {	/* Speed conversion with linear interpolation method. */	dl0 = pcm_s.last_l;	dr0 = pcm_s.last_r;	dl1 = ((t[0] + zlev) << 8) + t[1];	dr1 = ((t[2] + zlev) << 8) + t[3];	i = 0;	count /= 4;	while (i < count) {	    while (pcm_s.acc >= pcm_s.chipspeed) {		pcm_s.acc -= pcm_s.chipspeed;		i++;		dl0 = dl1;		dr0 = dr1;		if (i < count) {		    dl1 = ((*buf + zlev) << 8) + *(buf + 1);		    buf += 2;		    dr1 = ((*buf + zlev) << 8) + *(buf + 1);		    buf += 2;		} else		    dl1 = dr1 = 0;	    }	    dl = ((dl0 * (pcm_s.chipspeed - pcm_s.acc)) + (dl1 * pcm_s.acc))		/ pcm_s.chipspeed;	    dr = ((dr0 * (pcm_s.chipspeed - pcm_s.acc)) + (dr1 * pcm_s.acc))		/ pcm_s.chipspeed;	    outb(pcm_s.iobase + 12, (dl >> 8) & 0xff);	    outb(pcm_s.iobase + 12, dl & 0xff);	    outb(pcm_s.iobase + 12, (dr >> 8) & 0xff);	    outb(pcm_s.iobase + 12, dr & 0xff);	    pcm_s.acc += pcm_s.speed;	}	pcm_s.last_l = dl0;	pcm_s.last_r = dr0;    }}static voidfifo_send_mono_ulaw(pcm_data *buf, int count){    int i;    signed char d, d0, d1;    if (pcm_s.speed == pcm_s.chipspeed)	/* No reason to convert the pcm speed. */	for (i = 0; i < count; i++) {	    d = ulaw2linear[*buf++];	    outb(pcm_s.iobase + 12, d);	    outb(pcm_s.iobase + 12, d);	}    else {	/* Speed conversion with linear interpolation method. */	d0 = pcm_s.last_l;	d1 = ulaw2linear[*buf++];	i = 0;	while (i < count) {	    while (pcm_s.acc >= pcm_s.chipspeed) {		pcm_s.acc -= pcm_s.chipspeed;		i++;		d0 = d1;		d1 = (i < count) ? ulaw2linear[*buf++] : 0;	    }	    d = ((d0 * (pcm_s.chipspeed - pcm_s.acc)) + (d1 * pcm_s.acc))		/ pcm_s.chipspeed;	    outb(pcm_s.iobase + 12, d);	    outb(pcm_s.iobase + 12, d);	    pcm_s.acc += pcm_s.speed;	}	pcm_s.last_l = d0;    }}static voidfifo_send_mono_8(pcm_data *buf, int count, int uflag){    int i;    signed char d, d0, d1, zlev;    zlev = uflag ? -128 : 0;    if (pcm_s.speed == pcm_s.chipspeed)	/* No reason to convert the pcm speed. */	for (i = 0; i < count; i++) {	    d = *buf++ + zlev;	    outb(pcm_s.iobase + 12, d);	    outb(pcm_s.iobase + 12, d);	}    else {	/* Speed conversion with linear interpolation method. */	d0 = pcm_s.last_l;	d1 = *buf++ + zlev;	i = 0;	while (i < count) {	    while (pcm_s.acc >= pcm_s.chipspeed) {		pcm_s.acc -= pcm_s.chipspeed;		i++;		d0 = d1;		d1 = (i < count) ? *buf++ + zlev : 0;	    }	    d = ((d0 * (pcm_s.chipspeed - pcm_s.acc)) + (d1 * pcm_s.acc))		/ pcm_s.chipspeed;	    outb(pcm_s.iobase + 12, d);	    outb(pcm_s.iobase + 12, d);	    pcm_s.acc += pcm_s.speed;	}	pcm_s.last_l = d0;    }}static voidfifo_send_mono_16le(pcm_data *buf, int count, int uflag){    int i;    short d, d0, d1, zlev;    pcm_data t[2];    zlev = uflag ? -128 : 0;    for (i = 0; i < 2; i++)	t[i] = (tmpbuf.size > i) ? tmpbuf.buff[i] : *buf++;    if (pcm_s.speed == pcm_s.chipspeed) {	/* No reason to convert the pcm speed. */	outb(pcm_s.iobase + 12, t[1] + zlev);	outb(pcm_s.iobase + 12, t[0]);	outb(pcm_s.iobase + 12, t[1] + zlev);	outb(pcm_s.iobase + 12, t[0]);	count = count / 2 - 1;	for (i = 0; i < count; i++) {	    outb(pcm_s.iobase + 12, *(buf + 1) + zlev);	    outb(pcm_s.iobase + 12, *buf);	    outb(pcm_s.iobase + 12, *(buf + 1) + zlev);	    outb(pcm_s.iobase + 12, *buf);	    buf += 2;	}    } else {	/* Speed conversion with linear interpolation method. */	d0 = pcm_s.last_l;	d1 = t[0] + ((t[1] + zlev) << 8);	i = 0;	count /= 2;	while (i < count) {	    while (pcm_s.acc >= pcm_s.chipspeed) {		pcm_s.acc -= pcm_s.chipspeed;		i++;		d0 = d1;		if (i < count) {		    d1 = *buf + ((*(buf + 1) + zlev) << 8);		    buf += 2;		} else		    d1 = 0;	    }	    d = ((d0 * (pcm_s.chipspeed - pcm_s.acc)) + (d1 * pcm_s.acc))		/ pcm_s.chipspeed;	    outb(pcm_s.iobase + 12, (d >> 8) & 0xff);	    outb(pcm_s.iobase + 12, d & 0xff);	    outb(pcm_s.iobase + 12, (d >> 8) & 0xff);	    outb(pcm_s.iobase + 12, d & 0xff);	    pcm_s.acc += pcm_s.speed;	}	pcm_s.last_l = d0;    }}static voidfifo_send_mono_16be(pcm_data *buf, int count, int uflag){    int i;    short d, d0, d1, zlev;    pcm_data t[2];    zlev = uflag ? -128 : 0;    for (i = 0; i < 2; i++)	t[i] = (tmpbuf.size > i) ? tmpbuf.buff[i] : *buf++;    if (pcm_s.speed == pcm_s.chipspeed) {	/* No reason to convert the pcm speed. */	outb(pcm_s.iobase + 12, t[0] + zlev);	outb(pcm_s.iobase + 12, t[1]);	outb(pcm_s.iobase + 12, t[0] + zlev);	outb(pcm_s.iobase + 12, t[1]);	count = count / 2 - 1;	for (i = 0; i < count; i++) {	    outb(pcm_s.iobase + 12, *buf + zlev);	    outb(pcm_s.iobase + 12, *(buf + 1));	    outb(pcm_s.iobase + 12, *buf + zlev);	    outb(pcm_s.iobase + 12, *(buf + 1));	    buf += 2;	}    } else {	/* Speed conversion with linear interpolation method. */	d0 = pcm_s.last_l;	d1 = ((t[0] + zlev) << 8) + t[1];	i = 0;	count /= 2;	while (i < count) {	    while (pcm_s.acc >= pcm_s.chipspeed) {		pcm_s.acc -= pcm_s.chipspeed;		i++;		d0 = d1;		if (i < count) {		    d1 = ((*buf + zlev) << 8) + *(buf + 1);		    buf += 2;		} else		    d1 = 0;	    }	    d = ((d0 * (pcm_s.chipspeed - pcm_s.acc)) + (d1 * pcm_s.acc))		/ pcm_s.chipspeed;/*	    outb(pcm_s.iobase + 12, d & 0xff);	    outb(pcm_s.iobase + 12, (d >> 8) & 0xff);	    outb(pcm_s.iobase + 12, d & 0xff);	    outb(pcm_s.iobase + 12, (d >> 8) & 0xff); */	    outb(pcm_s.iobase + 12, (d >> 8) & 0xff);	    outb(pcm_s.iobase + 12, d & 0xff);	    outb(pcm_s.iobase + 12, (d >> 8) & 0xff);	    outb(pcm_s.iobase + 12, d & 0xff);	    pcm_s.acc += pcm_s.speed;	}	pcm_s.last_l = d0;    }}static voidfifo_input_block(void){    int chunksize;    if (pcm_s.pdma_chunkcount) {	/* Update chunksize and then receive the next chunk from FIFO. */	chunksize = pcm_s.pdma_count / pcm_s.pdma_chunkcount--;	fifo_recv(pcm_s.pdma_buf, chunksize);	pcm_s.pdma_buf += chunksize;

⌨️ 快捷键说明

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