1 /* 2 * Copyright (C) 2008 IPTEGO GmbH 3 * 4 * This file is part of SEMS, a free SIP media server. 5 * 6 * SEMS is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. This program is released under 10 * the GPL with the additional exemption that compiling, linking, 11 * and/or using OpenSSL is allowed. 12 * 13 * For a license to use the sems software under conditions 14 * other than those described here, or to purchase support for this 15 * software, please contact iptel.org by e-mail at the following addresses: 16 * info@iptel.org 17 * 18 * SEMS is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26 */ 27 28 #include "AmAudioMixer.h" 29 30 AmAudioMixer::AmAudioMixer(int external_sample_rate) { 31 sink_channel = mixer.addChannel(external_sample_rate); 32 sink_connector = 33 new AmAudioMixerConnector(mixer, sink_channel, NULL, 34 &srcsink_mut, &sinks); 35 } 36 37 AmAudioMixer::~AmAudioMixer() { 38 mixer.removeChannel(sink_channel); 39 for (std::map<AmAudioMixerConnector*, unsigned int>::iterator 40 it=sources.begin(); it != sources.end(); it++) { 41 mixer.removeChannel(it->second); 42 delete it->first; 43 } 44 delete sink_connector; 45 } 46 47 AmAudio* AmAudioMixer::addSource(int external_sample_rate) { 48 srcsink_mut.lock(); 49 unsigned int src_channel = mixer.addChannel(external_sample_rate); 50 // the first source will process the media in the mixer channel 51 AmAudioMixerConnector* conn = 52 new AmAudioMixerConnector(mixer, src_channel, 53 sources.empty() ? sink_connector : NULL); 54 sources[conn] = src_channel; 55 srcsink_mut.unlock(); 56 return conn; 57 } 58 59 void AmAudioMixer::releaseSource(AmAudio* s) { 60 srcsink_mut.lock(); 61 std::map<AmAudioMixerConnector*, unsigned int>::iterator it= 62 sources.find((AmAudioMixerConnector*)s); 63 if (it==sources.end()) { 64 srcsink_mut.unlock(); 65 ERROR("source [%p] is not part of this mixer.\n", s); 66 return; 67 } 68 mixer.removeChannel(it->second); 69 delete s; 70 sources.erase(it); 71 srcsink_mut.unlock(); 72 } 73 74 void AmAudioMixer::addSink(AmAudio* s) { 75 srcsink_mut.lock(); 76 sinks.insert(s); 77 srcsink_mut.unlock(); 78 } 79 80 void AmAudioMixer::releaseSink(AmAudio* s) { 81 srcsink_mut.lock(); 82 sinks.erase(s); 83 srcsink_mut.unlock(); 84 } 85 86 int AmAudioMixerConnector::get(unsigned long long system_ts, 87 unsigned char* buffer, 88 int output_sample_rate, 89 unsigned int nb_samples) 90 { 91 // in fact GCP here only needed for the mixed channel 92 unsigned int mixer_sample_rate; 93 mixer.GetChannelPacket(channel, system_ts, buffer, 94 nb_samples, mixer_sample_rate); 95 96 if ((audio_mut != NULL) && (sinks != NULL)) { 97 audio_mut->lock(); 98 // write to all sinks 99 for (std::set<AmAudio*>::iterator it=sinks->begin(); 100 it != sinks->end(); it++) { 101 (*it)->put(system_ts, buffer, output_sample_rate, nb_samples); 102 } 103 audio_mut->unlock(); 104 } 105 106 return nb_samples; 107 } 108 109 int AmAudioMixerConnector::put(unsigned long long system_ts, 110 unsigned char* buffer, 111 int input_sample_rate, 112 unsigned int size) 113 { 114 mixer.PutChannelPacket(channel, system_ts, buffer, size); 115 116 if (mix_channel != NULL) { 117 // we are processing the media of the mixed channel as well 118 ShortSample mix_buffer[SIZE_MIX_BUFFER]; 119 mix_channel->get(system_ts, (unsigned char*)mix_buffer, 120 input_sample_rate, size); 121 } 122 return size; 123 } 124