~ubuntu-branches/ubuntu/jaunty/xvidcap/jaunty-proposed

« back to all changes in this revision

Viewing changes to gt/sound.c

  • Committer: Bazaar Package Importer
  • Author(s): Christian Marillat
  • Date: 2004-08-29 10:53:42 UTC
  • Revision ID: james.westby@ubuntu.com-20040829105342-qgmnry37eadfkoxx
Tags: upstream-1.1.3
ImportĀ upstreamĀ versionĀ 1.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * sound.c, v0.5
 
3
 *
 
4
 * Copyright (C) 1998 Rasca, Berlin
 
5
 * EMail: thron@gmx.de
 
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
#include <stdlib.h>
 
23
#include <stdio.h>
 
24
#include <fcntl.h>
 
25
#include <unistd.h>
 
26
#include <sys/ioctl.h>
 
27
#include "sound.h"
 
28
 
 
29
#ifdef HasOSS
 
30
/* definitions for M$ WAVE format
 
31
 */
 
32
#define RIFF        0x46464952
 
33
#define WAVE        0x45564157
 
34
#define FMT         0x20746D66
 
35
#define DATA        0x61746164
 
36
#define PCM_CODE    1
 
37
#define WAVE_MONO   1
 
38
#define WAVE_STEREO 2
 
39
 
 
40
typedef struct {
 
41
  unsigned long    main_chunk; /* 'RIFF' */
 
42
  unsigned long    length;     /* filelen */
 
43
  unsigned long    chunk_type; /* 'WAVE' */
 
44
  unsigned long    sub_chunk;   /* 'fmt' */
 
45
  unsigned long    sub_c_len;   /* length of sub_chunk, =16 */
 
46
  unsigned short   format;     /* should be 1 for PCM-code */
 
47
  unsigned short   modus;      /* 1 mono, 2 stereo */
 
48
  unsigned long    sample_fq;  /* frequence of sample */
 
49
  unsigned long    byte_p_sec;
 
50
  unsigned short   byte_p_spl;  /* samplesize; 1 or 2 bytes */
 
51
  unsigned short   bits_p_spl;  /* 8, 12 or 16 bit */
 
52
} WAVheader;
 
53
 
 
54
typedef struct {
 
55
        unsigned long    data_chunk;    /* data */
 
56
        unsigned long    data_length;  /* samplecount */
 
57
} WAVdaHead;
 
58
 
 
59
#define VERBOSE         if(verbose)
 
60
#define VERBOSE2        if(verbose>1)
 
61
 
 
62
static char *dev = NULL;        /* name of the device */
 
63
static int audio = 0;           /* file descriptor of the device */
 
64
#ifdef DEBUG
 
65
static int verbose =1;
 
66
#else
 
67
static int verbose =0;
 
68
#endif
 
69
 
 
70
/*
 
71
 * check the device and remember the device name
 
72
 */
 
73
int snd_init (char *devname) {
 
74
        if (!devname)
 
75
                return (0);
 
76
        dev = (char *) malloc (strlen (devname) +1);
 
77
        if (!dev)
 
78
                return (0);
 
79
        strcpy (dev, devname);
 
80
        audio = open (dev, O_WRONLY);
 
81
        if (audio == -1) {
 
82
                perror (dev);
 
83
                return (0);
 
84
        }
 
85
        close (audio);
 
86
        return (1);
 
87
}
 
88
 
 
89
/*
 
90
 */
 
91
int
 
92
snd_open_play (void)
 
93
{
 
94
        audio = open (dev, O_WRONLY);
 
95
        if (audio == -1) {
 
96
                perror (dev);
 
97
                return (0);
 
98
        }
 
99
        return (audio);
 
100
}
 
101
 
 
102
/*
 
103
 */
 
104
int snd_close_play (void) {
 
105
        if (close (audio) == -1) {
 
106
                perror (dev);
 
107
                return (0);
 
108
        }
 
109
        audio =0;
 
110
        return (1);
 
111
}
 
112
 
 
113
/*
 
114
 */
 
115
int snd_open_rec (void) {
 
116
        audio = open (dev, O_RDONLY);
 
117
        if (audio == -1) {
 
118
                perror (dev);
 
119
                return (0);
 
120
        }
 
121
        return (1);
 
122
}
 
123
 
 
124
/*
 
125
 */
 
126
int snd_close_rec (void) {
 
127
        if (close (audio) == -1) {
 
128
                perror (dev);
 
129
                return (0);
 
130
        }
 
131
        audio =0;
 
132
        return (1);
 
133
}
 
134
 
 
135
/*
 
136
 */
 
137
void snd_verbose (int val) {
 
138
        verbose = val;
 
139
}
 
