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

📄 dspoutoss.cpp

📁 kphone-4.2,SHELL协议的VOIP电话
💻 CPP
字号:
#include <stdio.h>#include <stdlib.h>#include <sys/ioctl.h>#include <sys/time.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <qobject.h>#include "dspoutoss.h"DspOutOss::DspOutOss( const QString &fileName )	: DspOut(){	filename = fileName;	setDeviceName( "oss" );	audio_fd = -1;	audio_stereo = false;}DspOutOss::~DspOutOss( void ){	close( audio_fd );}bool DspOutOss::openDevice( DeviceMode mode ){	int oflag;	if( mode == ReadOnly ) {		oflag = O_RDONLY;	} else if( mode == WriteOnly ) {		oflag = O_WRONLY;	} else {		oflag = O_RDWR;	}	if( devstate == DeviceOpened ) {		lasterror = "Device Already Open";		printf( "ERROR: %s\n", lasterror.ascii() );		return false;	}	// Open immediately or else	audio_fd = open( filename.ascii(), oflag | O_NONBLOCK );	if( audio_fd == -1 ) {		lasterror = "Open Failed";		printf( "ERROR: %s\n", lasterror.ascii() );		return false;	}	// Remove O_NONBLOCK	int flags = fcntl( audio_fd, F_GETFL );	flags &= ~O_NONBLOCK;	fcntl( audio_fd, F_SETFL, flags );	// keep fragsize less than 20ms !!	int frag = ( ( 32767 << 16 ) | 7 );	if( ioctl( audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag ) ) {		lasterror = QString( "SETFRAG" ) + QString( strerror( errno ) );		printf( "ERROR: %s\n", lasterror.ascii() );		return false;	}	int format = AFMT_S16_LE;	if( ioctl( audio_fd, SNDCTL_DSP_SETFMT, &format ) == -1 ) {		lasterror = QString( "SETFMT" ) + QString( strerror( errno ) );		printf( "ERROR: %s\n", lasterror.ascii() );		return false;	}	if( format != AFMT_S16_LE ) {		lasterror = "Format not supported";		printf( "ERROR: %s\n", lasterror.ascii() );		return false;	}	int channels = 1;	if( ioctl( audio_fd, SNDCTL_DSP_CHANNELS, &channels ) == -1 ) {		lasterror = QString( "DSP_STEREO" ) + QString( strerror( errno ) );		printf( "ERROR: %s\n", lasterror.ascii() );		return false;	}	if( channels != 1 && channels != 2 ) {		lasterror = QObject::tr("Unsupported Number of Channels");		printf( "ERROR: %s\n", lasterror.ascii() );		return false;	}	if( channels == 2 ) {		printf( QObject::tr("WARNING: nonmonophonic driver, forced into stereo mode (experimental)") + "\n" );		audio_stereo=true;	} else {		audio_stereo=false;	}	rate = 8000;	if( ioctl( audio_fd, SNDCTL_DSP_SPEED, &rate ) == -1 ) {		lasterror = QString( "DSP_SPEED" ) + QString( strerror( errno ) );		printf( "ERROR: %s\n", lasterror.ascii() );		return false;	}	if( rate != 8000 ) {		printf( QObject::tr("WARNING: driver rounded %d Hz request to %d Hz, off by %f%%") + "\n",			8000, rate, 100*((rate-8000)/8000.0) );	}	audio_buf_info info;	if( mode == WriteOnly ) {		if( ioctl( audio_fd, SNDCTL_DSP_GETOSPACE, &info ) == -1 ) {			lasterror = QString( "GETISPACE" ) + QString( strerror( errno ) );			printf( "ERROR: %s\n", lasterror.ascii() );			return false;		}	} else {		if( ioctl( audio_fd, SNDCTL_DSP_GETISPACE, &info ) == -1 ) {			lasterror = QString( "GETOSPACE" ) + QString( strerror( errno ) );			printf( "ERROR: %s\n", lasterror.ascii() );			return false;		}	}	audio_buf.resize( info.fragsize * sizeof( short ) );	lasterror = QString::null;	devstate = DeviceOpened;	return true;}bool DspOutOss::openDevice( int exist_fs ){	audio_fd = exist_fs;	if( audio_fd == -1 ) {		lasterror = "Open Failed";		printf( "ERROR: %s\n", lasterror.ascii() );		return false;	}	audio_buf_info info;	if( ioctl( audio_fd, SNDCTL_DSP_GETISPACE, &info ) == -1 ) {		lasterror = QString( "GETISPACE" ) + QString( strerror( errno ) );		printf( "ERROR: %s\n", lasterror.ascii() );		return false;	}	audio_buf.resize( info.fragsize * sizeof( short ) );	lasterror = QString::null;	devstate = DeviceOpened;	return true;}// count is in 16-bit words in the smaller of the two buffersvoid mono_to_stereo(void *b_from, void *b_to, size_t count){	int8_t *b1 = reinterpret_cast<int8_t*>(b_from);	int8_t *b2 = reinterpret_cast<int8_t*>(b_to);	for( size_t i=0; i < count; i++ ) {		int8_t x0 = b1[2*i];		int8_t x1 = b1[2*i+1];		b2[4*i]   = x0;		b2[4*i+1] = x1;		b2[4*i+2] = x0;		b2[4*i+3] = x1;	}}// count is in 16-bit words in the smaller of the two buffersvoid stereo_to_mono(void *b_from, void *b_to, size_t count){	int8_t *b1 = reinterpret_cast<int8_t*>(b_from);	int8_t *b2 = reinterpret_cast<int8_t*>(b_to);	for( size_t i=0; i < count; i++ ) {		b2[2*i]   = b1[4*i];		b2[2*i+1] = b1[4*i+1];	}}bool DspOutOss::writeBuffer( void ){	if( devstate != DeviceOpened ) {		lasterror = "Device Not Open";		return false;	}	size_t count = audio_buf.getSize();	void *buf;	if( audio_stereo ) {		buf = alloca(2*count);		mono_to_stereo(audio_buf.getData(), buf, count/2);		count *= 2;	} else {		buf = audio_buf.getData();	}	audio_buf_info info;	if( ioctl( audio_fd, SNDCTL_DSP_GETOSPACE, &info ) == 0 ) {		if( info.fragstotal - info.fragments > 15 ) {			// drop the fragment if the buffer starts to fill up			return true;		}	}	for(;;) {		if( write( audio_fd, buf, count ) != -1 ) {			break;		}	}	return true;}unsigned int DspOutOss::readableBytes( void ){	audio_buf_info info;	struct timeval timeout;	fd_set read_fds;	if( devstate != DeviceOpened ) {		return 0;	}	timeout.tv_sec = 0;	timeout.tv_usec = 0;	FD_ZERO( &read_fds );	FD_SET( audio_fd, &read_fds );	if( select( audio_fd + 1, &read_fds, NULL, NULL, &timeout ) == -1 ) {		return 0;	}	if( !FD_ISSET( audio_fd, &read_fds ) ) {		return 0;	}	if( ioctl( audio_fd, SNDCTL_DSP_GETISPACE, &info ) == -1 ) {		lasterror = strerror( errno );		return 0;	}	return info.bytes;}bool DspOutOss::readBuffer( int bytes ){	if( devstate != DeviceOpened ) {		lasterror = "Device Not Open";		return false;	}	audio_buf.resize( bytes );	size_t count = bytes;	void *buf;	if( audio_stereo ) {		count *= 2;		buf = alloca(count);	} else {		buf = audio_buf.getData();	}	ssize_t rc = read( audio_fd, buf, count );	if( rc < 0 ) {		lasterror = strerror(errno);		return false;	}	if( (size_t)rc != count ) {		/* should we treat rc == 0 (EOF) specially? */		printf("warning: asked microphone for %lu bytes but got %lu\n",			(unsigned long)count, (unsigned long)rc);		/* assert: rc < count */		/* Does count have to be a multiple of 2 or even 4? */		count = rc;		audio_buf.resize( audio_stereo? count/2 : count );	}	if( (size_t)rc != count ) {		/* should we treat rc == 0 (EOF) specially? */		printf("warning: asked microphone for %lu bytes but got %lu\n",			(unsigned long)count, (unsigned long)rc);		/* assert: rc < count */		/* Does count have to be a multiple of 2 or even 4? */		count = rc;		audio_buf.resize( audio_stereo? count/2 : count );	}	if( (size_t)rc != count ) {		/* should we treat rc == 0 (EOF) specially? */		printf("warning: asked microphone for %lu bytes but got %lu\n",			(unsigned long)count, (unsigned long)rc);		/* assert: rc < count */		/* Does count have to be a multiple of 2 or even 4? */		count = rc;		audio_buf.resize( audio_stereo? count/2 : count );	}	if( audio_stereo ) {		stereo_to_mono(buf, audio_buf.getData(), count/4);	}	return true;}

⌨️ 快捷键说明

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