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 /** @file AmAdvancedAudio.h */
28 
29 #ifndef _AmAdvancedAudio_h_
30 #define _AmAdvancedAudio_h_
31 
32 #include "AmAudio.h"
33 #include "AmPlaylist.h"
34 
35 #include "AmThread.h"
36 #include "amci/codecs.h"
37 
38 #include <list>
39 #include "SampleArray.h"
40 
41 /**
42  * \brief Entry in an AudioQueue
43  */
44 struct AudioQueueEntry {
45   AmAudio* audio;
46   bool put;
47   bool get;
AudioQueueEntryAudioQueueEntry48   AudioQueueEntry(AmAudio* _audio, bool _put, bool _get)
49     : audio(_audio), put(_put), get(_get) { }
50 };
51 
52 /**
53  * \brief Holds AmAudios and reads/writes through all
54  *
55  * AmAudioQueue can hold AmAudios in input and output queue.
56  * Audio will be read through the whole output queue,
57  * and written through the whole input queue.
58  */
59 
60 class AmAudioQueue : public AmAudio
61 {
62 
63   AmMutex inputQueue_mut;
64   std::list<AudioQueueEntry> inputQueue;
65   AmMutex outputQueue_mut;
66   std::list<AudioQueueEntry> outputQueue;
67 
68   bool owning;
69 
70 public:
71   AmAudioQueue();
72   ~AmAudioQueue();
73 
74   enum QueueType { OutputQueue, InputQueue };
75   enum Pos { Front, Back };
76 
77   /** add an audio to a queue */
78   void pushAudio(AmAudio* audio, QueueType type, Pos pos, bool write, bool read);
79   /** pop an audio from queue and delete it @return 0 on success, -1 on failure */
80   int popAudio(QueueType type, Pos pos);
81   /** pop an audio from queue @return pointer to the audio */
82   AmAudio* popAndGetAudio(QueueType type, Pos pos);
83   /** this removes the audio if it is in on of the queues and does not
84       delete them */
85   int removeAudio(AmAudio* audio);
86   void setOwning(bool _owning);
87 
88   /** AmAudio interface */
89   int get(unsigned long long system_ts, unsigned char* buffer,
90 	  int output_sample_rate, unsigned int nb_samples);
91   int put(unsigned long long system_ts, unsigned char* buffer,
92 	  int input_sample_rate, unsigned int size);
93 
94 protected:
95   /** Fake implementation to satifsy AmAudio */
write(unsigned int user_ts,unsigned int size)96   int write(unsigned int user_ts, unsigned int size) { return 0; }
read(unsigned int user_ts,unsigned int size)97   int read(unsigned int user_ts, unsigned int size) { return 0; }
98 };
99 
100 /**
101  * \brief AmAudio device with a playlist and a background AmAudio
102  *
103  * AmAudioFrontlist is an AmAudio device, that has a playlist
104  * in front of a AmAudio entry, the 'back' device. The back device
105  * is only used if the playlist is empty. - This can be useful when
106  * for example announcements should be played to the participant
107  * while in a conference.
108  *
109  */
110 class AmAudioFrontlist : public AmPlaylist
111 {
112   AmMutex ba_mut;
113   AmAudio* back_audio;
114 
115 public:
116   AmAudioFrontlist(AmEventQueue* q);
117   AmAudioFrontlist(AmEventQueue* q, AmAudio* back_audio);
118   ~AmAudioFrontlist();
119 
120   void setBackAudio(AmAudio* new_ba);
121 
122   int put(unsigned long long system_ts, unsigned char* buffer,
123 	  int input_sample_rate, unsigned int size);
124 
125   int get(unsigned long long user_ts, unsigned char* buffer,
126 	  int output_sample_rate, unsigned int size);
127 };
128 
129 
130 /**
131  * \brief \ref AmAudio that directly connects input and output
132  *
133  *  AmAudioBridge simply connects input and output
134  *  This is useful e.g. at the end of a AudioQueue
135  */
136 class AmAudioBridge : public AmAudio
137 {
138   SampleArrayShort sarr;
139 
140 public:
141   AmAudioBridge(unsigned int sample_rate = SYSTEM_SAMPLECLOCK_RATE);
142   ~AmAudioBridge();
143 
144   int write(unsigned int user_ts, unsigned int size);
145   int read(unsigned int user_ts, unsigned int size);
146 };
147 
148 /**
149  * \brief \ref AmAudio that delays output from input
150  * delays delay_sec seconds (up to ~2)
151  */
152 class AmAudioDelay : public AmAudio
153 {
154   SampleArrayShort sarr;
155   float delay;
156 
157 public:
158   AmAudioDelay(float delay_sec = 0.0,
159 	       unsigned int sample_rate = SYSTEM_SAMPLECLOCK_RATE);
160   ~AmAudioDelay();
161 
setDelay(float delay)162   void setDelay(float delay) { this->delay = delay; }
163 
164   int write(unsigned int user_ts, unsigned int size);
165   int read(unsigned int user_ts, unsigned int size);
166 };
167 
168 /**
169  * AmNullAudio plays silence, and recording goes to void.
170  * it can be parametrized with a maximum length (in milliseconds),
171  * after which it is ended.
172  * Read and write length can also be set after creation (and possibly even
173  * when in use).
174  */
175 class AmNullAudio : public AmAudio
176 {
177   int read_msec;
178   int write_msec;
179 
180   bool read_end_ts_i;
181   unsigned long long read_end_ts;
182 
183   bool write_end_ts_i;
184   unsigned long long write_end_ts;
185 
186 public:
187   AmNullAudio(int read_msec = -1, int write_msec = -1)
read_msec(read_msec)188     : read_msec(read_msec), write_msec(write_msec),
189     read_end_ts_i(false), write_end_ts_i(false) { }
~AmNullAudio()190   ~AmNullAudio() { }
191 
192   /** (re) set maximum read length*/
193   void setReadLength(int n_msec);
194   /** (re) set maximum write length*/
195   void setWriteLength(int n_msec);
196 
197   /** AmAudio interface */
198   int get(unsigned long long system_ts, unsigned char* buffer,
199 	  int output_sample_rate, unsigned int nb_samples);
200   int put(unsigned long long system_ts, unsigned char* buffer,
201 	  int input_sample_rate, unsigned int size);
202 
203 protected:
204   /** Fake implementation to satifsy AmAudio */
write(unsigned int user_ts,unsigned int size)205   int write(unsigned int user_ts, unsigned int size) { return 0; }
read(unsigned int user_ts,unsigned int size)206   int read(unsigned int user_ts, unsigned int size) { return 0; }
207 };
208 
209 #endif // _AmAdvancedAudio_h_
210 
211