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

📄 oss.cpp

📁 一个KDE下的录音程序
💻 CPP
字号:
#if defined(HAVE_SOUNDCARD_H) || defined(HAVE_SYS_SOUNDCARD_H)#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <errno.h>#include <sys/ioctl.h>#ifdef HAVE_SOUNDCARD_H# include <soundcard.h>#endif#ifdef HAVE_SYS_SOUNDCARD_H# include <sys/soundcard.h>#endif#include "sound.h"#include "oss.moc"#ifndef OSS_GETVERSION#define OSS_GETVERSION       _IOR('M',118,int)#endif/* ---------------------------------------------------------------------- */Soundcard::Soundcard(const char *dev){    if (dev)	strcpy(devname,dev);    else	strcpy(devname,"/dev/dsp");        driver_name[0] = '\0';    stat = STATUS_CLOSED;    get_capabilities();    channels = 1;    rate = 22050;    fd = -1;}Soundcard::~Soundcard(){    /* nothing */}intSoundcard::start_record(){    switch (stat) {    case STATUS_CLOSED:	if (!init_done)	    get_capabilities();	if (!init_done)	    return -1;	return open_dev(TRUE);    case STATUS_RECORD:	return 0;    case STATUS_PLAYBACK:	close_dev();	return open_dev(TRUE);    }    return -1;}intSoundcard::start_playback(){    switch (stat) {    case STATUS_CLOSED:	if (!init_done)	    get_capabilities();	if (!init_done)	    return -1;	return open_dev(FALSE);    case STATUS_RECORD:	close_dev();	return open_dev(FALSE);    case STATUS_PLAYBACK:	return 0;    }    return -1;}intSoundcard::kill_buffer(){    ioctl(fd,SNDCTL_DSP_RESET,0);    return 0;}intSoundcard::stop(){    if (stat != STATUS_CLOSED)	close_dev();    return 0;}/* ---------------------------------------------------------------------- */voidSoundcard::get_capabilities(){    int i,dsp;    int try_afmt;    int try_channels;        afmt = 0;    if (-1 != (dsp = open(devname, O_RDONLY))) {	        ioctl(dsp, SNDCTL_DSP_SETFMT,  &afmt);     /* current */        ioctl(dsp, SNDCTL_DSP_GETFMTS, &afmt_hw);  /* hardware cap */        afmt_sw = 0;        for (i = 0; i < 16 /* XXX */; i++) {            try_afmt = (1<<i);            if (-1 == ioctl(dsp, SNDCTL_DSP_SETFMT, &try_afmt))                continue;            if (try_afmt != (1<<i))                continue;            afmt_sw |= try_afmt;        }        try_channels = 2;        if (-1 != ioctl(dsp, SNDCTL_DSP_CHANNELS, &try_channels) &&            2 == try_channels)            channels_hw = 2;        else            channels_hw = 1;	/* version check */	if (-1 == ioctl(dsp,OSS_GETVERSION,&i)) {	    strcpy(driver_name,"OSS (version unknown)");	} else {	    sprintf(driver_name,"OSS %d.%d.%d%c",		    (i>>16) & 0xff,(i>>8) & 0xff,(i>>4) & 0xf,(i&0xf)+'a');	}	        close(dsp);	init_done = 1;    } else {	init_done = 0;    }}intSoundcard::has_channels(){    if (!init_done)	return -1;    return channels_hw;}intSoundcard::has_format(int f){    if (!init_done)	return -1;    switch (f) {    case FMT_8BIT:	return (afmt_hw & AFMT_U8) ? 1 : 0;	break;    case FMT_16BIT:	return (afmt_hw & AFMT_S16_LE) ? 1 : 0;	break;    case FMT_MULAW:    case FMT_ALAW:    default:	return 0;    }}char*Soundcard::driver(){    return driver_name;}intSoundcard::open_dev(int record){    struct SOUNDPARAMS p;    int frag,rrate;    if (-1 == (fd = open(devname,record ? O_RDONLY : O_WRONLY)))        goto err;    fcntl(fd,F_SETFD,FD_CLOEXEC);    /* try to get ~50 ms latency */    blocksize = 50*channels*rate/1000;    if (afmt == AFMT_U16_BE || afmt == AFMT_S16_BE ||	afmt == AFMT_U16_LE || afmt == AFMT_S16_LE)	blocksize *= 2;    for (frag = 0; blocksize != 1; frag++)	blocksize >>= 1;#if 0    fprintf(stderr,"asking for %d byte blocksize\n",1 << frag);#endif    frag |= 0x7fff0000;    if (-1 == ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag))        perror("ioctl SNDCTL_DSP_SETFRAGMENT");    rrate = rate;    if (-1 == ioctl(fd, SNDCTL_DSP_SETFMT,      &afmt)) {        perror("ioctl SNDCTL_DSP_SETFMT");        goto err;    }    if (-1 == ioctl(fd, SNDCTL_DSP_CHANNELS,    &channels)) {        perror("ioctl SNDCTL_DSP_SETFMT");        goto err;    }    if (-1 == ioctl(fd, SNDCTL_DSP_SPEED,       &rrate)) {        perror("ioctl SNDCTL_DSP_SETFMT");        goto err;    }    if (-1 == ioctl(fd, SNDCTL_DSP_GETBLKSIZE,  &blocksize)) {        perror("ioctl SNDCTL_DSP_SETFMT");        goto err;    }    if (0 == blocksize)	blocksize = 4096;    if (rrate != rate) {	fprintf(stderr,"sample rate: asked for %d, hardware uses %d. ",		rate,rrate);	if (abs(rate-rrate)*100 < rate) {	    fprintf(stderr,"that's fine (diff <1%%).\n");	} else {	    fprintf(stderr,"way off, using hardware rate.\n");	    rate = rrate;	}    }        latency = blocksize*1000/channels/rate;    if (afmt == AFMT_U16_BE || afmt == AFMT_S16_BE ||        afmt == AFMT_U16_LE || afmt == AFMT_S16_LE)        latency = latency/2;    telmi = new QSocketNotifier	(fd, record ? QSocketNotifier::Read : QSocketNotifier::Write);    QObject::connect(telmi,SIGNAL(activated(int)),		     this, SLOT(sounddata(int)));    stat = record ? STATUS_RECORD : STATUS_PLAYBACK;#if 0    fprintf(stderr,"%s (format=%d, %s, rate=%d, blocksize=%d, latency=%d ms)\n",	    record ? "recording" : "playback",	    afmt,	    (channels == 2) ? "stereo" : "mono",	    rate, blocksize, latency);#endif    p.channels  = channels;    p.rate      = rate;    p.blocksize = blocksize;    p.latency   = latency;    switch (afmt) {    case AFMT_U8:      p.format = FMT_8BIT;   break;    case AFMT_S16_LE:  p.format = FMT_16BIT;  break;    default: fprintf(stderr,"oops(open): unsupported sound format\n"); exit(1);    }    emit newparams(&p);    if (record) {	trigger = ~PCM_ENABLE_INPUT;	ioctl(fd,SNDCTL_DSP_SETTRIGGER,&trigger);	trigger = PCM_ENABLE_INPUT;	ioctl(fd,SNDCTL_DSP_SETTRIGGER,&trigger);    }    return 0;err:    if (-1 != fd)        close(fd);    stat = STATUS_CLOSED;    fd = -1;    return -1;}voidSoundcard::close_dev(){    close(fd);    fd = -1;    stat = STATUS_CLOSED;    delete telmi;    return;}voidSoundcard::setparams(struct SOUNDPARAMS *p){    rate     = p->rate;    channels = p->channels;    switch (p->format) {    case FMT_8BIT:   afmt = AFMT_U8;      break;    case FMT_16BIT:  afmt = AFMT_S16_LE;  break;    default: fprintf(stderr,"oops(set): unsupported sound format\n"); exit(1);    }    switch (stat) {    case STATUS_RECORD:    	close_dev();	open_dev(TRUE);	break;    case STATUS_PLAYBACK:	close_dev();	open_dev(FALSE);	break;    case STATUS_CLOSED:	if (!init_done)	    get_capabilities();	if (!init_done)	    return;	if (0 == open_dev(TRUE))	    close_dev();	break;    }}voidSoundcard::sounddata(int s){    int rc,have;        switch (stat) {    case STATUS_RECORD:	/* read */	for (have = 0; have < blocksize;) {	    rc = read(fd,buffer+have,blocksize-have);	    switch (rc) {	    case -1:		if (EINTR != errno) {		    perror("read sound");		    exit(1);		}		break;	    case 0:		fprintf(stderr,"Huh? got 0 bytes from sound device?\n");		exit(1);	    default:		have += rc;	    }	}	emit senddata((void*)buffer);	break;    case STATUS_PLAYBACK:	emit receivedata((void*)buffer);	if (-1 != fd)	    write(fd,buffer,blocksize);	emit senddata((void*)buffer); /* fft :-) */	break;    }}#endif /* SOUNDCARD_H */

⌨️ 快捷键说明

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