output_solaris.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:4k
源码类别:

DVD

开发平台:

Unix_Linux

  1. /*
  2.  *
  3.  *  output_solaris.c
  4.  *
  5.  * Copyright (C) Aaron Holtzman - May 1999
  6.  *
  7.  *  This file is part of ac3dec, a free Dolby AC-3 stream decoder.
  8.  *
  9.  *  ac3dec is free software; you can redistribute it and/or modify
  10.  *  it under the terms of the GNU General Public License as published by
  11.  *  the Free Software Foundation; either version 2, or (at your option)
  12.  *  any later version.
  13.  *   
  14.  *  ac3dec is distributed in the hope that it will be useful,
  15.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  *  GNU General Public License for more details.
  18.  *   
  19.  *  You should have received a copy of the GNU General Public License
  20.  *  along with GNU Make; see the file COPYING.  If not, write to
  21.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  22.  *
  23.  *
  24.  */
  25. #ifdef HAVE_CONFIG_H
  26. #  include <config.h>
  27. #endif
  28. #include <stdio.h>
  29. #include <errno.h>
  30. #include <string.h>
  31. #include <unistd.h>
  32. #include <fcntl.h>
  33. #include <sys/audioio.h>
  34. #include <sys/ioctl.h>
  35. #include <stropts.h>
  36. #include <signal.h>
  37. //FIXME broken solaris headers!
  38.  int usleep(unsigned int useconds);
  39. #include "ac3.h"
  40. #include "decode.h"
  41. #include "debug.h"
  42. #include "downmix.h"
  43. #include "ring_buffer.h"
  44. #include "output.h"
  45. #define BUFFER_SIZE 1024 
  46. /* Global to keep track of old state */
  47. static char dev[] = "/dev/audio";
  48. static audio_info_t info;
  49. static int fd;
  50. /*
  51.  * open the audio device for writing to
  52.  */
  53. int output_open(int bits, int rate, int channels)
  54. {
  55.   /*
  56.    * Open the device driver
  57.    */
  58. fd=open(dev,O_WRONLY | O_NDELAY);
  59.   if(fd < 0) 
  60.   {
  61.     dprintf("%s: Opening audio device %sn",
  62.         strerror(errno), dev);
  63.     goto ERR;
  64.   }
  65. dprintf("Opened audio device "%s"n",dev);
  66. fcntl(fd,F_SETFL,O_NONBLOCK);
  67. /* Setup our parameters */
  68. AUDIO_INITINFO(&info);
  69. info.play.sample_rate = rate;
  70. info.play.precision = bits;
  71. info.play.channels = channels;
  72. info.play.buffer_size = 2048;
  73. info.play.encoding = AUDIO_ENCODING_LINEAR;
  74. //info.play.port = AUDIO_SPEAKER;
  75. info.play.gain = 110;
  76. /* Write our configuration */
  77. /* An implicit GETINFO is also performed so we can get
  78.  * the buffer_size */
  79.   if(ioctl(fd, AUDIO_SETINFO, &info) < 0)
  80.   {
  81.     fprintf(stderr, "%s: Writing audio config blockn",strerror(errno));
  82.     goto ERR;
  83.   }
  84. //fprintf(stderr,"buffer_size = %dn",info.play.buffer_size);
  85. /* Initialize the ring buffer */
  86. rb_init();
  87. return 1;
  88. ERR:
  89.   if(fd >= 0) { close(fd); }
  90.   return 0;
  91. }
  92. static void
  93. output_flush(void)
  94. {
  95. int i,j = 0;
  96. sint_16 *out_buf = 0;
  97. i = 0;
  98. do
  99. {
  100. out_buf = rb_begin_read();
  101. if(out_buf)
  102. i = write(fd, out_buf,BUFFER_SIZE);
  103. else
  104. break;
  105. if(i == BUFFER_SIZE)
  106. {
  107. rb_end_read();
  108. j++;
  109. }
  110. }
  111. while(i == BUFFER_SIZE);
  112. //FIXME remove
  113. //fprintf(stderr,"(output) Flushed %d blocks, wrote %d bytes last framen",j,i);
  114. }
  115. /*
  116.  * play the sample to the already opened file descriptor
  117.  */
  118. void output_play(bsi_t *bsi,stream_samples_t *samples)
  119. {
  120.   int i;
  121. float *left,*right;
  122. float norm = 1.0;
  123. float left_tmp = 0.0;
  124. float right_tmp = 0.0;
  125. sint_16 *out_buf;
  126. if(fd < 0)
  127. return;
  128. out_buf = rb_begin_write();
  129. /* Keep trying to dump frames from the ring buffer until we get a 
  130.  * write slot available */
  131. while(!out_buf)
  132. {
  133. usleep(5000);
  134. output_flush();
  135. out_buf = rb_begin_write();
  136. //Downmix if necessary 
  137. downmix(bsi,samples);
  138. //Determine a normalization constant if the signal exceeds 
  139. //100% digital [-1.0,1.0]
  140. //
  141. //perhaps use the dynamic range info to do this instead
  142. for(i=0; i< 256;i++)
  143. {
  144.     left_tmp = samples->channel[0][i];
  145.     right_tmp = samples->channel[1][i];
  146. if(left_tmp > norm)
  147. norm = left_tmp;
  148. if(left_tmp < -norm)
  149. norm = -left_tmp;
  150. if(right_tmp > norm)
  151. norm = right_tmp;
  152. if(right_tmp < -norm)
  153. norm = -right_tmp; 
  154. }
  155. norm = 32000.0/norm;
  156. /* Take the floating point audio data and convert it into
  157.  * 16 bit signed PCM data */
  158. left = samples->channel[0];
  159. right = samples->channel[1];
  160. for(i=0; i < 256; i++)
  161. {
  162. // if((fabs(*left * norm) > 32768.0) || (fabs(*right * norm) > 32768.0))
  163. // printf("clipping (%f, %f)n",*left,*right);
  164. out_buf[i * 2 ]    = (sint_16) (*left++  * norm);
  165. out_buf[i * 2 + 1] = (sint_16) (*right++ * norm);
  166. }
  167. rb_end_write();
  168. }
  169. void
  170. output_close(void)
  171. {
  172. /* Reset the saved parameters */
  173.   if(ioctl(fd, AUDIO_SETINFO, &info) < 0)
  174.   {
  175.     fprintf(stderr, "%s: Writing audio config blockn",strerror(errno));
  176.   }
  177. close(fd);
  178. }