diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftdm_analog_em.h b/libs/freetdm/src/ftmod/ftmod_analog_em/ftdm_analog_em.h
index 37c90c3b4f..fb9959d061 100644
--- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftdm_analog_em.h
+++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftdm_analog_em.h
@@ -33,6 +33,7 @@
  * Contributor(s):
  *
  * John Wehle (john@feith.com)
+ * Moises Silva (moy@sangoma.com)
  *
  */
 
@@ -53,6 +54,8 @@ struct ftdm_analog_data {
 	uint32_t digit_timeout;
 	uint32_t dial_timeout;
 	ftdm_bool_t answer_supervision;
+	ftdm_bool_t ringback_during_collect;
+	char ringback_file[512];
 };
 
 static void *ftdm_analog_em_run(ftdm_thread_t *me, void *obj);
diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c
index 598a8cd302..13160ca8e6 100644
--- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c
+++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c
@@ -33,6 +33,7 @@
  * Contributor(s):
  *
  * John Wehle (john@feith.com)
+ * Moises Silva (moy@sangoma.com)
  *
  */
 
@@ -43,6 +44,106 @@
 struct tm * localtime_r(const time_t *clock, struct tm *result);
 #endif
 
+/* check if the given file is a wave file and skip the header if it is */
+#define WAVE_CHUNK_ID "RIFF"
+#define WAVE_FMT "WAVEfmt "
+#define WAVE_HEADER_LEN 44
+static int skip_wave_header(const char *fname, FILE *f)
+{
+	char rbuff[10] = { 0 };
+	unsigned int hz = 0;
+	unsigned int hs = 0;
+	unsigned short fmt = 0;
+	unsigned short chans = 0;
+	unsigned int size = 0;
+
+	/* check chunk id */
+	if (fread(rbuff, 1, 4, f) != 4) {
+		ftdm_log(FTDM_LOG_ERROR, "Unable to read wav chunk id from file %s\n", fname);
+		goto error;
+	}
+	rbuff[4] = 0;
+
+	if (strncasecmp(rbuff, WAVE_CHUNK_ID, sizeof(WAVE_CHUNK_ID)-1)) {
+		goto notwave;
+	}
+
+	/* read chunk size */
+	if (fread(&size, 1, 4, f) != 4) {
+		ftdm_log(FTDM_LOG_ERROR, "Unable to read wav chunk size from file %s\n", fname);
+		goto error;
+	}
+
+	/* check format and sub chunk id */
+	if (fread(rbuff, 1, 8, f) != 8) {
+		ftdm_log(FTDM_LOG_ERROR, "Unable to read wav format and sub chunk id from file %s\n", fname);
+		goto error;
+	}
+	rbuff[8] = 0;
+
+	if (strncasecmp(rbuff, WAVE_FMT, sizeof(WAVE_FMT)-1)) {
+		goto notwave;
+	}
+
+	/* At this point we know is a wav file ... */
+
+	/* validate sub chunk size */
+	if (fread(&hs, 1, 4, f) != 4) {
+		ftdm_log(FTDM_LOG_ERROR, "Unable to read wav sub chunk size from file %s\n", fname);
+		goto error;
+	}
+
+	if (hs != 16) {
+		ftdm_log(FTDM_LOG_ERROR, "Unsupported wav sub chunk size %d from file %s\n", hs, fname);
+		goto error;
+	}
+
+	/* validate audio format */
+	if (fread(&fmt, 1, 2, f) != 2) {
+		ftdm_log(FTDM_LOG_ERROR, "Unable to read wav audio format from file %s\n", fname);
+		goto error;
+	}
+
+	if (fmt != 1) {
+		ftdm_log(FTDM_LOG_ERROR, "Unsupported wav audio format %d in file %s, we only support PCM\n", fmt, fname);
+		goto error;
+	}
+
+	/* validate channels */
+	if (fread(&chans, 1, 2, f) != 2) {
+		ftdm_log(FTDM_LOG_ERROR, "Unable to read wav channels from file %s\n", fname);
+		goto error;
+	}
+
+	if (chans != 1) {
+		ftdm_log(FTDM_LOG_ERROR, "Unsupported number of channels %d in file %s, we only support 1 (mono)\n", chans, fname);
+		goto error;
+	}
+
+	/* validate sampling rate */
+	if (fread(&hz, 1, 2, f) != 2) {
+		ftdm_log(FTDM_LOG_ERROR, "Unable to read wav sampling rate from file %s\n", fname);
+		goto error;
+	}
+
+	if (hz != 8000) {
+		ftdm_log(FTDM_LOG_ERROR, "Invalid input wav sampling rate %dHz, only 8000Hz supported\n", hz);
+		goto error;
+	}
+
+	ftdm_log(FTDM_LOG_DEBUG, "Found input file %s. PCM mono wav of %d bytes at %dHz, skipping header ...\n", fname, size, hz);
+	fseek(f, WAVE_HEADER_LEN, SEEK_SET);
+
+	return 0;
+
+notwave:
+	ftdm_log(FTDM_LOG_ERROR, "File %s is not a wav file\n", fname);
+	return -1;
+
+error:
+	return -1;
+}
+
 static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj);
 
 /**
@@ -82,6 +183,19 @@ static ftdm_status_t ftdm_analog_em_start(ftdm_span_t *span)
 	return ftdm_thread_create_detached(ftdm_analog_em_run, span);
 }
 
+/**
+ * \brief Stops EM span thread (monitor)
+ * \param span Span to monitor
+ * \return Success or failure
+ */
+static ftdm_status_t ftdm_analog_em_stop(ftdm_span_t *span)
+{
+	ftdm_analog_em_data_t *analog_data = span->signal_data;
+	ftdm_clear_flag(analog_data, FTDM_ANALOG_EM_RUNNING);
+	ftdm_sleep(100);
+	return FTDM_SUCCESS;
+}
+
 /**
  * \brief Returns the signalling status on a channel
  * \param ftdmchan Channel to get status on
@@ -120,8 +234,10 @@ static FIO_SPAN_GET_SIG_STATUS_FUNCTION(analog_em_get_span_sig_status)
 static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
 //ftdm_status_t ftdm_analog_em_configure_span(ftdm_span_t *span, char *tonemap, uint32_t digit_timeout, uint32_t max_dialstr, fio_signal_cb_t sig_cb)
 {
-	ftdm_analog_em_data_t *analog_data;
+	ftdm_analog_em_data_t *analog_data = NULL;
 	const char *tonemap = "us";
+	const char *ringback_file = "";
+	ftdm_bool_t ringback_during_collect = FTDM_FALSE;
 	uint32_t digit_timeout = 2000;
 	uint32_t max_dialstr = 11;
 	uint32_t dial_timeout = 0;
@@ -136,9 +252,8 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
 		return FTDM_FAIL;
 	}
 	
-	analog_data = ftdm_malloc(sizeof(*analog_data));
+	analog_data = ftdm_calloc(1, sizeof(*analog_data));
 	assert(analog_data != NULL);
-	memset(analog_data, 0, sizeof(*analog_data));
 
 	while((var = va_arg(ap, char *))) {
 		ftdm_log(FTDM_LOG_DEBUG, "Parsing analog em parameter '%s'\n", var);
@@ -147,6 +262,16 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
 				break;
 			}
 			tonemap = val;
+		} else if (!strcasecmp(var, "ringback_during_collect")) {
+			if (!(val = va_arg(ap, char *))) {
+				break;
+			}
+			ringback_during_collect = ftdm_true(val);
+		} else if (!strcasecmp(var, "ringback_file")) {
+			if (!(val = va_arg(ap, char *))) {
+				break;
+			}
+			ringback_file = val;
 		} else if (!strcasecmp(var, "answer_supervision")) {
 			if (!(val = va_arg(ap, char *))) {
 				break;
@@ -184,6 +309,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
 	}
 
 	span->start = ftdm_analog_em_start;
+	span->stop = ftdm_analog_em_stop;
 	analog_data->digit_timeout = digit_timeout;
 	analog_data->max_dialstr = max_dialstr;
 	analog_data->dial_timeout = dial_timeout;
@@ -195,6 +321,10 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
 	span->get_channel_sig_status = analog_em_get_channel_sig_status;
 	span->get_span_sig_status = analog_em_get_span_sig_status;
 	ftdm_span_load_tones(span, tonemap);
+	if (ringback_during_collect) {
+		analog_data->ringback_during_collect = FTDM_TRUE;
+		ftdm_set_string(analog_data->ringback_file, ringback_file);
+	}
 
 	return FTDM_SUCCESS;
 
@@ -241,6 +371,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
 	int cas_bits = 0;
 	uint32_t cas_answer = 0;
 	int cas_answer_ms = 500;
+	FILE *ringback_f = NULL;
 	ftdm_bool_t digits_sent = FTDM_FALSE;
 
 	ftdm_unused_arg(me);
@@ -283,6 +414,18 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
 	assert(interval != 0);
 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IO Interval: %u\n", interval);
 
+	if (analog_data->ringback_during_collect && !ftdm_strlen_zero(analog_data->ringback_file)) {
+		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Using ringback file '%s'\n", analog_data->ringback_file);
+		ringback_f = fopen(analog_data->ringback_file, "rb");
+		if (!ringback_f) {
+			ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to open ringback file '%s'\n", analog_data->ringback_file);
+		} else {
+			if (skip_wave_header(analog_data->ringback_file, ringback_f)) {
+				ringback_f = NULL;
+			}
+		}
+	}
+
 	while (ftdm_running() && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) {
 		ftdm_wait_flag_t flags = FTDM_READ;
 		ftdm_size_t dlen = 0;
@@ -515,7 +658,6 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
 			}
 		}
 
-
 		if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) > analog_data->max_dialstr))) {
 			ftdm_log(FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
 			ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
@@ -576,6 +718,14 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
 			ftdm_channel_write(ftdmchan, frame, sizeof(frame), &rlen);
 			continue;
 		}
+
+		if (analog_data->ringback_during_collect && ringback_f &&
+		    (ftdmchan->state == FTDM_CHANNEL_STATE_COLLECT ||
+		     ftdmchan->state == FTDM_CHANNEL_STATE_RING ||
+		     ftdmchan->state == FTDM_CHANNEL_STATE_RINGING
+		     )) {
+			indicate = 1;
+		}
 		
 		if (!indicate) {
 			continue;
@@ -585,7 +735,25 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
 			len *= 2;
 		}
 
-		rlen = ftdm_buffer_read_loop(dt_buffer, frame, len);
+		if (ringback_f) {
+			uint8_t failed_read = 0;
+read_try:
+			rlen = fread(frame, 1, len, ringback_f);
+			if (rlen != len) {
+				if (!feof(ringback_f)) {
+					ftdm_log(FTDM_LOG_ERROR, "Error reading from ringback file");
+				}
+				if (failed_read) {
+					continue;
+				}
+				/* return cursor to start of wav file */
+				fseek(ringback_f, WAVE_HEADER_LEN, SEEK_SET);
+				failed_read++;
+				goto read_try;
+			}
+		} else {
+			rlen = ftdm_buffer_read_loop(dt_buffer, frame, len);
+		}
 
 		if (ftdmchan->effective_codec != FTDM_CODEC_SLIN) {
 			fio_codec_t codec_func = NULL;
@@ -599,7 +767,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
 			if (codec_func) {
 				codec_func(frame, sizeof(frame), &rlen);
 			} else {
-				snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
+				ftdm_log(FTDM_LOG_ERROR, "codec error, no codec function for native codec %d!", ftdmchan->native_codec);
 				goto done;
 			}
 		}
@@ -624,6 +792,10 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
 		ftdm_buffer_destroy(&dt_buffer);
 	}
 
+	if (ringback_f) {
+		fclose(ringback_f);
+	}
+
 	ftdm_clear_flag(closed_chan, FTDM_CHANNEL_INTHREAD);
 
 	ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM CHANNEL thread ended.\n");