1 /*
2  * Copyright (C) 2002-2003 Fhg Fokus
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 "AmAdvancedAudio.h"
29 
30 #include <set>
31 using std::set;
32 
33 #include "math.h"
34 
35 /* AudioQueue */
AmAudioQueue()36 AmAudioQueue::AmAudioQueue()
37   : AmAudio(new AmAudioFormat(CODEC_PCM16)), // we get and put in this (internal) fmt
38     owning(true)
39 {
40 }
41 
~AmAudioQueue()42 AmAudioQueue::~AmAudioQueue() {
43   if (owning) {
44     set<AmAudio*> deleted_audios; // don't delete them twice
45     for (std::list<AudioQueueEntry>::iterator it = inputQueue.begin();it != inputQueue.end(); it++) {
46       if (deleted_audios.find(it->audio) == deleted_audios.end()) {
47 	deleted_audios.insert(it->audio);
48 	delete it->audio;
49       }
50     }
51 
52     for (std::list<AudioQueueEntry>::iterator it = outputQueue.begin();it != outputQueue.end(); it++) {
53       if (deleted_audios.find(it->audio) == deleted_audios.end()) {
54 	deleted_audios.insert(it->audio);
55 	delete it->audio;
56       }
57     }
58   }
59 }
60 
setOwning(bool _owning)61 void AmAudioQueue::setOwning(bool _owning) {
62   owning = _owning;
63 }
64 
put(unsigned long long system_ts,unsigned char * buffer,int input_sample_rate,unsigned int size)65 int AmAudioQueue::put(unsigned long long system_ts, unsigned char* buffer,
66 		      int input_sample_rate, unsigned int size)
67 {
68    inputQueue_mut.lock();
69    int size_trav = (int)size;
70    for (std::list<AudioQueueEntry>::iterator it = inputQueue.begin();
71 	it != inputQueue.end(); it++) {
72      if (it->audio == NULL)
73        continue;
74      if (it->put) {
75        size_trav = it->audio->put(system_ts, buffer,
76 				  input_sample_rate, size_trav);
77        if (size_trav < 0)
78 	 break;
79      }
80      if (it->get) {
81        input_sample_rate = it->audio->getSampleRate();
82        size_trav = it->audio->get(system_ts, buffer,
83 				  input_sample_rate, size_trav>>1);
84        if (size_trav < 0)
85 	 break;
86      }
87    }
88    inputQueue_mut.unlock();
89    return size_trav;
90 }
91 
get(unsigned long long system_ts,unsigned char * buffer,int output_sample_rate,unsigned int nb_samples)92 int AmAudioQueue::get(unsigned long long system_ts, unsigned char* buffer,
93 		      int output_sample_rate, unsigned int nb_samples)
94 {
95   outputQueue_mut.lock();
96   int size_trav = (int)(nb_samples << 1);
97   for (std::list<AudioQueueEntry>::iterator it = outputQueue.begin();
98        it != outputQueue.end(); it++) {
99     if (it->audio == NULL)
100       continue;
101     if (it->put) {
102       size_trav = it->audio->put(system_ts, samples,
103 				 output_sample_rate, size_trav);
104       if (size_trav < 0)
105 	break;
106     }
107     if (it->get) {
108       output_sample_rate = it->audio->getSampleRate();
109       size_trav = it->audio->get(system_ts, samples,
110 				 output_sample_rate, size_trav>>1);
111       if (size_trav < 0)
112 	break;
113     }
114   }
115   outputQueue_mut.unlock();
116   return size_trav;
117 }
118 
pushAudio(AmAudio * audio,QueueType type,Pos pos,bool write,bool read)119 void AmAudioQueue::pushAudio(AmAudio* audio, QueueType type, Pos pos, bool write, bool read) {
120   AmMutex* q_mut;
121   std::list<AudioQueueEntry>* q;
122   switch (type) {
123   case OutputQueue:
124     q_mut = &outputQueue_mut;
125     q = &outputQueue;
126     break;
127   case InputQueue:
128   default:  q_mut = &inputQueue_mut;
129     q = &inputQueue;
130     break;
131   };
132   q_mut->lock();
133   if (pos == Front)
134     q->push_front(AudioQueueEntry(audio, write, read));
135   else
136     q->push_back(AudioQueueEntry(audio, write, read));
137   q_mut->unlock();
138 }
139 
popAudio(QueueType type,Pos pos)140 int AmAudioQueue::popAudio(QueueType type, Pos pos) {
141   AmAudio* audio = popAndGetAudio(type, pos);
142   if (audio) {
143     delete audio;
144     return 0;
145   }
146   return -1; // error
147 }
148 
popAndGetAudio(QueueType type,Pos pos)149 AmAudio* AmAudioQueue::popAndGetAudio(QueueType type, Pos pos) {
150   AmMutex* q_mut;
151   std::list<AudioQueueEntry>* q;
152   switch (type) {
153   case OutputQueue:
154     q_mut = &outputQueue_mut;
155     q = &outputQueue;
156     break;
157   case InputQueue:
158   default:  q_mut = &inputQueue_mut;
159     q = &inputQueue;
160     break;
161   };
162   q_mut->lock();
163   if (q->empty()) {
164     q_mut->unlock();
165     return 0;
166   }
167 
168   AmAudio* audio;
169   if (pos == Front) {
170     audio = q->front().audio;
171     q->pop_front();
172   }  else {
173     audio = q->back().audio;
174     q->pop_back();
175   }
176   q_mut->unlock();
177   return audio;
178 }
179 
removeAudio(AmAudio * audio)180 int AmAudioQueue::removeAudio(AmAudio* audio) {
181   bool found = false;
182   outputQueue_mut.lock();
183   for (std::list<AudioQueueEntry>::iterator it = outputQueue.begin();
184        it != outputQueue.end(); it++) {
185     if (it->audio == audio) {
186       found = true;
187       outputQueue.erase(it);
188       break;
189     }
190 
191   }
192   outputQueue_mut.unlock();
193   if (found)
194     return 0;
195   inputQueue_mut.lock();
196   for (std::list<AudioQueueEntry>::iterator it = inputQueue.begin();
197        it != inputQueue.end(); it++) {
198     if (it->audio == audio) {
199       found = true;
200       inputQueue.erase(it);
201       break;
202     }
203 
204   }
205   inputQueue_mut.unlock();
206   if (found)
207     return 0;
208   else {
209     ERROR("could not find audio in queue\n");
210     return -1; // error
211   }
212 }
213 
214 
215 /* AudioBridge */
AmAudioBridge(unsigned int sample_rate)216 AmAudioBridge::AmAudioBridge(unsigned int sample_rate)
217   : AmAudio(new AmAudioFormat(CODEC_PCM16,sample_rate))
218 {
219   sarr.clear_all();
220 }
221 
~AmAudioBridge()222 AmAudioBridge::~AmAudioBridge() {
223 }
224 
write(unsigned int user_ts,unsigned int size)225 int AmAudioBridge::write(unsigned int user_ts, unsigned int size) {
226   sarr.write(user_ts, (short*) ((unsigned char*) samples), size >> 1);
227   return size;
228 }
229 
read(unsigned int user_ts,unsigned int size)230 int AmAudioBridge::read(unsigned int user_ts, unsigned int size) {
231   sarr.read(user_ts, (short*) ((unsigned char*) samples), size >> 1);
232   return size;
233 }
234 
235 /* AudioDelay */
AmAudioDelay(float delay_sec,unsigned int sample_rate)236 AmAudioDelay::AmAudioDelay(float delay_sec, unsigned int sample_rate)
237   : AmAudio(new AmAudioFormat(CODEC_PCM16,sample_rate))
238 {
239   sarr.clear_all();
240   delay = delay_sec;
241 }
242 
~AmAudioDelay()243 AmAudioDelay::~AmAudioDelay() {
244 }
245 
write(unsigned int user_ts,unsigned int size)246 int AmAudioDelay::write(unsigned int user_ts, unsigned int size) {
247   sarr.write(user_ts,(short*) ((unsigned char*) samples), size >> 1);
248   return size;
249 }
250 
read(unsigned int user_ts,unsigned int size)251 int AmAudioDelay::read(unsigned int user_ts, unsigned int size) {
252   sarr.read((unsigned int) (user_ts  - delay*(float)getSampleRate()),
253 	    (short*) ((unsigned char*) samples), size >> 1);
254   return size;
255 }
256 
AmAudioFrontlist(AmEventQueue * q)257 AmAudioFrontlist::AmAudioFrontlist(AmEventQueue* q)
258   : AmPlaylist(q), back_audio(NULL)
259 {
260 }
261 
AmAudioFrontlist(AmEventQueue * q,AmAudio * back_audio)262 AmAudioFrontlist::AmAudioFrontlist(AmEventQueue* q, AmAudio* back_audio)
263   : AmPlaylist(q), back_audio(back_audio)
264 {
265 }
266 
~AmAudioFrontlist()267 AmAudioFrontlist::~AmAudioFrontlist() {
268 //   ba_mut.lock();
269 //   if (back_audio)
270 //     back_audio->close();
271 //   ba_mut.unlock();
272 }
273 
setBackAudio(AmAudio * new_ba)274 void AmAudioFrontlist::setBackAudio(AmAudio* new_ba) {
275   ba_mut.lock();
276   back_audio = new_ba;
277   ba_mut.unlock();
278 }
279 
put(unsigned long long system_ts,unsigned char * buffer,int input_sample_rate,unsigned int size)280 int AmAudioFrontlist::put(unsigned long long system_ts, unsigned char* buffer,
281 			  int input_sample_rate, unsigned int size) {
282 
283   // stay consistent with Playlist - if empty return size
284   int res = size;
285   ba_mut.lock();
286 
287   if (isEmpty()) {
288     if (back_audio)
289       res = back_audio->put(system_ts, buffer, input_sample_rate, size);
290   } else {
291     res = AmPlaylist::put(system_ts, buffer, input_sample_rate, size);
292   }
293 
294   ba_mut.unlock();
295   return res;
296 }
297 
get(unsigned long long system_ts,unsigned char * buffer,int output_sample_rate,unsigned int nb_samples)298 int AmAudioFrontlist::get(unsigned long long system_ts, unsigned char* buffer,
299 			  int output_sample_rate, unsigned int nb_samples) {
300 
301   // stay consistent with Playlist - if empty return size
302   int res = nb_samples;
303 
304   ba_mut.lock();
305   if (isEmpty() && back_audio) {
306       res = back_audio->get(system_ts, buffer, output_sample_rate, nb_samples);
307   } else {
308     res = AmPlaylist::get(system_ts, buffer, output_sample_rate, nb_samples);
309   }
310   ba_mut.unlock();
311   return res;
312 }
313 
314 
put(unsigned long long system_ts,unsigned char * buffer,int output_sample_rate,unsigned int size)315 int AmNullAudio::put(unsigned long long system_ts, unsigned char* buffer,
316 		     int output_sample_rate, unsigned int size)
317 {
318   // need to stop at some point?
319   if (write_msec < 0)
320     return size;
321 
322   if (!write_end_ts_i) {
323     write_end_ts_i = true;
324     write_end_ts = system_ts + (write_msec*WALLCLOCK_RATE)/1000;
325   }
326 
327   if (!sys_ts_less()(system_ts, write_end_ts)) {
328     DBG("%dms of silence ended (write)\n", write_msec);
329     return -1;
330   }
331 
332   return size;
333 }
334 
get(unsigned long long system_ts,unsigned char * buffer,int output_sample_rate,unsigned int nb_samples)335 int AmNullAudio::get(unsigned long long system_ts, unsigned char* buffer,
336 		     int output_sample_rate, unsigned int nb_samples)
337 {
338   int size = (int)(nb_samples << 1);
339 
340   // need to stop at some point?
341   if (read_msec < 0) {
342     memset((unsigned char*) samples, 0, size);
343     return size;
344   }
345 
346   if (!read_end_ts_i) {
347     read_end_ts_i = true;
348     read_end_ts = system_ts + (read_msec*WALLCLOCK_RATE)/1000;
349   }
350 
351   if (!sys_ts_less()(system_ts, read_end_ts)) {
352     DBG("%dms of silence ended (read)\n", read_msec);
353     return -1;
354   }
355 
356   memset((unsigned char*) samples, 0, size);
357   return size;
358 }
359 
setReadLength(int n_msec)360 void AmNullAudio::setReadLength(int n_msec) {
361   read_msec = n_msec;
362   read_end_ts_i = false;
363 }
364 
setWriteLength(int n_msec)365 void AmNullAudio::setWriteLength(int n_msec) {
366   write_msec = n_msec;
367   write_end_ts_i = false;
368 }
369 
370