📄 audio.c
字号:
new_config->primary = codec_get_by_payload(sp->encodings[0]);
} else if (codec_audio_formats_compatible(new_config->primary, codec_get_by_payload(sp->encodings[0])) == FALSE) {
/* Request to change primary and format incompatible so
* device needs rejigging */
change_req = TRUE;
debug_msg("Change primary requested.\n");
} else {
/* Request to change primary to compatible coding. */
sp->encodings[0] = codec_get_payload(new_config->primary);
}
if (new_config->render_3d == -1) {
/* No request to change 3d rendering */
new_config->render_3d = sp->render_3d;
} else if (new_config->render_3d != sp->render_3d) {
change_req = TRUE;
debug_msg("Change 3d rendering enabled requested.\n");
}
if (change_req) {
/* Store current config in case it reconfig attempt fails */
prev_config.device = sp->audio_device;
prev_config.primary = codec_get_by_payload(sp->encodings[0]);
prev_config.render_3d = sp->render_3d;
if (sp->audio_device) {
audio_device_release(sp, sp->audio_device);
}
if (audio_device_attempt_config(sp, new_config)) {
/* New config acceptable */
curr_config = new_config;
} else if (audio_device_attempt_config(sp, &prev_config)) {
/* else attempt to fallback to previous config */
curr_config = &prev_config;
debug_msg("Fellback to old dev config\n");
} else {
/* Fallback to guaranteed config - something
* went badly wrong */
ac_destroy(&new_config);
audio_device_get_safe_config(&new_config);
assert(new_config);
if (audio_device_attempt_config(sp, new_config) == FALSE) {
/* should never get here */
abort();
}
curr_config = new_config;
debug_msg("Fell back to safe config\n");
}
debug_msg("0x%08x 0x%08x\n", prev_config.device, curr_config->device);
if (prev_config.device == curr_config->device) {
debug_msg("Restoring ports\n");
audio_set_iport(curr_config->device, iport);
audio_set_oport(curr_config->device, oport);
} else {
const audio_port_details_t *papd;
/* Ports will be squiffy */
papd = audio_get_iport_details(curr_config->device, 0);
audio_set_iport(curr_config->device, papd->port);
papd = audio_get_oport_details(curr_config->device, 0);
audio_set_oport(curr_config->device, papd->port);
}
audio_loopback(curr_config->device, sp->loopback_gain);
sp->audio_device = curr_config->device;
sp->encodings[0] = codec_get_payload(curr_config->primary);
/* If using redundancy check it is still relevent */
if (sp->num_encodings > 1 &&
!codec_audio_formats_compatible(curr_config->primary, codec_get_by_payload(sp->encodings[1]))) {
const cc_details_t *ccd;
channel_encoder_destroy(&sp->channel_coder);
ccd = channel_get_null_coder();
channel_encoder_create(ccd->descriptor, &sp->channel_coder);
sp->num_encodings = 1;
}
sp->render_3d = curr_config->render_3d;
} else {
debug_msg("audio device reconfigure - nothing to do.\n");
if (tx_is_sending(sp->tb)) {
tx_stop(sp->tb);
tx_start(sp->tb);
}
}
tx_igain_update(sp->tb);
ac_destroy(&sp->new_config);
return change_req;
}
int
audio_device_get_safe_config(audio_config **ppac)
{
if (ac_create(ppac)) {
audio_config *pac = *ppac;
pac->device = audio_get_null_device();
pac->primary = codec_get_by_name("PCMU-8K-Mono");
pac->render_3d = FALSE;
assert(pac->primary);
return TRUE;
}
return FALSE;
}
/*****************************************************************************/
static int
audio_device_write(session_t *sp, sample *buf, int dur)
{
const audio_format *ofmt = audio_get_ofmt(sp->audio_device);
int len;
assert(dur >= 0);
if (sp->out_file) {
snd_write_audio(&sp->out_file, buf, (uint16_t)(dur * ofmt->channels));
}
len = audio_write(sp->audio_device, buf, dur * ofmt->channels);
xmemchk();
return len;
}
/* This function needs to be modified to return some indication of how well
* or not we are doing.
*/
int
audio_rw_process(session_t *spi, session_t *spo, struct s_mixer *ms)
{
uint32_t cushion_size, read_dur;
struct s_cushion_struct *c;
int trailing_silence, new_cushion, cushion_step, diff;
const audio_format* ofmt;
sample *bufp;
session_validate(spi);
session_validate(spo);
c = spi->cushion;
if ((read_dur = tx_read_audio(spi->tb)) <= 0) {
return 0;
} else {
if (!spi->audio_device) {
/* no device means no cushion */
return read_dur;
}
}
xmemchk();
/* read_dur now reflects the amount of real time it took us to get
* through the last cycle of processing.
*/
if (spo->lecture == TRUE && spo->auto_lecture == 0) {
cushion_update(c, read_dur, CUSHION_MODE_LECTURE);
} else {
cushion_update(c, read_dur, CUSHION_MODE_CONFERENCE);
}
/* Following code will try to achieve new cushion size without
* messing up the audio...
* First case is when we are in trouble and the output has gone dry.
* In this case we write out a complete new cushion with the desired
* size. We do not care how much of it is going to be real audio and
* how much silence so long as the silence is at the head of the new
* cushion. If the silence was at the end we would be creating
* another silence gap...
*/
cushion_size = cushion_get_size(c);
ofmt = audio_get_ofmt(spi->audio_device);
if (cushion_size < read_dur) {
debug_msg("catch up! read_dur(%d) > cushion_size(%d)\n",
read_dur,
cushion_size);
/* Use a step for the cushion to keep things nicely rounded */
/* in the mixing. Round it up. */
new_cushion = cushion_use_estimate(c);
assert(new_cushion >= 0 && new_cushion < 100000);
/* The mix routine also needs to know for how long the */
/* output went dry so that it can adjust the time. */
mix_new_cushion(ms,
cushion_size,
new_cushion,
(read_dur - cushion_size),
&bufp);
audio_device_write(spo, bufp, new_cushion);
/* We've blocked for this long for whatever reason */
cushion_size = new_cushion;
} else {
trailing_silence = mix_get_audio(ms, read_dur * ofmt->channels, &bufp);
cushion_step = cushion_get_step(c);
diff = 0;
if (trailing_silence > cushion_step) {
/* Check whether we need to adjust the cushion */
diff = cushion_diff_estimate_size(c);
if (abs(diff) < cushion_step) {
diff = 0;
}
}
/* If diff is less than zero then we must decrease the */
/* cushion so loose some of the trailing silence. */
if (diff < 0 &&
mix_active(ms) == FALSE &&
source_list_source_count(spi->active_sources) == 0) {
/* Only decrease cushion if not playing anything out */
uint32_t old_cushion;
old_cushion = cushion_get_size(c);
if (read_dur > (unsigned)cushion_step) {
cushion_step_down(c);
if (cushion_get_size(c) != old_cushion) {
debug_msg("Decreasing cushion\n");
read_dur -= cushion_step;
}
}
}
assert(read_dur < 0x7fffffff);
audio_device_write(spo, bufp, read_dur);
/*
* If diff is greater than zero then we must increase the
* cushion so increase the amount of trailing silence.
*/
if (diff > 0) {
assert(cushion_step > 0);
audio_device_write(spo, zero_buf, cushion_step);
cushion_step_up(c);
debug_msg("Increasing cushion.\n");
}
}
return (read_dur);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -