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

📄 csoundoutput.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
						mCoderRate = 0x15880000;
					#elif	PGP_WIN32
						mCoderRate = 5512.0;
					#endif
					break;
				case 'GS6L':
					#ifdef	PGP_MACINTOSH
						mCoderRate = 0x17700000;
					#elif	PGP_WIN32
						mCoderRate = 6000.0;
					#endif
					break;
				case 'GS7L':
					#ifdef	PGP_MACINTOSH
						mCoderRate = 0x1cb60000;
					#elif	PGP_WIN32
						mCoderRate = 7350.0;
					#endif
					break;
				case 'GL80':
					#ifdef	PGP_MACINTOSH
						mCoderRate = 0x1f400000;
					#elif	PGP_WIN32
						mCoderRate = 8000.0;
					#endif
					break;
				case 'GS8L':
					#ifdef	PGP_MACINTOSH
						mCoderRate = 0x22740000;
					#elif	PGP_WIN32
						mCoderRate = 8820.0;
					#endif
					break;
				case 'GS1L':
					#ifdef	PGP_MACINTOSH
						mCoderRate = rate11025hz;
					#elif	PGP_WIN32
						mCoderRate = 11025.0;
					#endif
					break;
			}
			inx = 1;
			gsm_option(mGSM, GSM_OPT_LTP_CUT, &inx);
			break;
		case 'GSM4':
		case 'GSM5':
		case 'GSM6':
		case 'GSM7':
		case 'GS80':
		case 'GSM8':
		case 'GSM1':			// 160 shorts -> 33 bytes
			mGSM = gsm_create();
			mCFrameSize = 33;
			mFrameSamples = 160;
			mSampleSize = 16;
			mBufferQuant = 320;
			switch(type)
			{
				case 'GSM4':
					#ifdef	PGP_MACINTOSH
						mCoderRate = 0x113A0000;
					#elif	PGP_WIN32
						mCoderRate = 4410.0;
					#endif
					break;
				case 'GSM5':
					#ifdef	PGP_MACINTOSH
						mCoderRate = 0x15880000;
					#elif	PGP_WIN32
						mCoderRate = 5512.0;
					#endif
					break;
				case 'GSM6':
					#ifdef	PGP_MACINTOSH
						mCoderRate = 0x17700000;
					#elif	PGP_WIN32
						mCoderRate = 6000.0;
					#endif
					break;
				case 'GSM7':
					#ifdef	PGP_MACINTOSH
						mCoderRate = 0x1cb60000;
					#elif	PGP_WIN32
						mCoderRate = 7350.0;
					#endif
					break;
				case 'GS80':
					#ifdef	PGP_MACINTOSH
						mCoderRate = 0x1f400000;
					#elif	PGP_WIN32
						mCoderRate = 8000.0;
					#endif
					break;
				case 'GSM8':
					#ifdef	PGP_MACINTOSH
						mCoderRate = 0x22740000;
					#elif	PGP_WIN32
						mCoderRate = 8820.0;
					#endif
					break;
				case 'GSM1':
					#ifdef	PGP_MACINTOSH
						mCoderRate = rate11025hz;
					#elif	PGP_WIN32
						mCoderRate = 11025.0;
					#endif
					break;
			}
			break;
		case 'ADP8':
			memset(&mADPCM,0,sizeof(adpcm_state));
			mCFrameSize = 80;
			mFrameSamples = 160;
			mSampleSize = 16;
			mBufferQuant = 320;
			#ifdef	PGP_MACINTOSH
				mCoderRate = 0x1f400000;
			#elif	PGP_WIN32
				mCoderRate = 8000.0;
			#endif
			mCoderHeaderSize = 3;
			break;
#ifdef USEVOXWARE
		case 'VOXW':{
			VOXWARE_RETCODE voxerr;
			ushort framesPerPkt;
			
			#ifdef	PGP_MACINTOSH
				mCoderRate = 0x1f400000;
			#elif	PGP_WIN32
				mCoderRate = 8000.0;
			#endif
			mCFrameSize = 30;
			mSampleSize = 16;
			
			voxerr = RTInitEncoder(&mtVoxComVars, &mtVoxCoderReqs);	pgpAssert(IsntErr(voxerr));
			framesPerPkt = ((mCFrameSize * 8) / mtVoxCoderReqs.wNumBitsPerFrame);
			mtVoxComVars.dwNumBytesInSpeechBuffer =
				framesPerPkt * (mtVoxCoderReqs.wNumSamplesPerFrame * mtVoxCoderReqs.wBytesPerSample);
			mtVoxComVars.dwNumBytesInCodedDataBuffer =
				((framesPerPkt * mtVoxCoderReqs.wNumBitsPerFrame) / 8);
			mtVoxComVars.dwNumBytesInCodedDataBuffer +=
				(0 != ((framesPerPkt * mtVoxCoderReqs.wNumBitsPerFrame) % 8));
			mFrameSamples = mtVoxComVars.dwNumBytesInSpeechBuffer / 2;
			mCFrameSize = mtVoxComVars.dwNumBytesInCodedDataBuffer;
			mVoxComVars.lpVoxwareHeader = &(mtVoxComVars.lpVoxStreamHeader->voxStreamHeader);
			voxerr = RTInitDecoder(&mVoxComVars, &mVoxCoderReqs);	pgpAssert(IsntErr(voxerr));
			mVoxComVars.dwNumBytesInCodedDataBuffer = mtVoxComVars.dwNumBytesInCodedDataBuffer;
			mVoxComVars.dwNumBytesInSpeechBuffer = mtVoxComVars.dwNumBytesInSpeechBuffer;
			mBufferQuant = mtVoxComVars.dwNumBytesInSpeechBuffer;
			break;}
#endif
		default:
			pgp_errstring("Bad codec");
			break;
	}
	mSampleBufLen = SAMPLEBUFMAX / mBufferQuant * mBufferQuant;
	mCodec = type;
	mPFWindow->SetDecoder(type);
#ifdef	PGP_MACINTOSH
	SndCommand sndCmd;

	sndCmd.cmd = flushCmd;
	sndCmd.param1 = 0;
	sndCmd.param2 = 0;
	SndDoImmediate(mSndChannel, &sndCmd);
	sndCmd.cmd = quietCmd;
	sndCmd.param1 = 0;
	sndCmd.param2 = 0;
	SndDoImmediate(mSndChannel, &sndCmd);
#endif
	mPlaying = FALSE;
	mSoundMutex.Signal();
}

void
CSoundOutput::ChannelSwitch()
{
	mSoundMutex.Wait();
#ifdef	PGP_MACINTOSH
	SndCommand sndCmd;

	sndCmd.cmd = flushCmd;
	sndCmd.param1 = 0;
	sndCmd.param2 = 0;
	SndDoImmediate(mSndChannel, &sndCmd);		/* flush the queue */
	sndCmd.cmd = quietCmd;
	sndCmd.param1 = 0;
	sndCmd.param2 = 0;
	SndDoImmediate(mSndChannel, &sndCmd);		/* stop the sound playing */
	mPlaying = FALSE;
	sndCmd.cmd = freqDurationCmd;
	sndCmd.param1 = 75;							/* play for 150 milliseconds */
	sndCmd.param2 = 85;							/* octave 8, C# */
	SndDoCommand(mBeepChannel, &sndCmd, TRUE);
	sndCmd.cmd = quietCmd;
	sndCmd.param1 = 0;
	sndCmd.param2 = 0;
	SndDoCommand(mBeepChannel, &sndCmd, TRUE);	/* make sure the beep stops */
#elif	PGP_WIN32
	Open();
	if(mOpen)
	{
		short err;

		err = waveOutRestart(mWaveHandle);	CheckWaveError("waveOutReset", err);
		InterlockedDecrement(&sBufReturn);
		mToneHeader.lpData = (char *)(mHardwareIs16Bit ? mToneBuffers[0] : mToneBuffers[1]);
		mToneHeader.dwBufferLength = mHardwareIs16Bit ? TONELENGTH*2 : TONELENGTH;
		mToneHeader.dwFlags = 0;
		mToneHeader.dwLoops = 0;
		err = waveOutPrepareHeader(mWaveHandle, &mToneHeader, sizeof(WAVEHDR));
		CheckWaveError("waveOutPrepareHeader", err);
		if(!(err = waveOutWrite(mWaveHandle, &mToneHeader, sizeof(WAVEHDR))))
		{
			while(!(mToneHeader.dwFlags & WHDR_DONE))
				Sleep(0);
			err = waveOutUnprepareHeader(mWaveHandle, &mToneHeader, sizeof(WAVEHDR));
			CheckWaveError("waveOutUnprepareHeader", err);
		}
		else
			CheckWaveError("waveOutWrite", err);

		Close();
	}
#endif
	mSoundMutex.Signal();
}

void
CSoundOutput::SetVolume(long volume)
{
#ifdef	PGP_MACINTOSH
	SndCommand sndCmd;
	long newVolume;

	newVolume = (volume << 16) | volume;
	if(newVolume != mVolume)
	{
		mVolume = newVolume;
		sndCmd.cmd = volumeCmd;
		sndCmd.param1 = 0;
		sndCmd.param2 = mVolume;
		SndDoImmediate(mSndChannel, &sndCmd);
	}
#elif	PGP_WIN32
	mVolume = volume;
	if(!mOpen)
		return;
	DWORD tvol = (DWORD)(volume << 16 | volume);
	waveOutSetVolume(mWaveHandle, tvol);
#endif
}

// ControlThread calls the following function to inform SoundOutput whether it
// should be playing packets or discarding them

void
CSoundOutput::Play(Boolean play)
{
	mSoundMutex.Wait();
#ifdef	PGP_WIN32
	short err;
	
	if(play && !mPlay)
	{
		Open();
		err = waveOutRestart(mWaveHandle);	CheckWaveError("waveOutRestart", err);
	}
	else if(!play && mPlay)
	{
		err = waveOutReset(mWaveHandle);	CheckWaveError("waveOutReset", err);
		Close();
		// refill the semaphore
		while(sBufReturn < NUMOUTPUTBUFFERS)
			InterlockedIncrement(&sBufReturn);
	}
#endif
	mPlay = play;
	mIndex = mOutdex = 0;
	mSoundMutex.Signal();
}

// Called to halt playing of sound packets temporarily

void
CSoundOutput::Pause(Boolean pause)
{
	mSoundMutex.Wait();
#ifdef	PGP_WIN32
	if(mOpen)
	{
		short err;
		
		if(mPlay && pause)
		{
			// stop playing blocks
			err = waveOutReset(mWaveHandle);	CheckWaveError("waveOutReset", err);
			// refill the semaphore
			while(sBufReturn < NUMOUTPUTBUFFERS)
				InterlockedIncrement(&sBufReturn);
		}
		else if(!mPlay && pause)
		{
			// start playing blocks
			err = waveOutRestart(mWaveHandle);	CheckWaveError("waveOutRestart", err);
		}
	}
#endif
	mPlayQueue->FreeAll();
	if(mOpen)
		mPlay = !pause;
	mIndex = mOutdex = 0;
	mSoundMutex.Signal();
}

