#include "asterisk/pbx.h"
#include "asterisk/frame.h"
+#include "asterisk/mod_format.h"
#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include "asterisk/musiconhold.h"
return 0;
}
+/*!
+ * \brief calculates the number of samples to jump forward with in a monitor stream.
+
+ * \note When using ast_seekstream() with the read and write streams of a monitor,
+ * the number of samples to seek forward must be of the same sample rate as the stream
+ * or else the jump will not be calculated correctly.
+ *
+ * \retval number of samples to seek forward after rate conversion.
+ */
+static inline int calc_monitor_jump(int samples, int sample_rate, int seek_rate)
+{
+ int diff = sample_rate - seek_rate;
+
+ if (diff > 0) {
+ samples = samples / (float) (sample_rate / seek_rate);
+ } else if (diff < 0) {
+ samples = samples * (float) (seek_rate / sample_rate);
+ }
+
+ return samples;
+}
+
static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
{
struct ast_frame *f = NULL; /* the return value */
#ifndef MONITOR_CONSTANT_DELAY
int jump = chan->outsmpl - chan->insmpl - 4 * f->samples;
if (jump >= 0) {
- jump = chan->outsmpl - chan->insmpl;
+ jump = calc_monitor_jump((chan->outsmpl - chan->insmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format));
if (ast_seekstream(chan->monitor->read_stream, jump, SEEK_FORCECUR) == -1)
ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
- chan->insmpl += jump + f->samples;
+ chan->insmpl += (chan->outsmpl - chan->insmpl) + f->samples;
} else
chan->insmpl+= f->samples;
#else
- int jump = chan->outsmpl - chan->insmpl;
+ int jump = calc_monitor_jump((chan->outsmpl - chan->insmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format));
if (jump - MONITOR_DELAY >= 0) {
if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
- chan->insmpl += jump;
+ chan->insmpl += chan->outsmpl - chan->insmpl;
} else
chan->insmpl += f->samples;
#endif
#ifndef MONITOR_CONSTANT_DELAY
int jump = chan->insmpl - chan->outsmpl - 4 * cur->samples;
if (jump >= 0) {
- jump = chan->insmpl - chan->outsmpl;
+ jump = calc_monitor_jump((chan->insmpl - chan->outsmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format));
if (ast_seekstream(chan->monitor->write_stream, jump, SEEK_FORCECUR) == -1)
ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
- chan->outsmpl += jump + cur->samples;
+ chan->outsmpl += (chan->insmpl - chan->outsmpl) + cur->samples;
} else {
chan->outsmpl += cur->samples;
}
#else
- int jump = chan->insmpl - chan->outsmpl;
+ int jump = calc_monitor_jump((chan->insmpl - chan->outsmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format));
if (jump - MONITOR_DELAY >= 0) {
if (ast_seekstream(chan->monitor->write_stream, jump - cur->samples, SEEK_FORCECUR) == -1)
ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
- chan->outsmpl += jump;
+ chan->outsmpl += chan->insmpl - chan->outsmpl;
} else {
chan->outsmpl += cur->samples;
}