output_linux.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:4k
- /*
- *
- * output_linux.c
- *
- * Copyright (C) Aaron Holtzman - May 1999
- *
- * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
- *
- * ac3dec is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * ac3dec is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- */
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <math.h>
- #include <sys/soundcard.h>
- #include <sys/ioctl.h>
- #include "ac3.h"
- #include "decode.h"
- #include "debug.h"
- #include "output.h"
- #include "downmix.h"
- static char dev[] = "/dev/dsp";
- static int fd;
- //FIXME uncomment all the matlab calls in this module
- // and you'll get a handy matlab output file
- // of the signal.
- //#include "matlab.h"
- //static matlab_file_t *foo;
- //
- /*
- * open the audio device for writing to
- */
- int output_open( void )
- {
- int bits = 16;
- int rate = 48000;
- int stereo = 1;
- int frag = 0x7fff000A; /* 2^10 = 1024 */
-
- /* open device */
- if ((fd = open( dev, O_WRONLY )) == -1) {
- perror(dev);
- return 0;
- }
- /* set sample size */
- if (ioctl(fd, SNDCTL_DSP_SAMPLESIZE, &bits) == -1) {
- perror("SNDCTL_DSP_SAMPLESIZE");
- return 0;
- }
- if (bits != 16) {
- fprintf( stderr, "Device does not support 16 bit samplesn");
- return 0;
- }
- /* set number of channels */
- if (ioctl(fd, SNDCTL_DSP_STEREO, &stereo) == -1) {
- perror("SNDCTL_DSP_STEREO");
- return 0;
- }
- if (stereo != 1) {
- fprintf( stderr, "Device does not support stereon");
- return 0;
- }
-
- /* set sample rate */
- if (ioctl(fd, SNDCTL_DSP_SPEED, &rate) == -1) {
- perror("SNDCTL_DSP_SPEED");
- return 0;
- }
- if (rate != 48000) {
- fprintf( stderr, "Device does not support %d, appears to support %dn",
- 48000, rate );
- }
- /* set fragment size */
- if (ioctl( fd, SNDCTL_DSP_SETFRAGMENT, &frag ) == -1) {
- perror("SNDCTL_DSP_SETFRAGMENT");
- return 0;
- }
- if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag) == -1) {
- perror("SNDCTL_DSP_GETBLKSIZE");
- return 0;
- }
-
- if (frag != 1024) {
- fprintf( stderr, "Device does not support fragment size of 1024n" );
- return 0;
- }
-
- return 1;
- }
- /*
- * play the sample to the already opened file descriptor
- */
- void output_play(bsi_t *bsi,stream_samples_t *samples)
- {
- int i;
- float *left,*right;
- float norm = 1.0;
- float left_tmp = 0.0;
- float right_tmp = 0.0;
- sint_16 out_buf[1024];
- if(fd < 0)
- return;
- //FIXME remove
- //matlab_write(foo,samples->channel[0],512);
-
- //Downmix if necessary
- downmix(bsi,samples);
- //Determine a normalization constant if the signal exceeds
- //100% digital [-1.0,1.0]
- //
- //perhaps use the dynamic range info to do this instead
- for(i=0; i< 256;i++)
- {
- left_tmp = samples->channel[0][i];
- right_tmp = samples->channel[1][i];
- if(left_tmp > norm)
- norm = left_tmp;
- if(left_tmp < -norm)
- norm = -left_tmp;
- if(right_tmp > norm)
- norm = right_tmp;
- if(right_tmp < -norm)
- norm = -right_tmp;
- }
- norm = 32768.0/norm;
- /* Take the floating point audio data and convert it into
- * 16 bit signed PCM data */
- left = samples->channel[0];
- right = samples->channel[1];
- for(i=0; i < 256; i++)
- {
- // if((fabs(*left * norm) > 32768.0) || (fabs(*right * norm) > 32768.0))
- // printf("clipping (%f, %f)n",*left,*right);
- out_buf[i * 2 ] = (sint_16) (*left++ * norm);
- out_buf[i * 2 + 1] = (sint_16) (*right++ * norm);
- }
- if (write(fd, out_buf, 1024) != 1024) {
- fprintf( stderr, "Bytes written not 1024n" );
- }
- }
- void
- output_close(void)
- {
- close(fd);
- }