/*
Copyright (C) 2005-2007 Michel de Boer <michel@twinklephone.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <cassert>
#include <cstring>
#include <sys/time.h>
#include "dtmf_player.h"
#include "audio_rx.h"
#include "line.h"
#include "rtp_telephone_event.h"
#include "log.h"
/////////////////////////////////////////
// class t_dtmf_player
/////////////////////////////////////////
t_dtmf_player::t_dtmf_player(t_audio_rx *audio_rx, t_audio_encoder *audio_encoder,
t_user *user_config, uint8 dtmf_tone, uint32 dtmf_timestamp,
uint16 nsamples) :
_audio_rx(audio_rx),
_audio_encoder(audio_encoder),
_user_config(user_config),
_dtmf_current(dtmf_tone),
_dtmf_timestamp(dtmf_timestamp),
_nsamples(nsamples),
_dtmf_pause(false),
_dtmf_stop(false),
_dtmf_duration(0)
{}
uint32 t_dtmf_player::get_timestamp(void) {
return _dtmf_timestamp;
}
bool t_dtmf_player::finished(void) {
return _dtmf_stop;
}
/////////////////////////////////////////
// class t_rtp_event_dtmf_player
/////////////////////////////////////////
t_rtp_event_dtmf_player::t_rtp_event_dtmf_player(t_audio_rx *audio_rx,
t_audio_encoder *audio_encoder, t_user *user_config,
uint8 dtmf_tone, uint32 dtmf_timestamp,
uint16 nsamples) :
t_dtmf_player(audio_rx, audio_encoder, user_config, dtmf_tone, dtmf_timestamp,
nsamples)
{
}
uint16 t_rtp_event_dtmf_player::get_payload(uint8 *payload,
uint16 payload_size, uint32 timestamp, uint32 &rtp_timestamp)
{
t_rtp_telephone_event *dtmf_payload = (t_rtp_telephone_event *)payload;
assert(sizeof(t_rtp_telephone_event) <= payload_size);
// RFC 2833 3.5, 3.6
dtmf_payload->set_event(_dtmf_current);
dtmf_payload->set_reserved(false);
dtmf_payload->set_volume(_user_config->get_dtmf_volume());
if (_dtmf_pause) {
// Trailing pause phase of a DTMF tone
// Repeat the last packet
dtmf_payload->set_end(true);
int pause_duration = timestamp - _dtmf_timestamp - _dtmf_duration +
_nsamples;
if (pause_duration / _nsamples * _audio_encoder->get_ptime() >=
_user_config->get_dtmf_pause())
{
// This is the last packet to be sent for the
// current DTMF tone.
_dtmf_stop = true;
log_file->write_header("t_rtp_event_dtmf_player::get_payload",
LOG_NORMAL);
log_file->write_raw("Audio rx line ");
log_file->write_raw(_audio_rx->get_line()->get_line_number()+1);
log_file->write_raw(": finish DTMF event - ");
log_file->write_raw(_dtmf_current);
log_file->write_endl();
log_file->write_footer();
}
} else {
// Play phase of a DTMF tone
// The duration counts from the start of the tone.
_dtmf_duration = timestamp - _dtmf_timestamp + _nsamples;
// Check if the tone must end
if (_dtmf_duration / _nsamples * _audio_encoder->get_ptime() >=
_user_config->get_dtmf_duration())
{
dtmf_payload->set_end(true);
_dtmf_pause = true;
} else {
dtmf_payload->set_end(false);
}
}
dtmf_payload->set_duration(_dtmf_duration);
rtp_timestamp = _dtmf_timestamp;
return sizeof(t_rtp_telephone_event);
}
/////////////////////////////////////////
// class t_inband_dtmf_player
/////////////////////////////////////////
t_inband_dtmf_player::t_inband_dtmf_player(t_audio_rx *audio_rx,
t_audio_encoder *audio_encoder, t_user *user_config,
uint8 dtmf_tone, uint32 dtmf_timestamp,
uint16 nsamples) :
t_dtmf_player(audio_rx, audio_encoder, user_config, dtmf_tone, dtmf_timestamp,
nsamples),
_freq_gen(dtmf_tone, -(user_config->get_dtmf_volume()))
{
}
uint16 t_inband_dtmf_player::get_payload(uint8 *payload,
uint16 payload_size, uint32 timestamp, uint32 &rtp_timestamp)
{
int16 sample_buf[_nsamples];
if (_dtmf_pause) {
int pause_duration = timestamp - _dtmf_timestamp - _dtmf_duration +
_nsamples;
memset(sample_buf, 0, _nsamples * 2);
if (pause_duration / _nsamples * _audio_encoder->get_ptime() >=
_user_config->get_dtmf_pause())
{
// This is the last packet to be sent for the
// current DTMF tone.
_dtmf_stop = true;
log_file->write_header("t_inband_dtmf_player::get_payload", LOG_NORMAL);
log_file->write_raw("Audio rx line ");
log_file->write_raw(_audio_rx->get_line()->get_line_number()+1);
log_file->write_raw(": finish DTMF event - ");
log_file->write_raw(_dtmf_current);
log_file->write_endl();
log_file->write_footer();
}
} else {
// Timestamp and interval for _freq_gen must be in usec
uint32 ts_start = (timestamp - _dtmf_timestamp) * 1000000 /
_audio_encoder->get_sample_rate();
_freq_gen.get_samples(sample_buf, _nsamples, ts_start,
1000000.0 / _audio_encoder->get_sample_rate());
// The duration counts from the start of the tone.
_dtmf_duration = timestamp - _dtmf_timestamp + _nsamples;
// Check if the tone must end
if (_dtmf_duration / _nsamples * _audio_encoder->get_ptime() >=
_user_config->get_dtmf_duration())
{
_dtmf_pause = true;
}
}
// Encode audio samples
bool silence;
rtp_timestamp = timestamp;
return _audio_encoder->encode(sample_buf, _nsamples, payload, payload_size, silence);
}
syntax highlighted by Code2HTML, v. 0.9.1