app_mixmonitor: Add 'D' option for dual-channel audio.

Adds the 'D' option to app_mixmonitor that interleaves the input and
output frames of the channel being recorded in the monitor output frame.
This allows for two streams in the recording: the transmitted audio and
the received audio. The 't' and 'r' options are compatible with this.

Fixes: #945

UserNote: The MixMonitor application now has a new 'D' option which
interleaves the recorded audio in the output frames. This allows for
stereo recording output with one channel being the transmitted audio and
the other being the received audio. The 't' and 't' options are
compatible with this.
pull/1060/head
Ben Ford 6 months ago
parent 3963364ae7
commit 84c0266faa

@ -127,6 +127,11 @@
Like with the basic filename argument, if an absolute path isn't given, it will create
the file in the configured monitoring directory.</para>
</option>
<option name="D">
<para>Interleave the audio coming from the channel and the audio coming to the channel in
the output audio as a dual channel stream, rather than mix it.</para>
<note><para>Use .raw as the extension.</para></note>
</option>
<option name="n">
<para>When the <replaceable>r</replaceable> or <replaceable>t</replaceable> option is
used, MixMonitor will insert silence into the specified files to maintain
@ -418,6 +423,7 @@ enum mixmonitor_flags {
MUXFLAG_NO_RWSYNC = (1 << 15),
MUXFLAG_AUTO_DELETE = (1 << 16),
MUXFLAG_REAL_CALLERID = (1 << 17),
MUXFLAG_INTERLEAVED = (1 << 18),
};
enum mixmonitor_args {
@ -447,6 +453,7 @@ AST_APP_OPTIONS(mixmonitor_opts, {
AST_APP_OPTION_ARG('W', MUXFLAG_VOLUME, OPT_ARG_VOLUME),
AST_APP_OPTION_ARG('r', MUXFLAG_READ, OPT_ARG_READNAME),
AST_APP_OPTION_ARG('t', MUXFLAG_WRITE, OPT_ARG_WRITENAME),
AST_APP_OPTION('D', MUXFLAG_INTERLEAVED),
AST_APP_OPTION_ARG('i', MUXFLAG_UID, OPT_ARG_UID),
AST_APP_OPTION_ARG('m', MUXFLAG_VMRECIPIENTS, OPT_ARG_VMRECIPIENTS),
AST_APP_OPTION_ARG('S', MUXFLAG_DEPRECATED_RWSYNC, OPT_ARG_DEPRECATED_RWSYNC),
@ -797,6 +804,46 @@ static void *mixmonitor_thread(void *obj)
}
}
if (ast_test_flag(mixmonitor, MUXFLAG_INTERLEAVED)) {
/* The 'D' option is set, so mix the frame as an interleaved dual channel frame */
int i;
short read_buf[SAMPLES_PER_FRAME];
short write_buf[SAMPLES_PER_FRAME];
short stereo_buf[SAMPLES_PER_FRAME * 2];
struct ast_frame stereo_frame = {
.frametype = AST_FRAME_VOICE,
.datalen = sizeof(stereo_buf),
.samples = SAMPLES_PER_FRAME,
};
if (fr) {
ast_frame_free(fr, 0);
fr = NULL;
}
if (fr_read) {
memcpy(read_buf, fr_read->data.ptr, sizeof(read_buf));
} else {
memset(read_buf, 0, sizeof(read_buf));
}
if (fr_write) {
memcpy(write_buf, fr_write->data.ptr, sizeof(write_buf));
} else {
memset(write_buf, 0, sizeof(write_buf));
}
for (i = 0; i < SAMPLES_PER_FRAME; i++) {
stereo_buf[i * 2] = read_buf[i];
stereo_buf[i * 2 + 1] = write_buf[i];
}
stereo_frame.data.ptr = stereo_buf;
stereo_frame.subclass.format = ast_format_cache_get_slin_by_rate(SAMPLES_PER_FRAME);
fr = ast_frdup(&stereo_frame);
}
if ((*fs) && (fr)) {
struct ast_frame *cur;

Loading…
Cancel
Save