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="S">
+ <para>When combined with the <replaceable>r</replaceable> or <replaceable>t</replaceable>
+ option, inserts silence when necessary to maintain synchronization between the receive
+ and transmit audio streams.</para>
+ </option>
<option name="i">
<argument name="chanvar" required="true" />
<para>Stores the MixMonitor's ID on this channel variable.</para>
MUXFLAG_VMRECIPIENTS = (1 << 10),
MUXFLAG_BEEP = (1 << 11),
MUXFLAG_BEEP_START = (1 << 12),
- MUXFLAG_BEEP_STOP = (1 << 13)
+ MUXFLAG_BEEP_STOP = (1 << 13),
+ MUXFLAG_RWSYNC = (1 << 14),
};
enum mixmonitor_args {
OPT_ARG_UID,
OPT_ARG_VMRECIPIENTS,
OPT_ARG_BEEP_INTERVAL,
+ OPT_ARG_RWSYNC,
OPT_ARG_ARRAY_SIZE, /* Always last element of the enum */
};
AST_APP_OPTION_ARG('t', MUXFLAG_WRITE, OPT_ARG_WRITENAME),
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_RWSYNC, OPT_ARG_RWSYNC),
});
struct mixmonitor_ds {
}
ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
+ if ((ast_test_flag(mixmonitor, MUXFLAG_RWSYNC))) {
+ ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_SUBSTITUTE_SILENCE);
+ }
if (readvol)
mixmonitor->audiohook.options.read_volume = readvol;
--- /dev/null
+Subject: app_mixmonitor
+
+An option 'S' has been added to MixMonitor. If used in combination with
+the r() and/or t() options, if a frame is available to write to one of
+those files but not the other, a frame of silence if written to the file
+that does not have an audio frame. This should prevent the two files
+from "drifting" when mixed after the fact.
AST_AUDIOHOOK_MUTE_READ = (1 << 5), /*!< audiohook should be mute frames read */
AST_AUDIOHOOK_MUTE_WRITE = (1 << 6), /*!< audiohook should be mute frames written */
AST_AUDIOHOOK_COMPATIBLE = (1 << 7), /*!< is the audiohook native slin compatible */
+
+ AST_AUDIOHOOK_SUBSTITUTE_SILENCE = (1 << 8), /*!< Substitute silence for missing audio */
};
enum ast_audiohook_init_flags {
frame.subclass.format = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate);
+ /* Should we substitute silence if one side lacks audio? */
+ if ((ast_test_flag(audiohook, AST_AUDIOHOOK_SUBSTITUTE_SILENCE))) {
+ if (read_reference && !read_buf && write_buf) {
+ read_buf = buf1;
+ memset(buf1, 0, sizeof(buf1));
+ } else if (write_reference && read_buf && !write_buf) {
+ write_buf = buf2;
+ memset(buf2, 0, sizeof(buf2));
+ }
+ }
+
/* Basically we figure out which buffer to use... and if mixing can be done here */
if (read_buf && read_reference) {
frame.data.ptr = read_buf;