/* playing raw data, this proc handels WAVE files and
   .VOCs (as one block) */
static int
do_play (int fd, int loaded, u_long count, int rtype, char *name)
{
  int l, real_l;
  u_long c;
  char one_chn = 0;
  char to_8 = 0;
  int tmps;

  sync_dsp ();
  tmps = samplesize;
  ioctl (audio, SNDCTL_DSP_SETFMT, &tmps);
  if (tmps != samplesize)
    {
      fprintf (stderr, "Unable to set %d bit sample size", samplesize);
      if (samplesize == 16)
	{
	  samplesize = 8;
	  ioctl (audio, SNDCTL_DSP_SETFMT, &samplesize);
	  if (samplesize != 8)
	    {
	      fprintf (stderr, "Unable to set 8 bit sample size!\n");
	      return -1;
	    }
	  fprintf (stderr, "; playing 8 bit\n");
	  to_8 = 1;
	}
      else
	{
	  fprintf (stderr, "\n");
	  return -1;
	}
    }
#ifdef OSS_VERSION
  if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo) < 0)
    {
#else
  if (dsp_stereo != ioctl (audio, SNDCTL_DSP_STEREO, dsp_stereo))
    {
#endif
      fprintf (stderr, "Can't play in Stereo; playing only one channel\n");
      dsp_stereo = MODE_MONO;
      one_chn = 1;
    }
  if (set_dsp_speed (&dsp_speed) < 0)
    return -1;

  abuf_size = 512;

  while (count)
    {
      c = count;

      if (c > abuf_size)
	c = abuf_size;

      if ((l = read (fd, (char *) audiobuf + loaded, c - loaded)) > 0)
	{
	  l += loaded;
	  loaded = 0;		/* correct the count; ugly but ... */
	  real_l = (one_chn
		    || to_8) ? one_channel (audiobuf, l, one_chn, to_8) : 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);
	      return -1;
	    }
	  count -= l;
	}
      else
	{
	  if (l == -1)
	    {
	      perror (name);
	      return -1;
	    }
	  count = 0;		/* Stop */
	}
    }				/* while (count) */

  return 0;
}

