📄 pcm86.c
字号:
/* 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 + -