📄 csoundinput.cpp
字号:
passedThreshold = TRUE;
break;
}
}
else
{
if(*p >= mThreshold)
{
passedThreshold = TRUE;
break;
}
}
}
if(!passedThreshold)
{
// The sound did not pass the amplitude test,
// ditch it all so it never gets sent.
mDownDone = 0;
SetStatus(FALSE);
}
else
{
mTrailSamples = mDefaultTrail;
SetStatus(TRUE);
}
}
}
break;
case 8:
break;
/*{// mSampleSize == 8
char *p, *s, *e;
downSize = newlen / mDownsampleD;
p = (char *)src;
e = p + newlen / mDownsampleD * mDownsampleD;
s = mDownBuf + mDownDone;
for(;p<e;p++)
{
if(!toggle)
*s++ = *p;
if(++toggle == mDownsampleD)
toggle=0;
}
mDownDone += downSize;
break;}*/
}
if(mDownDone >= mFrameSize)
{
if(!mCompSnd)
{
mCompSnd = safe_malloc(mCFrameSize * mFrames + mCoderSizeSlack);
mCompDone = 0;
// Record the sampling instant for RTP
}
s = (short *)mDownBuf;
e = (short *)(mDownBuf + mDownDone);
d = (uchar *)mCompSnd + mCompDone + (mCompDone ? mCoderSizeSlack : 0);
de = (uchar *)mCompSnd + (mCFrameSize * mFrames) + mCoderSizeSlack;
switch(mCodec)
{
case 'GS4L':
case 'GS7L':
case 'GS6L':
case 'GL80':
case 'GS1L':
case 'GSM4':
case 'GSM7':
case 'GSM6':
case 'GS80':
case 'GSM1':
for(;(d < de) && (e-s >= 160);s+=160,d+=mCFrameSize)
{
gsm_encode(mGSM, s, d);
mCompDone += mCFrameSize;
}
pgp_memcpy(mDownBuf, s, (char *)e-(char *)s);
mDownDone = (char *)e-(char *)s;
break;
case 'ADP8':
if(!mCompDone)
{
SHORT_TO_BUFFER(mADPCM.valprev, d); d += sizeof(short);
*d++ = mADPCM.index;
}
for(;(d < de) && (e-s >= 160);s+=160,d+=mCFrameSize)
{
adpcm_coder(s,(char *)d,mFrameSize/2,&mADPCM);
mCompDone += mCFrameSize;
}
pgp_memcpy(mDownBuf, s, (char *)e-(char *)s);
mDownDone = (char *)e-(char *)s;
break;
#ifdef USEVOXWARE
case 'VOXW':{
VOXWARE_RETCODE voxerr;
mVoxComVars.lpSpeechBuffer = (uchar *)s;
mVoxComVars.lpCodedDataBuffer = d;
voxerr = RTEncode(&mVoxComVars); pgpAssert(IsntErr(voxerr));
d += mCFrameSize;
mCompDone += mCFrameSize;
s += mFrameSize / 2;
pgp_memcpy(mDownBuf, s, (char *)e-(char *)s);
mDownDone = (char *)e-(char *)s;
break;}
#endif
case 0:
break;
}
if(d >= de)
{
pgpAssert(d == de); //make sure we didn't go over
if(mOutQueue->GetSize() < SOUNDINPUTQUEUEMAX)
mOutQueue->Send(_mt_voicePacket, mCompSnd,
mFrames * mCFrameSize + mCoderSizeSlack, 1);
else
{
safe_free(mCompSnd);
gPacketWatch->OverflowOut(1);
}
mCompSnd = NIL;
mCompDone = 0;
}
}
}
}
mOutdex += newlen;
mOutdex %= mSampleBufSize;
}
#ifdef PGP_MACINTOSH
if(mOpen)
{
::SPBGetDeviceInfo(mSoundRef, siLevelMeterOnOff, &levelInfo);
mLevelMeter->SetLevel(levelInfo & 0xFFFF);
}
#endif
mSoundMutex.Signal();
#ifdef PGP_MACINTOSH
Yield(mOutThread);
#elif PGP_WIN32
Yield();
#endif
}
return (void *)1L;
}
void
CSoundInput::SetGain(short gain)
{
#ifdef PGP_MACINTOSH
ulong step = 0x00010000;
mGain = 0x00007FFF + (step / 256 * gain);
if(mOpen)
::SPBSetDeviceInfo(mSoundRef, siInputGain, &mGain);
#elif PGP_WIN32
mGain = gain;
#endif //PGP_WIN32
}
void
CSoundInput::DisposeCodec(void)
{
mSoundMutex.Wait();
switch(mCodec)
{
case 'GSM4':
case 'GSM6':
case 'GSM7':
case 'GS80':
case 'GSM1':
case 'GS4L':
case 'GS6L':
case 'GS7L':
case 'GL80':
case 'GS1L':
gsm_destroy(mGSM);
break;
#ifdef USEVOXWARE
case 'VOXW':{
VOXWARE_RETCODE voxerr;
voxerr = RTFreeEncoder(&mVoxComVars); pgpAssert(IsntErr(voxerr));
break;}
#endif
case 'ADP8':
case 0:
break;
}
mCodec = 0;
mSoundMutex.Signal();
}
void
CSoundInput::SetCodec(ulong type)
{
short inx;
mSoundMutex.Wait();
DisposeCodec();
mIndex = mOutdex = 0;
mCoderSizeSlack = 0;
switch(type)
{
#ifdef USEVOXWARE
case 'VOXW':{
VOXWARE_RETCODE voxerr;
ushort framesPerPkt;
#ifdef PGP_MACINTOSH
mCoderRate = 0x1f400000;
#elif PGP_WIN32
mCoderRate = 8000.0;
#endif
mSampleSize = 16;
mCFrameSize = 30; // We use less than 30 byte packets with Voxware!!
mFrames = 1;
voxerr = RTInitEncoder(&mVoxComVars, &mVoxCoderReqs); pgpAssert(IsntErr(voxerr));
if((mVoxCoderReqs.dwSamplingRate == 8000) &&
(mVoxCoderReqs.wBytesPerSample == 2))
{
framesPerPkt = ((mCFrameSize * 8) / mVoxCoderReqs.wNumBitsPerFrame);
mVoxComVars.dwNumBytesInSpeechBuffer =
framesPerPkt * (mVoxCoderReqs.wNumSamplesPerFrame * mVoxCoderReqs.wBytesPerSample);
mVoxComVars.dwNumBytesInCodedDataBuffer =
((framesPerPkt * mVoxCoderReqs.wNumBitsPerFrame) / 8);
mVoxComVars.dwNumBytesInCodedDataBuffer +=
(0 != ((framesPerPkt * mVoxCoderReqs.wNumBitsPerFrame) % 8));
mFrameSize = mVoxComVars.dwNumBytesInSpeechBuffer;
mCFrameSize = mVoxComVars.dwNumBytesInCodedDataBuffer;
}
break;}
#endif
case 'ADP8':
mSampleSize = 16;
mFrameSize = 320;
mCFrameSize = 80;
mFrames = 4;
memset(&mADPCM, 0, sizeof(adpcm_state));
mCoderSizeSlack = 3;
#ifdef PGP_MACINTOSH
mCoderRate = 0x1f400000;
#elif PGP_WIN32
mCoderRate = 8000.0;
#endif
break;
case 'GS4L':
case 'GS6L':
case 'GS7L':
case 'GL80':
case 'GS1L': /* 160 shorts -> 29 bytes */
mGSM = gsm_create();
mFrameSize = 320;
mCFrameSize = 29;
mSampleSize = 16;
switch(type)
{
case 'GS4L': // 4410 hz
#ifdef PGP_MACINTOSH
mCoderRate = 0x113A0000;
#elif PGP_WIN32
mCoderRate = 4410.0;
#endif
mFrames = 2;
break;
case 'GS5L': // 5512 hz
#ifdef PGP_MACINTOSH
mCoderRate = 0x15880000;
#elif PGP_WIN32
mCoderRate = 5512.0;
#endif
mFrames = 3;
break;
case 'GS6L': // 6000 hz
#ifdef PGP_MACINTOSH
mCoderRate = 0x17700000;
#elif PGP_WIN32
mCoderRate = 6000.0;
#endif
mFrames = 3;
break;
case 'GS7L': // 7350 hz
#ifdef PGP_MACINTOSH
mCoderRate = 0x1cb60000;
#elif PGP_WIN32
mCoderRate = 7350.0;
#endif
mFrames = 4;
break;
case 'GL80': // 8000 hz
#ifdef PGP_MACINTOSH
mCoderRate = 0x1f400000;
#elif PGP_WIN32
mCoderRate = 8000.0;
#endif
mFrames = 5;
break;
case 'GS8L': // 8820 hz
#ifdef PGP_MACINTOSH
mCoderRate = 0x22740000;
#elif PGP_WIN32
mCoderRate = 8820.0;
#endif
mFrames = 6;
break;
case 'GS1L': // 11025 hz
#ifdef PGP_MACINTOSH
mCoderRate = rate11025hz;
#elif PGP_WIN32
mCoderRate = 11025.0;
#endif
mFrames = 6;
break;
}
inx = 1;
gsm_option(mGSM, GSM_OPT_LTP_CUT, &inx);
break;
case 'GSM4':
case 'GSM6':
case 'GSM7':
case 'GS80':
case 'GSM1': /* 160 shorts -> 33 bytes 4.8:1 */
mGSM = gsm_create();
mFrameSize = 320;
mCFrameSize = 33;
mSampleSize = 16;
switch(type)
{
case 'GSM4': // 4410 hz
#ifdef PGP_MACINTOSH
mCoderRate = 0x113A0000;
#elif PGP_WIN32
mCoderRate = 4410.0;
#endif
mFrames = 2;
break;
case 'GSM6': // 6000 hz
#ifdef PGP_MACINTOSH
mCoderRate = 0x17700000;
#elif PGP_WIN32
mCoderRate = 6000.0;
#endif
mFrames = 3;
break;
case 'GSM7': // 7350 hz
#ifdef PGP_MACINTOSH
mCoderRate = 0x1cb60000;
#elif PGP_WIN32
mCoderRate = 7350.0;
#endif
mFrames = 4;
break;
case 'GS80': // 8000 hz
#ifdef PGP_MACINTOSH
mCoderRate = 0x1f400000;
#elif PGP_WIN32
mCoderRate = 8000.0;
#endif
mFrames = 5;
break;
case 'GSM1': // 11025 hz
#ifdef PGP_MACINTOSH
mCoderRate = rate11025hz;
#elif PGP_WIN32
mCoderRate = 11025.0;
#endif
mFrames = 6;
break;
}
break;
case 'rand':
mFrames = 100;
mFrameSize = 2;
mCFrameSize = 2;
mSampleSize = 16;
break;
default:
/* unknown codec */
pgp_errstring("CSoundInput: Bad Codec");
break;
}
mUpSampleSize = FALSE;
if(mHardwareIs16Bit)
{
if(mOpen)
{
#ifdef PGP_MACINTOSH
::SPBSetDeviceInfo(mSoundRef, siSampleSize, &mSampleSize);
#elif PGP_WIN32
//Not implemented yet, careful using 8 bit coders on WIN32.
//We dont have any 8 bit coders right now.
#endif
}
}
else if(mSampleSize == 16)
mUpSampleSize = TRUE;
/*
// Use the following code to force 8 bit samples
mUpSampleSize = TRUE; inx=8;
::SPBSetDeviceInfo(mSoundRef, siSampleSize, &inx);
*/
mSampleBufSize = INSAMPLEBUFMAX / mFrameSize * mFrameSize;
#ifdef PGP_MACINTOSH
mDefaultTrail = mCoderRate >> 16; // send for half a second
#elif PGP_WIN32
mDefaultTrail = mCoderRate; // send for half a second
#endif
mCodec = type;
// Tell the packet thread milliseconds between packets
if(mPacketThread)
mPacketThread->SetSound(1000.0 /
((float)mDefaultTrail / ((float)(mFrames * (mFrameSize / 2)))));
mTrailSamples = 0;
mPFWindow->SetEncoder(type);
mSoundMutex.Signal();
}
void
CSoundInput::Record(Boolean record)
{
#ifdef PGP_WIN32
short i;
int err;
#endif
mSoundMutex.Wait();
if(mRecording != record)
{
mRecording = record;
if(mRecording)
{
SetStatus(TRUE);
mLevelMeter->SetStatus(TRUE);
Open();
if(mCompSnd)
safe_free(mCompSnd);
mCompSnd = NIL;
mCompDone = 0;
mDownDone = 0;
mTrailSamples = 0;
#ifdef PGP_MACINTOSH
mSPB.count = 0;
mSPB.milliseconds = 0;
mSPB.bufferLength = 0;
mSPB.bufferPtr = NIL;
::SPBRecord(&mSPB, TRUE);
#elif PGP_WIN32
SetThreadPriority(mThreadHandle, THREAD_PRIORITY_NORMAL);
mHeaderIndex = sHeaderIndex = 0;
for(i=0;i<NUMINPUTBUFFERS;i++)
{
if(!(mHeaders[i].dwFlags & WHDR_PREPARED))
{
mHeaders[i].dwBufferLength = RAWRECORDQUANT;
mHeaders[i].lpData = (char *)mMemPtrs[i];
err = waveInPrepareHeader(mWaveHandle, &(mHeaders[i]), sizeof(WAVEHDR));
CheckWaveError("waveInPrepareHeader", err);
}
err = waveInAddBuffer(mWaveHandle, &(mHeaders[i]), sizeof(WAVEHDR));
CheckWaveError("waveInAddBuffer", err);
}
// start recording
err = waveInStart(mWaveHandle);
CheckWaveError("waveInStart", err);
#endif
}
else
{
SetStatus(FALSE);
mLevelMeter->SetStatus(FALSE);
#ifdef PGP_MACINTOSH
::SPBStopRecording(mSoundRef);
#elif PGP_WIN32
err = waveInReset(mWaveHandle);
CheckWaveError("waveInReset", err);
#endif
Close();
#ifdef PGP_WIN32
// Wait until all of the blocks are finished.
// This is necessary to ensure that half duplex
// machines do not open the output before the input
// is finished.
for(i=0;i<NUMINPUTBUFFERS;i++)
while(mHeaders[i].dwFlags && !(mHeaders[i].dwFlags & WHDR_DONE))
Sleep(0);
#endif
}
}
mSoundMutex.Signal();
}
void
CSoundInput::Pause(Boolean pause)
{
mSoundMutex.Wait();
mPaused = pause;
if(mCompSnd)
safe_free(mCompSnd);
mCompSnd = NIL;
mCompDone = 0;
mDownDone = 0;
mTrailSamples = 0;
SetStatus(!pause);
mSoundMutex.Signal();
}
void
CSoundInput::SetOutput(LThread *outThread, CMessageQueue *outQueue)
{
mSoundMutex.Wait();
mOutThread = outThread;
mOutQueue = outQueue;
mSoundMutex.Signal();
}
void
CSoundInput::SetPacketThread(CPFPacketsOut *packetThread)
{
mSoundMutex.Wait();
mPacketThread = packetThread;
mSoundMutex.Signal();
}
void
CSoundInput::SetThreshold(long thresh)
{
// We are given a threshold value from 0-32767
// representing the amplitude which we should
// require before sending sound packets
pgpAssert(thresh <= MAX_THRESHOLD);
mThreshold = thresh;
mTrailSamples = 0;
if(mRecording)
SetStatus(TRUE);
}
void
CSoundInput::SetStatus(Boolean status)
{
// We set the window to the actual status just to let the user know,
// but if we are not in a real call, we set our internal status
// to false.
mPFWindow->SetSoundInStatus(status);
if(mPacketThread)
{
if(mCodec == 'rand')
mPacketThread->SetSoundStatus(FALSE);
else
mPacketThread->SetSoundStatus(status);
}
}
void
CSoundInput::AbortSync()
{
mAbort = TRUE;
#ifdef PGP_WIN32
long count;
ReleaseSemaphore(siSemaphore, 1, &count);
#endif
}
void Amplify(short *samples, int numSamples, double gain)
{
/*
* The following is equivalent to gain * 256, but rounds to the
* nearest integer instead of truncating the fractional part
*/
short x = (gain * 512 + 1) / 2;
while (numSamples--)
{
*samples = ((long)*samples * x) >> 8;
samples++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -