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
26extern "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
108typedef 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
218extern int SnackGetInputDevices(char **arr, int n);
219extern int SnackGetOutputDevices(char **arr, int n);
220extern int SnackGetMixerDevices(char **arr, int n);
221
222extern void SnackAudioInit();
223extern void SnackAudioFree();
224extern int  SnackAudioOpen(ADesc *A, Tcl_Interp *interp, char *device,
225			   int mode, int freq, int channels,
226			   int encoding);
227extern int  SnackAudioClose(ADesc *A);
228extern long SnackAudioPause(ADesc *A);
229extern void SnackAudioResume(ADesc *A);
230extern void SnackAudioFlush(ADesc *A);
231extern void SnackAudioPost(ADesc *A);
232extern int  SnackAudioRead(ADesc *A, void *buf, int nSamples);
233extern int  SnackAudioWrite(ADesc *A, void *buf, int nSamples);
234extern int  SnackAudioReadable(ADesc *A);
235extern long SnackAudioPlayed(ADesc *A);
236extern int  SnackAudioWriteable(ADesc *A);
237
238extern int SnackAudioGetEncodings(char *device);
239extern void SnackAudioGetRates(char *device, char *buf, int n);
240extern int SnackAudioMaxNumberChannels(char *device);
241extern int SnackAudioMinNumberChannels(char *device);
242
243extern void ASetRecGain(int gain);
244extern void ASetPlayGain(int gain);
245extern int  AGetRecGain();
246extern int  AGetPlayGain();
247
248extern void SnackMixerGetInputJackLabels(char *buf, int n);
249extern void SnackMixerGetOutputJackLabels(char *buf, int n);
250extern void SnackMixerGetInputJack(char *buf, int n);
251extern int  SnackMixerSetInputJack(Tcl_Interp *interp, char *jack,
252				   CONST84 char *status);
253extern void SnackMixerGetOutputJack(char *buf, int n);
254extern void SnackMixerSetOutputJack(char *jack, char *status);
255extern void SnackMixerGetChannelLabels(char *mixer, char *buf, int n);
256extern void SnackMixerGetVolume(char *mixer, int channel, char *buf, int n);
257extern void SnackMixerSetVolume(char *mixer, int channel, int volume);
258extern void SnackMixerGetLineLabels(char *buf, int n);
259extern void SnackMixerLinkJacks(Tcl_Interp *interp, char *jack, Tcl_Obj *var);
260extern void SnackMixerLinkVolume(Tcl_Interp *interp, char *mixer, int n,
261			Tcl_Obj *CONST objv[]);
262extern void SnackMixerUpdateVars(Tcl_Interp *interp);
263extern int  SnackGetInDevices(char **arr, int n);
264extern 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
287extern short Snack_Alaw2Lin(unsigned char a_val);
288extern short Snack_Mulaw2Lin(unsigned char u_val);
289extern unsigned char Snack_Lin2Alaw(short pcm_val);
290extern unsigned char Snack_Lin2Mulaw(short pcm_val);
291#endif*/
292extern double SnackCurrentTime();
293
294typedef 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
305extern char *SnackStrDup(const char *str);
306
307#define QUERYBUFSIZE 1000
308#define MAX_DEVICE_NAME_LENGTH 100
309#define MAX_NUM_DEVICES 20
310
311extern int strncasecmp(const char *s1, const char *s2, size_t n);
312
313#ifdef __cplusplus
314}
315#endif
316
317#endif /* _SNACK_AUDIO */
318