140
 
 
141
/*
 
142
 */
 
143
int snd_sync (void) {
 
144
#ifdef HasOSS
 
145
        if (ioctl (audio, SNDCTL_DSP_SYNC, 0) == 0) {
 
146
                return (1);
 
147
        }
 
148
#endif
 
149
        perror (dev);
 
150
        return (0);
 
151
}
 
152
 
 
153
/*
 
154
 */
 
155
int
 
156
snd_post (void) {
 
157
#ifdef HasOSS
 
158
        if (ioctl (audio, SNDCTL_DSP_POST, 0) == 0) {
 
159
                return (1);
 
160
        }
 
161
#endif
 
162
        perror (dev);
 
163
        return (0);
 
164
}
 
165
 
 
166
/*
 
167
 * must be called if sound was played and now
 
168
 * device options should be changed!
 
169
 */
 
170
int snd_reset (void) {
 
171
 
 
172
#ifdef HasOSS
 
173
        if (ioctl (audio, SNDCTL_DSP_RESET, 0) == 0) {
 
174
                return (1);
 
175
        }
 
176
#endif
 
177
        perror (dev);
 
178
        return (0);
 
179
}
 
180
 
 
181
/*
 
182
 */
 
183
int snd_get_fmts (void) {
 
184
#ifdef HasOSS
 
185
        int mask = 0;
 
186
        if (ioctl (audio, SNDCTL_DSP_GETFMTS, &mask) == 0) {
 
187
                return (mask);
 
188
        }
 
189
#endif
 
190
        perror (dev);
 
191
        return (0);
 
192
}
 
193
 
 
194
/*
 
195
 */
 
196
int
 
197
snd_set_fmt (int fmt)
 
198
{
 
199
        if (ioctl (audio, SNDCTL_DSP_SETFMT, &fmt) == 0) {
 
200
                return (fmt);
 
201
        }
 
202
        perror (dev);
 
203
        return(0);
 
204
}
 
205
 
 
206
/*
 
207
 * set the sample rate
 
208
 */
 
209
int snd_set_speed (int speed) {
 
210
        int tmp = speed;
 
211
 
 
212
#ifdef HasOSS
 
213
        if (ioctl (audio, SNDCTL_DSP_SPEED, &tmp) < 0) {
 
214
                perror (dev);
 
215
                return (0);
 
216
        }
 
217
#endif
 
218
        VERBOSE fprintf (stderr, "snd_set_speed (%d) ->%d\n", speed, tmp);
 
219
        return (tmp);
 
220
}
 
221
 
 
222
/*
 
223
 */
 
224
int snd_set_stereo (int boolval) {
 
225
        int tmp = boolval;
 
226
#ifdef HasOSS
 
227
        if (ioctl (audio, SNDCTL_DSP_STEREO, &tmp) < 0) {
 
228
                perror (dev);
 
229
                return (0);
 
230
        }
 
231
#endif
 
232
        VERBOSE fprintf (stderr, "snd_set_stereo (%s) ->%s\n",
 
233
                                        boolval ? "on" : "off", boolval != tmp? "failed" : "ok");
 
234
        if (boolval != tmp) {
 
235
                return (0);
 
236
        }
 
237
        return (1);
 
238
}
 
239
 
 
240
/*
 
241
 */
 
242
int
 
243
snd_set_channels (int num)
 
244
{
 
245
#ifdef HasOSS
 
246
        if (ioctl (audio, SNDCTL_DSP_CHANNELS, &num) < 0) {
 
247
                perror (dev);
 
248
                return (0);
 
249
        }
 
250
#endif
 
251
        return (num);
 
252
}
 
253
 
 
254
/*
 
255
 */
 
256
int snd_set_samplesize (int samplesize) {
 
257
        int tmp = samplesize;
 
258
 
 
259
#ifdef HasOSS
 
260
        if (ioctl (audio, SNDCTL_DSP_SAMPLESIZE, &tmp) < 0) {
 
261
                perror (dev);
 
262
                return (0);
 
263
        }
 
264
#endif
 
265
        VERBOSE fprintf (stderr, "snd_set_samplesize (%d) ->%s\n",
 
266
                                                samplesize, tmp == samplesize? "ok" : "failed");
 
267
        if (samplesize != tmp) {
 
268
                return (0);
 
269
        }
 
270
        return (tmp);
 
271
}
 
272
 
 
273
/*
 
274
 */
 
275
int snd_get_blksize (void) {
 
276
        int blksize = 0;
 
277
 
 
278
#ifdef HasOSS
 
279
        if (ioctl (audio, SNDCTL_DSP_GETBLKSIZE, &blksize) < 0) {
 
280
                perror (dev);
 
281
                return (0);
 
282
        }
 
283
#endif
 
284
        VERBOSE fprintf (stderr, "snd_get_buffer () ->%d\n", blksize);
 
285
        return (blksize);
 
286
}
 
287
 
 
288
 
 
289
/*
 
290
 * convert buffer from 16 to 8 bit
 
291
 */
 
292
int snd_16to8_bits (char *buf, int size) {
 
293
        unsigned long c;
 
294
        char *p1 = buf;
 
295
        char *p2 = buf;
 
296
 
 
297
        VERBOSE2 fprintf (stderr, "snd_16to8_bits(.., %d) ->%d\n", size, (size>>1));
 
298
        c = size >> 1;
 
299
        p2++;
 
300
        while (c--) {
 
301
                *p1++ = *p2 + 128;
 
302
                p2 += 2;
 
303
        }
 
304
        return (size >> 1);
 
305
}
 
306
 
 
307
/*
 
308
 * buff should be at least 36 bytes long ..
 
309
 * checks if it is a wave file and returns the sample size
 
310
 */
 
311
int snd_is_wave (unsigned char *buff) {
 
312
        WAVheader *wh;
 
313
 
 
314
        if (!buff)
 
315
                return (0);
 
316
        wh = (WAVheader *) buff;
 
317
        if (!(wh->main_chunk == RIFF && wh->chunk_type == WAVE &&
 
318
                        wh->sub_chunk == FMT)) {
 
319
                return (0);
 
320
        }
 
321
        if (wh->modus > 2) {
 
322
                return (0);
 
323
        }
 
324
        return (wh->bits_p_spl);
 
325
}
 
326
 
 
327
/*
 
328
 */
 
329
int snd_wave_speed (unsigned char *buff) {
 
330
        WAVheader *wh;
 
331
 
 
332
        if (!buff)
 
333
                return (0);
 
334
        wh = (WAVheader *) buff;
 
335
        return (wh->sample_fq);
 
336
}
 
337
 
 
338
/*
 
339
 * returns the length of the sound data in the wave file
 
340
 */
 
341
int snd_wave_length (unsigned char *buff) {
 
342
        WAVdaHead *wdh;
 
343
 
 
344
        if (!buff)
 
345
                return (0);
 
346
        wdh = (WAVdaHead *) (buff + sizeof (WAVheader));
 
347
        return (wdh->data_length);
 
348
}
 
349
 
 
350
/*
 
351
 */
 
352
int snd_wave_stereo (unsigned char *buff) {
 
353
        WAVheader *wh;
 
354
 
 
355
        if (!buff)
 
356
                return (0);
 
357
        wh = (WAVheader *) buff;
 
358
        if (wh->modus == WAVE_STEREO)
 
359
                return (1);
 
360
        return (0);
 
361
}
 
362
 
 
363
/*
 
364
 * 'header' must be at least 44 bytes long
 
365
 */
 
366
int snd_wave_info (unsigned char *header, int *mode) {
 
367
        int samplesize;
 
368
 
 
369
        *mode = 0;
 
370
        samplesize = snd_is_wave(header);
 
371
        if (!samplesize)
 
372
                return (0);
 
373
        if (samplesize == 16)
 
374
                *mode |= SND_16BIT;
 
375
        else
 
376
                *mode |= SND_8BIT;
 
377
        if (snd_wave_stereo (header))
 
378
                *mode |= SND_STEREO;
 
379
        else
 
380
                *mode |= SND_MONO;
 
381
        return(snd_wave_speed (header));
 
382
}
 
383
 
 
384
/*
 
385
 * prepare for playing wave files, returns the internal buffer
 
386
 * fragmentation size which we need to build one buffer,
 
387
 */
 
388
int snd_wave_prepare (int *speed, int *mode) {
 
389
        int samplesize, blksize;
 
390
 
 
391
        samplesize = snd_set_samplesize (*mode & (SND_16BIT | SND_8BIT));
 
392
        if (!samplesize) {
 
393
                samplesize = snd_set_samplesize (8);
 
394
                *mode |= SND_16TO8;
 
395
                *mode  = *mode & ~SND_16BIT;
 
396
                *mode  = *mode | SND_8BIT;
 
397
        }
 
398
        if (*mode & SND_STEREO) {
 
399
                snd_set_stereo(1);
 
400
        } else
 
401
                snd_set_stereo(0);
 
402
        *speed = snd_set_speed (*speed);
 
403
 
 
404
        blksize = snd_get_blksize();
 
405
        if (*mode & SND_16TO8)
 
406
                blksize *= 2;
 
407
        return (blksize);
 
408
}
 
409
 
 
410
/*
 
411
 */
 
412
int snd_wave_prepare_header (int speed, int mode, char **dst) {
 
413
        static char header[sizeof(WAVheader) + sizeof (WAVdaHead)];
 
414
        WAVheader *wav;
 
415
        WAVdaHead *da;
 
416
        wav = (WAVheader *) header;
 
417
        wav->main_chunk = RIFF;
 
418
        wav->length     = 0;
 
419
        wav->chunk_type = WAVE;
 
420
        wav->sub_chunk  = FMT;
 
421
        wav->sub_c_len  = 16;
 
422
        wav->format             = PCM_CODE;
 
423
        wav->modus              = (mode & SND_MONO) ? WAVE_MONO : WAVE_STEREO;
 
424
        wav->sample_fq  = speed;
 
425
        wav->byte_p_spl = (mode & SND_16BIT) ? 2 : 1;
 
426
        wav->byte_p_sec = wav->sample_fq * wav->modus * wav->byte_p_spl;
 
427
        wav->bits_p_spl = (mode & SND_16BIT) ? 16 : 8;
 
428
        da = (WAVdaHead*) (header + sizeof (WAVheader));
 
429
        da->data_chunk = DATA;
 
430
        da->data_length= 0;
 
431
        *dst = header;
 
432
        return (sizeof (WAVheader) + sizeof (WAVdaHead));
 
433
}
 
434
 
 
435
/*
 
436
 */
 
437
int snd_get_interval (bufsize, speed, mode) {
 
438
        int kb_per_sec, milisec;
 
439
 
 
440
        if (mode & SND_16TO8)
 
441
                bufsize /= 2;
 
442
        kb_per_sec = speed * ((mode & (SND_16BIT | SND_8BIT)) / 8) *
 
443
                                ((mode & SND_STEREO) ? 2 : 1);
 
444
 
 
445
        milisec = 1000 * ((double)1 / ((double)kb_per_sec / bufsize));
 
446
 
 
447
        VERBOSE fprintf (stderr, "snd_get_interval (%d, %d, %d) %d ->%d mili sec\n",
 
448
                                                bufsize, speed, mode, kb_per_sec, milisec);
 
449
        return (milisec);
 
450
}
 
451
 
 
452
/*
 
453
 * play sound data from buffer
 
454
 */
 
455
int snd_play_data (unsigned char *buf, int size, int mode) {
 
456
        unsigned char *p;
 
457
        int written;
 
458
 
 
459
        if (mode & SND_16TO8) {
 
460
                p = (unsigned char *) malloc (sizeof (unsigned  char) * size);
 
461
                if (!p)
 
462
                        return (0);
 
463
                memcpy (p, buf, size);
 
464
                size = snd_16to8_bits (p, size);
 
465
        } else {
 
466
                p = buf;
 
467
        }
 
468
 
 
469
        VERBOSE2 fprintf (stderr, "snd_play_data (.., %d, ..)\n", size);
 
470
        written = write (audio, p, size);
 
471
        if (mode & SND_16TO8)
 
472
                free (p);
 
473
        return (written);
 
474
}
 
475
 
 
476
/*
 
477
 */
 
478
int snd_rec_data (unsigned char *buf, int max_size) {
 
479
        int num;
 
480
        num = read (audio, buf, max_size);
 
481
        return (num);
 
482
}
 
483
 
 
484
/*
 
485
 */
 
486
unsigned int snd_get_caps (void) {
 
487
        unsigned int caps = 0;
 
488
 
 
489
#ifdef HasOSS
 
490
        if (ioctl (audio, SNDCTL_DSP_GETCAPS, &caps) < 0) {
 
491
                perror (dev);
 
492
                return (0);
 
493
        }
 
494
        VERBOSE fprintf (stderr, "snd_get_caps () ->0x%x\n", caps);
 
495
#endif
 
496
        return (caps);
 
497
}
 
498
 
 
499
/*
 
500
 */
 
501
int snd_has_feature (unsigned int feature) {
 
502
        int caps;
 
503
        if ((caps = snd_get_caps()) == 0)
 
504
                return (-1);
 
505
        return (caps & feature);
 
506
}
 
507
 
 
508
/*
 
509
 */
 
510
int
 
511
snd_set_trigger_out (void)
 
512
{
 
513
        int trigger = ~PCM_ENABLE_OUTPUT;
 
514
        ioctl (audio, SNDCTL_DSP_SETTRIGGER, &trigger);
 
515
        trigger = PCM_ENABLE_OUTPUT;
 
516
        ioctl (audio, SNDCTL_DSP_SETTRIGGER, &trigger);
 
517
        return (trigger);
 
518
}
 
519
 
 
520
#endif