📄 play.c
字号:
/* vplay.c - plays and records CREATIVE LABS VOICE-files, Microsoft WAVE-files and raw data Autor: Michael Beck - beck@informatik.hu-berlin.de*/#include <stdio.h>#include <malloc.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <sys/ioctl.h>#include "soundcard.h"#include "fmtheaders.h"#include <netinet/in.h>#define DEFAULT_DSP_SPEED 8000#define DEBUG_SPEED#ifdef DEBUG_SPEED#define DEBUG printf#else #define DEBUG#endif#define AUDIO "/dev/dsp"#define min(a,b) ((a) <= (b) ? (a) : (b))/* global data */int audio,fd;int timelimit = 0, dsp_speed = DEFAULT_DSP_SPEED, dsp_stereo = 0;int samplesize = 8;int convert = 0;int abuf_size;u_long count;u_char *audiobuf;char *command;/* needed prototypes */void recplay (u_long count);void adjust_buf(u_char *buf, int num);int test_wavefile(void *buffer);int main (int argc, char *argv[]){ u_long temp; audio_buf_info inf; count_info cinf; if(argc != 2){ printf("Usage : %s [filename]\n",argv[0]); exit(-1); } if ((audio = open (AUDIO, O_WRONLY, 0)) == -1) { perror (AUDIO); exit (-1); } if((fd = open (argv[1], O_RDONLY, 0)) == -1) { printf("Open file error or file does not exist!\n"); exit(-1); } abuf_size = -1; ioctl(audio, SNDCTL_DSP_GETBLKSIZE, &abuf_size); if (abuf_size < 4 || abuf_size > 65536) { if (abuf_size == -1){ perror (AUDIO); exit (-1); } abuf_size = 1024; } DEBUG("abuf_size = %d\n",abuf_size); if ( (audiobuf = (u_char *)malloc (abuf_size)) == NULL ) { printf ( "%s: Unable to allocate input/output buffer\n", argv[0]); exit (-1); } if (ioctl (audio, SNDCTL_DSP_SYNC, NULL) < 0) { perror(AUDIO); exit (-1); } /* set volume */ temp = 0x00; ioctl(audio,SNDCTL_DSP_SETVOL,&temp); temp = 0; /* read volume */ ioctl(audio,SNDCTL_DSP_GETVOL,&temp); printf("vol = 0x%x\n",temp); /* Following do some ioctls */ #if 0 printf("\nFollowing do some ioctls!\n"); ioctl(audio, OSS_GETVERSION, &temp); printf("SNDCTL_DSP_GETCAPS = 0x%x\n",SNDCTL_DSP_GETCAPS); printf(" The OSS Version is 0x%x\n",temp); ioctl(audio, SNDCTL_DSP_GETCAPS, &temp); printf(" Capability = 0x%x\n",temp); /* Not quite sure here */ temp = 2; ioctl(audio, SNDCTL_DSP_SETFRAGMENT, &temp); temp = 0; ioctl(audio, SNDCTL_DSP_GETBLKSIZE, &temp); printf(" BLKSIZE = %d\n",temp); ioctl(audio, SNDCTL_DSP_GETOSPACE, &inf); printf(" Output fragments = %d\n",inf.fragments); printf(" Output fragstotal = %d\n",inf.fragstotal); printf(" Output fragsize = %d\n",inf.fragsize); printf(" Output bytes = %d\n",inf.bytes); ioctl(audio, SNDCTL_DSP_GETOPTR, &cinf); printf(" Output total bytes processed = %d\n",cinf.bytes); printf(" Output fragment transitions since last time = %d\n",cinf.blocks); printf(" Output Current DMA pointer value = %d\n",cinf.ptr); printf("\n"); #endif read (fd, (char *)audiobuf, sizeof(WaveHeader)); if (test_wavefile (audiobuf) >= 0) recplay (count); close (audio); close (fd); return 0; } int test_wavefile(void *buffer) { WaveHeader *wp = buffer; #if 0 DEBUG("wp address = 0x%x\n",wp); DEBUG("main_chunk = 0x%x\n",wp->main_chunk); DEBUG("wp->chunktype = 0x%x\n",wp->chunk_type); DEBUG("wp-sub_chunk = 0x%x\n",wp->sub_chunk); DEBUG("wp->data_chunk = 0x%x\n",wp->data_chunk); #endif //if (wp->main_chunk == RIFF && wp->chunk_type == WAVE && // wp->sub_chunk == FMT && wp->data_chunk == DATA) { if (1){ if (wp->format != PCM_CODE) { printf ( "Can't play not PCM-coded WAVE-files\n"); exit (-1); } if (wp->modus > 2) { printf ( "Can't play WAVE-files with %d tracks\n", wp->modus); exit (-1); } dsp_stereo = (wp->modus == WAVE_STEREO) ? 1 : 0; samplesize = wp->bit_p_spl; dsp_speed = wp->sample_fq; count = wp->data_length; DEBUG("In test_wavefile dsp_stereo=%d\n",dsp_stereo); DEBUG("In test_wavefile samplesize=%d\n",samplesize); DEBUG("In test_wavefile dsp_speed=%d\n",dsp_speed); DEBUG("In test_wavefile count=%ld\n",count); return 0; } return -1; } void sync_dsp(void) {#if 0 if (ioctl (audio, SNDCTL_DSP_SYNC, NULL) < 0) { perror(AUDIO); exit (-1); }#endif } /* setting the speed for output */ void set_dsp_speed (int *dsp_speed) { if (ioctl(audio, SNDCTL_DSP_SPEED, dsp_speed) < 0) { printf ( "%s: unable to set audio speed\n", command); perror (AUDIO); exit (-1); } }#if 0 /* if to_mono: compress 8 bit stereo data 2:1, needed if we want play 'one track'; this is usefull, if you habe SB 1.0 - 2.0 (I have 1.0) and want hear the sample (in Mono) if to_8: compress 16 bit to 8 by using hi-byte; wave-files use signed words, so we need to convert it in "unsigned" sample (0x80 is now zero) WARNING: this procedure can't compress 16 bit stereo to 16 bit mono, because if you have a 16 (or 12) bit card you should have stereo (or I'm wrong ?? ) */ u_long one_channel(u_char *buf, u_long l, char to_mono, char to_8) { register u_char *w = buf; register u_char *w2 = buf; char ofs = 0; u_long incr = 0; u_long c, ret; if (to_mono) ++incr; if (to_8) { ++incr; ++w2; ofs = 128; } ret = c = l >> incr; incr = incr << 1; while (c--) { *w++ = *w2 + ofs; w2 += incr; } return ret;}#endif#if 0/* calculate the data count to read from/to dsp */u_long calc_count(void){ u_long count; if (!timelimit) count = 0x7fffffff; else { count = timelimit * dsp_speed; if (dsp_stereo) count *= 2; if (samplesize != 8) count *= 2; } return count;}#endifvoid recplay (u_long count){ int length, real_l; u_long c,i; int nbytes; int point; char one_chn = 0; char to_8 = 0; int tmps; if(samplesize != 16){ printf("Currently onlys support 16 bits !\n"); exit (-1); } //DEBUG("In recplay"); sync_dsp(); set_dsp_speed (&dsp_speed); printf ( "Playing WAV " ); printf ( "Speed %d Hz ", dsp_speed); printf ( "%d bits ", samplesize); printf ( "%s ...\n", dsp_stereo ? "Stereo" : "Mono"); nbytes = abuf_size; if( !dsp_stereo) nbytes >>= 1; if(samplesize == 8) nbytes >>= 1; DEBUG("abuf_size = %d nbytes = %d\n",abuf_size,nbytes); while (count) { c = count; if (c > abuf_size) c = abuf_size; #if 0 if (point > abuf_size) point = abuf_size/8; if(!dsp_stereo) point /= 2; if(samplesize == 16){ point /= 2; } else if (samplesize == 8){ } #endif for(i=0; i<abuf_size/nbytes; i++){ if((length = read (fd, (char *)audiobuf, nbytes)) > 0) { if(!dsp_stereo){ adjust_buf(audiobuf,nbytes); length *= 2; } if (write (audio, (char *)audiobuf, length) != length) { perror (AUDIO); exit (-1); } count -= nbytes; } else{ if (length == -1) { printf("Error!\n"); exit (-1); } count = 0; /* Stop */ } } #if 0 if((l = read (fd, (char *)audiobuf + loaded, c - loaded)) > 0) { //DEBUG("l = %d\t loaded = %d\t",l,loaded); l += loaded; loaded = 0; /* correct the count; ugly but ... */ real_l = (one_chn || to_8) ? one_channel(audiobuf, l, one_chn, to_8) : l; //DEBUG("real_l = %d\n",real_l); /* change byte order if necessary */ if(convert && (samplesize==16)){ long i; for(i=0; i< real_l; i+=2) *( (short*) (audiobuf+i) ) = htons( *( (short*) (audiobuf+i))); } if (write (audio, (char *)audiobuf, real_l) != real_l) { perror (AUDIO); exit (-1); } count -= l; } else{ if (l == -1) { printf("Error!\n"); exit (-1); } count = 0; /* Stop */ } #endif } /* while (count) */}void adjust_buf(u_char *buf, int num){#if 1//u_char *p=(buf+num-1);u_short *tail = (u_short *)(buf+num*2-2);u_short *begin = (u_short *)(buf+num-2);int i; if(samplesize == 16){ for(i=0; i<num/2; i++){ //printf("tail = %x *tail = 0x%x begin = %x *begin = 0x%x\n",tail,*tail,begin,*begin); *(tail--) = *begin; *(tail--) = *begin--; } }//if(samplesize==16) else if(samplesize ==8){#if 0 for(i=0; i<num; i++,p--){ *(tail) = (((u_short)(*p)) << 8)&0xff00; *(tail-1) = *tail; tail-=2; }#endif }#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -