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

📄 winsnd.c

📁 基于osip、eXosip、speex、ffmpeg的VoIP源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*mediastreamer2 library - modular sound and video processing and streamingCopyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.*/#if defined(_WIN32_WCE)#define DISABLE_SPEEX#endif#ifndef WINSND_BUFLEN#define WINSND_BUFLEN 320#endif#ifndef MAX_WAVEHDR#define MAX_WAVEHDR 6#endif#ifndef DISABLE_SPEEX#include <speex/speex_preprocess.h>#endif#include "mediastreamer2/mssndcard.h"#include "mediastreamer2/msfilter.h"#include "mediastreamer2/msticker.h"#ifdef WIN32#include <malloc.h> /* for alloca */#endif#include <mmsystem.h>#ifdef _MSC_VER#include <mmreg.h>#endif#include <msacm.h>MSFilter *ms_winsnd_read_new(MSSndCard *card);MSFilter *ms_winsnd_write_new(MSSndCard *card);typedef struct WinSndData{	char *pcmdev;	char *mixdev;	int   devid;    int sound_err;    WAVEFORMATEX wfx;#ifdef CONTROLVOLUME	DWORD dwOldVolume;#endif	WAVEHDR waveouthdr[30];    char waveoutbuffer[30][3200];    HWAVEOUT waveoutdev;    int buffer_playing;	int pos_whdr;    WAVEHDR waveinhdr[30];    HWAVEIN waveindev;    char waveinbuffer[30][3200];    int rate;	int bits;	ms_thread_t thread;	ms_mutex_t mutex;	queue_t rq;	MSBufferizer * bufferizer;	bool_t read_started;	bool_t write_started;	bool_t stereo;#ifndef DISABLE_SPEEX	SpeexPreprocessState *pst;#endif	uint64_t bytes_read;	int32_t stat_input;	int32_t stat_output;	int32_t stat_notplayed;} WinSndData;static uint64_t winsnd_get_cur_time( void *data){	WinSndData *d=(WinSndData*)data;	uint64_t curtime=(d->bytes_read*1000)/(d->rate*(d->bits/8)*((d->stereo==FALSE) ? 1 : 2));	ms_debug("winsnd_get_cur_time: bytes_read=%lu, rate=%i, bits=%i, stereo=%i return %lu\n",	(unsigned long)d->bytes_read,d->rate,d->bits,d->stereo,(unsigned long)curtime);	return curtime;}static void CALLBACKSpeakerCallback (HWAVEOUT _waveoutdev, UINT uMsg, DWORD dwInstance,                 DWORD dwParam1, DWORD dwParam2){  WAVEHDR *wHdr;  WinSndData *device;  switch (uMsg)    {      case WOM_OPEN:          ms_message("SpeakerCallback : WOM_OPEN");        break;      case WOM_CLOSE:          ms_message("SpeakerCallback : WOM_CLOSE");        break;      case WOM_DONE:        wHdr = (WAVEHDR *) dwParam1;        device = (WinSndData *)dwInstance;        device->buffer_playing--;		if (device->stat_output==0)		{			device->stat_input=1; /* reset */			device->stat_notplayed=0;		}		device->stat_output++;        break;      default:        break;    }}static void CALLBACKWaveInCallback (HWAVEIN waveindev, UINT uMsg, DWORD dwInstance, DWORD dwParam1,                DWORD dwParam2){  WAVEHDR *wHdr;  MMRESULT mr = NOERROR;  WinSndData *device;  device = (WinSndData *)dwInstance;  switch (uMsg)    {      case MM_WOM_DONE:        wHdr = (WAVEHDR *) dwParam1;        /* A waveform-audio data block has been played and            can now be freed. */        ms_message("WaveInCallback : MM_WOM_DONE");        waveInUnprepareHeader (waveindev, (LPWAVEHDR) wHdr, sizeof (WAVEHDR));        break;      case WIM_OPEN:        ms_message("WaveInCallback : WIM_OPEN");        break;      case WIM_CLOSE:        ms_message("WaveInCallback : WIM_CLOSE");        break;      case WIM_DATA:        wHdr = (WAVEHDR *) dwParam1;		device->bytes_read+=wHdr->dwBytesRecorded;        if (!device->read_started && !device->write_started)          {            mr = waveInUnprepareHeader (device->waveindev, (LPWAVEHDR) wHdr, sizeof (WAVEHDR));            ms_warning("WaveInCallback : unprepare header (waveInUnprepareHeader:0x%i)", mr);            return;          }        if (wHdr->dwBufferLength!=wHdr->dwBytesRecorded)        {            mr = waveInAddBuffer (device->waveindev,                wHdr,                sizeof (device->waveinhdr[wHdr->dwUser]));            if (mr != MMSYSERR_NOERROR)            {                ms_warning("WaveInCallback : error adding buffer to sound card (waveInAddBuffer:0x%i)", mr);            }            return;        }    	ms_mutex_lock(&device->mutex);		if (device->read_started)        {            mblk_t *rm=NULL;            if (rm==NULL) rm=allocb(wHdr->dwBufferLength,0);			memcpy(rm->b_wptr,wHdr->lpData, wHdr->dwBufferLength);#ifndef DISABLE_SPEEX			if (device->pst!=NULL)			{				int vad;				//memset(rm->b_wptr,0, wHdr->dwBufferLength);				vad = speex_preprocess(device->pst, (short*)rm->b_wptr, NULL);#if 0				if (vad!=1)		            ms_message("WaveInCallback : %d", vad);#endif			}#endif			rm->b_wptr+=wHdr->dwBufferLength;			putq(&device->rq,rm);			device->stat_input++;		    rm=NULL;        }    	ms_mutex_unlock(&device->mutex);        mr = waveInAddBuffer (device->waveindev,            wHdr,            sizeof (device->waveinhdr[wHdr->dwUser]));        if (mr != MMSYSERR_NOERROR)        {            ms_warning("WaveInCallback : error adding buffer to sound card (waveInAddBuffer:0x%i)", mr);            return;        }    }}static int winsnd_open(WinSndData *device, int devnumber, int bits,int stereo, int rate, int *minsz){    MMRESULT mr = NOERROR;    DWORD dwFlag;    int i;    int channel = 1;    if (stereo>0)        channel = stereo;	device->wfx.wFormatTag = WAVE_FORMAT_PCM;	device->wfx.cbSize = 0;	device->wfx.nAvgBytesPerSec = 16000;	device->wfx.nBlockAlign = 2;	device->wfx.nChannels = channel;	device->wfx.nSamplesPerSec = rate; /* 8000; */	device->wfx.wBitsPerSample = bits;	    dwFlag = CALLBACK_FUNCTION;    if (devnumber != WAVE_MAPPER)        dwFlag = WAVE_MAPPED | CALLBACK_FUNCTION;    mr = waveOutOpen (&(device->waveoutdev), devnumber, &(device->wfx), (DWORD) SpeakerCallback,                    (DWORD)device, dwFlag);    if (mr != NOERROR)    {        ms_warning("Failed to open device: trying default device. (waveOutOpen:0x%i)", mr);        dwFlag = CALLBACK_FUNCTION;        mr = waveOutOpen (&(device->waveoutdev), WAVE_MAPPER, &(device->wfx), (DWORD) SpeakerCallback,                        (DWORD)device, dwFlag);    }    if (mr != NOERROR)    {        ms_warning("Failed to open windows sound device. (waveOutOpen:0x%i)", mr);        return -1;    }#if 0#define MM_WOM_SETSECONDARYGAINCLASS   (WM_USER)#define MM_WOM_SETSECONDARYGAINLIMIT   (WM_USER+1)#define MM_WOM_FORCESPEAKER            (WM_USER+2)	bool bSpeaker=TRUE;	mr = waveOutMessage(device->waveoutdev, MM_WOM_FORCESPEAKER, bSpeaker, 0);    if (mr != NOERROR)    {        ms_warning("Failed to use earphone. (waveOutMessage:0x%i)", mr);        return -1;    }	typedef HRESULT (* _SetSpeakerMode)(DWORD mode);	_SetSpeakerMode pfnSetSpeakerMode;	HINSTANCE hDll = LoadLibrary(L"\\windows\\ossvcs.dll");	//_debug(L"ossvcs.dll h=%X",hDll);	pfnSetSpeakerMode = (_SetSpeakerMode)GetProcAddress(hDll,(LPCTSTR)218);	if (pfnSetSpeakerMode)	{	//_debug(L"SetSpeakerMode imported.");	DWORD sm = 0;	//_debug(L"SpeakerMode set to %d", sm);	pfnSetSpeakerMode(sm);	}	//else	//_debug(L"pfnSetSpeakerMode import failed.");	FreeLibrary(hDll);#endif#ifdef CONTROLVOLUME	mr = waveOutGetVolume(device->waveoutdev, &device->dwOldVolume);    if (mr != NOERROR)    {        ms_warning("Failed to get volume device. (waveOutGetVolume:0x%i)", mr);    }	mr = waveOutSetVolume(device->waveoutdev, 0xFFFFFFFF);    if (mr != NOERROR)    {        ms_warning("Failed to set volume device. (waveOutSetVolume:0x%i)", mr);    }#endif    /* prepare windows buffers */    for (i = 0; i < MAX_WAVEHDR; i++)    {        memset (&(device->waveouthdr[i]), 0, sizeof (device->waveouthdr[i]));        device->waveouthdr[i].lpData = device->waveoutbuffer[i];        /* BUG: on ne connait pas la taille des frames a recevoir...         on utilise enc_frame_per_packet au lien de dec_frame_per_packet */        device->waveouthdr[i].dwBufferLength = device->rate/8000 * WINSND_BUFLEN;        /* 480 pour 98 (speex) */        device->waveouthdr[i].dwFlags = 0;        device->waveouthdr[i].dwUser = i;        mr = waveOutPrepareHeader (device->waveoutdev, &(device->waveouthdr[i]),            sizeof (device->waveouthdr[i]));        if (mr != MMSYSERR_NOERROR){            ms_warning("Failed to prepare windows sound device. (waveOutPrepareHeader:0x%i)", mr);        }        else        {            ms_message("Sound Header prepared %i for windows sound device. (waveOutPrepareHeader)", i);        }    }    /* Init Microphone device */    dwFlag = CALLBACK_FUNCTION;    if (devnumber != WAVE_MAPPER)        dwFlag = WAVE_MAPPED | CALLBACK_FUNCTION;    mr = waveInOpen (&(device->waveindev), devnumber, &(device->wfx),                (DWORD) WaveInCallback, (DWORD)device, dwFlag);    if (mr != NOERROR)    {        ms_warning("Failed to open device: trying default device. (waveInOpen:0x%i)", mr);        dwFlag = CALLBACK_FUNCTION;        mr = waveInOpen (&(device->waveindev), WAVE_MAPPER, &(device->wfx),                    (DWORD) WaveInCallback, (DWORD)device, dwFlag);    }    if (mr != NOERROR)    {        ms_warning("Failed to prepare windows sound device. (waveInOpen:0x%i)", mr);        return -1;    }    for (i = 0; i < MAX_WAVEHDR; i++)    {        memset (&(device->waveinhdr[i]), 0, sizeof (device->waveinhdr[i]));        device->waveinhdr[i].lpData = device->waveinbuffer[i];        /* frameSize */        device->waveinhdr[i].dwBufferLength = device->rate/8000 * WINSND_BUFLEN;        device->waveinhdr[i].dwFlags = 0;        device->waveinhdr[i].dwUser = i;        mr = waveInPrepareHeader (device->waveindev, &(device->waveinhdr[i]),                         sizeof (device->waveinhdr[i]));        if (mr == MMSYSERR_NOERROR){            mr = waveInAddBuffer (device->waveindev, &(device->waveinhdr[i]),                sizeof (device->waveinhdr[i]));            if (mr == MMSYSERR_NOERROR)            {                ms_message("Sound Header prepared %i for windows sound device. (waveInAddBuffer)", i);            }            else            {                ms_warning("Failed to prepare windows sound device. (waveInAddBuffer:0x%i)", mr);            }        }        else        {            ms_warning("Failed to prepare windows sound device. (waveInPrepareHeader:0x%i)", mr);        }    }#ifndef DISABLE_SPEEX#if 0	device->pst = speex_preprocess_state_init((device->rate/8000 * 320)/2, device->rate);	if (device->pst!=NULL) {		float f;		i=1;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_VAD, &i);		i=1;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DENOISE, &i);		i=0;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_AGC, &i);		f=8000;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_AGC_LEVEL, &f);		i=0;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DEREVERB, &i);		f=.4;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);		f=.3;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);	}#endif#endif	mr = waveInStart (device->waveindev);    if (mr != MMSYSERR_NOERROR)    {        ms_warning("Failed to start recording on windows sound device. (waveInStart:0x%i)", mr);        return -1;    }	*minsz=device->rate/8000 * 320;	return 0;}static void winsnd_set_level(MSSndCard *card, MSSndCardMixerElem e, int percent){	WinSndData *d=(WinSndData*)card->data;    MMRESULT mr = NOERROR;    DWORD dwVolume = 0xFFFF;    dwVolume = ((0xFFFF) * percent) / 100;	if (d->mixdev==NULL) return;	switch(e){		case MS_SND_CARD_MASTER:            mr = waveOutSetVolume(d->waveoutdev, dwVolume);	        if (mr != MMSYSERR_NOERROR)	        {                ms_warning("Failed to set master volume. (waveOutSetVolume:0x%i)", mr);                return;	        }            return;        break;#if 0        case MS_SND_CARD_CAPTURE:			wincmd=SOUND_MIXER_IGAIN;		break;		case MS_SND_CARD_PLAYBACK:			wincmd=SOUND_MIXER_PCM;		break;#endif        default:			ms_warning("winsnd_card_set_level: unsupported command.");			return;	}}static int winsnd_get_level(MSSndCard *card, MSSndCardMixerElem e){	WinSndData *d=(WinSndData*)card->data;    MMRESULT mr = NOERROR;    DWORD dwVolume = 0x0000;	if (d->mixdev==NULL) return -1;	switch(e){		case MS_SND_CARD_MASTER:            mr=waveOutGetVolume(d->waveoutdev, &dwVolume);            // Transform to 0 to 100 scale            //dwVolume = (dwVolume *100) / (0xFFFF);            return 60;        break;#if 0        case MS_SND_CARD_CAPTURE:			osscmd=SOUND_MIXER_IGAIN;		break;		case MS_SND_CARD_PLAYBACK:			osscmd=SOUND_MIXER_PCM;		break;#endif		default:			ms_warning("winsnd_card_get_level: unsupported command.");			return -1;	}	return -1;}static void winsnd_set_source(MSSndCard *card, MSSndCardCapture source){	WinSndData *d=(WinSndData*)card->data;	if (d->mixdev==NULL) return;	switch(source){		case MS_SND_CARD_MIC:		break;		case MS_SND_CARD_LINE:		break;	}	}static void winsnd_init(MSSndCard *card){	WinSndData *d=(WinSndData*)ms_new(WinSndData,1);    memset(d, 0, sizeof(WinSndData));

⌨️ 快捷键说明

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