"Fossies" - the Fresh Open Source Software archive

Member "tplay-0.6.1/audio_oss.c" of archive tplay-0.6.1.tar.gz:


/* 
 * tplay - buffered audio player
 *
 * (c) 1997 ilkka karvinen <ik@iki.fi>
 *
 * Copyright under the GNU GENERAL PUBLIC LICENSE
 *   (see the file COPYING in this directory)
 *
 * 
 *   common functions for audio in OSS/API machines
 */

#include <stdarg.h>
#include "common.h"
#include "audio_oss.h"


void open_audio()
{
  int block_size;
  char *device;

  /* Use predefined audio device if info.device is not set     */
  /* (is NULL). Otherwise use user given audio device.         */
  if (info.device == NULL)
    device = AUDIO_DEVICE;
  else
    device = info.device;

  if ((info.audio_fd = open(device, O_WRONLY, 0)) == -1)
    errdie("Cannot open audio device");

  ioctl(info.audio_fd, SNDCTL_DSP_GETBLKSIZE, &block_size);

  /* Audio device driver may give exotic audio buffer size     */
  /* for some adapters, we'd better set limits to it           */
  /* In the newer sound drivers, this should work according to */
  /* 4Front documents                                          */
  if (block_size < MIN_BLOCK_SIZE)
    block_size = MIN_BLOCK_SIZE;
  else if (block_size > MAX_BLOCK_SIZE)
    block_size = MAX_BLOCK_SIZE;

  /* Set audio block size and number of blocks */
  info.blocksize = block_size;

}

void set_audio_parameters()
{
  int format, stereo, stereo0, speed0;
  double percentage;

  /*   sync_audio(); */
  reset_audio();

  stereo = 1;
  switch(info.channels) {
  case 1 :
    stereo = 0;
    break;
  case 2 :
    stereo = 1;
    break;
  default :
    if (!info.force)
      errdie("Invalid number of channels");
    break;
  }

  /* Set format */
  format = info.encoding;
  if (ioctl(info.audio_fd, SNDCTL_DSP_SETFMT, &format) == -1)
    errdie("SNDCTL_DSP_SETFMT");

  if (!info.force && (format != info.encoding))
    errdie("Audio device doesn't support this precision");

  /* Set stereo mode */
  stereo0 = stereo;
  if (ioctl(info.audio_fd, SNDCTL_DSP_STEREO, &stereo0) == -1)
    errdie("SNDCTL_DSP_STEREO");

  if (!info.force && (stereo0 != stereo))
    errdie("Audio device doesn't support stereo mode");

  info.channels = stereo0 + 1;

  /* Set sampling speed */
  speed0 = info.speed;
  if (ioctl(info.audio_fd, SNDCTL_DSP_SPEED, &speed0) == -1)
    errdie("SNDCTL_DSP_SPEED");

  /* Q: What to do if you cannot tune audio-card on exact speed? */
  /* Author: Jerko Golubovic <jerko.golubovic@public.srce.hr> */
  /* */
  /* Variant A: you force playing even if speed is not exact */
  /*   - Don't say anything - user choosed this way with force option */
  /*     We assume he/she knows what this means..... */
  /*   - Just skip and go ahead, jump :) (100.000 Lemmings can't be wrong :) )*/
  if (!info.force) { 
  /* Variant B: you don't force playing if speed is not exact */
     /* If speed doesn't match, die and inform user about alternative */
     if (speed0 != info.speed) { 
	fprintf(stderr, "Audio device doesn't support requested speed\n");
	fprintf(stderr, " -> Requested: %d Hz, Got: %d Hz", info.speed, speed0);
	percentage = ( (speed0-info.speed)/(double)info.speed ) * 100.0;
	fprintf(stderr, " (%+dHz/%+.2f%%) \n", speed0-info.speed, percentage);
	errdie("Use --force or -f in command-line to override.");
     }
     /*	If they match, you have:       */
     /*    a) good audio-card          */
     /*    b) reasonable requirements  */
     /* Just proceed and be happy about. Don't bother user with messages :) */
  }

  info.speed = speed0;

  /*  sync_audio(); */
}

void sync_audio(void)
{
  if (ioctl(info.audio_fd, SNDCTL_DSP_SYNC, NULL) < 0)
    errdie("Audio sync failed");
}

void reset_audio(void)
{
  if (ioctl(info.audio_fd, SNDCTL_DSP_RESET, 0) < 0)
    errdie("Audio reset failed");
}

void post_audio(void)
{
  if (ioctl(info.audio_fd, SNDCTL_DSP_POST, 0) < 0)
    errdie("Audio reset failed");
}

void close_audio(void)
{
  if (info.audio_fd != -1) {
    close(info.audio_fd);
    info.audio_fd = -1;
  }
}