⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vplay.c

📁 fix point版本的Ogg Vorbis decoder
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   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>#ifndef __STDC__#include <getopt.h>#endif /* __STDC__ */#include <fcntl.h>#include <sys/ioctl.h>#ifdef __STDC__#include <sys/soundcard.h>#else /* __STDC__ */#include <linux/soundcard.h>#endif /* __STDC__ */#include "fmtheaders.h"/* trying to define independent ioctl for sounddrivers version 1 and 2+ ,   but it dosn't work everywere */#ifdef SOUND_VERSION#define IOCTL(a,b,c)		ioctl(a,b,&c)#else#define IOCTL(a,b,c)		(c = ioctl(a,b,c) )#endif#define DEFAULT_DSP_SPEED 	8000#define RECORD	0#define PLAY	1#define AUDIO "/dev/dsp"#define min(a,b) 		((a) <= (b) ? (a) : (b))#ifdef __STDC__#define d_printf(x)        if (verbose_mode) fprintf x#else /* __STDC__ */#define d_printf(f,a...)        if (verbose_mode) fprintf (stderr,f,##a)#endif /* __STDC__ */#define VOC_FMT			0#define WAVE_FMT		1#define RAW_DATA		2/* global data */int timelimit = 0, dsp_speed = DEFAULT_DSP_SPEED, dsp_stereo = 0;int samplesize   = 8;int quiet_mode   = 0;int verbose_mode = 0;int record_type  = VOC_FMT;u_long count;int audio, abuf_size, zbuf_size;int direction, omode;u_char *audiobuf, *zerobuf;char *command;int vocminor, vocmajor;		/* .VOC version *//* defaults for playing raw data */struct {  int timelimit, dsp_speed, dsp_stereo, samplesize;} raw_info = { 0, DEFAULT_DSP_SPEED, 0, 8 };/* needed prototypes */void record_play (char *name);void start_voc (int fd, u_long count);void start_wave (int fd, u_long count);void end_voc (int fd);void end_wave_raw (int fd);struct fmt_record {  void (*start) (int fd, u_long count);  void (*end) (int fd);  char *what;} fmt_rec_table[] = {  { start_voc,  end_voc,      "VOC" },  { start_wave, end_wave_raw, "WAVE" },  { NULL,       end_wave_raw, "raw data" }}; int main (int argc, char *argv[]){  int c;  command = argv[0];  if (strstr (argv[0], "vrec")) {    direction = RECORD;    omode = O_RDONLY;  }  else if (strstr (argv[0], "vplay")) {    direction = PLAY;    omode = O_WRONLY;  }  else {    fprintf (stderr,             "Error: command should be named either vrec or vplay\n");    exit (1);  }  while ((c = getopt (argc, argv, "qs:St:b:vrwd")) != EOF)    switch (c) {      case 'S':	dsp_stereo = raw_info.dsp_stereo = 1;	break;      case 'q':	quiet_mode = 1;	break;      case 'r':        record_type = RAW_DATA;        break;      case 'v' :        record_type = VOC_FMT;        break;      case 'w' :        record_type = WAVE_FMT;        break;      case 's':	dsp_speed = atoi (optarg);	if (dsp_speed < 300)	  dsp_speed *= 1000;        raw_info.dsp_speed = dsp_speed;	break;      case 't':	timelimit = raw_info.timelimit = atoi (optarg);	break;      case 'b':	samplesize = raw_info.samplesize = atoi (optarg);	break;      case 'd':        verbose_mode = 1; quiet_mode = 0;        break;      default:	fprintf (stderr, 	 "Usage: %s [-qvwrS] [-t secs] [-s Hz] [-b 8|12|16] [filename]\n", command);	exit (-1);    }  audio = open (AUDIO, omode, 0);  if (audio == -1) {    perror (AUDIO);    exit (-1);  }  IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);  if (abuf_size < 1024 || abuf_size > 65536) {    if (abuf_size == -1)      perror (AUDIO);    else//      fprintf (stderr, "Invalid audio buffers size %d\n", abuf_size);//    exit (-1);	abuf_size = 1024;  }   zbuf_size = 256;  if ( (audiobuf = (u_char *)malloc (abuf_size)) == NULL ||       (zerobuf  = (u_char *)malloc (zbuf_size)) == NULL )  {    fprintf (stderr, "%s: unable to allocate input/output buffer\n", command);    exit (-1);  }  memset ((char *)zerobuf, 128, zbuf_size);   if (optind > argc - 1)    record_play (NULL);  else    while (optind <= argc - 1) {      record_play (argv[optind++]);    }  close (audio);  return 0;}/* test, if it is a .VOC file and return >=0 if ok (this is the length of rest)                                       < 0 if not */int test_vocfile(void *buffer){  VocHeader *vp = buffer;  if (strstr((const char *)vp->magic, MAGIC_STRING) ) {    vocminor = vp->version & 0xFF;    vocmajor = vp->version / 256;    if (vp->version != (0x1233 - vp->coded_ver) )      return -2;				/* coded version mismatch */    return vp->headerlen - sizeof(VocHeader);	/* 0 mostly */  }  return -1;					/* magic string fail */}/* test, if it's a .WAV file, 0 if ok (and set the speed, stereo etc.)                          < 0 if not*/int test_wavefile(void *buffer){  WaveHeader *wp = buffer;  if (wp->main_chunk == RIFF && wp->chunk_type == WAVE &&      wp->sub_chunk == FMT && wp->data_chunk == DATA) {    if (wp->format != PCM_CODE) {      fprintf (stderr, "%s: can't play not PCM-coded WAVE-files\n", command);      exit (-1);    }    if (wp->modus > 2) {      fprintf (stderr, "%s: can't play WAVE-files with %d tracks\n",               command, 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;    return 0;  }  return -1;} /*  writing zeros from the zerobuf to simulate silence,  perhaps it's enough to use a long var instead of zerobuf ?*/void write_zeros (unsigned x){  unsigned l;   while (x) {    l = min (x, zbuf_size);    if (write (audio, (char *)zerobuf, l) != l) {      perror (AUDIO);      exit (-1);    }    x -= l;  }} /* if need a SYNC,    (is needed if we plan to change speed, stereo ... during output)*/#ifdef __STDC__void sync_dsp(void)#else /* __STDC__ */inline void sync_dsp(void)#endif /* __STDC__ */{  if (ioctl (audio, SNDCTL_DSP_SYNC, NULL) < 0) {    perror(AUDIO);    exit (-1);  }}/* setting the speed for output */void set_dsp_speed (int dsp_speed){  if (IOCTL(audio, SNDCTL_DSP_SPEED, dsp_speed) < 0) {    fprintf (stderr, "%s: unable to set audio speed\n", command);    perror (AUDIO);    exit (-1);  }}/* 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 ?? )   */#ifdef __STDC__u_long one_channel(u_char *buf, u_long l, char to_mono, char to_8)#else /* __STDC__ */inline u_long one_channel(char *buf, u_long l, char to_mono, char to_8)#endif /* __STDC__ */{  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;}/*  ok, let's play a .voc file*/ void vplay (int fd, int ofs, char *name){  int l, real_l;  BlockType *bp;  Voice_data *vd;  Ext_Block *eb;  u_long nextblock, in_buffer;  u_char *data = audiobuf;  char was_extended = 0, output = 0;  u_short *sp, repeat = 0;  u_long silence;  int filepos = 0;  char one_chn = 0;#define COUNT(x)	nextblock -= x; in_buffer -=x ;data += x  /* first SYNC the dsp */  sync_dsp();   if (!quiet_mode)     fprintf (stderr, "Playing Creative Labs Voice file ...\n");  /* first we waste the rest of header, ugly but we don't need seek */  while (ofs > abuf_size) {	    read (fd, (char *)audiobuf, abuf_size);    ofs -= abuf_size;  }  if (ofs)    read (fd, audiobuf, ofs);  /* .voc files are 8 bit (now) */  samplesize = VOC_SAMPLESIZE;  IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);  if (samplesize != VOC_SAMPLESIZE) {    fprintf(stderr, "%s: unable to set 8 bit sample size!\n", command);    exit (-1);  }  /* and there are MONO by default */  dsp_stereo = MODE_MONO;  IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);  in_buffer = nextblock = 0;  while (1) {    Fill_the_buffer:		/* need this for repeat */    if ( in_buffer < 32 ) {      /* move the rest of buffer to pos 0 and fill the audiobuf up */      if (in_buffer)        memcpy ((char *)audiobuf, data, in_buffer);      data = audiobuf;      if ((l = read (fd, (char *)audiobuf + in_buffer, abuf_size - in_buffer) ) > 0)         in_buffer += l;      else if (! in_buffer) {	/* the file is truncated, so simulate 'Terminator'            and reduce the datablock for save landing */        nextblock = audiobuf[0] = 0;        if (l == -1) {          perror (name);          exit (-1);        }      }    }    while (! nextblock) { 	/* this is a new block */      bp = (BlockType *)data; COUNT(sizeof (BlockType));      nextblock = DATALEN(bp);      if (output && !quiet_mode)        fprintf (stderr, "\n");	/* write /n after ASCII-out */      output = 0;      switch (bp->type) {        case 0:#ifdef __STDC__          d_printf ((stderr, "Terminator\n"));#else /* __STDC__ */          d_printf ("Terminator\n");#endif /* __STDC__ */          return;		/* VOC-file stop */        case 1:          vd = (Voice_data *)data; COUNT(sizeof(Voice_data));          /* we need a SYNC, before we can set new SPEED, STEREO ... */          sync_dsp();          if (! was_extended) {            dsp_speed = (int)(vd->tc);            dsp_speed = 1000000 / (256 - dsp_speed); #ifdef __STDC__            d_printf ((stderr, "Voice data %d Hz\n", dsp_speed));#else /* __STDC__ */            d_printf ("Voice data %d Hz\n", dsp_speed);#endif /* __STDC__ */            if (vd->pack) {	/* /dev/dsp can't it */              fprintf (stderr, "%s: can't play packed .voc files\n", command);              return;            }            if (dsp_stereo) {	/* if we are in Stereo-Mode, switch back */              dsp_stereo = MODE_MONO;              IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);             }          }          else {		/* there was extended block */            if (one_chn)	/* if one Stereo fails, why test another ? */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -