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

📄 sound.cpp

📁 Dream.exe soft source (Visual C++)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	{
		if (ret == -EPIPE) 
		{    
			qDebug("rpipe");
			/* Under-run */
			qDebug("rprepare");
			ret = snd_pcm_prepare(rhandle);

			if (ret < 0)
				qDebug("Can't recover from underrun, prepare failed: %s", snd_strerror(ret));

			ret = snd_pcm_start(rhandle);

			if (ret < 0)
				qDebug("Can't recover from underrun, start failed: %s", snd_strerror(ret));
			return 0;

		} 
		else if (ret == -ESTRPIPE) 
		{
			qDebug("strpipe");

			/* Wait until the suspend flag is released */
			while ((ret = snd_pcm_resume(rhandle)) == -EAGAIN)
				sleep(1);       

			if (ret < 0) 
			{
				ret = snd_pcm_prepare(rhandle);

				if (ret < 0)
					qDebug("Can't recover from suspend, prepare failed: %s", snd_strerror(ret));
					throw CGenErr("CSound:Read");
			}
			return 0;
		} 
		else 
		{
			qDebug("CSound::Read: %s", snd_strerror(ret));
			throw CGenErr("CSound:Read");
		}
	} else 
		return ret;
			
}

int CSound::write_HW( _SAMPLE *playbuf, int size ){

	int start = 0;
	int ret;

	while (size) {

		ret = snd_pcm_writei(phandle, &playbuf[start], size );
		if (ret < 0) {
			if (ret ==  -EAGAIN) {
				if ((ret = snd_pcm_wait (phandle, 100)) < 0) {
			        	qDebug ("poll failed (%s)", snd_strerror (ret));
			        	break;
				}	           
				continue;
			} else 
			if (ret == -EPIPE) {    /* under-run */
qDebug("underrun");
        			ret = snd_pcm_prepare(phandle);
        			if (ret < 0)
                			qDebug("Can't recover from underrun, prepare failed: %s", snd_strerror(ret));
        			continue;
			} else if (ret == -ESTRPIPE) {
qDebug("strpipe");
        			while ((ret = snd_pcm_resume(phandle)) == -EAGAIN)
                			sleep(1);       /* wait until the suspend flag is released */
        			if (ret < 0) {
                			ret = snd_pcm_prepare(phandle);
                			if (ret < 0)
                        			qDebug("Can't recover from suspend, prepare failed: %s", snd_strerror(ret));
        			}
        			continue;
			} else {
                                qDebug("Write error: %s", snd_strerror(ret));
								throw CGenErr("Write error");
                        }
                        break;  /* skip one period */
		}
		size -= ret;
		start += ret;
	}
	return 0;
}
void CSound::close_HW( void ) {

	if (rhandle != NULL)
		snd_pcm_close( rhandle );

	rhandle = NULL;
}

#endif




/* ************************************************************************* */

class CSoundBuf : public CCyclicBuffer<_SAMPLE> {

public:
	CSoundBuf() : keep_running(TRUE) {}
	void lock (void){ data_accessed.lock(); }
	void unlock (void){ data_accessed.unlock(); }
	
	bool keep_running;
protected:
	QMutex	data_accessed;
} SoundBufP, SoundBufR;


class RecThread : public QThread {
public:
	virtual void run() {
	
	
		while (SoundBufR.keep_running) {

			int fill;

			SoundBufR.lock();
			fill = SoundBufR.GetFillLevel();
			SoundBufR.unlock();
				
			if (  (SOUNDBUFLEN - fill) > (FRAGSIZE * NUM_IN_OUT_CHANNELS) ) {
				// enough space in the buffer
				
				int size = CSound::read_HW( tmprecbuf, FRAGSIZE);

				// common code
				if (size > 0) {
					CVectorEx<_SAMPLE>*	ptarget;

					/* Copy data from temporary buffer in output buffer */
					SoundBufR.lock();

					ptarget = SoundBufR.QueryWriteBuffer();

					for (int i = 0; i < size * NUM_IN_OUT_CHANNELS; i++)
						(*ptarget)[i] = tmprecbuf[i];

					SoundBufR.Put( size * NUM_IN_OUT_CHANNELS );
					SoundBufR.unlock();
				}
			} else {
				msleep( 1 );
			}
		}
		qDebug("Rec Thread stopped");
	}

protected:
	_SAMPLE	tmprecbuf[NUM_IN_OUT_CHANNELS * FRAGSIZE];
} RecThread1;



/* Wave in ********************************************************************/

