4
* Copyright (C) 1998 Rasca, Berlin
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.
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.
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.
26
#include <sys/ioctl.h>
30
/* definitions for M$ WAVE format
32
#define RIFF 0x46464952
33
#define WAVE 0x45564157
34
#define FMT 0x20746D66
35
#define DATA 0x61746164
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 */
55
unsigned long data_chunk; /* data */
56
unsigned long data_length; /* samplecount */
59
#define VERBOSE if(verbose)
60
#define VERBOSE2 if(verbose>1)
62
static char *dev = NULL; /* name of the device */
63
static int audio = 0; /* file descriptor of the device */
65
static int verbose =1;
67
static int verbose =0;
71
* check the device and remember the device name
73
int snd_init (char *devname) {
76
dev = (char *) malloc (strlen (devname) +1);
79
strcpy (dev, devname);
80
audio = open (dev, O_WRONLY);
94
audio = open (dev, O_WRONLY);
104
int snd_close_play (void) {
105
if (close (audio) == -1) {
115
int snd_open_rec (void) {
116
audio = open (dev, O_RDONLY);
126
int snd_close_rec (void) {
127
if (close (audio) == -1) {
137
void snd_verbose (int val) {
143
int snd_sync (void) {
145
if (ioctl (audio, SNDCTL_DSP_SYNC, 0) == 0) {
158
if (ioctl (audio, SNDCTL_DSP_POST, 0) == 0) {
167
* must be called if sound was played and now
168
* device options should be changed!
170
int snd_reset (void) {
173
if (ioctl (audio, SNDCTL_DSP_RESET, 0) == 0) {
183
int snd_get_fmts (void) {
186
if (ioctl (audio, SNDCTL_DSP_GETFMTS, &mask) == 0) {
197
snd_set_fmt (int fmt)
199
if (ioctl (audio, SNDCTL_DSP_SETFMT, &fmt) == 0) {
207
* set the sample rate
209
int snd_set_speed (int speed) {
213
if (ioctl (audio, SNDCTL_DSP_SPEED, &tmp) < 0) {
218
VERBOSE fprintf (stderr, "snd_set_speed (%d) ->%d\n", speed, tmp);
224
int snd_set_stereo (int boolval) {
227
if (ioctl (audio, SNDCTL_DSP_STEREO, &tmp) < 0) {
232
VERBOSE fprintf (stderr, "snd_set_stereo (%s) ->%s\n",
233
boolval ? "on" : "off", boolval != tmp? "failed" : "ok");
234
if (boolval != tmp) {
243
snd_set_channels (int num)
246
if (ioctl (audio, SNDCTL_DSP_CHANNELS, &num) < 0) {
256
int snd_set_samplesize (int samplesize) {
257
int tmp = samplesize;
260
if (ioctl (audio, SNDCTL_DSP_SAMPLESIZE, &tmp) < 0) {
265
VERBOSE fprintf (stderr, "snd_set_samplesize (%d) ->%s\n",
266
samplesize, tmp == samplesize? "ok" : "failed");
267
if (samplesize != tmp) {
275
int snd_get_blksize (void) {
279
if (ioctl (audio, SNDCTL_DSP_GETBLKSIZE, &blksize) < 0) {
284
VERBOSE fprintf (stderr, "snd_get_buffer () ->%d\n", blksize);
290
* convert buffer from 16 to 8 bit
292
int snd_16to8_bits (char *buf, int size) {
297
VERBOSE2 fprintf (stderr, "snd_16to8_bits(.., %d) ->%d\n", size, (size>>1));
308
* buff should be at least 36 bytes long ..
309
* checks if it is a wave file and returns the sample size
311
int snd_is_wave (unsigned char *buff) {
316
wh = (WAVheader *) buff;
317
if (!(wh->main_chunk == RIFF && wh->chunk_type == WAVE &&
318
wh->sub_chunk == FMT)) {
324
return (wh->bits_p_spl);
329
int snd_wave_speed (unsigned char *buff) {
334
wh = (WAVheader *) buff;
335
return (wh->sample_fq);
339
* returns the length of the sound data in the wave file
341
int snd_wave_length (unsigned char *buff) {
346
wdh = (WAVdaHead *) (buff + sizeof (WAVheader));
347
return (wdh->data_length);
352
int snd_wave_stereo (unsigned char *buff) {
357
wh = (WAVheader *) buff;
358
if (wh->modus == WAVE_STEREO)
364
* 'header' must be at least 44 bytes long
366
int snd_wave_info (unsigned char *header, int *mode) {
370
samplesize = snd_is_wave(header);
373
if (samplesize == 16)
377
if (snd_wave_stereo (header))
381
return(snd_wave_speed (header));
385
* prepare for playing wave files, returns the internal buffer
386
* fragmentation size which we need to build one buffer,
388
int snd_wave_prepare (int *speed, int *mode) {
389
int samplesize, blksize;
391
samplesize = snd_set_samplesize (*mode & (SND_16BIT | SND_8BIT));
393
samplesize = snd_set_samplesize (8);
395
*mode = *mode & ~SND_16BIT;
396
*mode = *mode | SND_8BIT;
398
if (*mode & SND_STEREO) {
402
*speed = snd_set_speed (*speed);
404
blksize = snd_get_blksize();
405
if (*mode & SND_16TO8)
412
int snd_wave_prepare_header (int speed, int mode, char **dst) {
413
static char header[sizeof(WAVheader) + sizeof (WAVdaHead)];
416
wav = (WAVheader *) header;
417
wav->main_chunk = RIFF;
419
wav->chunk_type = WAVE;
420
wav->sub_chunk = FMT;
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;
432
return (sizeof (WAVheader) + sizeof (WAVdaHead));
437
int snd_get_interval (bufsize, speed, mode) {
438
int kb_per_sec, milisec;
440
if (mode & SND_16TO8)
442
kb_per_sec = speed * ((mode & (SND_16BIT | SND_8BIT)) / 8) *
443
((mode & SND_STEREO) ? 2 : 1);
445
milisec = 1000 * ((double)1 / ((double)kb_per_sec / bufsize));
447
VERBOSE fprintf (stderr, "snd_get_interval (%d, %d, %d) %d ->%d mili sec\n",
448
bufsize, speed, mode, kb_per_sec, milisec);
453
* play sound data from buffer
455
int snd_play_data (unsigned char *buf, int size, int mode) {
459
if (mode & SND_16TO8) {
460
p = (unsigned char *) malloc (sizeof (unsigned char) * size);
463
memcpy (p, buf, size);
464
size = snd_16to8_bits (p, size);
469
VERBOSE2 fprintf (stderr, "snd_play_data (.., %d, ..)\n", size);
470
written = write (audio, p, size);
471
if (mode & SND_16TO8)
478
int snd_rec_data (unsigned char *buf, int max_size) {
480
num = read (audio, buf, max_size);
486
unsigned int snd_get_caps (void) {
487
unsigned int caps = 0;
490
if (ioctl (audio, SNDCTL_DSP_GETCAPS, &caps) < 0) {
494
VERBOSE fprintf (stderr, "snd_get_caps () ->0x%x\n", caps);
501
int snd_has_feature (unsigned int feature) {
503
if ((caps = snd_get_caps()) == 0)
505
return (caps & feature);
511
snd_set_trigger_out (void)
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);