📄 csoundoutput.cpp
字号:
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 + -