📄 playwave.c
字号:
/* * playwave.c * * Play sound files in wave format. Only MicroSoft PCM is supported. * * Michel R. Prevenier. */#include <sys/types.h>#include <errno.h>#include <signal.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <string.h>#include <sys/ioctl.h>#include <minix/sound.h>_PROTOTYPE( void main, (int argc, char **argv));_PROTOTYPE( void usage, (void));/******* Wave format definitions *********/#define RIFF_ID 0x46464952#define WAVE_ID1 0x45564157#define WAVE_ID2 0x20746D66#define DATA_ID 0x61746164#define MS_PCM_FORMAT 0x0001 #define WORD short #define DWORD unsigned longstruct RIFF_fields{ DWORD RIFF_id; DWORD RIFF_len; DWORD WAVE_id1; DWORD WAVE_id2; DWORD data_ptr;} r_fields; struct common_fields{ WORD FormatTag; WORD Channels; DWORD SamplesPerSec; DWORD AvgBytesPerSec; WORD BlockAlign;} c_fields;struct specific_fields{ WORD BitsPerSample;} s_fields;DWORD data_id;DWORD data_len;/******** End of wave definitions *********/void usage(){ fprintf(stderr, "Usage: playwav [-i] file\n"); exit(-1);}void main ( int argc, char *argv[] ){ int i, audio, file; char *buffer, *file_name; unsigned int sign; unsigned int fragment_size; unsigned int channels; unsigned int bits; long data_pos; int showinfo = 0; /* Check Parameters */ if (argc > 2) { if (strncmp(argv[1], "-i", 2) == 0) { showinfo = 1; file_name = argv[2]; } else usage(); } else file_name = argv[1]; /* Open DSP */ if ((audio = open("/dev/audio", O_RDWR)) < 0) { printf("Cannot open /dev/audio\n"); exit(-1); } /* Get maximum fragment size and try to allocate a buffer */ ioctl(audio, DSPIOMAX, &fragment_size); if ((buffer = malloc(fragment_size)) == (char *)0) { fprintf(stderr, "Cannot allocate buffer\n"); exit(-1); } ioctl(audio, DSPIOSIZE, &fragment_size); /* Open wav file */ if((file = open(file_name, O_RDONLY)) < 0) { printf("Cannot open %s\n", file_name); exit(-1); } /* Check for valid wave format */ read(file, &r_fields, 20); if(r_fields.RIFF_id != RIFF_ID) { printf("%s not in RIFF format\n", file_name); exit(1); } if(r_fields.WAVE_id1 != WAVE_ID1 || r_fields.WAVE_id2 != WAVE_ID2) { printf("%s not in WAVE format\n", file_name); exit(1); } /* Store data_chunk position */ data_pos = lseek(file, 0L, 1) + r_fields.data_ptr; /* Read the common and specific fields */ read(file, &c_fields, 14); read(file, &s_fields, 2); /* Check for valid wave format, we can only play MicroSoft PCM */ if(c_fields.FormatTag != MS_PCM_FORMAT) { printf("%s not in MicroSoft PCM format\n", file_name); exit(1); } /* Set DSP parameters */ channels = c_fields.Channels; channels--; bits = s_fields.BitsPerSample; ioctl(audio, DSPIOSTEREO, &channels); ioctl(audio, DSPIORATE, &c_fields.SamplesPerSec); ioctl(audio, DSPIOBITS, &bits); sign = (bits == 16 ? 1 : 0); ioctl(audio, DSPIOSIGN, &sign); /* Goto data chunk */ lseek(file, data_pos, SEEK_SET); /* Check for valid data chunk */ read(file, &data_id, sizeof(data_id)); if(data_id != DATA_ID) { printf("Invalid data chunk\n"); exit(1); } /* Get length of data */ read(file, &data_len, sizeof(data_len)); if (showinfo) { printf("\nBits per sample : %d \n", s_fields.BitsPerSample); printf("Stereo : %s \n", (c_fields.Channels == 1 ? "yes" : "no")); printf("Samples per second: %ld \n", c_fields.SamplesPerSec); printf("Average bytes/sec : %ld \n", c_fields.AvgBytesPerSec); printf("Block alignment : %d \n", c_fields.BlockAlign); printf("Datalength (bytes): %ld \n\n", data_len); } /* Play data */ while(data_len > 0) { if (data_len > fragment_size) { /* Read next fragment */ read(file, buffer, fragment_size); data_len-= fragment_size; } else { /* Read until end of file and fill rest of buffer with silence, * in PCM this means: fill buffer with last played value */ read(file, buffer, data_len); for (i = data_len; i< fragment_size; i++) buffer[i] = buffer[(int)data_len-1]; data_len = 0; } /* Copy data to DSP */ write(audio, buffer, fragment_size); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -