1 /*
2  * Copyright (C) 1997-2004 Kare Sjolander <kare@speech.kth.se>
3  *
4  * This file is part of the Snack Sound Toolkit.
5  * The latest version can be found at http://www.speech.kth.se/snack/
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 
22 #ifndef _SNACK_AUDIO
23 #define _SNACK_AUDIO
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 #ifndef CONST84
30 #   define CONST84
31 #endif
32 
33 #ifdef HPUX
34 #  include <Alib.h>
35 #endif
36 
37 #ifdef Solaris
38 #  include <sys/types.h>
39 #  include <sys/file.h>
40 #  include <sys/ioctl.h>
41 #  include <sys/fcntl.h>
42 #  include <stropts.h>
43 #  include <sys/errno.h>
44 #  include <sys/audioio.h>
45 #  include <errno.h>
46 #  include <sys/filio.h>
47 #endif
48 
49 #ifdef WIN
50 #  include <windows.h>
51 #  include <mmsystem.h>
52 #  include <mmreg.h>
53 #  include <dsound.h>
54 # ifdef WAVEFORMATEXTENSIBLE
55 #  include <ks.h>
56 # endif
57 #endif
58 
59 #ifdef IRIX
60 #  include <audio.h>
61 #endif
62 
63 #if defined(MAC) || defined(OS_X_CORE_AUDIO)
64 
65 /* We need to temporarily redefine several symbols used by an obsolete
66  *  MacOS interface as they are also used by Snack */
67 
68 #  define convertCmd convertCmd_MacOS
69 #  define soundCmd   soundCmd_MacOS
70 #  define flushCmd   flushCmd_MacOS
71 #  define volumeCmd  volumeCmd_MacOS
72 #  define pauseCmd   pauseCmd_MacOS
73 
74 #if defined(OS_X_CORE_AUDIO)
75 #undef min
76 #undef max
77 #  include <CoreServices/CoreServices.h>
78 #  include <CoreAudio/AudioHardware.h>
79 #define min(a,b) ((a)<(b)?(a):(b))
80 #define max(a,b) ((a)>(b)?(a):(b))
81 #else
82 #  include <Sound.h>
83 #endif
84 
85 #  undef convertCmd
86 #  undef soundCmd
87 #  undef flushCmd
88 #  undef volumeCmd
89 #  undef pauseCmd
90 
91 #  ifndef rate44khz
92 #    define rate44khz ((unsigned long)(44100.0*65536))
93 #  endif /* !rate44khz */
94 /* How many buffers to maintain (2 is enough) */
95 #define NBUFS 2
96 /* The duration in seconds desired for each buffer */
97 /*#define DFLT_BUFTIME (0.0625) *//* i.e. frq/16, the favorite transfer size of the system */
98 #define DFLT_BUFTIME (0.25)	/* seems to work much better on the mac */
99 /* The number of SPBRecord calls to overlap.  I *think* this *has* to be zero */
100 #define INBUF_OVERLAP (0)
101 
102 #endif /* MAC */
103 
104 #ifdef ALSA
105 #include <alsa/asoundlib.h>
106 #endif
107 
108 typedef struct ADesc {
109 
110 #ifdef HPUX
111   Audio    *audio;
112   ATransID  transid;
113   int       Socket;
114   int       last;
115   int       convert;
116   double    time;
117   int       freq;
118 #endif
119 
120 #ifdef OSS
121   int    afd;
122   /*int    count;*/
123   int    frag_size;
124   double time;
125   double timep;
126   int    freq;
127   int    convert;
128   int    warm;
129 #endif
130 
131 #ifdef ALSA
132   snd_pcm_t *handle;
133   int       freq;
134   long      nWritten;
135   long      nPlayed;
136 #endif
137 
138 #ifdef Solaris
139   int afd;
140   audio_info_t ainfo;
141   double time;
142   double timep;
143   int freq;
144   int convert;
145   short *convBuf;
146   int convSize;
147 #endif
148 
149 #ifdef WIN
150   int curr;
151   int freq;
152   int shortRead;
153   int convert;
154 
155   PCMWAVEFORMAT pcmwf;
156   DSBUFFERDESC dsbdesc;
157   DSCBUFFERDESC dscbdesc;
158   LPDIRECTSOUNDBUFFER lplpDsb;
159   LPDIRECTSOUNDCAPTUREBUFFER lplpDscb;
160   PCMWAVEFORMAT pcmwfPB;
161   DSBUFFERDESC dsbdescPB;
162   LPDIRECTSOUNDBUFFER lplpDsPB;
163   unsigned int BufPos;
164   int BufLen;
165   long written;
166   long lastWritten;
167 #endif
168 
169 #ifdef IRIX
170   ALport   port;
171   ALconfig config;
172   unsigned long long startfn;
173   int count;
174 #endif
175 
176 #if defined(MAC)/* || defined(OS_X_CORE_AUDIO)*/
177   /* Fields for handling output */
178   SndChannelPtr schn;
179   SndCommand	  scmd;
180   SndDoubleBufferHeader2  dbh;
181   SndDoubleBufferPtr	   bufs[NBUFS]; /* the two double buffers */
182   int currentBuf;	/* our own track of which buf is current */
183   int bufsIssued;	/* For record: how many bufs have been set going */
184   int bufsCompleted;	/* For record: how many bufs have completed */
185   int bufFull[NBUFS];
186   long     bufFrames;	    /* number of frames allocated per buffer */
187   int running;	/* flag as to whether we have started yet */
188   int pause;    /* flag that we are paused (used on input only?) */
189   /* data for the callbacks */
190   void     *data;	    /* pointer to the base of the sampled data */
191   long     totalFrames;   /* how many frames there are */
192   long     doneFrames;    /* how many we have already copied */
193   /* Fields for input */
194   long inRefNum;	    /* MacOS reference to input channel */
195   SPBPtr spb[NBUFS];	    /* ptr to the parameter blocks for recording */
196   /* debug stats */
197   int completedblocks;
198   int underruns;
199 #endif /* MAC */
200 
201 #ifdef OS_X_CORE_AUDIO
202   AudioDeviceID	device;
203   UInt32 deviceBufferSize;
204   AudioStreamBasicDescription deviceFormat;
205   int rpos, wpos;
206   double time;
207   int tot;
208   int encoding;
209 #endif /* OS_X_CORE_AUDIO */
210 
211   int bytesPerSample;
212   int nChannels;
213   int mode;
214   int debug;
215 
216 } ADesc;
217 
218 extern int SnackGetInputDevices(char **arr, int n);
219 extern int SnackGetOutputDevices(char **arr, int n);
220 extern int SnackGetMixerDevices(char **arr, int n);
221 
222 extern void SnackAudioInit();
223 extern void SnackAudioFree();
224 extern int  SnackAudioOpen(ADesc *A, Tcl_Interp *interp, char *device,
225 			   int mode, int freq, int channels,
226 			   int encoding);
227 extern int  SnackAudioClose(ADesc *A);
228 extern long SnackAudioPause(ADesc *A);
229 extern void SnackAudioResume(ADesc *A);
230 extern void SnackAudioFlush(ADesc *A);
231 extern void SnackAudioPost(ADesc *A);
232 extern int  SnackAudioRead(ADesc *A, void *buf, int nSamples);
233 extern int  SnackAudioWrite(ADesc *A, void *buf, int nSamples);
234 extern int  SnackAudioReadable(ADesc *A);
235 extern long SnackAudioPlayed(ADesc *A);
236 extern int  SnackAudioWriteable(ADesc *A);
237 
238 extern int SnackAudioGetEncodings(char *device);
239 extern void SnackAudioGetRates(char *device, char *buf, int n);
240 extern int SnackAudioMaxNumberChannels(char *device);
241 extern int SnackAudioMinNumberChannels(char *device);
242 
243 extern void ASetRecGain(int gain);
244 extern void ASetPlayGain(int gain);
245 extern int  AGetRecGain();
246 extern int  AGetPlayGain();
247 
248 extern void SnackMixerGetInputJackLabels(char *buf, int n);
249 extern void SnackMixerGetOutputJackLabels(char *buf, int n);
250 extern void SnackMixerGetInputJack(char *buf, int n);
251 extern int  SnackMixerSetInputJack(Tcl_Interp *interp, char *jack,
252 				   CONST84 char *status);
253 extern void SnackMixerGetOutputJack(char *buf, int n);
254 extern void SnackMixerSetOutputJack(char *jack, char *status);
255 extern void SnackMixerGetChannelLabels(char *mixer, char *buf, int n);
256 extern void SnackMixerGetVolume(char *mixer, int channel, char *buf, int n);
257 extern void SnackMixerSetVolume(char *mixer, int channel, int volume);
258 extern void SnackMixerGetLineLabels(char *buf, int n);
259 extern void SnackMixerLinkJacks(Tcl_Interp *interp, char *jack, Tcl_Obj *var);
260 extern void SnackMixerLinkVolume(Tcl_Interp *interp, char *mixer, int n,
261 			Tcl_Obj *CONST objv[]);
262 extern void SnackMixerUpdateVars(Tcl_Interp *interp);
263 extern int  SnackGetInDevices(char **arr, int n);
264 extern int  SnackGetOutDevices(char **arr, int n);
265 
266 #define RECORD 1
267 #define PLAY   2
268 
269 #define SNACK_MONO   1
270 #define SNACK_STEREO 2
271 #define SNACK_QUAD   4
272 
273 #define LIN16        1
274 #define ALAW         2
275 #define MULAW        3
276 #define LIN8OFFSET   4
277 #define LIN8         5
278 #define LIN24        6
279 #define LIN32        7
280 #define SNACK_FLOAT  8
281 #define SNACK_DOUBLE 9
282 #define LIN24PACKED 10
283 
284 #define CAPABLEN 100
285 
286 /*#ifdef OSS
287 extern short Snack_Alaw2Lin(unsigned char a_val);
288 extern short Snack_Mulaw2Lin(unsigned char u_val);
289 extern unsigned char Snack_Lin2Alaw(short pcm_val);
290 extern unsigned char Snack_Lin2Mulaw(short pcm_val);
291 #endif*/
292 extern double SnackCurrentTime();
293 
294 typedef struct MixerLink {
295   char *mixer;
296   char *mixerVar;
297   char *jack;
298   CONST84 char *jackVar;
299   int channel;
300 } MixerLink;
301 
302 #define VOLBUFSIZE 20
303 #define JACKBUFSIZE 40
304 
305 extern char *SnackStrDup(const char *str);
306 
307 #define QUERYBUFSIZE 1000
308 #define MAX_DEVICE_NAME_LENGTH 100
309 #define MAX_NUM_DEVICES 20
310 
311 extern int strncasecmp(const char *s1, const char *s2, size_t n);
312 
313 #ifdef __cplusplus
314 }
315 #endif
316 
317 #endif /* _SNACK_AUDIO */
318