📄 jvoipsoundcardinput.cpp
字号:
/* This file is a part of JVOIPLIB, a library designed to facilitate the use of Voice over IP (VoIP). Copyright (C) 2000-2004 Jori Liesenborgs (jori@lumumba.luc.ac.be) This library (JVOIPLIB) is based upon work done for my thesis at the School for Knowledge Technology (Belgium/The Netherlands) The full GNU Library General Public License can be found in the file LICENSE.LGPL which is included in the source code archive. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include "jvoipconfig.h"#include "jvoipsoundcardinput.h"#include "jvoipsoundcardparams.h"#include "jvoipsounddevice.h"#include "jvoipsounddeviceblock.h"#include <stdlib.h>#include <string.h>#include <stdio.h>#include "debugnew.h"#define JVOIPSOUNDCARDINPUT_TOTALBUFFERTIME 10000#define JVOIPSOUNDCARDINPUT_EXTRABLOCKSIZE 32JVOIPSoundcardInput::JVOIPSoundcardInput(JVOIPSession *sess) throw (JVOIPException) : JVOIPVoiceInput(sess){ init = false; sounddev = NULL; if (sigwait.Init() < 0) throw JVOIPException(ERR_JVOIPLIB_GENERAL_CANTINITSIGWAIT);}JVOIPSoundcardInput::~JVOIPSoundcardInput(){ Cleanup();}int JVOIPSoundcardInput::Init(int sampinterval,int inputsamprate,int inputbytespersample,const JVOIPComponentParams *componentparams){ JVOIPSoundcardParams defparams,*usrparams; int status; if (init) return ERR_JVOIPLIB_GENERAL_COMPONENTALREADYINIT; // Get the soundcard parameters if (componentparams == NULL) usrparams = &defparams; else if ((usrparams = dynamic_cast<JVOIPSoundcardParams *>(const_cast<JVOIPComponentParams *>(componentparams))) == NULL) usrparams = &defparams; multiplyfactor = usrparams->GetMultiplyFactor(); if (multiplyfactor < 1 || multiplyfactor > 256) return ERR_JVOIPLIB_SOUNDCARDIO_ILLEGALMULTIPLYFACTOR; status = JVOIPSoundDevice::OpenDevice(&sounddev,usrparams->GetSoundDeviceName(),true,inputsamprate); if (status < 0) return status; status = sounddev->SetInputCallback(InputCallback,this); if (status < 0) { delete sounddev; return status; } sampleinterval = sampinterval; samprate = inputsamprate; bytespersample = inputbytespersample; sounddev->RequestSamplingRate(samprate); if ((status = InitBuffers()) < 0) { delete sounddev; return status; } InitSampleConverter(); sigwait.ClearSignalBuffers(); init = true; firsttime = true; return 0;}int JVOIPSoundcardInput::Cleanup(){ if (!init) return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT; delete sounddev; ClearBuffers(); init = false; return 0;}int JVOIPSoundcardInput::StartSampling(){ int i,size,numsamp,status; double diff; if (!init) return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT; if (firsttime) { firsttime = false; srcsampletime = 0; wantedsrcsampletime = 0; for (i = 0 ; i < numblocks ; i++) { wantedsrcsampletime += (double)sampleinterval; diff = wantedsrcsampletime-srcsampletime; diff /= 1000.0; // convert to seconds numsamp = (int)(diff*(double)drvsamprate+0.5); size = numsamp*drvstereo*drvbytespersample; sampleblocks[i].datalen = size; if ((status = sounddev->AddBuffer(&sampleblocks[i])) < 0) return status; srcsampletime += ((double)numsamp)/((double)drvsamprate)*1000.0; } blockpos = 0; } else { wantedsrcsampletime += (double)sampleinterval; diff = wantedsrcsampletime-srcsampletime; diff /= 1000.0; // convert to seconds numsamp = (int)(diff*(double)drvsamprate+0.5); size = numsamp*drvstereo*drvbytespersample; sampleblocks[blockpos].datalen = size; if ((status = sounddev->AddBuffer(&sampleblocks[blockpos])) < 0) return status; srcsampletime += ((double)numsamp)/((double)drvsamprate)*1000.0; blockpos++; if (blockpos >= numblocks) blockpos = 0; } return 0;}void JVOIPSoundcardInput::ResetDevice(){ if (!init) return; firsttime = true; sounddev->Reset(); sigwait.ClearSignalBuffers();}void JVOIPSoundcardInput::Reset(){ int status; if (!init) return; firsttime = true; sounddev->Reset(); sigwait.ClearSignalBuffers(); ClearBuffers(); if ((status = InitBuffers()) < 0) { delete sounddev; init = false; std::cerr << "JVOIPSoundcardInput: couldn't init buffers during Reset, device closed" << std::endl; return; } InitSampleConverter();}int JVOIPSoundcardInput::GetSampleBlock(VoIPFramework::VoiceBlock *vb){ int numsamp,size; double diff; if (!init) return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT; if (firsttime) // this will happen only once, and 'firsttime' will be set { // to 'false', in 'StartSampling' (which is called after this function) dstsampletime = 0; wanteddstsampletime = 0; } wanteddstsampletime += (double)sampleinterval; diff = wanteddstsampletime-dstsampletime; diff /= 1000.0; // convert to seconds numsamp = (int)(diff*(double)samprate+0.5); size = numsamp*bytespersample; dstsampletime += ((double)numsamp)/((double)samprate)*1000.0; if (firsttime) // we'll have to return silence, since we haven't sampled anything yet { // Here, we follow the assumption that we deliver sample in big endian and unsigned if (bytespersample == 1) memset(convertbuffer,127,numsamp); else // two bytes per sample { for (int i = 0 ; i < size ; i += 2) { convertbuffer[i] = 127; convertbuffer[i+1] = 255; } } } else { int actualsize; actualsize = sampconvert.Convert(sampleblocks[blockpos].data,sampleblocks[blockpos].datalen,convertbuffer,size); if (actualsize < size) // we'll have to fill a bit { if (bytespersample == 1) { unsigned char b; b = convertbuffer[actualsize-1]; for ( ; actualsize < size ; actualsize++) convertbuffer[actualsize] = b; } else // two bytes per sample { unsigned char b1,b2; b1 = convertbuffer[actualsize-2]; b2 = convertbuffer[actualsize-1]; for ( ; actualsize < size ; actualsize += 2) { convertbuffer[actualsize] = b1; convertbuffer[actualsize + 1] = b2; } } } } // Ok, now we have what we want, and we'll just have to fill in the info in the // voice block vb->SetSamples(convertbuffer,size); vb->SetNumSamples(numsamp); vb->SetStereo(false); vb->SetBytesPerSample(bytespersample); vb->SetSampleRate(samprate); vb->SetDataDeleteHandler(BlockDeleteHandler,this); return 0;}bool JVOIPSoundcardInput::SupportsSampleInterval(int ival){ return true;}bool JVOIPSoundcardInput::SupportsInputSamplingRate(int irate){ return true;}bool JVOIPSoundcardInput::SupportsInputBytesPerSample(int inputbytespersample){ return true; }int JVOIPSoundcardInput::SetSampleInterval(int ival){ int status; if (!init) return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT; if (ival == sampleinterval) return 0; sampleinterval = ival; ResetDevice(); ClearBuffers(); if ((status = InitBuffers()) < 0) { delete sounddev; init = false; return status; } InitSampleConverter(); return 0;}int JVOIPSoundcardInput::SetInputSamplingRate(int irate){ int status; if (!init) return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT; if (irate == samprate) return 0; samprate = irate; ResetDevice(); ClearBuffers(); if ((status = InitBuffers()) < 0) { delete sounddev; init = false; return status; } InitSampleConverter(); return 0;}int JVOIPSoundcardInput::SetInputBytesPerSample(int inputbytespersample){ int status; if (!init) return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT; if (inputbytespersample == bytespersample) return 0; bytespersample = inputbytespersample; ResetDevice(); ClearBuffers(); if ((status = InitBuffers()) < 0) { delete sounddev; init = false; return status; } InitSampleConverter(); return 0;}bool JVOIPSoundcardInput::HasTimeOut(){ if (!init) return false; if (firsttime) return true; return sampleblocks[blockpos].IsDone();}int JVOIPSoundcardInput::RestartTimer(){ if (!init) return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT; // NOTE: nothing needs to be done here return 0;}int JVOIPSoundcardInput::GetComponentState(JVOIPComponentState **compstate){ if (!init) return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT; *compstate = NULL; return 0;}int JVOIPSoundcardInput::SetComponentState(JVOIPComponentState *compstate){ if (!init) return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT; // NOTE: nothing needs to be done here return 0;}std::string JVOIPSoundcardInput::GetComponentName(){ return std::string("JVOIPSoundcardInput");}std::string JVOIPSoundcardInput::GetComponentDescription(){ return std::string("JVOIPLIB Internal soundcard input module (OSS version)");}std::vector<JVOIPCompParamInfo> *JVOIPSoundcardInput::GetComponentParameters() throw (JVOIPException){ std::vector<JVOIPCompParamInfo> *paraminfo; paraminfo = new std::vector<JVOIPCompParamInfo>(2); if (paraminfo == NULL) throw JVOIPException(ERR_JVOIPLIB_GENERAL_OUTOFMEM); (*paraminfo)[0].SetParameterName(std::string("Device")); if (sounddev == NULL) (*paraminfo)[0].SetParameterValue(std::string("None")); else (*paraminfo)[0].SetParameterValue(sounddev->GetDeviceName()); char val[256]; sprintf(val,"%d",multiplyfactor); (*paraminfo)[1].SetParameterName(std::string("Multiply Factor")); (*paraminfo)[1].SetParameterValue(std::string(val)); return paraminfo;}int JVOIPSoundcardInput::InitBuffers(){ int i; // Request the most appropriate sampling rate sounddev->RequestSamplingRate(samprate); // allocate buffers for the sounddevice drvsamprate = sounddev->GetSamplingRate(); drvbytespersample = sounddev->GetBytesPerSample(); drvstereo = (sounddev->IsStereo())?2:1; numblocks = (int)(((double)JVOIPSOUNDCARDINPUT_TOTALBUFFERTIME)/((double)sampleinterval)+0.5); blocksize = (int)((((double)drvsamprate*(double)sampleinterval)/1000.0)*(double)drvbytespersample*(double)drvstereo+0.5); blocksize += JVOIPSOUNDCARDINPUT_EXTRABLOCKSIZE; sampleblocks = new JVOIPSoundDeviceBlock [numblocks]; if (sampleblocks == NULL) return ERR_JVOIPLIB_GENERAL_OUTOFMEM; for (i = 0 ; i < numblocks ; i++) { sampleblocks[i].data = new unsigned char[blocksize]; if (sampleblocks[i].data == NULL) { for (int j = 0 ; j < i ; j++) delete [] sampleblocks[j].data; delete [] sampleblocks; return ERR_JVOIPLIB_GENERAL_OUTOFMEM; } } // allocate a buffer to hold the converted data convertbufsize = (int)((((double)samprate*(double)sampleinterval)/1000.0)*(double)bytespersample+0.5); convertbufsize += JVOIPSOUNDCARDINPUT_EXTRABLOCKSIZE; convertbuffer = new unsigned char [convertbufsize]; if (convertbuffer == NULL) { for (i = 0 ; i < numblocks ; i++) delete [] sampleblocks[i].data; delete [] sampleblocks; } return 0;}void JVOIPSoundcardInput::ClearBuffers(){ for (int i = 0 ; i < numblocks ; i++) delete [] sampleblocks[i].data; delete [] sampleblocks; delete [] convertbuffer;}void JVOIPSoundcardInput::InputCallback(void *param){ JVOIPSoundcardInput *inst; if (!param) return; inst = (JVOIPSoundcardInput *)param; inst->sigwait.Signal();}void JVOIPSoundcardInput::BlockDeleteHandler(unsigned char **data,void *param){ *data = NULL;}void JVOIPSoundcardInput::InitSampleConverter(){ int srcrate,srcbytespersample,dstrate,dstbytespersample; bool srcstereo,srcsigned,srcLE,dststereo,dstsigned,dstLE; srcrate = sounddev->GetSamplingRate(); srcbytespersample = sounddev->GetBytesPerSample(); srcstereo = sounddev->IsStereo(); srcsigned = sounddev->IsSampleSigned(); srcLE = sounddev->IsSampleLittleEndian(); dstrate = samprate; dstbytespersample = bytespersample; dststereo = false; dstsigned = false; dstLE = false; sampconvert.SetConversionParams(srcrate,srcstereo,srcbytespersample,srcsigned,srcLE, dstrate,dststereo,dstbytespersample,dstsigned,dstLE, multiplyfactor);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -