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

Open Mash Cross Reference
mash/audio/audio-sgi.cc

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

  1 /*
  2  * audio-sgi.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 static const char rcsid[] =
 35     "@(#) $Header: /usr/mash/src/repository/mash/mash-1/audio/audio-sgi.cc,v 1.9 2002/02/03 03:10:46 lim Exp $";
 36 
 37 #include "config.h"
 38 #define _BSD_COMPAT 1
 39 #include "tclcl.h"
 40 
 41 /*
 42  * We have AF/audio.h, ./audio.h and /usr/include/audio.h.  Crimony.
 43  */
 44 #include </usr/include/audio.h>
 45 #include "audio.h"
 46 
 47 class SGIAudio : public Audio {
 48     public:
 49         SGIAudio();
 50         virtual int FrameReady();
 51         virtual u_char* Read();
 52         virtual void Write(u_char *);
 53         virtual void SetRGain(int);
 54         virtual void SetPGain(int);
 55         virtual void InputPort(int);
 56         virtual void Obtain();
 57         virtual void Release();
 58     protected:
 59         int GainClip(int);
 60 
 61         u_int lastsamp_;
 62         u_int lastout_;
 63         u_char* buf_;
 64         ALport in;
 65         ALport out;
 66         ALconfig conf;
 67 };
 68 
 69 
 70 extern const u_char lintomulawX[];
 71 extern const short mulawtolin[];
 72 
 73 
 74 #define AUDIO_MIN_GAIN 0
 75 #define AUDIO_MAX_GAIN 255
 76 
 77 static class SGIAudioClass : public TclClass {
 78 public:
 79         SGIAudioClass() : TclClass("Audio/SGI") {}
 80         TclObject* create(int argc, const char*const* argv) {
 81                 return (new SGIAudio);
 82         }
 83 } sgiaudio_class;
 84 
 85 SGIAudio::SGIAudio()
 86 {
 87         /* open (or create) the lock file */
 88         openlock();
 89         conf = ALnewconfig();
 90         ALsetwidth(conf, AL_SAMPLE_16);
 91         ALsetqueuesize(conf, 8000);
 92         ALsetchannels(conf, AL_MONO);
 93         fd_ = -1;
 94         lastout_ = 0;
 95         lastsamp_ = 0;
 96         buf_ = new u_char[blksize_];
 97 
 98         input_names_ = "mike linein";
 99         output_names_ = "speaker";
100 }
101 
102 void SGIAudio::Release()
103 {
104         if (haveaudio()) {
105                 unlock();
106                 unlink();
107                 fd_ = -1;
108                 ALcloseport(in);
109                 ALcloseport(out);
110                 notify();
111         }
112 }
113 
114 void SGIAudio::Obtain()
115 {
116         if (haveaudio())
117                 abort();
118 
119         if (lock() == 0) {
120                 out = ALopenport("vatOut", "w", conf);
121                 if (out == NULL) {
122                         fprintf(stderr,
123                                 "vat: couldn't open AL output port.\n");
124                         return;
125                 }
126                 in = ALopenport("vatIn", "r", conf);
127                 if (in == NULL) {
128                         fprintf(stderr,
129                                 "vat: couldn't open AL input port.\n");
130                         return;
131                 }
132                 ALsetfillpoint(in, 160);
133                 long pvbuf[6];
134                 pvbuf[0] = AL_INPUT_RATE;
135                 pvbuf[1] = 8000;
136                 pvbuf[2] = AL_OUTPUT_RATE;
137                 pvbuf[3] = 8000;
138                 pvbuf[4] = AL_INPUT_SOURCE;
139                 pvbuf[5] = iport_? AL_INPUT_LINE : AL_INPUT_MIC;
140                 ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 6);
141                 fd_ = ALgetfd(in);
142                 SetRGain(rgain_);
143                 SetPGain(pgain_);
144                 Audio::Obtain();
145         }
146 }
147 
148 void SGIAudio::Write(u_char *cp)
149 {
150         register int len = blksize_;
151         u_int samps[MAXAUDIOSIZE/2];
152         register u_int* sp = samps;
153         register u_int* ep = sp + len / 2;
154         register const u_short* u2l = (u_short*)mulawtolin;
155         register u_int* ip = (u_int*)cp;
156         for ( ; sp < ep; sp += 4) {
157                 register u_int s = *ip++;
158                 sp[0] = (u2l[(s >> 24) & 0xff] << 16) | u2l[(s >> 16) & 0xff];
159                 sp[1] = (u2l[(s >> 8) & 0xff] << 16) | u2l[s & 0xff];
160                 s = *ip++;
161                 sp[2] = (u2l[(s >> 24) & 0xff] << 16) | u2l[(s >> 16) & 0xff];
162                 sp[3] = (u2l[(s >> 8) & 0xff] << 16) | u2l[s & 0xff];
163         }
164         ALwritesamps(out, samps, len);
165 }
166 
167 int SGIAudio::FrameReady()
168 {
169         return (ALgetfilled(in) >= blksize_);
170 }
171 
172 u_char* SGIAudio::Read()
173 {
174         register long len = blksize_;
175         u_char* cp = buf_;
176 
177         /*
178          * for some reason, SGI didn't bother to filter out the
179          * mike 'phantom power' DC signal (god forbid they should
180          * use the Indigo DSP for anything or invest a dime in
181          * transformer coupling the mike) so we end up with a
182          * large DC offset that screws up the lin-to-mu conversion
183          * and the speakerphone power calculations.  So all the
184          * extra junk in the following loop is a low pass filter
185          * to estimate the DC bias & remove it.
186          *
187          * The multiply by 2 on the samples is because SGI maps
188          * stereo to mono by doing (L+R)/2 rather than clip(L+R).
189          * Since the mikes they ship are mono, this effectively
190          * cuts the mike gain by a factor of two.  We can't
191          * restore the 1 bit of dynamic range they throw away
192          * but we jack the gain back up where is should be.
193          */
194         short samps[MAXAUDIOSIZE];
195         register short* sp = samps;
196         ALreadsamps(in, sp, len);
197         register short* ep = sp + len;
198         register const u_char* l2u = lintomulawX;
199         register u_int* ip = (u_int*)cp;
200         register int smean = lastsamp_;
201         for ( ; sp < ep; sp += 4) {
202                 register int mean, dif;
203                 register u_int res;
204                 register int s0 = sp[0] << 1;
205                 register int s1 = sp[1] << 1;
206                 register int s2 = sp[2] << 1;
207                 register int s3 = sp[3] << 1;
208 
209                 mean = smean >> 13;
210                 dif = s0 - mean;
211                 smean += dif;
212                 res = l2u[dif & 0x1ffff] << 24;
213 
214                 mean = smean >> 13;
215                 dif = s1 - mean;
216                 smean += dif;
217                 res |= l2u[dif & 0x1ffff] << 16;
218 
219                 mean = smean >> 13;
220                 dif = s2 - mean;
221                 smean += dif;
222                 res |= l2u[dif & 0x1ffff] << 8;
223 
224                 mean = smean >> 13;
225                 dif = s3 - mean;
226                 smean += dif;
227                 res |= l2u[dif & 0x1ffff];
228 
229                 *ip++ = res;
230         }
231         lastsamp_ = smean;
232         return (cp);
233 }
234 
235 int SGIAudio::GainClip(int level)
236 {
237         if (level < AUDIO_MIN_GAIN)
238                 return AUDIO_MIN_GAIN;
239         else if (level > AUDIO_MAX_GAIN)
240                 return AUDIO_MAX_GAIN;
241         else
242                 return level;
243 }
244 
245 void SGIAudio::SetRGain(int level)
246 {
247         rgain_ = GainClip(level);
248         if (fd_ >= 0) {
249                 static long atten[] = { 34, 37, 40, 45, 50, 55, 63 };
250                 long pvbuf[4];
251                 int index = ((255 - rgain_) * 39) / 255;
252                 pvbuf[3] = pvbuf[1] = (index > 32) ?
253                                         (atten[index-33] << 2) : (index << 2);
254                 pvbuf[0] = AL_LEFT_INPUT_ATTEN;
255                 pvbuf[2] = AL_RIGHT_INPUT_ATTEN;
256                 ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 4);
257         }
258 }
259 
260 void SGIAudio::SetPGain(int level)
261 {
262         pgain_ = GainClip(level);
263         if (fd_ >= 0) {
264                 long pvbuf[4];
265 #ifdef SGI_COMPAT
266                 float gain = pgain_ <= 0?
267                             0.
268                             : pow(10.0, float(pgain_)*(2.406540183/255.)) + 0.5;
269                 pvbuf[3] = pvbuf[1] = long(gain);
270 #else
271                 pvbuf[3] = pvbuf[1] = long(pgain_);
272 #endif
273                 pvbuf[0] = AL_LEFT_SPEAKER_GAIN;
274                 pvbuf[2] = AL_RIGHT_SPEAKER_GAIN;
275                 ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 4);
276         }
277 }
278 
279 void SGIAudio::InputPort(int p)
280 {
281         iport_ = p;
282         if (fd_ >= 0) {
283                 long pvbuf[2];
284                 pvbuf[0] = AL_INPUT_SOURCE;
285                 pvbuf[1] = iport_? AL_INPUT_LINE : AL_INPUT_MIC;
286                 ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 2);
287         }
288 }
289 

~ [ 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.