📄 sound_port.c
字号:
return PJ_SUCCESS;
}
/*
* Stop the sound device.
* This may be called even when there's no sound device in the port.
*/
static pj_status_t stop_sound_device( pjmedia_snd_port *snd_port )
{
/* Check if we have sound stream device. */
if (snd_port->snd_stream) {
pjmedia_snd_stream_stop(snd_port->snd_stream);
pjmedia_snd_stream_close(snd_port->snd_stream);
snd_port->snd_stream = NULL;
}
/* Destroy AEC */
if (snd_port->ec_state) {
pjmedia_echo_destroy(snd_port->ec_state);
snd_port->ec_state = NULL;
}
return PJ_SUCCESS;
}
/*
* Create bidirectional port.
*/
PJ_DEF(pj_status_t) pjmedia_snd_port_create( pj_pool_t *pool,
int rec_id,
int play_id,
unsigned clock_rate,
unsigned channel_count,
unsigned samples_per_frame,
unsigned bits_per_sample,
unsigned options,
pjmedia_snd_port **p_port)
{
pjmedia_snd_port *snd_port;
PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);
snd_port = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_port);
PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM);
snd_port->rec_id = rec_id;
snd_port->play_id = play_id;
snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
snd_port->options = options | DEFAULT_OPTIONS;
snd_port->clock_rate = clock_rate;
snd_port->channel_count = channel_count;
snd_port->samples_per_frame = samples_per_frame;
snd_port->bits_per_sample = bits_per_sample;
*p_port = snd_port;
/* Start sound device immediately.
* If there's no port connected, the sound callback will return
* empty signal.
*/
return start_sound_device( pool, snd_port );
}
/*
* Create sound recorder AEC.
*/
PJ_DEF(pj_status_t) pjmedia_snd_port_create_rec( pj_pool_t *pool,
int dev_id,
unsigned clock_rate,
unsigned channel_count,
unsigned samples_per_frame,
unsigned bits_per_sample,
unsigned options,
pjmedia_snd_port **p_port)
{
pjmedia_snd_port *snd_port;
PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);
snd_port = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_port);
PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM);
snd_port->rec_id = dev_id;
snd_port->dir = PJMEDIA_DIR_CAPTURE;
snd_port->options = options | DEFAULT_OPTIONS;
snd_port->clock_rate = clock_rate;
snd_port->channel_count = channel_count;
snd_port->samples_per_frame = samples_per_frame;
snd_port->bits_per_sample = bits_per_sample;
*p_port = snd_port;
/* Start sound device immediately.
* If there's no port connected, the sound callback will return
* empty signal.
*/
return start_sound_device( pool, snd_port );
}
/*
* Create sound player port.
*/
PJ_DEF(pj_status_t) pjmedia_snd_port_create_player( pj_pool_t *pool,
int dev_id,
unsigned clock_rate,
unsigned channel_count,
unsigned samples_per_frame,
unsigned bits_per_sample,
unsigned options,
pjmedia_snd_port **p_port)
{
pjmedia_snd_port *snd_port;
PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);
snd_port = PJ_POOL_ZALLOC_T(pool, pjmedia_snd_port);
PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM);
snd_port->play_id = dev_id;
snd_port->dir = PJMEDIA_DIR_PLAYBACK;
snd_port->options = options | DEFAULT_OPTIONS;
snd_port->clock_rate = clock_rate;
snd_port->channel_count = channel_count;
snd_port->samples_per_frame = samples_per_frame;
snd_port->bits_per_sample = bits_per_sample;
*p_port = snd_port;
/* Start sound device immediately.
* If there's no port connected, the sound callback will return
* empty signal.
*/
return start_sound_device( pool, snd_port );
}
/*
* Destroy port (also destroys the sound device).
*/
PJ_DEF(pj_status_t) pjmedia_snd_port_destroy(pjmedia_snd_port *snd_port)
{
PJ_ASSERT_RETURN(snd_port, PJ_EINVAL);
return stop_sound_device(snd_port);
}
/*
* Retrieve the sound stream associated by this sound device port.
*/
PJ_DEF(pjmedia_snd_stream*) pjmedia_snd_port_get_snd_stream(
pjmedia_snd_port *snd_port)
{
PJ_ASSERT_RETURN(snd_port, NULL);
return snd_port->snd_stream;
}
/*
* Enable AEC
*/
PJ_DEF(pj_status_t) pjmedia_snd_port_set_ec( pjmedia_snd_port *snd_port,
pj_pool_t *pool,
unsigned tail_ms,
unsigned options)
{
pjmedia_snd_stream_info si;
pj_status_t status;
/* Sound must be opened in full-duplex mode */
PJ_ASSERT_RETURN(snd_port &&
snd_port->dir == PJMEDIA_DIR_CAPTURE_PLAYBACK,
PJ_EINVALIDOP);
/* Sound port must have 16bits per sample */
PJ_ASSERT_RETURN(snd_port->bits_per_sample == 16,
PJ_EINVALIDOP);
/* Destroy AEC */
if (snd_port->ec_state) {
pjmedia_echo_destroy(snd_port->ec_state);
snd_port->ec_state = NULL;
}
snd_port->aec_tail_len = tail_ms;
if (tail_ms != 0) {
unsigned delay_ms;
status = pjmedia_snd_stream_get_info(snd_port->snd_stream, &si);
if (status != PJ_SUCCESS)
si.rec_latency = si.play_latency = 0;
delay_ms = (si.rec_latency + si.play_latency) * 1000 /
snd_port->clock_rate;
status = pjmedia_echo_create(pool, snd_port->clock_rate,
snd_port->samples_per_frame,
tail_ms, delay_ms,
options, &snd_port->ec_state);
if (status != PJ_SUCCESS)
snd_port->ec_state = NULL;
else
snd_port->ec_suspended = PJ_FALSE;
} else {
PJ_LOG(4,(THIS_FILE, "Echo canceller is now disabled in the "
"sound port"));
status = PJ_SUCCESS;
}
return status;
}
/* Get AEC tail length */
PJ_DEF(pj_status_t) pjmedia_snd_port_get_ec_tail( pjmedia_snd_port *snd_port,
unsigned *p_length)
{
PJ_ASSERT_RETURN(snd_port && p_length, PJ_EINVAL);
*p_length = snd_port->ec_state ? snd_port->aec_tail_len : 0;
return PJ_SUCCESS;
}
/*
* Connect a port.
*/
PJ_DEF(pj_status_t) pjmedia_snd_port_connect( pjmedia_snd_port *snd_port,
pjmedia_port *port)
{
pjmedia_port_info *pinfo;
PJ_ASSERT_RETURN(snd_port && port, PJ_EINVAL);
/* Check that port has the same configuration as the sound device
* port.
*/
pinfo = &port->info;
if (pinfo->clock_rate != snd_port->clock_rate)
return PJMEDIA_ENCCLOCKRATE;
if (pinfo->samples_per_frame != snd_port->samples_per_frame)
return PJMEDIA_ENCSAMPLESPFRAME;
if (pinfo->channel_count != snd_port->channel_count)
return PJMEDIA_ENCCHANNEL;
if (pinfo->bits_per_sample != snd_port->bits_per_sample)
return PJMEDIA_ENCBITS;
/* Port is okay. */
snd_port->port = port;
return PJ_SUCCESS;
}
/*
* Get the connected port.
*/
PJ_DEF(pjmedia_port*) pjmedia_snd_port_get_port(pjmedia_snd_port *snd_port)
{
PJ_ASSERT_RETURN(snd_port, NULL);
return snd_port->port;
}
/*
* Disconnect port.
*/
PJ_DEF(pj_status_t) pjmedia_snd_port_disconnect(pjmedia_snd_port *snd_port)
{
PJ_ASSERT_RETURN(snd_port, PJ_EINVAL);
snd_port->port = NULL;
return PJ_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -