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

DVD

开发平台:

Unix_Linux

  1. /*
  2.  *
  3.  *  output_wav.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.  *  This file is based on output_linux.c by Aaron Holtzman.
  24.  *  All .wav modifications were done by Jorgen Lundman <lundman@lundman.net>
  25.  *  Any .wav bugs and errors should be reported to him.
  26.  *
  27.  *
  28.  */
  29. #ifdef HAVE_CONFIG_H
  30. #  include <config.h>
  31. #endif
  32. #include <stdio.h>
  33. #include <errno.h>
  34. #include <string.h>
  35. #include <unistd.h>
  36. #include <fcntl.h>
  37. #include "ac3.h"
  38. #include "decode.h"
  39. #include "debug.h"
  40. #include "output.h"
  41. #include "downmix.h"
  42. #include "ring_buffer.h"
  43. #include "wav.h"
  44. #define BUFFER_SIZE 1024 
  45. static char output_file[] = "output.wav";
  46. static int fd;
  47. static struct wave_header wave;
  48. /*
  49.  * open the file for writing to
  50.  */
  51. int output_open(int bits, int rate, int channels)
  52. {
  53.   /*  int tmp;*/
  54.   
  55.   /*
  56.    * Open the output file
  57.    */
  58.   fd=open(output_file,O_WRONLY | O_TRUNC | O_CREAT, 0644);
  59.  
  60.   if(fd < 0) 
  61.     {
  62.       dprintf("%s: Opening audio output %sn",
  63.       strerror(errno), output_file);
  64.       goto ERR;
  65.     }
  66.   dprintf("Opened audio output "%s"n",output_file);
  67.   /* Write out a ZEROD wave header first */
  68.   memset(&wave, 0, sizeof(wave));
  69.   /* Store information */
  70.   wave.common.wChannels = channels;
  71.   wave.common.wBitsPerSample = bits;
  72.   wave.common.dwSamplesPerSec = rate;
  73.   if (write(fd, &wave, sizeof(wave)) != sizeof(wave)) {
  74.     dprintf("failed to write wav-header: %sn", strerror(errno));
  75.     goto ERR;
  76.   }
  77.   return 1;
  78.   
  79.  ERR:
  80.   if(fd >= 0) { close(fd); }
  81.   return 0;
  82. }
  83. /*
  84.  * play the sample to the already opened file descriptor
  85.  */
  86. void output_play(bsi_t *bsi,stream_samples_t *samples)
  87. {
  88.   int i;
  89. float *left,*right;
  90. float norm = 1.0;
  91. float left_tmp = 0.0;
  92. float right_tmp = 0.0;
  93. sint_16 *out_buf;
  94.   
  95.   if(fd < 0)
  96.     return;
  97.   
  98. //Downmix if necessary 
  99. downmix(bsi,samples);
  100. //Determine a normalization constant if the signal exceeds 
  101. //100% digital [-1.0,1.0]
  102. //
  103. //perhaps use the dynamic range info to do this instead
  104. for(i=0; i< 256;i++)
  105. {
  106.     left_tmp = samples->channel[0][i];
  107.     right_tmp = samples->channel[1][i];
  108. if(left_tmp > norm)
  109. norm = left_tmp;
  110. if(left_tmp < -norm)
  111. norm = -left_tmp;
  112. if(right_tmp > norm)
  113. norm = right_tmp;
  114. if(right_tmp < -norm)
  115. norm = -right_tmp; 
  116. }
  117. norm = 32000.0/norm;
  118. /* Take the floating point audio data and convert it into
  119.  * 16 bit signed PCM data */
  120. left = samples->channel[0];
  121. right = samples->channel[1];
  122. for(i=0; i < 256; i++)
  123. {
  124. out_buf[i * 2 ]    = (sint_16) (*left++  * norm);
  125. out_buf[i * 2 + 1] = (sint_16) (*right++ * norm);
  126. }
  127. write(fd, out_buf,BUFFER_SIZE);
  128. }
  129. void
  130. output_close(void)
  131. {
  132.   off_t offset;
  133.   /* Find how long our file is in total, including header */
  134.   offset = lseek(fd, 0, SEEK_CUR);
  135.   if (offset < 0) 
  136. {
  137.     dprintf("lseek failed - wav-header is corruptn");
  138.     goto ERR;
  139.   }
  140.   /* Rewind file */
  141.   if (lseek(fd, 0, SEEK_SET) < 0) 
  142. {
  143.     dprintf("rewind failed - wav-header is corruptn");
  144.     goto ERR;
  145.   }
  146.   /* Fill out our wav-header with some information. */
  147.   offset -= 8;
  148.   strcpy(wave.riff.id, "RIFF");
  149.   wave.riff.len = offset + 24;
  150.   strcpy(wave.riff.wave_id, "WAVE");
  151.   offset -= 4;
  152.   offset -= 8;
  153.   strcpy(wave.format.id, "fmt ");
  154.   wave.format.len = sizeof(struct common_struct);
  155.   wave.common.wFormatTag = WAVE_FORMAT_PCM;
  156.   wave.common.dwAvgBytesPerSec = 
  157.     wave.common.wChannels * wave.common.dwSamplesPerSec *
  158.     (wave.common.wBitsPerSample >> 4);
  159.   wave.common.wBlockAlign = wave.common.wChannels * 
  160.     (wave.common.wBitsPerSample >> 4);
  161.   strcpy(wave.data.id, "data");
  162.   offset -= sizeof(struct common_struct);
  163.   wave.data.len = offset;
  164.   offset -= 8;
  165.   strcpy(wave.riffdata.id, "RIFF");
  166.   wave.riffdata.len = offset;
  167.   strcpy(wave.riffdata.wave_id, "WAVE");
  168.   offset -= 4;
  169.   offset -= 8;
  170.   strcpy(wave.dataformat.id, "DATA");
  171.   wave.dataformat.len = offset;
  172.   if (write(fd, &wave, sizeof(wave)) < sizeof(wave)) 
  173. {
  174.     dprintf("wav-header write failed -- file is corruptn");
  175.     goto ERR;
  176.   }
  177.  ERR:
  178.   close(fd);
  179. }