pasound.c

来自「基于sip协议的网络电话源码」· C语言 代码 · 共 818 行 · 第 1/2 页

C
818
字号
			 "bits=%d, %d samples per frame, latency=%d ms",			 paDevInfo->name, paHostApiInfo->name,			 paRate, channel_count,			 bits_per_sample, samples_per_frame,			 paLatency));    *p_snd_strm = stream;    return PJ_SUCCESS;}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_pool_t *pool;    pjmedia_snd_stream *stream;    PaStreamParameters outputParam;    int sampleFormat;    const PaDeviceInfo *paDevInfo = NULL;    const PaHostApiInfo *paHostApiInfo = NULL;    const PaStreamInfo *paSI;    unsigned paFrames, paRate, paLatency;    PaError err;    if (index < 0) {	index = pa_get_default_output_dev(channel_count);	if (index < 0) {	    /* No such device. */	    return PJMEDIA_ENOSNDPLAY;	}    }     paDevInfo = Pa_GetDeviceInfo(index);    if (!paDevInfo) {	/* Assumed it is "No such device" error. */	return PJMEDIA_ESNDINDEVID;    }    if (bits_per_sample == 8)	sampleFormat = paUInt8;    else if (bits_per_sample == 16)	sampleFormat = paInt16;    else if (bits_per_sample == 32)	sampleFormat = paInt32;    else	return PJMEDIA_ESNDINSAMPLEFMT;        pool = pj_pool_create( snd_mgr.factory, "sndstream", 1024, 1024, NULL);    if (!pool)	return PJ_ENOMEM;    stream = pj_pool_calloc(pool, 1, sizeof(*stream));    stream->pool = pool;    pj_strdup2_with_null(pool, &stream->name, paDevInfo->name);    stream->dir = stream->dir = PJMEDIA_DIR_PLAYBACK;    stream->play_id = index;    stream->rec_id = -1;    stream->user_data = user_data;    stream->samples_per_sec = clock_rate;    stream->samples_per_frame = samples_per_frame;    stream->bytes_per_sample = bits_per_sample / 8;    stream->channel_count = channel_count;    stream->play_cb = play_cb;    pj_bzero(&outputParam, sizeof(outputParam));    outputParam.device = index;    outputParam.channelCount = channel_count;    outputParam.hostApiSpecificStreamInfo = NULL;    outputParam.sampleFormat = sampleFormat;    outputParam.suggestedLatency = 1.0 * samples_per_frame / clock_rate;;    paHostApiInfo = Pa_GetHostApiInfo(paDevInfo->hostApi);    /* Frames in PortAudio is number of samples in a single channel */    paFrames = samples_per_frame / channel_count;    err = Pa_OpenStream( &stream->play_strm, NULL, &outputParam,			 clock_rate,  paFrames, 			 paClipOff, &PaPlayerCallback, stream );    if (err != paNoError) {	pj_pool_release(pool);	return PJMEDIA_ERRNO_FROM_PORTAUDIO(err);    }    paSI = Pa_GetStreamInfo(stream->play_strm);    paRate = (unsigned)(paSI->sampleRate);    paLatency = (unsigned)(paSI->outputLatency * 1000);    PJ_LOG(5,(THIS_FILE, "Opened device %d: %s(%s) for playing, sample rate=%d"			 ", ch=%d, "			 "bits=%d, %d samples per frame, latency=%d ms",			 index, paDevInfo->name, paHostApiInfo->name, 			 paRate, channel_count,		 	 bits_per_sample, samples_per_frame, paLatency));    *p_snd_strm = stream;    return PJ_SUCCESS;}/* * 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_pool_t *pool;    pjmedia_snd_stream *stream;    PaStream *paStream = NULL;    PaStreamParameters inputParam;    PaStreamParameters outputParam;    int sampleFormat;    const PaDeviceInfo *paRecDevInfo = NULL;    const PaDeviceInfo *paPlayDevInfo = NULL;    const PaHostApiInfo *paRecHostApiInfo = NULL;    const PaHostApiInfo *paPlayHostApiInfo = NULL;    const PaStreamInfo *paSI;    unsigned paFrames, paRate, paInputLatency, paOutputLatency;    PaError err;    if (rec_id < 0) {	rec_id = pa_get_default_input_dev(channel_count);	if (rec_id < 0) {	    /* No such device. */	    return PJMEDIA_ENOSNDREC;	}    }    paRecDevInfo = Pa_GetDeviceInfo(rec_id);    if (!paRecDevInfo) {	/* Assumed it is "No such device" error. */	return PJMEDIA_ESNDINDEVID;    }    if (play_id < 0) {	play_id = pa_get_default_output_dev(channel_count);	if (play_id < 0) {	    /* No such device. */	    return PJMEDIA_ENOSNDPLAY;	}    }     paPlayDevInfo = Pa_GetDeviceInfo(play_id);    if (!paPlayDevInfo) {	/* Assumed it is "No such device" error. */	return PJMEDIA_ESNDINDEVID;    }    if (bits_per_sample == 8)	sampleFormat = paUInt8;    else if (bits_per_sample == 16)	sampleFormat = paInt16;    else if (bits_per_sample == 32)	sampleFormat = paInt32;    else	return PJMEDIA_ESNDINSAMPLEFMT;        pool = pj_pool_create( snd_mgr.factory, "sndstream", 1024, 1024, NULL);    if (!pool)	return PJ_ENOMEM;    stream = pj_pool_zalloc(pool, sizeof(*stream));    stream->pool = pool;    pj_strdup2_with_null(pool, &stream->name, paRecDevInfo->name);    stream->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;    stream->play_id = play_id;    stream->rec_id = rec_id;    stream->user_data = user_data;    stream->samples_per_sec = clock_rate;    stream->samples_per_frame = samples_per_frame;    stream->bytes_per_sample = bits_per_sample / 8;    stream->channel_count = channel_count;    stream->rec_cb = rec_cb;    stream->play_cb = play_cb;    pj_bzero(&inputParam, sizeof(inputParam));    inputParam.device = rec_id;    inputParam.channelCount = channel_count;    inputParam.hostApiSpecificStreamInfo = NULL;    inputParam.sampleFormat = sampleFormat;    inputParam.suggestedLatency = paRecDevInfo->defaultLowInputLatency;    paRecHostApiInfo = Pa_GetHostApiInfo(paRecDevInfo->hostApi);    pj_bzero(&outputParam, sizeof(outputParam));    outputParam.device = play_id;    outputParam.channelCount = channel_count;    outputParam.hostApiSpecificStreamInfo = NULL;    outputParam.sampleFormat = sampleFormat;    outputParam.suggestedLatency = paPlayDevInfo->defaultLowOutputLatency;    paPlayHostApiInfo = Pa_GetHostApiInfo(paPlayDevInfo->hostApi);    /* Frames in PortAudio is number of samples in a single channel */    paFrames = samples_per_frame / channel_count;    /* If both input and output are on the same device, open a single stream     * for both input and output.     */    if (rec_id == play_id) {	err = Pa_OpenStream( &paStream, &inputParam, &outputParam,			     clock_rate, paFrames, 			     paClipOff, &PaRecorderPlayerCallback, stream );	if (err == paNoError) {	    /* Set play stream and record stream to the same stream */	    stream->play_strm = stream->rec_strm = paStream;	}    } else {	err = -1;    }    /* .. otherwise if input and output are on the same device, OR if we're     * unable to open a bidirectional stream, then open two separate     * input and output stream.     */    if (paStream == NULL) {	/* Open input stream */	err = Pa_OpenStream( &stream->rec_strm, &inputParam, NULL,			     clock_rate, paFrames, 			     paClipOff, &PaRecorderCallback, stream );	if (err == paNoError) {	    /* Open output stream */	    err = Pa_OpenStream( &stream->play_strm, NULL, &outputParam,				 clock_rate, paFrames, 				 paClipOff, &PaPlayerCallback, stream );	    if (err != paNoError)		Pa_CloseStream(stream->rec_strm);	}    }    if (err != paNoError) {	pj_pool_release(pool);	return PJMEDIA_ERRNO_FROM_PORTAUDIO(err);    }    paSI = Pa_GetStreamInfo(stream->rec_strm);    paRate = (unsigned)(paSI->sampleRate);    paInputLatency = (unsigned)(paSI->inputLatency * 1000);    paSI = Pa_GetStreamInfo(stream->play_strm);    paOutputLatency = (unsigned)(paSI->outputLatency * 1000);    PJ_LOG(5,(THIS_FILE, "Opened device %s(%s)/%s(%s) for recording and "			 "playback, sample rate=%d, ch=%d, "			 "bits=%d, %d samples per frame, input latency=%d ms, "			 "output latency=%d ms",			 paRecDevInfo->name, paRecHostApiInfo->name,			 paPlayDevInfo->name, paPlayHostApiInfo->name,			 paRate, channel_count,			 bits_per_sample, samples_per_frame,			 paInputLatency, paOutputLatency));    *p_snd_strm = stream;    return PJ_SUCCESS;}/* * Get stream info. */PJ_DEF(pj_status_t) pjmedia_snd_stream_get_info(pjmedia_snd_stream *strm,						pjmedia_snd_stream_info *pi){    const PaStreamInfo *paPlaySI = NULL, *paRecSI = NULL;    PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);    PJ_ASSERT_RETURN(strm->play_strm || strm->rec_strm, PJ_EINVALIDOP);    if (strm->play_strm) {	paPlaySI = Pa_GetStreamInfo(strm->play_strm);    }    if (strm->rec_strm) {	paRecSI = Pa_GetStreamInfo(strm->rec_strm);    }    pj_bzero(pi, sizeof(*pi));    pi->dir = strm->dir;    pi->play_id = strm->play_id;    pi->rec_id = strm->rec_id;    pi->clock_rate = (unsigned)(paPlaySI ? paPlaySI->sampleRate : 				paRecSI->sampleRate);    pi->channel_count = strm->channel_count;    pi->samples_per_frame = strm->samples_per_frame;    pi->bits_per_sample = strm->bytes_per_sample * 8;    pi->rec_latency = (unsigned)(paRecSI ? paRecSI->inputLatency * 					   paRecSI->sampleRate : 0);    pi->play_latency = (unsigned)(paPlaySI ? paPlaySI->outputLatency * 					     paPlaySI->sampleRate : 0);    return PJ_SUCCESS;}/* * Start stream. */PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream){    int err = 0;    PJ_LOG(5,(THIS_FILE, "Starting %s stream..", stream->name.ptr));    if (stream->play_strm)	err = Pa_StartStream(stream->play_strm);    if (err==0 && stream->rec_strm && stream->rec_strm != stream->play_strm) {	err = Pa_StartStream(stream->rec_strm);	if (err != 0)	    Pa_StopStream(stream->play_strm);    }    PJ_LOG(5,(THIS_FILE, "Done, status=%d", err));    return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS;}/* * Stop stream. */PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream){    int i, err = 0;    stream->quit_flag = 1;    for (i=0; !stream->rec_thread_exited && i<100; ++i)	pj_thread_sleep(10);    for (i=0; !stream->play_thread_exited && i<100; ++i)	pj_thread_sleep(10);    pj_thread_sleep(1);    PJ_LOG(5,(THIS_FILE, "Stopping stream.."));    if (stream->play_strm)	err = Pa_StopStream(stream->play_strm);    if (stream->rec_strm && stream->rec_strm != stream->play_strm)	err = Pa_StopStream(stream->rec_strm);    PJ_LOG(5,(THIS_FILE, "Done, status=%d", err));    return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS;}/* * Destroy stream. */PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream){    int i, err = 0;    stream->quit_flag = 1;    for (i=0; !stream->rec_thread_exited && i<100; ++i) {	pj_thread_sleep(1);    }    for (i=0; !stream->play_thread_exited && i<100; ++i) {	pj_thread_sleep(1);    }    PJ_LOG(5,(THIS_FILE, "Closing %.*s: %lu underflow, %lu overflow",			 (int)stream->name.slen,			 stream->name.ptr,			 stream->underflow, stream->overflow));    if (stream->play_strm)	err = Pa_CloseStream(stream->play_strm);    if (stream->rec_strm && stream->rec_strm != stream->play_strm)	err = Pa_CloseStream(stream->rec_strm);    pj_pool_release(stream->pool);    return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS;}/* * Deinitialize sound library. */PJ_DEF(pj_status_t) pjmedia_snd_deinit(void){    int err;    PJ_LOG(4,(THIS_FILE, "PortAudio sound library shutting down.."));    err = Pa_Terminate();    return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS;}#endif	/* PJMEDIA_SOUND_IMPLEMENTATION */

⌨️ 快捷键说明

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