void *
CSoundOutput::Run(void)
{
	PFMessage *msg;
	uchar *buf, *d, frames;
	short done = 0, err;
	long len, processed, avail, outdex, overrunDivisor;
	
	while(!done)
	{
		if(msg = (PFMessage *)mPlayQueue->Recv())
		{
			switch(msg->type)
			{
				case _mt_voicePacket:
					mSoundMutex.Wait();
					if(mOpen && mPlay)
					{
						/*if(mSendRR)
						{
							uchar *p, *e;
							
							p = e = (uchar *)safe_malloc(1);
							*e++ = 0;
							mControlThread->GetOutQueue()->Send(_mt_rr, p, 1, TRUE);
							mSendRR = FALSE;
						}*/
						outdex = mOutdex;
						if(mIndex > outdex)
							avail = mIndex - outdex;
						else if(mIndex < outdex)
							avail = mSampleBufLen - outdex + mIndex;
						else
							avail = 0;
						if(mPlaypoint <= 2)
							overrunDivisor = 5;
						else if(mPlaypoint <= 4)
							overrunDivisor = 4;
						else if(mPlaypoint <= 6)
							overrunDivisor = 3;
						else if(mPlaypoint <= 10)
							overrunDivisor = 2;
						else
							overrunDivisor = 1;
#ifdef	PGP_MACINTOSH
						if((avail / (mSampleSize == 16 ? 2 : 1)) > (mCoderRate >> 16) / overrunDivisor)
#else
						if((avail / (mSampleSize == 16 ? 2 : 1)) > mCoderRate / overrunDivisor)
#endif
						{
							// If the number of samples waiting to play is greater than
							// one fifth the sample rate, drop old stuff to reduce latency
							mIndex = mOutdex;
						}
						if(msg->len > 5)
						{
							d = (uchar *)msg->data;
							frames = msg->len / mCFrameSize;
							len = (frames * mFrameSamples) * (mSampleSize == 16 ? 2 : 1);
							processed = 0;
							while(processed<len)
							{
								buf = &mSamples[mIndex];
								switch(mCodec)
								{
									case 'GS4L':
									case 'GS5L':
									case 'GS6L':
									case 'GS7L':
									case 'GL80':
									case 'GS8L':
									case 'GS1L':
									case 'GSM4':
									case 'GSM5':
									case 'GSM6':
									case 'GSM7':
									case 'GS80':
									case 'GSM8':
									case 'GSM1':
										if(gsm_decode(mGSM, d, (short *)buf))
										{
											//GSM buffer was bad!
											
											//Let the upper layer know about this because if we
											//are on a serial connection this could mean
											//that the line has disconnected unexpectedly and
											//we should hangup.
											//We only do this only if processed is 0 because it is
											//theoretically possible to receive sound encoded by
											//another GSM which would have a different CFrameSize,
											//causing it to falsely invoke on the second GSM frame.
											
											if(!processed)
												mControlThread->ProtocolViolation(_pv_invalidSound);
										}
										d+=mCFrameSize;
										processed+=mBufferQuant;
										break;
									case 'ADP8':
										if(!processed)
										{
											BUFFER_TO_SHORT(d, mADPCM.valprev);	d += sizeof(short);
											mADPCM.index = *d++;
										}
										adpcm_decoder((char *)d, (short *)buf, mCFrameSize*2, &mADPCM);
										d+=mCFrameSize;
										processed+=320;
										break;
#ifdef USEVOXWARE
									case 'VOXW':{
										VOXWARE_RETCODE voxerr;
										
										mVoxComVars.lpCodedDataBuffer = d;
										mVoxComVars.lpSpeechBuffer = buf;
										voxerr = RTDecode(&mVoxComVars);	pgpAssert(IsntErr(voxerr));
										
										d+=mCFrameSize;
										processed+=mBufferQuant;
										break;}
#endif
									case 0:
										break;
								}
								mIndex+=mBufferQuant;
								mIndex %= mSampleBufLen;
								// how much sound is available?
								outdex = mOutdex;
								if(mIndex > outdex)
									avail = mIndex - outdex;
								else if(mIndex < outdex)
									avail = mSampleBufLen - outdex + mIndex;
								else
									avail = 0;
#ifdef	PGP_MACINTOSH
								if(!mPlaying && (avail >= mBufferQuant * mPlaypoint))// are we starting up/underflowing?
								{
									SndCommand sndCmd;
									
									// there is enough sound to start up a double
									// buffer
									sndCmd.cmd = flushCmd;
									sndCmd.param1 = 0;
									sndCmd.param2 = 0;
									// cancel anything old
									SndDoImmediate(mSndChannel, &sndCmd);
									mDoubleBufHdr.dbhNumChannels = 1;
									mDoubleBufHdr.dbhSampleSize = mSampleSize;
									mDoubleBufHdr.dbhCompressionID = 0;
									mDoubleBufHdr.dbhPacketSize = 0;
									mDoubleBufHdr.dbhSampleRate = mCoderRate;
									mDoubleBufHdr.dbhDoubleBack = mDoubleBackProc;
									mDoubleBufHdr.dbhBufferPtr[0] = mDblBufOne;
									mDoubleBufHdr.dbhBufferPtr[1] = mDblBufTwo;
									mDblBufOne->dbNumFrames = mDblBufTwo->dbNumFrames =
										mBufferQuant / (mSampleSize == 16 ? 2 : 1);
									mPlaying = TRUE;
									FillDoubleBuffer(mDblBufOne);
									FillDoubleBuffer(mDblBufTwo);
									mDblBufOne->dbUserInfo[0] = mDblBufTwo->dbUserInfo[0] =
										(long)this;
									err = SndPlayDoubleBuffer(mSndChannel, &mDoubleBufHdr);
									pgpAssert(IsntErr(err));
								}
#elif	PGP_WIN32
								if(avail >= mBufferQuant * mPlaypoint)
									while((avail >= mBufferQuant) && (sBufReturn>0))
									{
										// send the buffer to the sound card
										InterlockedDecrement(&sBufReturn);
										mHeaders[mHeaderIndex].dwBufferLength = RateChange((short *)&mSamples[mOutdex],
													(short *)mHeaders[mHeaderIndex].lpData,
													mBufferQuant / 2, mCoderRate, mSampleRate) * 2;
										mOutdex += mBufferQuant;
										mOutdex %= mSampleBufLen;
										err = waveOutWrite(mWaveHandle, &(mHeaders[mHeaderIndex]), sizeof(WAVEHDR));
										CheckWaveError("waveOutWrite", err);
										mHeaderIndex++;
										mHeaderIndex %= NUMOUTPUTBUFFERS;
										avail -= mBufferQuant;
									}
#endif
							}
						}
						else
						{
							//	fill buf with silence data
							//	we have received a "silence" packet which
							//	is a way of saving bandwidth during silence
							//	first byte is # of frames, next 4 are random
							//+++++todo
						}
						Yield();
					}
					else
					{
						/* we are not playing sound now, so discard this packet */
					}
					mSoundMutex.Signal();
					break;
				case _mt_quit:
					done = 1;
					break;
			}
			mPlayQueue->Free(msg);
		}
	}
	return (void *)1L;
}

⌨️ 快捷键说明

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