/*
  let's play)
*/
static int
player (char *name)
{
  int fd, ofs;

  if (!name)
    {
      fd = 0;
      name = "stdin";
    }
  else if ((fd = open (name, O_RDONLY, 0)) == -1)
    {
      perror (name);
      return -1;
    }
  /* Read the smallest header first, then the
     missing bytes for the next, etc. */

  /* read SND-header */
  read (fd, (char *) audiobuf, sizeof (SndHeader));
  if (test_sndfile (audiobuf, fd) >= 0)
    {
      if (do_play (fd, 0, count, SND_FMT, name) < 0)
	return -1;
    }

  else
    {
      /* read VOC-Header */
      read (fd, (char *) audiobuf + sizeof (SndHeader),
	    sizeof (VocHeader) - sizeof (SndHeader));
      if ((ofs = test_vocfile (audiobuf)) >= 0)
	{
	  if (vplay (fd, ofs, name) < 0)
	    return -1;
	}

      else
	{
	  /* read bytes for WAVE-header */
	  read (fd, (char *) audiobuf + sizeof (VocHeader),
		sizeof (WaveHeader) - sizeof (VocHeader));
	  if (test_wavefile (audiobuf) >= 0)
	    {
	      if (do_play (fd, 0, count, WAVE_FMT, name) < 0)
		return -1;
	    }
	  else
	    {
	      /* should be raw data */
	      init_raw_data ();
	      count = calc_count ();
	      if (do_play (fd, sizeof (WaveHeader), count, RAW_DATA, name) <
		  0)
		return -1;
	    }
	}
    }
  if (fd != 0)
    close (fd);
  return 0;
}
Exemple #2
0
int music::play_music()
{


    MainWindow *mine=(MainWindow*)arg;
    mine->my_words();
        int music_len;
        long rate;
        char* buf;
        long n;
        int min;
        min=ftell(music_fp);
        music_len = head.ChunkSize+8;

        mine->set_line(music_len,min);

        ///安装dsp  设置 			 采样率   声道个数
        if(setup_dsp(dsp_fd,head.SampleRate,head.NumChannels) != 0)
        {
                perror("setup_dsp failed");
                return -1;
        }
        ////生效setup_dsp设置
        if(sync_dsp(dsp_fd) != 0)
        {
                perror("sync dsp failed");
                return -1;
        }
        //-----设置采样率--------
    //采样位数*采样率/8 =  字节数量
    //+7 方式采样率不是8的整数倍的情况
    //  /8*2 = /4 都按照双声道处理
    //size =  (head.BitsPerSample*head.SampleRate+7)>>2;
    rate = head.ByteRate;	//每次读取的字节 = 字节速率
    buf = (char*)malloc(rate);	//音乐数据缓存


        if(buf != NULL)
        {
                do{

                        pthread_mutex_lock(&my_mutex);
                        pthread_mutex_unlock(&my_mutex);

                        mine->word_move();
                        n = fread(buf,1,rate,music_fp);
                        //cout<<"n:"<<n<<endl;
                        if(n > 0)
                        {

                            write(dsp_fd,buf,n);

                        }

                        if(feof(music_fp))
                        {

                            perror("play over.");
                                break;
                        }

                        mine->add_second();
                        mine->move_line(ftell(music_fp));
                        this->set_vol();
                }while(1);


        }
    return 1;

}
/*
  ok, let's play a .voc file
*/
static int
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_SETFMT, &samplesize);
  if (samplesize != VOC_SAMPLESIZE)
    {
      fprintf (stderr, "Unable to set 8 bit sample size!\n");
      return -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);
		  return -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:
	      d_printf ((stderr, "Terminator\n"));
	      return -1;	/* 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);
		  d_printf ((stderr, "Voice data %d Hz\n", dsp_speed));
		  if (vd->pack)
		    {		/* /dev/dsp can't it */
		      fprintf (stderr, "Can't play packed .voc files\n");
		      return -1;
		    }
		  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 ? */
		    dsp_stereo = MODE_MONO;
		  else if (dsp_stereo)
		    {		/* want Stereo */
		      /* shit, my MACRO dosn't work here */
#ifdef OSS_VERSION
		      if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo) < 0)
			{
#else
		      if (dsp_stereo !=
			  ioctl (audio, SNDCTL_DSP_STEREO, dsp_stereo))
			{
#endif
			  dsp_stereo = MODE_MONO;
			  fprintf (stderr,
				   "Can't play in Stereo; playing only one channel\n");
			  one_chn = 1;
			}
		    }
		  was_extended = 0;
		}
	      if (set_dsp_speed (&dsp_speed) < 0)
		return -1;
	      break;
	    case 2:		/* nothing to do, pure data */
	      d_printf ((stderr, "Voice continuation\n"));
	      break;
	    case 3:		/* a silence block, no data, only a count */
	      sp = (u_short *) data;
	      COUNT (sizeof (u_short));
	      dsp_speed = (int) (*data);
	      COUNT (1);
	      dsp_speed = 1000000 / (256 - dsp_speed);
	      sync_dsp ();
	      if (set_dsp_speed (&dsp_speed) < 0)
		return -1;
	      silence = (((u_long) * sp) * 1000) / dsp_speed;
	      d_printf ((stderr, "Silence for %ld ms\n", silence));
	      break;
	    case 4:		/* a marker for syncronisation, no effect */
	      sp = (u_short *) data;
	      COUNT (sizeof (u_short));
	      d_printf ((stderr, "Marker %d\n", *sp));
	      break;
	    case 5:		/* ASCII text, we copy to stderr */
	      output = 1;
	      d_printf ((stderr, "ASCII - text :\n"));
	      break;
	    case 6:		/* repeat marker, says repeatcount */
	      /* my specs don't say it: maybe this can be recursive, but
	         I don't think somebody use it */
	      repeat = *(u_short *) data;
	      COUNT (sizeof (u_short));
	      d_printf ((stderr, "Repeat loop %d times\n", repeat));
	      if (filepos >= 0)	/* if < 0, one seek fails, why test another */
		if ((filepos = lseek (fd, 0, 1)) < 0)
		  {
		    fprintf (stderr,
			     "Can't play loops; %s isn't seekable\n", name);
		    repeat = 0;
		  }
		else
		  filepos -= in_buffer;	/* set filepos after repeat */
	      else
		repeat = 0;
	      break;
	    case 7:		/* ok, lets repeat that be rewinding tape */
	      if (repeat)
		{
		  if (repeat != 0xFFFF)
		    {
		      d_printf ((stderr, "Repeat loop %d\n", repeat));
		      --repeat;
		    }
		  else
		    d_printf ((stderr, "Neverending loop\n"));
		  lseek (fd, filepos, 0);
		  in_buffer = 0;	/* clear the buffer */
		  goto Fill_the_buffer;
		}
	      else
		d_printf ((stderr, "End repeat loop\n"));
	      break;
	    case 8:		/* the extension to play Stereo, I have SB 1.0 :-( */
	      was_extended = 1;
	      eb = (Ext_Block *) data;
	      COUNT (sizeof (Ext_Block));
	      dsp_speed = (int) (eb->tc);
	      dsp_speed = 256000000L / (65536 - dsp_speed);
	      dsp_stereo = eb->mode;
	      if (dsp_stereo == MODE_STEREO)
		dsp_speed = dsp_speed >> 1;
	      if (eb->pack)
		{		/* /dev/dsp can't it */
		  fprintf (stderr, "Can't play packed .voc files\n");
		  return -1;
		}
	      d_printf ((stderr, "Extended block %s %d Hz\n",
			 (eb->mode ? "Stereo" : "Mono"), dsp_speed));
	      break;
	    default:
	      fprintf (stderr, "Unknown blocktype %d. terminate.\n",
		       bp->type);
	      return -1;
	    }			/* switch (bp->type) */
	}			/* while (! nextblock)  */
      /* put nextblock data bytes to dsp */
      l = min (in_buffer, nextblock);
      if (l)
	{
	  if (output && !quiet_mode)
	    write (2, data, l);	/* to stderr */
	  else
	    {
	      real_l = one_chn ? one_channel (data, l, one_chn, 0) : l;
	      if (write (audio, data, real_l) != real_l)
		{
		  perror (AUDIO);
		  return -1;
		}
	    }
	  COUNT (l);
	}
    }				/* while(1) */
}

/* that was a big one, perhaps somebody split it :-) */

/* setting the globals for playing raw data */
static void
init_raw_data (void)
{
  timelimit = raw_info.timelimit;
  dsp_speed = raw_info.dsp_speed;
  dsp_stereo = raw_info.dsp_stereo;
  samplesize = raw_info.samplesize;
}