?? obuffer.cc
字號:
/* File: obuffer.cc Description: Audio output buffer implementation*/#ifdef __GNUG__#pragma implementation#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <String.h>#include <unistd.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/types.h>#ifndef LINUX#include <stropts.h>#endif#include <fstream.h>#ifdef IRIXextern "C" {#include <dmedia/audio.h>}#endif#ifdef SOLARIS#include <sys/audioio.h>#endif#ifdef LINUX#include <sys/soundcard.h>#endif#include <memory.h>#include <sys/select.h>#include <sys/time.h> // Time#ifndef LINUXextern "C" {int ioctl(int, int, ...);}#else#define IOCTL(a,b,c) ioctl(a,b,&c)#endif#include "athread.hh"#include <errno.h>#include "error.hh"#include "debug.hh"#include "util.hh"#include "sync.hh"#include "mpeg2const.hh"#include "mpeg2buff.hh"#include "astream.hh"#include "crc.hh"#include "header.hh"#include "obuffer.hh"ShortObuffer::ShortObuffer(uint32 number_of_channels){#ifdef DEBUG if (!number_of_channels || number_of_channels > MAXCHANNELS){ String err("ShortObuffer: number of channels has to be in [1, "); err+=itoa(MAXCHANNELS); err+="]!"; error(err.chars()); athr_exit(0); }#endif channels = number_of_channels; for (unsigned int i=0; i<number_of_channels; i++) bufferp[i]=buffer+i;}void ShortObuffer::append(uint32 channel, int16 value){#ifdef DEBUG if (channel >= channels){ error("illegal channelnumber in ShortObuffer::append()!"); athr_exit(0); } if (bufferp[channel] - buffer >= OBUFFERSIZE){ error("ShortObuffer: buffer overflow!"); athr_exit(0); }#endif *bufferp[channel] = value; bufferp[channel] += channels;}void ShortObuffer::write_buffer (int fd){ int length = (int)((char *)bufferp[0] - (char *)buffer); if (write (fd, buffer, length) != length) warning("couldn't write all samples"); for (unsigned int i=0; i<channels; i++) bufferp[i]=buffer+i;}#ifdef IRIX IrixObuffer::IrixObuffer(uint32 number_of_channels, Header* header){#ifdef DEBUG if (!number_of_channels || number_of_channels > MAXCHANNELS){ cerr << "IrixObuffer: number of channels has to be in [1, " << MAXCHANNELS << "] !\n"; exit(1); }#endif channels = number_of_channels; for (int i = 0; i < number_of_channels; ++i) bufferp[i] = buffer + i; // open an audio port and configure it: ALconfig config; if (!(config = ALnewconfig())){ error("ALnewconfig failed!"); exit(1); } ALsetwidth(config, AL_SAMPLE_16); if (channels == 1) ALsetchannels(config, AL_MONO); else ALsetchannels(config, AL_STEREO); if (!(port = ALopenport("MPEG audio player", "w", config))){ error("can't allocate an audio port!"); exit (1); } // set sample rate: long pvbuffer[2] = { AL_OUTPUT_RATE, 0 }; pvbuffer[1] = header->frequency (); ALsetparams(AL_DEFAULT_DEVICE, pvbuffer, 2); ALfreeconfig(config);}IrixObuffer::~IrixObuffer(){ while (ALgetfilled(port) > 0) sleep (1); ALcloseport(port);}// All inline to avoid linking problem!void IrixObuffer::append(uint32 channel, int16 value){#ifdef DEBUG if (channel >= channels){ error("illegal channelnumber in IrixObuffer::append()!"); athr_exit(0); } if (bufferp[channel] - buffer >= OBUFFERSIZE){ error("IrixObuffer: buffer overflow!"); athr_exit(0); }#endif *bufferp[channel] = value; bufferp[channel] += channels;}void IrixObuffer::write_buffer(int /* dummy */){ ALwritesamps(port, buffer, (long)(bufferp[0] - buffer)); for (int i = 0; i < channels; ++i) bufferp[i] = buffer + i;}#endif // IRIX#ifdef SOLARISint SparcObuffer::audio_fd = -1;SparcObuffer::SparcObuffer (uint32 number_of_channels, Header *header, bool use_speaker, bool use_headphone, bool use_line_out){ channels=number_of_channels;#ifdef DEBUG if (!number_of_channels || number_of_channels > MAXCHANNELS){ cerr << "SparcObuffer: 0 < number of channels < " << MAXCHANNELS << "!\n"; exit (1); }#endif for (unsigned int i=0; i<number_of_channels; i++) bufferp[i]=buffer+i; if (audio_fd < 0){ error("SparcObuffer::audio_fd has to be initialized by SparcObuffer::class_suitable()!"); athr_exit(0); } // configure the device: audio_info info; AUDIO_INITINFO (&info); info.output_muted = False; info.play.sample_rate = header->frequency (); info.play.channels = channels; info.play.precision = 16; info.play.encoding = AUDIO_ENCODING_LINEAR;// info.play.gain=AUDIO_MAX_GAIN/3; if (use_speaker) info.play.port |= AUDIO_SPEAKER; if (use_headphone) info.play.port |= AUDIO_HEADPHONE; if (use_line_out) info.play.port |= AUDIO_LINE_OUT; info.play.buffer_size=OBUFFERSIZE; info.play.samples=0; info.play.eof=0; info.play.pause=0; info.play.error=0; info.play.waiting=0; info.play.balance = AUDIO_MID_BALANCE; if (ioctl(audio_fd, AUDIO_SETINFO, &info)){ error("configuration of /dev/audio failed"); athr_exit(0); }}static int droppedframes=0;static timeval timeout;SparcObuffer::~SparcObuffer (void){ ioctl(audio_fd, AUDIO_DRAIN); close (audio_fd); msg("Number of interrupted frames: "); message(itoa(droppedframes));}void SparcObuffer::append(uint32 channel, int16 value){#ifdef DEBUG if (channel >= channels){ cerr << "illegal channelnumber in SparcObuffer::append()!\n"; exit (1); } if (bufferp[channel] - buffer >= OBUFFERSIZE){ cerr << "buffer overflow!\n"; exit (1); }#endif *bufferp[channel] = value; bufferp[channel] += channels;}void SparcObuffer::write_buffer(int){ int length = (int)((char*) bufferp[0] - (char*) buffer);#ifdef SPARC5 // This stuff seems useful on a SUN Sparc 5 static fd_set wfs; FD_ZERO(&wfs); FD_SET(audio_fd, &wfs); if (select(FD_SETSIZE, 0, &wfs, 0, &timeout)>=0){ if (FD_ISSET(audio_fd, &wfs)){#endif if (write(audio_fd, buffer, length) != length){ message("Warning: couldn't write all samples to /dev/audio"); }#ifdef SPARC5 } else { ioctl(audio_fd, I_FLUSH, FLUSHW); // flush current stuff and replace by new msg("flush audio"); droppedframes++; if (write(audio_fd, buffer, length) != length){ message("Warning: couldn't write all samples to /dev/audio"); } } }#endif for (unsigned int i=0; i<channels; i++) bufferp[i]=buffer+i;}int SparcObuffer::open_audio_device (void){ int fd=0; // just check if ((fd=open("/dev/audio", O_WRONLY | O_NDELAY)) < 0) // if (errno == EBUSY){ cerr << "Sorry, the audio device is busy!\n"; exit (1); } else{ perror ("can't open /dev/audio for writing"); exit (1); } ioctl(fd, I_FLUSH, FLUSHRW); close(fd); /* now open (blocking) // | O_NDELAY)) */ if ((fd=open("/dev/audio", O_WRONLY))< 0){ if (errno == EBUSY){ error("Sorry, the audio device is busy!"); athr_exit(0); } else { error("can't open /dev/audio for writing"); athr_exit(0); } } ioctl(fd, I_FLUSH, FLUSHW); // next time out timeout.tv_sec=0; // length/5513; // length/5513=length*8 / 44100 (bps) timeout.tv_usec=752600; // (long int) (length*181); // length*181= length*8/ 44100 * 1000000}void SparcObuffer::get_device_type (int fd, audio_device *devtype){ if (ioctl (fd, AUDIO_GETDEV, devtype)){ error("ioctl on /dev/audio"); athr_exit(0); }}bool SparcObuffer::class_suitable (void){ audio_fd=open_audio_device(); // check for the CS4231 or dbri audio device audio_device devtype; get_device_type(audio_fd, &devtype); // Sparc 5: CS4321, Sparc 10: dbri return (!strcmp (devtype.name, "SUNW,CS4231") || !strcmp (devtype.name, "SUNW,dbri")) ? True : False;}#endif // SOLARIS#ifdef LINUXint LinuxObuffer::audio_fd = -1;LinuxObuffer::LinuxObuffer (uint32 number_of_channels,Header *header) { int abuf_size; int sample_rate; int sample_bits=16; int chan = channels=number_of_channels; #ifdef DEBUG if (!number_of_channels || number_of_channels > MAXCHANNELS){ cerr << "LinuxObuffer: 0 < number of channels < " << MAXCHANNELS << "!\n"; exit (1); }#endif for (unsigned int i=0; i<number_of_channels; i++) bufferp[i]=buffer+i; if (audio_fd < 0){ error("LinuxObuffer::audio_fd has to be initialized by LinuxObuffer::class_suitable()!"); athr_exit(0); } IOCTL(audio_fd, SNDCTL_DSP_GETBLKSIZE, abuf_size); if (abuf_size < 4096 || abuf_size > 65536) { if (abuf_size == -1) { error ("LinuxObuffer::abufsize failure"); } else { error("Invalid audio buffers size \n"); } athr_exit (0); } // configure the device: sample_rate = header->frequency (); if (IOCTL(audio_fd, SNDCTL_DSP_SPEED, sample_rate) < 0) { error("unable to set audio speed"); athr_exit (0); } if ( IOCTL(audio_fd, SNDCTL_DSP_CHANNELS, chan) < 0 ) { printf("LinuxObuffer::amount of channels (%d) not supported\n",chan); athr_exit(0); } chan--; if ( IOCTL(audio_fd, SNDCTL_DSP_STEREO, chan) < 0 ) { printf("LinuxObuffer::Error when setting stereo\n"); athr_exit(0); } IOCTL(audio_fd, SNDCTL_DSP_SAMPLESIZE, sample_bits);}static int droppedframes=0;static timeval timeout;LinuxObuffer::~LinuxObuffer (void){ ioctl(audio_fd, SNDCTL_DSP_SYNC,NULL); close (audio_fd); msg("Number of interrupted frames: "); message(itoa(droppedframes));}void LinuxObuffer::append(uint32 channel, int16 value){#ifdef DEBUG if (channel >= channels){ cerr << "illegal channelnumber in SparcObuffer::append()!\n"; exit (1); } if (bufferp[channel] - buffer >= OBUFFERSIZE){ cerr << "buffer overflow!\n"; exit (1); }#endif *bufferp[channel] = value; bufferp[channel] += channels;}void LinuxObuffer::write_buffer(int){ int length = (int)((char*) bufferp[0] - (char*) buffer); if (write(audio_fd, buffer, length) != length){ message("Warning: couldn't write all samples to /dev/audio"); } for (unsigned int i=0; i<channels; i++) bufferp[i]=buffer+i;}int LinuxObuffer::open_audio_device (void){ int fd=0; // just check if ((fd=open("/dev/dsp", O_WRONLY | O_NDELAY)) < 0) // if (errno == EBUSY){ cerr << "Sorry, the audio device is busy!\n"; exit (1); } else{ perror ("can't open /dev/audio for writing"); exit (1); } ioctl(fd, SNDCTL_DSP_SYNC,NULL); close(fd); /* now open (blocking) // | O_NDELAY)) */ if ((fd=open("/dev/dsp", O_WRONLY))< 0){ if (errno == EBUSY){ error("Sorry, the audio device is busy!"); athr_exit(0); } else { error("can't open /dev/audio for writing"); athr_exit(0); } } ioctl(fd, SNDCTL_DSP_SYNC,NULL); // next time out timeout.tv_sec=0; // length/5513; // length/5513=length*8 / 44100 (bps) timeout.tv_usec=752600; // (long int) (length*181); // length*181= length*8/ 44100 * 1000000 return fd;}bool LinuxObuffer::class_suitable (void){ audio_fd=open_audio_device(); // check for audio device if (audio_fd == -1) return False; return True;}#endif // LINUX
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -