obuffer.cc
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:11k
- /*
- 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 IRIX
- extern "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 LINUX
- extern "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 SOLARIS
- int 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 LINUX
- int 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 supportedn",chan);
- athr_exit(0);
- }
- chan--;
- if ( IOCTL(audio_fd, SNDCTL_DSP_STEREO, chan) < 0 ) {
- printf("LinuxObuffer::Error when setting stereon");
- 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