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

📄 dsound.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (rc == WAIT_OBJECT_0) {	    if (events[0] == strm->play_strm.hEvent)		signalled_dir = PJMEDIA_DIR_PLAYBACK;	    else		signalled_dir = PJMEDIA_DIR_CAPTURE;	} else {	    if (events[1] == strm->play_strm.hEvent)		signalled_dir = PJMEDIA_DIR_PLAYBACK;	    else		signalled_dir = PJMEDIA_DIR_CAPTURE;	}	if (signalled_dir == PJMEDIA_DIR_PLAYBACK) {	    	    struct dsound_stream *dsound_strm;	    /*	     * DirectSound has requested us to feed some frames to	     * playback buffer.	     */	    dsound_strm = &strm->play_strm;	    status = PJ_SUCCESS;	    /* Get frame from application. */	    status = (*strm->play_cb)(strm->user_data, 				      dsound_strm->timestamp.u32.lo,				      strm->buffer,				      bytes_per_frame);	    if (status != PJ_SUCCESS)		break;	    /* Write to DirectSound buffer. */	    AppWriteDataToBuffer( dsound_strm->ds.play.lpDsBuffer, 				  dsound_strm->dwBytePos,				  (LPBYTE)strm->buffer, 				  bytes_per_frame);	    /* Increment position. */	    dsound_strm->dwBytePos += bytes_per_frame;	    if (dsound_strm->dwBytePos >= dsound_strm->dwDsBufferSize)		dsound_strm->dwBytePos -= dsound_strm->dwDsBufferSize;	    dsound_strm->timestamp.u64 += strm->samples_per_frame;	} else {	    /*	     * DirectSound has indicated that it has some frames ready	     * in the capture buffer. Get as much frames as possible to	     * prevent overflows.	     */	    struct dsound_stream *dsound_strm;	    BOOL rc;	    dsound_strm = &strm->rec_strm;	    do {		/* Capture from DirectSound buffer. */		rc = AppReadDataFromBuffer(dsound_strm->ds.capture.lpDsBuffer, 					   dsound_strm->dwBytePos,					   (LPBYTE)strm->buffer, 					   bytes_per_frame);				if (!rc) {		    pj_bzero(strm->buffer, bytes_per_frame);		} 		/* Call callback */		status = (*strm->rec_cb)(strm->user_data, 					 dsound_strm->timestamp.u32.lo, 					 strm->buffer, 					 bytes_per_frame);		/* Quit thread on error. */		if (status != PJ_SUCCESS)		    goto on_error;		/* Increment position. */		dsound_strm->dwBytePos += bytes_per_frame;		if (dsound_strm->dwBytePos >= dsound_strm->dwDsBufferSize)		    dsound_strm->dwBytePos -= dsound_strm->dwDsBufferSize;		dsound_strm->timestamp.u64 += strm->samples_per_frame;		/* Fetch while we have more than 1 frame */	    } while (dsound_captured_size(dsound_strm) > bytes_per_frame);	}    }on_error:    PJ_LOG(5,(THIS_FILE, "DirectSound: thread stopping.."));    return 0;}/* DirectSound enum device callback */static BOOL CALLBACK DSEnumCallback( LPGUID lpGuid, LPCSTR lpcstrDescription,  				     LPCSTR lpcstrModule, LPVOID lpContext){    unsigned index, max = sizeof(dev_info[index].info.name);    pj_bool_t is_capture_device = (lpContext != NULL);    PJ_UNUSED_ARG(lpcstrModule);    /* Put the capture and playback of the same devices to the same      * dev_info item, by looking at the GUID.     */    for (index=0; index<dev_count; ++index) {	if (dev_info[index].lpGuid == lpGuid)	    break;    }    if (index == dev_count)	++dev_count;    else if (dev_count >= MAX_HARDWARE) {	pj_assert(!"Too many DirectSound hardware found");	PJ_LOG(4,(THIS_FILE, "Too many hardware found, some devices will "			     "not be listed"));	return FALSE;    }    strncpy(dev_info[index].info.name, lpcstrDescription, max);    dev_info[index].info.name[max-1] = '\0';    dev_info[index].lpGuid = lpGuid;    dev_info[index].info.default_samples_per_sec = 44100;        /* Just assumed that device supports stereo capture/playback */    if (is_capture_device)	dev_info[index].info.input_count+=2;    else	dev_info[index].info.output_count+=2;    return TRUE;}/* * Init sound library. */PJ_DEF(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory){    HRESULT hr;    unsigned i;    pool_factory = factory;    /* Enumerate sound playback devices */    hr = DirectSoundEnumerate(&DSEnumCallback, NULL);    if (FAILED(hr))	return PJ_RETURN_OS_ERROR(hr);    /* Enumerate sound capture devices */    hr = DirectSoundCaptureEnumerate(&DSEnumCallback, (void*)1);    if (FAILED(hr))	return PJ_RETURN_OS_ERROR(hr);    PJ_LOG(4,(THIS_FILE, "DirectSound initialized, found %d devices:",	      dev_count));    for (i=0; i<dev_count; ++i) {	PJ_LOG(4,(THIS_FILE, " dev_id %d: %s  (in=%d, out=%d)", 		  i, dev_info[i].info.name, 		  dev_info[i].info.input_count, 		  dev_info[i].info.output_count));    }    return PJ_SUCCESS;}/* * Deinitialize sound library. */PJ_DEF(pj_status_t) pjmedia_snd_deinit(void){    return PJ_SUCCESS;}/* * Get device count. */PJ_DEF(int) pjmedia_snd_get_dev_count(void){    return dev_count;}/* * Get device info. */PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index){    if (index == (unsigned)-1) 	index = 0;    PJ_ASSERT_RETURN(index < dev_count, NULL);    return &dev_info[index].info;}/* * Open stream. */static pj_status_t open_stream( pjmedia_dir dir,			        int rec_id,				int play_id,				unsigned clock_rate,				unsigned channel_count,				unsigned samples_per_frame,				unsigned bits_per_sample,				pjmedia_snd_rec_cb rec_cb,				pjmedia_snd_play_cb play_cb,				void *user_data,				pjmedia_snd_stream **p_snd_strm){    pj_pool_t *pool;    pjmedia_snd_stream *strm;    pj_status_t status;    /* Make sure sound subsystem has been initialized with     * pjmedia_snd_init()     */    PJ_ASSERT_RETURN( pool_factory != NULL, PJ_EINVALIDOP );    /* Can only support 16bits per sample */    PJ_ASSERT_RETURN(bits_per_sample == BITS_PER_SAMPLE, PJ_EINVAL);    /* Create and Initialize stream descriptor */    pool = pj_pool_create(pool_factory, "dsound-dev", 1000, 1000, NULL);    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);    strm = pj_pool_zalloc(pool, sizeof(pjmedia_snd_stream));    strm->dir = dir;    strm->play_id = play_id;    strm->rec_id = rec_id;    strm->pool = pool;    strm->rec_cb = rec_cb;    strm->play_cb = play_cb;    strm->user_data = user_data;    strm->clock_rate = clock_rate;    strm->samples_per_frame = samples_per_frame;    strm->bits_per_sample = bits_per_sample;    strm->channel_count = channel_count;    strm->buffer = pj_pool_alloc(pool, samples_per_frame * BYTES_PER_SAMPLE);    if (!strm->buffer) {	pj_pool_release(pool);	return PJ_ENOMEM;    }    /* Create player stream */    if (dir & PJMEDIA_DIR_PLAYBACK) {	status = init_player_stream( &strm->play_strm, play_id, clock_rate,				     channel_count, samples_per_frame,				     DEFAULT_BUFFER_COUNT );	if (status != PJ_SUCCESS) {	    pjmedia_snd_stream_close(strm);	    return status;	}    }    /* Create capture stream */    if (dir & PJMEDIA_DIR_CAPTURE) {	status = init_capture_stream( &strm->rec_strm, rec_id, clock_rate,				      channel_count, samples_per_frame,				      DEFAULT_BUFFER_COUNT);	if (status != PJ_SUCCESS) {	    pjmedia_snd_stream_close(strm);	    return status;	}    }    /* Create and start the thread */    status = pj_thread_create(pool, "dsound", &dsound_dev_thread, strm,			      0, 0, &strm->thread);    if (status != PJ_SUCCESS) {	pjmedia_snd_stream_close(strm);	return status;    }    *p_snd_strm = strm;    return PJ_SUCCESS;}/* * Open stream. */PJ_DEF(pj_status_t) pjmedia_snd_open_rec( int index,					  unsigned clock_rate,					  unsigned channel_count,					  unsigned samples_per_frame,					  unsigned bits_per_sample,					  pjmedia_snd_rec_cb rec_cb,					  void *user_data,					  pjmedia_snd_stream **p_snd_strm){    PJ_ASSERT_RETURN(rec_cb && p_snd_strm, PJ_EINVAL);    return open_stream( PJMEDIA_DIR_CAPTURE, index, -1,			clock_rate, channel_count, samples_per_frame,			bits_per_sample, rec_cb, NULL, user_data,			p_snd_strm);}PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index,					unsigned clock_rate,					unsigned channel_count,					unsigned samples_per_frame,					unsigned bits_per_sample,					pjmedia_snd_play_cb play_cb,					void *user_data,					pjmedia_snd_stream **p_snd_strm){    PJ_ASSERT_RETURN(play_cb && p_snd_strm, PJ_EINVAL);    return open_stream( PJMEDIA_DIR_PLAYBACK, -1, index,			clock_rate, channel_count, samples_per_frame,			bits_per_sample, NULL, play_cb, user_data,			p_snd_strm);}/* * Open both player and recorder. */PJ_DEF(pj_status_t) pjmedia_snd_open( int rec_id,				      int play_id,				      unsigned clock_rate,				      unsigned channel_count,				      unsigned samples_per_frame,				      unsigned bits_per_sample,				      pjmedia_snd_rec_cb rec_cb,				      pjmedia_snd_play_cb play_cb,				      void *user_data,				      pjmedia_snd_stream **p_snd_strm){    PJ_ASSERT_RETURN(rec_cb && play_cb && p_snd_strm, PJ_EINVAL);    return open_stream( PJMEDIA_DIR_CAPTURE_PLAYBACK, rec_id, play_id,			clock_rate, channel_count, samples_per_frame,			bits_per_sample, rec_cb, play_cb, user_data,			p_snd_strm );}/* * Get stream info. */PJ_DEF(pj_status_t) pjmedia_snd_stream_get_info(pjmedia_snd_stream *strm,						pjmedia_snd_stream_info *pi){    PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);    pj_bzero(pi, sizeof(*pi));    pi->dir = strm->dir;    pi->play_id = strm->play_id;    pi->rec_id = strm->rec_id;    pi->clock_rate = strm->clock_rate;    pi->channel_count = strm->channel_count;    pi->samples_per_frame = strm->samples_per_frame;    pi->bits_per_sample = strm->bits_per_sample;    pi->rec_latency = 0;    pi->play_latency = 0;    return PJ_SUCCESS;}/* * Start stream. */PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream){    HRESULT hr;    PJ_UNUSED_ARG(stream);    if (stream->play_strm.ds.play.lpDsBuffer) {	hr = IDirectSoundBuffer_Play(stream->play_strm.ds.play.lpDsBuffer, 				     0, 0, DSBPLAY_LOOPING);	if (FAILED(hr))	    return PJ_RETURN_OS_ERROR(hr);	PJ_LOG(5,(THIS_FILE, "DirectSound playback stream started"));    }        if (stream->rec_strm.ds.capture.lpDsBuffer) {	hr = IDirectSoundCaptureBuffer_Start(stream->rec_strm.ds.capture.lpDsBuffer,					     DSCBSTART_LOOPING );	if (FAILED(hr))	    return PJ_RETURN_OS_ERROR(hr);	PJ_LOG(5,(THIS_FILE, "DirectSound capture stream started"));    }    return PJ_SUCCESS;}/* * Stop stream. */PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream){    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);    if (stream->play_strm.ds.play.lpDsBuffer) {	PJ_LOG(5,(THIS_FILE, "Stopping DirectSound playback stream"));	IDirectSoundBuffer_Stop( stream->play_strm.ds.play.lpDsBuffer );    }    if (stream->rec_strm.ds.capture.lpDsBuffer) {	PJ_LOG(5,(THIS_FILE, "Stopping DirectSound capture stream"));	IDirectSoundCaptureBuffer_Stop(stream->rec_strm.ds.capture.lpDsBuffer);    }    return PJ_SUCCESS;}/* * Destroy stream. */PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream){    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);    pjmedia_snd_stream_stop(stream);    if (stream->thread) {	stream->thread_quit_flag = 1;	pj_thread_join(stream->thread);	pj_thread_destroy(stream->thread);	stream->thread = NULL;    }    if (stream->play_strm.lpDsNotify) {	IDirectSoundNotify_Release( stream->play_strm.lpDsNotify );	stream->play_strm.lpDsNotify = NULL;    }        if (stream->play_strm.hEvent) {	CloseHandle(stream->play_strm.hEvent);	stream->play_strm.hEvent = NULL;    }    if (stream->play_strm.ds.play.lpDsBuffer) {	IDirectSoundBuffer_Release( stream->play_strm.ds.play.lpDsBuffer );	stream->play_strm.ds.play.lpDsBuffer = NULL;    }    if (stream->play_strm.ds.play.lpDs) {	IDirectSound_Release( stream->play_strm.ds.play.lpDs );	stream->play_strm.ds.play.lpDs = NULL;    }    if (stream->rec_strm.lpDsNotify) {	IDirectSoundNotify_Release( stream->rec_strm.lpDsNotify );	stream->rec_strm.lpDsNotify = NULL;    }        if (stream->rec_strm.hEvent) {	CloseHandle(stream->rec_strm.hEvent);	stream->rec_strm.hEvent = NULL;    }    if (stream->rec_strm.ds.capture.lpDsBuffer) {	IDirectSoundCaptureBuffer_Release( stream->rec_strm.ds.capture.lpDsBuffer );	stream->rec_strm.ds.capture.lpDsBuffer = NULL;    }    if (stream->rec_strm.ds.capture.lpDs) {	IDirectSoundCapture_Release( stream->rec_strm.ds.capture.lpDs );	stream->rec_strm.ds.capture.lpDs = NULL;    }    pj_pool_release(stream->pool);    return PJ_SUCCESS;}#endif	/* PJMEDIA_SOUND_IMPLEMENTATION */

⌨️ 快捷键说明

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