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