void CSound::InitRecording(int iNewBufferSize, _BOOLEAN bNewBlocking)
{
	qDebug("initrec %d", iNewBufferSize);

	/* Save < */
	SoundBufR.lock();
	iInBufferSize = iNewBufferSize;
	bBlockingRec = bNewBlocking;
	SoundBufR.unlock();
	
	Init_HW( RECORD );

	if ( RecThread1.running() == FALSE ) {
		SoundBufR.Init( SOUNDBUFLEN );
		SoundBufR.unlock();
		RecThread1.start();
	}

}


_BOOLEAN CSound::Read(CVector< _SAMPLE >& psData)
{
	CVectorEx<_SAMPLE>*	p;

	SoundBufR.lock();	// we need exclusive access
	
	
	while ( SoundBufR.GetFillLevel() < iInBufferSize ) {
	
		
		// not enough data, sleep a little
		SoundBufR.unlock();
		usleep(1000); //1ms
		SoundBufR.lock();
	}
	
	// copy data
	
	p = SoundBufR.Get( iInBufferSize );
	for (int i=0; i<iInBufferSize; i++)
		psData[i] = (*p)[i];
	
	SoundBufR.unlock();

	return FALSE;
}


/* Wave out *******************************************************************/


class PlayThread : public QThread {
public:
	virtual void run() {
	
		while ( SoundBufP.keep_running ) {
			int fill;

			SoundBufP.lock();
			fill = SoundBufP.GetFillLevel();
			SoundBufP.unlock();
				
			if ( fill > (FRAGSIZE * NUM_IN_OUT_CHANNELS) ) {

				// enough data in the buffer

				CVectorEx<_SAMPLE>*	p;
				
				SoundBufP.lock();
				p = SoundBufP.Get( FRAGSIZE * NUM_IN_OUT_CHANNELS );

				for (int i=0; i < FRAGSIZE * NUM_IN_OUT_CHANNELS; i++)
					tmpplaybuf[i] = (*p)[i];

				SoundBufP.unlock();
				
				CSound::write_HW( tmpplaybuf, FRAGSIZE );

			} else {
			
				do {			
					msleep( 1 );
					
					SoundBufP.lock();
					fill = SoundBufP.GetFillLevel();
					SoundBufP.unlock();

				} while ((SoundBufP.keep_running) && ( fill < SOUNDBUFLEN/2 ));	// wait until buffer is at least half full
			}
		}
		qDebug("Play Thread stopped");
	}

protected:
	_SAMPLE	tmpplaybuf[NUM_IN_OUT_CHANNELS * FRAGSIZE];
} PlayThread1;


void CSound::InitPlayback(int iNewBufferSize, _BOOLEAN bNewBlocking)
{
	qDebug("initplay %d", iNewBufferSize);
	
	/* Save buffer size */
	SoundBufP.lock();
	iBufferSize = iNewBufferSize;
	bBlockingPlay = bNewBlocking;
	SoundBufP.unlock();

	Init_HW( PLAY );

	if ( PlayThread1.running() == FALSE ) {
		SoundBufP.Init( SOUNDBUFLEN );
		SoundBufP.unlock();
		PlayThread1.start();
	}
}


_BOOLEAN CSound::Write(CVector< _SAMPLE >& psData)
{

	if ( bBlockingPlay ) {
		// blocking write
		while( SoundBufP.keep_running ) {
			SoundBufP.lock();
			int fill = SOUNDBUFLEN - SoundBufP.GetFillLevel();
			SoundBufP.unlock();
			if ( fill > iBufferSize) break;
		}
	}
	
	SoundBufP.lock();	// we need exclusive access

	if ( ( SOUNDBUFLEN - SoundBufP.GetFillLevel() ) > iBufferSize) {
		 
		CVectorEx<_SAMPLE>*	ptarget;
		 
		 // data fits, so copy
		 ptarget = SoundBufP.QueryWriteBuffer();

		 for (int i=0; i < iBufferSize; i++)
		 	(*ptarget)[i] = psData[i];

		 SoundBufP.Put( iBufferSize );
	}
	
	SoundBufP.unlock();

	return FALSE;
}
void CSound::Close()
{
	qDebug("stoprec/play");
	
	// stop the recording and playback threads
	
	if (RecThread1.running() ) {
		SoundBufR.keep_running = FALSE;
		// wait 1sec max. for the threads to terminate
		RecThread1.wait(1000);
	}
	
	if (PlayThread1.running() ) {
		SoundBufP.keep_running = FALSE;
		PlayThread1.wait(1000);
	}
	
	close_HW();	
}


#endif

⌨️ 快捷键说明

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