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.

(cherry picked from commit 8273eefd87)
This commit is contained in:
Ben Ford
2024-10-28 14:06:29 -05:00
committed by Asterisk Development Team
parent 9374ae1036
commit c895d3692e

View File

@@ -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
@@ -414,6 +419,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 {
@@ -443,6 +449,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),
@@ -792,6 +799,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;