~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Open Mash Cross Reference
mash/tgw/real_audio_enc.cc

Component: ~ [ mash ] ~ [ apps ] ~ [ gsm ] ~ [ lib ] ~ [ otcl ] ~ [ srm ] ~ [ tcl8.3 ] ~ [ tclcl ] ~ [ tk8.3 ] ~ [ tutorials ] ~

  1 /*
  2  * real_audio_enc.cc --
  3  *
  4  *      FIXME: This file needs a description here.
  5  *
  6  * Copyright (c) 1991-2002 The Regents of the University of California.
  7  * All rights reserved.
  8  *
  9  * Redistribution and use in source and binary forms, with or without
 10  * modification, are permitted provided that the following conditions are met:
 11  *
 12  * A. Redistributions of source code must retain the above copyright notice,
 13  *    this list of conditions and the following disclaimer.
 14  * B. Redistributions in binary form must reproduce the above copyright notice,
 15  *    this list of conditions and the following disclaimer in the documentation
 16  *    and/or other materials provided with the distribution.
 17  * C. Neither the names of the copyright holders nor the names of its
 18  *    contributors may be used to endorse or promote products derived from this
 19  *    software without specific prior written permission.
 20  *
 21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
 22  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 23  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
 25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 31  * POSSIBILITY OF SUCH DAMAGE.
 32  */
 33 
 34 /*
 35  * This is the Virtual Device abstraction to grab raw PCM from an audio stream.
 36  *
 37  */
 38 
 39 
 40 //#include <osfcn.h>
 41 #include <fcntl.h>
 42 #include "audio.h"
 43 #include "mulaw.h"
 44 #include "tclcl.h"
 45 #include "real_encoder.h"
 46 
 47 #define ULAW_ZERO 0x7f
 48 
 49 // and encoder that takes that PCM audio and gives it to a Real Networks
 50 // encoding engine.
 51 
 52 class RealAudioEnc : public Audio {
 53 public:
 54   RealAudioEnc();
 55   ~RealAudioEnc();
 56   virtual int FrameReady();
 57   virtual u_char* Read();
 58   virtual void Write(u_char *);
 59   virtual void SetRGain(int);
 60   virtual void SetPGain(int);
 61   virtual void OutputPort(int);
 62   virtual void InputPort(int);
 63   virtual void Obtain();
 64   virtual void Release();
 65   int command(int argc, const char*const* argv);
 66 protected:
 67   void WriteHelper(u_char *);
 68   int droppedPackets;
 69   int interval;
 70   int intervalPos;
 71   
 72   RealWindow* encoder;
 73   int bufferSize;
 74   u_char* dummyReadBuf;
 75   u_short* WriteBuf0;
 76   u_short* WriteBuf1;
 77   ULONG32 TimeCode;
 78   int currentBuf;
 79   int bufferPosition;
 80   int timerFlag;
 81   int secondReadFlag;
 82 };
 83 
 84 static class RealAudioEncClass : public TclClass {
 85 public:
 86         RealAudioEncClass() : TclClass("Audio/RealAudioVirtualDevice") {}
 87         TclObject* create(int, const char*const*) {
 88             return (new RealAudioEnc);
 89         }
 90 } real_audio_enc_class;
 91 
 92 int RealAudioEnc::command(int argc, const char*const* argv) {
 93   int howOften = 1000; // in milliseconds
 94   int temp;
 95 
 96   if (argc == 2) {
 97     Tcl& tcl = Tcl::instance();
 98     if (strcmp(argv[1], "start_output") == 0) {
 99       tcl.evalf("after %d %s start_output", howOften, name());
100       temp = ((50*howOften)/1000); // this is the number of blocks per interval.
101 
102       if (droppedPackets <= 0)
103         interval = temp*2; // big so that it doesn't inject a blank when not needed.
104       else if (droppedPackets > 16) {
105         while (droppedPackets > 5) {
106           Write(dummyReadBuf);
107           secondReadFlag = 0;
108           //      printf("blank audio here\n");
109         }
110         interval = temp/droppedPackets;
111       } else
112         interval = temp/droppedPackets;
113 
114       intervalPos = 0;
115       droppedPackets = droppedPackets + temp;
116       return (TCL_OK);
117     } else if (strcmp(argv[1], "grab_audio") == 0) {
118       tcl.evalf("after %d %s grab_audio", 10, name());
119       timerFlag = 1;
120       return (TCL_OK);
121     } else if (strcmp(argv[1], "stop_output") == 0) {
122       encoder = 0;
123       return (TCL_OK);
124     }
125   } 
126   if (argc == 3) {
127     if (strcmp(argv[1], "linkEncoder") == 0) {
128       encoder = (RealWindow*)TclObject::lookup(argv[2]);
129       return (TCL_OK);
130     }
131   }
132   return Audio::command(argc,argv);
133 }
134 
135 RealAudioEnc::RealAudioEnc() : droppedPackets(0), interval(100), intervalPos(0), encoder(0), bufferSize(0), TimeCode(0), currentBuf(0), bufferPosition(0), timerFlag(0), secondReadFlag(0) {
136     /*
137      * The only way to determine if the device is full duplex
138      * or not is by actually opening it.  Unfortunately, we might
139      * not be able to open it because some other process is
140      * using it.  Assume half-duplex.  Obtain() will override
141      * if appropriate.
142      */
143   duplex_ = 0;
144 
145   dummyReadBuf = new u_char[blksize_];
146 
147   memset(dummyReadBuf, ULAW_ZERO, blksize_);
148 
149   input_names_ = "mike";
150   output_names_ = "speaker";
151 }
152 
153 RealAudioEnc::~RealAudioEnc() {
154   Tcl& tcl = Tcl::instance();
155   tcl.evalf("after cancel %s start_output", name());  
156   delete dummyReadBuf;
157 }
158 
159 void RealAudioEnc::Obtain() {
160   //  printf("Obtain is called\n");
161       
162   Tcl& tcl = Tcl::instance();
163   tcl.evalf("after %d %s start_output", 100, name());
164   
165   if (haveaudio())
166     abort();
167 
168   if (duplex_ == 0) {
169     fd_ = 9;
170     notify();
171   } else {
172     // this is a hack, this should never happen. 
173     fd_ = open("/dev/audio", O_RDWR );    
174     Audio::Obtain();
175     tcl.evalf("after %d %s grab_audio", 1000, name());
176   }
177 }
178 
179 
180 void RealAudioEnc::Release() {
181   //  printf("called release\n");
182   if (haveaudio()) {
183       notify();
184   }
185 }
186 
187 // write data to the encoder (encode data and send to server)
188 void RealAudioEnc::Write(u_char *cp) {
189   //printf("got a packet to the virtual device, num is: %d!\n", (int)cp[0]);
190   u_char cp2[blksize_];
191   u_int i, j;
192   
193   if (secondReadFlag)
194     return;
195   else
196     secondReadFlag = 1;
197   
198   if (encoder == 0)
199     return;
200 
201   if (bufferSize == 0) {
202     // this only happens at the start, to initialize the encoder.
203     bufferSize = encoder->SuggestAudioBufferSize();
204     bufferSize = (bufferSize - (bufferSize % (blksize_*2)))/2;
205     if (bufferSize == 0) {
206       encoder->setup_encoder();
207       return;
208     }
209     WriteBuf0 = new u_short[bufferSize];
210     WriteBuf1 = new u_short[bufferSize];
211   }
212 
213   if (intervalPos >= interval) {
214     // we need to elongate samples to fill in for lost data...
215     // shouldn't happen often.
216     //    printf("making up, interval is: %d, position is: %d\n", interval, intervalPos);
217     intervalPos = 0;
218     j = blksize_/2;
219     for (i=0; i< j; i++) {
220       cp2[(2*i)] = cp[i];
221       cp2[(2*i)+1] = cp[i];
222     }      
223     for (i=0; j< blksize_; j++,i+=2) {
224       cp[i] = cp[j];
225       cp[i+1] = cp[j];
226     }
227     WriteHelper(cp2);
228   }
229   WriteHelper(cp);
230   intervalPos++;
231 }
232 
233 // this is the function that actually writes the data to the Real engine.
234 void RealAudioEnc::WriteHelper(u_char* cp){
235   u_short* writeBuf;
236   
237   droppedPackets--;
238 
239   if (currentBuf == 0)
240     writeBuf = WriteBuf0;
241   else
242     writeBuf = WriteBuf1;
243 
244   if (bufferPosition == 0)
245     TimeCode = GetTime();
246   
247   for (u_int i=0; i< blksize_; i++)
248     writeBuf[i+bufferPosition] = mulawtolin[cp[i]] ;
249 
250   bufferPosition += blksize_;
251 
252   if (bufferPosition == bufferSize) {
253     currentBuf = (currentBuf+1)%2;
254     bufferPosition = 0;
255     encoder->encodeAudio(writeBuf, (2*bufferSize), TimeCode);
256   }
257 }
258 
259 u_char* RealAudioEnc::Read() {
260   //  printf("Read was called\n");
261   secondReadFlag = 0;
262   return dummyReadBuf;
263 }
264 
265 void RealAudioEnc::SetRGain(int level)
266 {    
267   //  printf("setRgain() called\n");
268 }
269 
270 void RealAudioEnc::SetPGain(int level)
271 {
272   //  printf("SetPgain() called\n");
273 }
274 
275 void RealAudioEnc::OutputPort(int p)
276 {
277   
278   printf("outputPort() called\n");
279   oport_ = p;
280 }
281 
282 void RealAudioEnc::InputPort(int p)
283 {
284   printf("inputPort() called for %d\n",p);
285 }
286 
287 /*
288  * FrameReady must return 0 every so often, or the system will keep
289  * processing mike data and not other events.
290  *
291  * This should never get called because we are not going in duplex mode.
292  */
293 int RealAudioEnc::FrameReady() {
294   printf("in FrameReady\n");
295   if (timerFlag == 1) {
296     timerFlag = 0;
297     return 1;
298   }
299   return 0;
300 }
301 
302 /*** end of file ***/
303 
304 
305 
306 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.