sndconfig.c
上传用户:xiejiait
上传日期:2007-01-06
资源大小:881k
文件大小:9k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)sndconfig.c 1.3 00/01/02 Copyright 1998,1999,2000 Heiko Eissfeldt */
  2. #ifndef lint
  3. static char     sccsid[] =
  4. "@(#)sndconfig.c 1.3 00/01/02 Copyright 1998,1999,2000 Heiko Eissfeldt";
  5. #endif
  6. /* os dependent functions */
  7. #include "config.h"
  8. #include <stdio.h>
  9. #include <strdefs.h>
  10. #include <fcntl.h>
  11. #include <unistd.h>
  12. #include <sys/ioctl.h>
  13. /* soundcard setup */
  14. #if defined (HAVE_SOUNDCARD_H) || defined (HAVE_LINUX_SOUNDCARD_H) || defined (HAVE_SYS_SOUNDCARD_H) || defined (HAVE_MACHINE_SOUNDCARD_H)
  15. # if defined (HAVE_SOUNDCARD_H)
  16. #  include <soundcard.h>
  17. # else
  18. #  if defined (HAVE_MACHINE_SOUNDCARD_H)
  19. #   include <machine/soundcard.h>
  20. #  else
  21. #   if defined (HAVE_SYS_SOUNDCARD_H)
  22. #    include <sys/soundcard.h>
  23. #   else
  24. #    if defined (HAVE_LINUX_SOUNDCARD_H)
  25. #     include <linux/soundcard.h>
  26. #    endif
  27. #   endif
  28. #  endif
  29. # endif
  30. #endif
  31. #include "mytype.h"
  32. #include "byteorder.h"
  33. #include "lowlevel.h"
  34. #include "global.h"
  35. #include "sndconfig.h"
  36. #ifdef ECHO_TO_SOUNDCARD
  37. #   if defined(__CYGWIN32__)
  38. #include <windows.h>
  39. #include "mmsystem.h"
  40. #endif
  41. static char snd_device[200] = SOUND_DEV;
  42. int set_snd_device(devicename)
  43. const char *devicename;
  44. {
  45. strncpy(snd_device, devicename, sizeof(snd_device));
  46. return 0;
  47. }
  48. #if defined __CYGWIN32__
  49. static HWAVEOUT DeviceID;
  50. #define WAVEHDRS 3
  51. static WAVEHDR wavehdr[WAVEHDRS];
  52. static unsigned lastwav = 0;
  53. static int check_winsound_caps __PR((int bits, double rate, int channels));
  54. static int check_winsound_caps(bits, rate, channels)
  55. int bits;
  56. double rate;
  57. int channels;
  58. {
  59.   int result = 0;
  60.   WAVEOUTCAPS caps;
  61.   /* get caps */
  62.   if (waveOutGetDevCaps(0, &caps, sizeof(caps))) {
  63.      fprintf(stderr, "cannot get soundcard capabilities!n");
  64.      return 1;
  65.   }
  66.   /* check caps */
  67.   if ((bits == 8 && !(caps.dwFormats & 0x333)) ||
  68.       (bits == 16 && !(caps.dwFormats & 0xccc))) {
  69.       fprintf(stderr, "%d bits sound are not supportedn", bits);
  70.       result = 2;
  71.   }
  72.   if ((channels == 1 && !(caps.dwFormats & 0x555)) ||
  73.       (channels == 2 && !(caps.dwFormats & 0xaaa))) {
  74.       fprintf(stderr, "%d sound channels are not supportedn", channels);
  75.       result = 3;
  76.   }
  77.   if ((rate == 44100.0 && !(caps.dwFormats & 0xf00)) ||
  78.       (rate == 22050.0 && !(caps.dwFormats & 0xf0)) ||
  79.       (rate == 11025.0 && !(caps.dwFormats & 0xf))) {
  80.       fprintf(stderr, "%d sample rate is not supportedn", (int)rate);
  81.       result = 4;
  82.   }
  83.   return result;
  84. }
  85. #endif
  86. #endif
  87. #ifdef HAVE_SUN_AUDIOIO_H
  88. # include <sun/audioio.h>
  89. #endif
  90. #ifdef HAVE_SYS_AUDIOIO_H
  91. # include <sys/audioio.h>
  92. #endif
  93. int init_soundcard(rate, bits)
  94. double rate;
  95. int bits;
  96. {
  97. #ifdef ECHO_TO_SOUNDCARD
  98.   if (global.echo) {
  99. # if defined(HAVE_OSS) && HAVE_OSS == 1
  100.     if (open_snd_device() != 0) {
  101. perror("");
  102.         fprintf(stderr, "Cannot open %sn",snd_device);
  103.         global.echo = 0;
  104.     } else { 
  105. /* This the sound device initialisation for 4front Open sound drivers */
  106. int dummy;
  107. int garbled_rate = rate;
  108. int stereo = (global.channels == 2);
  109. int format = bits == 8 ? AFMT_U8 :
  110.          (MY_LITTLE_ENDIAN ? AFMT_S16_LE : AFMT_S16_BE);
  111. int mask;
  112. if (ioctl(global.soundcard_fd, (int)SNDCTL_DSP_GETBLKSIZE, &dummy) == -1) {
  113.     fprintf(stderr, "Cannot get blocksize for %sn", snd_device);
  114.     global.echo = 0;
  115. }
  116. if (ioctl(global.soundcard_fd, (int)SNDCTL_DSP_SYNC, NULL) == -1) {
  117.     fprintf(stderr, "Cannot sync for %sn", snd_device);
  118.     global.echo = 0;
  119. }
  120. /* check, if the sound device can do the requested format */
  121. if (ioctl(global.soundcard_fd, (int)SNDCTL_DSP_GETFMTS, &mask) == -1) {
  122. perror("fatal error:");
  123. return -1;
  124. }
  125. if ((mask & format) == 0) {
  126. fprintf(stderr, "sound format (%d bits signed) is not availablen", bits);
  127. if ((mask & AFMT_U8) != 0) {
  128. bits = 8;
  129. format = AFMT_U8;
  130. }
  131. }
  132. if (ioctl(global.soundcard_fd, (int)SNDCTL_DSP_SETFMT, &format) == -1) {
  133.     fprintf(stderr, "Cannot set %d bits/sample for %sn",bits, snd_device);
  134.     global.echo = 0;
  135. }
  136. /* limited sound devices may not support stereo */
  137. if (stereo
  138.     && ioctl(global.soundcard_fd, (int)SNDCTL_DSP_STEREO, &stereo) == -1) {
  139.     fprintf(stderr, "Cannot set stereo mode for %sn", snd_device);
  140.     stereo = 0;
  141. }
  142. if (!stereo
  143.             && ioctl(global.soundcard_fd, (int)SNDCTL_DSP_STEREO, &stereo) == -1) {
  144.     fprintf(stderr, "Cannot set mono mode for %sn", snd_device);
  145.     global.echo = 0;
  146. }
  147. /* set the sample rate */
  148. if (ioctl(global.soundcard_fd, (int)SNDCTL_DSP_SPEED, &garbled_rate) == -1) {
  149.     fprintf(stderr, "Cannot set rate %d.%2d Hz for %sn",
  150. (int)rate, (int)(rate*100)%100, snd_device);
  151.     global.echo = 0;
  152. }
  153. if ( abs((long)rate - garbled_rate) > rate / 20) {
  154.     fprintf(stderr, "sound device: next best sample rate is %dn",garbled_rate);
  155. }
  156.     }
  157. # else /* HAVE_OSS */
  158. #  if defined HAVE_SYS_AUDIOIO_H || defined HAVE_SUN_AUDIOIO_H
  159. /* This is the SunOS / Solaris and compatibles sound initialisation */
  160.     if ((global.soundcard_fd = open(snd_device, O_WRONLY, 0)) == EOF) {
  161. perror("");
  162.         fprintf(stderr, "Cannot open %sn",snd_device);
  163.         global.echo = 0;
  164.     } else { 
  165.         audio_info_t            info;
  166. #   if defined (AUDIO_INITINFO) && defined (AUDIO_ENCODING_LINEAR)
  167.         AUDIO_INITINFO(&info);
  168.         info.play.sample_rate = rate;
  169.         info.play.channels = global.channels;
  170.         info.play.precision = bits;
  171.         info.play.encoding = AUDIO_ENCODING_LINEAR;
  172.         info.play.pause = 0;
  173.         info.record.pause = 0;
  174.         info.monitor_gain = 0;
  175.         if (ioctl(global.soundcard_fd, AUDIO_SETINFO, &info) < 0) {
  176.     fprintf(stderr, "Cannot init %s (sun)n", snd_device);
  177.     global.echo = 0;
  178. }
  179. #   else
  180. fprintf(stderr, "Cannot init sound device with 44.1 KHz sample rate on %s (sun compatible)n", snd_device);
  181. global.echo = 0;
  182. #   endif
  183.     }
  184. #  else /* SUN audio */
  185. #   if defined(__CYGWIN32__)
  186.     /* Windows sound info */
  187.     MMRESULT mmres;
  188.     WAVEFORMATEX wavform;
  189.     if (waveOutGetNumDevs() < 1) {
  190. fprintf( stderr, "no sound devices available!n");
  191. global.echo = 0;
  192. return 1;
  193.     }
  194.     /* check capabilities */
  195.     if (check_winsound_caps(bits, rate, global.channels) != 0) {
  196. fprintf( stderr, "soundcard capabilities are not sufficient!n");
  197. global.echo = 0;
  198. return 1;
  199.     }
  200.     wavform.wFormatTag = WAVE_FORMAT_PCM;
  201.     wavform.nChannels = global.channels;
  202.     wavform.nSamplesPerSec = (int)rate;
  203.     wavform.wBitsPerSample = bits;
  204.     wavform.cbSize = 0;
  205.     wavform.nAvgBytesPerSec = (int)rate * global.channels *
  206. (wavform.wBitsPerSample / 8);
  207.     wavform.nBlockAlign = global.channels * (wavform.wBitsPerSample / 8);
  208.   
  209.     DeviceID = 0;
  210.     mmres = waveOutOpen(&DeviceID, 0, &wavform, 0, 0, 0);
  211.     if (mmres) {
  212. char erstr[329];
  213. waveOutGetErrorText(mmres, erstr, sizeof(erstr));
  214. fprintf( stderr, "soundcard open error: %s!n", erstr);
  215. global.echo = 0;
  216. return 1;
  217.     }
  218.     global.soundcard_fd = 0;
  219.     /* init all wavehdrs */
  220.     { int i;
  221. for (i=0; i < WAVEHDRS; i++) {
  222.     wavehdr[i].dwBufferLength = (global.channels*(bits/ 8)*(int)rate*
  223.      global.nsectors)/75;
  224.     wavehdr[i].lpData = (unsigned char *) malloc(wavehdr[i].dwBufferLength);
  225.     if (wavehdr[i].lpData == NULL) {
  226.     fprintf(stderr, "no memory for sound buffers availablen");
  227.       waveOutReset(0);
  228.     waveOutClose(DeviceID);
  229.     return 1;
  230.     }
  231.     
  232.     wavehdr[i].dwLoops = 0;
  233.     wavehdr[i].dwFlags = WHDR_DONE;
  234.     wavehdr[i].dwBufferLength = 0;
  235. }
  236.     }
  237. #   endif /* CYGWIN Windows sound */
  238. #  endif /* else SUN audio */
  239. # endif /* else HAVE_OSS */
  240.   }
  241. #endif /* ifdef ECHO_TO_SOUNDCARD */
  242.   return 0;
  243. }
  244. int open_snd_device ()
  245. {
  246. #if defined ECHO_TO_SOUNDCARD && !defined __CYGWIN32__
  247. return (global.soundcard_fd = open(snd_device, O_WRONLY, 0)) < 0;
  248. #else
  249. return 0;
  250. #endif
  251. }
  252. int close_snd_device ()
  253. {
  254. #if defined __CYGWIN32__ && defined ECHO_TO_SOUNDCARD
  255.  waveOutReset(0);
  256.  return waveOutClose(DeviceID);
  257. #else
  258. #ifdef ECHO_TO_SOUNDCARD
  259.  return close(global.soundcard_fd);
  260. #else
  261.  return 0;
  262. #endif /* ifdef ECHO_TO_SOUNDCARD */
  263. #endif
  264. }
  265. #if !defined __CYGWIN32__
  266. # include <sys/time.h>
  267. #endif
  268. int write_snd_device (buffer, todo)
  269. char *buffer;
  270. unsigned todo;
  271. {
  272. int result = 0;
  273. #ifdef ECHO_TO_SOUNDCARD
  274. #if defined __CYGWIN32__
  275. MMRESULT mmres;
  276. wavehdr[lastwav].dwBufferLength = todo;
  277. memcpy(wavehdr[lastwav].lpData, buffer, todo);
  278. mmres = waveOutPrepareHeader(DeviceID, &wavehdr[lastwav], sizeof(WAVEHDR));
  279. if (mmres) {
  280. char erstr[129];
  281. waveOutGetErrorText(mmres, erstr, sizeof(erstr));
  282. fprintf( stderr, "soundcard prepare error: %s!n", erstr);
  283. return 1;
  284. }
  285. mmres = waveOutWrite(DeviceID, &wavehdr[lastwav], sizeof(WAVEHDR));
  286. if (mmres) {
  287. char erstr[129];
  288. waveOutGetErrorText(mmres, erstr, sizeof(erstr));
  289. fprintf( stderr, "soundcard write error: %s!n", erstr);
  290. return 1;
  291. }
  292. lastwav = (lastwav + 1) % WAVEHDRS;
  293. result = mmres;
  294. #else
  295. int retval2;
  296. do {
  297. fd_set writefds[1];
  298. struct timeval timeout2;
  299. int wrote;
  300. timeout2.tv_sec = 0;
  301. timeout2.tv_usec = 120000;
  302. FD_ZERO(writefds);
  303. FD_SET(global.soundcard_fd, writefds);
  304. retval2 = select(global.soundcard_fd + 1,
  305.  NULL, writefds, NULL, &timeout2);
  306. switch (retval2) {
  307. default:
  308. case -1: perror ("select failed");
  309. /* fall through */
  310. case 0: /* timeout */
  311. result = 2;
  312. goto outside_loop;
  313. case 1: break;
  314. }
  315. wrote = write(global.soundcard_fd, buffer, todo);
  316. if (wrote <= 0) {
  317. perror( "cant write audio");
  318. result = 1;
  319. goto outside_loop;
  320. } else {
  321. todo -= wrote;
  322. buffer += wrote;
  323. }
  324. } while (todo > 0);
  325. outside_loop:
  326. ;
  327. #endif
  328. #endif
  329. return result;
  330. }