diff options
Diffstat (limited to 'mpeglib/lib/util/audio')
-rw-r--r-- | mpeglib/lib/util/audio/Makefile.am | 18 | ||||
-rw-r--r-- | mpeglib/lib/util/audio/audioIO.cpp | 49 | ||||
-rw-r--r-- | mpeglib/lib/util/audio/audioIO.h | 80 | ||||
-rw-r--r-- | mpeglib/lib/util/audio/audioIO_AIX.cpp | 533 | ||||
-rw-r--r-- | mpeglib/lib/util/audio/audioIO_BeOS.cpp | 227 | ||||
-rw-r--r-- | mpeglib/lib/util/audio/audioIO_HPUX.cpp | 190 | ||||
-rw-r--r-- | mpeglib/lib/util/audio/audioIO_IRIX.cpp | 157 | ||||
-rw-r--r-- | mpeglib/lib/util/audio/audioIO_Linux.cpp | 220 | ||||
-rw-r--r-- | mpeglib/lib/util/audio/audioIO_SDL.cpp | 164 | ||||
-rw-r--r-- | mpeglib/lib/util/audio/audioIO_SunOS.cpp | 167 | ||||
-rw-r--r-- | mpeglib/lib/util/audio/dspWrapper.cpp | 193 | ||||
-rw-r--r-- | mpeglib/lib/util/audio/dspWrapper.h | 75 |
12 files changed, 2073 insertions, 0 deletions
diff --git a/mpeglib/lib/util/audio/Makefile.am b/mpeglib/lib/util/audio/Makefile.am new file mode 100644 index 00000000..968d1d46 --- /dev/null +++ b/mpeglib/lib/util/audio/Makefile.am @@ -0,0 +1,18 @@ + +# ---- @OS_TYPE@/@ARCH_TYPE@ ---- + +INCLUDES = $(all_includes) + +EXTRA_DIST = audioIO_AIX.cpp audioIO_BeOS.cpp \ + audioIO_HPUX.cpp \ + audioIO_IRIX.cpp audioIO_Linux.cpp \ + audioIO_SunOS.cpp audioIO_SDL.cpp + +noinst_HEADERS = audioIO.h dspWrapper.h + +noinst_LTLIBRARIES = libaudio.la + +libaudio_la_SOURCES = audioIO.cpp dspWrapper.cpp + + + diff --git a/mpeglib/lib/util/audio/audioIO.cpp b/mpeglib/lib/util/audio/audioIO.cpp new file mode 100644 index 00000000..d066210f --- /dev/null +++ b/mpeglib/lib/util/audio/audioIO.cpp @@ -0,0 +1,49 @@ + + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#ifdef SDL_WRAPPER + + #include "audioIO_SDL.cpp" + +// +// If native sound is defined compiled for that +// + +#else + + +#ifdef OS_AIX + #include "audioIO_AIX.cpp" +#endif + +#ifdef OS_Linux + #include "audioIO_Linux.cpp" +#endif + +#ifdef OS_BSD + #include "audioIO_Linux.cpp" +#endif + +#if defined(OS_IRIX) || defined(OS_IRIX64) + #include "audioIO_IRIX.cpp" +#endif + +#ifdef OS_HPUX + #include "audioIO_HPUX.cpp" +#endif + +#ifdef OS_SunOS + #include "audioIO_SunOS.cpp" +#endif + +#ifdef __BEOS__ + #include "audioIO_BeOS.cpp" +#endif + + +#endif diff --git a/mpeglib/lib/util/audio/audioIO.h b/mpeglib/lib/util/audio/audioIO.h new file mode 100644 index 00000000..41e1ceb2 --- /dev/null +++ b/mpeglib/lib/util/audio/audioIO.h @@ -0,0 +1,80 @@ + + +#ifndef __AUDIOIO_H +#define __AUDIOIO_H + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + + +extern "C" { +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <stdlib.h> +} + +/* AUSUZ should be the amount of data your audio device will accept after it + * has said it is ready to receive data. ie when the device is ready + * for data it + * will accept it without blocking. It must also be a multiple of 128 + */ + +#ifdef OS_AIX + #define AUSIZ 32768 +#endif + +#ifdef OS_Linux + extern int AUSIZ; +#endif + +#ifdef OS_BSD + #define AUSIZ 32768 +#endif + +#if defined(OS_IRIX) || defined(OS_IRIX64) + #define AUSIZ 32768 +#endif + +#ifdef OS_HPUX + #define AUSIZ 4096 +#endif + +#ifdef OS_SunOS + #define AUSIZ 4096 +#endif + + +#ifdef DEBUG + #define DB(type,cmd) if (debugFlags.type) { cmd ; } +#else + #define DB(type,cmd) +#endif + + + + +//Prototypes: + +int audioConstruct(); +void audioDestruct(); + + + +int audioOpen(); +void audioClose(); +void audioInit(int sampleSize,int frequency, int stereo,int sign, int bigendian); + + +int mixerOpen(); +void mixerClose(); +void mixerSetVolume(int volumeLeft,int volumeRight); + +int audioWrite(char *buffer, int count); +int getAudioFd(); +int getAudioBufferSize(); + +#endif diff --git a/mpeglib/lib/util/audio/audioIO_AIX.cpp b/mpeglib/lib/util/audio/audioIO_AIX.cpp new file mode 100644 index 00000000..15316852 --- /dev/null +++ b/mpeglib/lib/util/audio/audioIO_AIX.cpp @@ -0,0 +1,533 @@ +/* + * AIX audio - griff@acm.org 02aug2000 + * tested on 43P 260 with builtin audio + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +/* A conflict within AIX 4.3.3 <sys/> headers and probably others as well. + * I guess nobody ever uses audio... Shame over AIX header files. */ +#include <sys/machine.h> +#undef BIG_ENDIAN +#include <sys/audio.h> + +static int audio_fd; + +static void debugUpdate( unsigned long& flags, long& bsize ); + +#ifndef AUDIO_BIG_ENDIAN +#define AUDIO_BIG_ENDIAN BIG_ENDIAN +#endif + + + +int audioConstruct() { + printf("audioConstruct AIX ********\n"); + audio_fd=-1; + return true; +} + + +void audioDestruct() { + +} + +int audioOpen() +{ + char devname[14]; + for ( int dev=0; dev<4; dev++ ) + { + for ( int chan=1; chan<8; chan++ ) + { + sprintf(devname,"/dev/paud%d/%d",dev,chan); + audio_fd = open (devname, O_WRONLY, 0); + if ( audio_fd >= 0 ) + { + return 1; + } + sprintf(devname,"/dev/baud%d/%d",dev,chan); + audio_fd = open (devname, O_WRONLY, 0); + if ( audio_fd >= 0 ) + { + return 1; + } + } + } + + fprintf(stderr, "Could not open AIX audio device, faking\n" ); + return 1; +} + +int getAudioBufferSize() +{ + audio_buffer paud_bufinfo; + + if( audio_fd < 0 ) return 1024*65; + + if ( ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0 ) + { + perror("ioctl getAudioBufferSize using default"); + return 1024*65; + } + + /* + * Do you need the total capacity or the current capacity? + * This is the total capacity: + */ + return paud_bufinfo.write_buf_cap; + /* + * This is the current capacity: + * return (paud_bufinfo.write_buf_cap - paud_bufinfo.write_buf_size); + */ +} + +void audioInit(int sampleSize,int frequency, int stereo, int sign, int bigendian ) +{ + // int format; + int bytes_per_sample; + audio_init paud_init; + audio_buffer paud_bufinfo; + // audio_status paud_status; + audio_control paud_control; + audio_change paud_change; + + if( audio_fd < 0 ) return; + + /* + * We can't set the buffer size - just ask the device for the maximum + * that we can have. + */ + if ( ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0 ) + { + perror("Couldn't get audio buffer information"); + return; + } + + /* + * Fields in the audio_init structure: + * + * Ignored by us: + * + * paud.loadpath[LOAD_PATH]; * DSP code to load, MWave chip only? + * paud.slot_number; * slot number of the adapter + * paud.device_id; * adapter identification number + * + * Input: + * + * paud.srate; * the sampling rate in Hz + * paud.bits_per_sample; * 8, 16, 32, ... + * paud.bsize; * block size for this rate + * paud.mode; * ADPCM, PCM, MU_LAW, A_LAW, SOURCE_MIX + * paud.channels; * 1=mono, 2=stereo + * paud.flags; * FIXED - fixed length data + * * LEFT_ALIGNED, RIGHT_ALIGNED (var len only) + * * TWOS_COMPLEMENT - 2's complement data + * * SIGNED - signed? comment seems wrong in sys/audio.h + * * BIG_ENDIAN + * paud.operation; * PLAY, RECORD + * + * Output: + * + * paud.flags; * PITCH - pitch is supported + * * INPUT - input is supported + * * OUTPUT - output is supported + * * MONITOR - monitor is supported + * * VOLUME - volume is supported + * * VOLUME_DELAY - volume delay is supported + * * BALANCE - balance is supported + * * BALANCE_DELAY - balance delay is supported + * * TREBLE - treble control is supported + * * BASS - bass control is supported + * * BESTFIT_PROVIDED - best fit returned + * * LOAD_CODE - DSP load needed + * paud.rc; * NO_PLAY - DSP code can't do play requests + * * NO_RECORD - DSP code can't do record requests + * * INVALID_REQUEST - request was invalid + * * CONFLICT - conflict with open's flags + * * OVERLOADED - out of DSP MIPS or memory + * paud.position_resolution; * smallest increment for position + */ + + paud_init.srate = frequency; + paud_init.mode = PCM; + paud_init.operation = PLAY; + paud_init.channels = (stereo?2:1); + + /* + * options in AIX: + * paud_init.bits_per_sample: 8 | 16 + * paud_init.flags: AUDIO_BIG_ENDIAN (not used here) + * SIGNED (always used here) + * TWOS_COMPLEMENT (always on for Linux dsp porting?) + * FIXED <- that's right for SDL + * or LEFT_ALIGNED <- that's right for mpeglib + * or RIGHT_ALIGNED + * paud_init.bsize: sample byte size, + * bits_per_sample * (stereo?2:1) - for SDL + * bits_per_sample * (stereo?2:1) * 2 - for mpeglib + */ + if ( sampleSize == 8 ) + { + /* AFMT_S8 in linux dsp */ + bytes_per_sample = 2; // why not 1 ? + paud_init.bits_per_sample = 8; + paud_init.flags = TWOS_COMPLEMENT | LEFT_ALIGNED; + } + else + { + /* AFMT_S16_LE in linux dsp */ + bytes_per_sample = 4; // why not 2 ? + paud_init.bits_per_sample = 16; + paud_init.flags = TWOS_COMPLEMENT | LEFT_ALIGNED; + } + if( sign ) paud_init.flags |= SIGNED; + if( bigendian ) paud_init.flags |= AUDIO_BIG_ENDIAN; + + paud_init.bsize = bytes_per_sample * (stereo?2:1); + +#if 0 + debugUpdate(paud_init.flags, paud_init.bsize); + + printf("CG: sampleSize = %d\n", sampleSize); + printf("CG: frequency = %d\n", frequency); + printf("CG: stereo = %s\n", (stereo)?"y":"n"); + printf("CG: mode = %s\n", "PCM"); + printf("CG: channels = %d\n", paud_init.channels); + printf("CG: bsize = %d\n", paud_init.bsize); + printf("CG: bits_per_sample = %d\n", paud_init.bits_per_sample); + printf("CG: flags & BIG_ENDIAN = %s\n", ((paud_init.flags&AUDIO_BIG_ENDIAN)?"y":"n")); + printf("CG: flags & SIGNED = %s\n", ((paud_init.flags&SIGNED)?"y":"n")); + printf("CG: flags & TWOS_COMPLEMENT = %s\n", ((paud_init.flags&TWOS_COMPLEMENT)?"y":"n")); + printf("CG: flags & FIXED = %s\n", ((paud_init.flags&FIXED)?"y":"n")); + printf("CG: flags & LEFT_ALIGNED = %s\n", ((paud_init.flags&LEFT_ALIGNED)?"y":"n")); + printf("CG: flags & RIGHT_ALIGNED = %s\n", ((paud_init.flags&RIGHT_ALIGNED)?"y":"n")); +#endif + + /* + * We know the buffer size and the max number of subsequent writes + * that can be pending. If more than one can pend, allow the application + * to do something like double buffering between our write buffer and + * the device's own buffer that we are filling with write() anyway. + * + * We can calculate the number of samples that fit into the audio + * device buffer if that is necessary: + * + * samples_capacity = paud_bufinfo.write_buf_cap + * / bytes_per_sample + * / (stereo?2:1); + * if ( paud_bufinfo.request_buf_cap != 1 ) samples_capacity /= 2; + */ + + /* + * The AIX paud device init can't modify the values of the audio_init + * structure that we pass to it. So we don't need any recalculation + * of this stuff and no reinit call as in linux SDL dsp and dma code. + * + * /dev/paud supports all of the encoding formats, so we don't need + * to do anything like reopening the device, either. + */ + if ( ioctl(audio_fd, AUDIO_INIT, &paud_init) < 0 ) + { + switch ( paud_init.rc ) + { + case 1 : + perror("Couldn't set audio format: DSP can't do play requests"); + return; + break; + case 2 : + perror("Couldn't set audio format: DSP can't do record requests"); + return; + break; + case 4 : + perror("Couldn't set audio format: request was invalid"); + return; + break; + case 5 : + perror("Couldn't set audio format: conflict with open's flags"); + return; + break; + case 6 : + perror("Couldn't set audio format: out of DSP MIPS or memory"); + return; + break; + default : + perror("Couldn't set audio format: not documented in sys/audio.h"); + return; + break; + } + } + + /* + * Set some parameters: full volume, first speaker that we can find. + * Ignore the other settings for now. + */ + paud_change.input = AUDIO_IGNORE; /* the new input source */ + paud_change.output = OUTPUT_1; + /* EXTERNAL_SPEAKER, + * INTERNAL_SPEAKER, + * OUTPUT_1 */ + paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */ + paud_change.volume = 0x7fffffff; /* volume level [0-0x7fffffff] */ + paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */ + paud_change.balance = 0x3fffffff; /* the new balance */ + paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */ + paud_change.treble = AUDIO_IGNORE; /* the new treble state */ + paud_change.bass = AUDIO_IGNORE; /* the new bass state */ + paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */ + + paud_control.ioctl_request = AUDIO_CHANGE; + paud_control.request_info = (char*)&paud_change; + if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 ) + { + perror("Can't change audio display settings (ignoring)" ); + } + + /* + * Tell the device to expect data. Actual start will wait for + * the first write() call. + */ + paud_control.ioctl_request = AUDIO_START; + paud_control.position = 0; + if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 ) + { + perror("Can't start audio play"); + return; + } +} + + +void audioSetVolume(int volume) +{ + long vol = (long)(volume/100.0) * 0x7fffffff; + if( audio_fd < 0 ) return; + + audio_control paud_control; + audio_change paud_change; + + paud_change.input = AUDIO_IGNORE; /* the new input source */ + paud_change.output = OUTPUT_1; /* EXTERNAL_SPEAKER,INTERNAL_SPEAKER, + OUTPUT_1 */ + paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */ + paud_change.volume = vol; /* volume level [0-0x7fffffff] */ + paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */ + paud_change.balance = AUDIO_IGNORE; /* the new balance */ + paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */ + paud_change.treble = AUDIO_IGNORE; /* the new treble state */ + paud_change.bass = AUDIO_IGNORE; /* the new bass state */ + paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */ + + paud_control.ioctl_request = AUDIO_CHANGE; + paud_control.request_info = (char*)&paud_change; + + if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 ) + { + perror("Change audio volume failed"); + } +} + +void audioFlush() +{ + if( audio_fd < 0 ) return; + + if ( ioctl(audio_fd, AUDIO_WAIT, NULL) < 0 ) + { + perror("Flush audio buffers failed"); + } +} + +void audioClose() +{ + if( audio_fd < 0 ) return; + + if ( ioctl(audio_fd, AUDIO_WAIT, NULL) < 0 ) + { + perror("Flush audio buffers failed"); + } + close(audio_fd); +} + +int audioWrite(char *buffer, int count) +{ + int written = write(audio_fd, buffer, count); + if( written < count ) + { + return count; + } + + return written; +} + +int +getAudioFd() +{ + return audio_fd; +} + +int mixerOpen() +{ + return true; +} + +void mixerClose() +{ +} + +void mixerSetVolume(int leftVolume,int rightVolume) +{ + long balance; + + if( audio_fd < 0 ) return; + + balance = 2 * (leftVolume-rightVolume) / (leftVolume+rightVolume); + balance = 0x3fffffff + balance*0x3fffffff; + + audio_control paud_control; + audio_change paud_change; + + paud_change.input = AUDIO_IGNORE; /* the new input source */ + paud_change.output = OUTPUT_1; /* EXTERNAL_SPEAKER,INTERNAL_SPEAKER, + OUTPUT_1 */ + paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */ + paud_change.volume = AUDIO_IGNORE; /* volume level [0-0x7fffffff] */ + paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */ + paud_change.balance = balance; /* the new balance */ + paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */ + paud_change.treble = AUDIO_IGNORE; /* the new treble state */ + paud_change.bass = AUDIO_IGNORE; /* the new bass state */ + paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */ + + paud_control.ioctl_request = AUDIO_CHANGE; + paud_control.request_info = (char*)&paud_change; + + if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 ) + { + perror("Change audio volume failed"); + } +} + +static void debugUpdate( unsigned long& flags, long& bsize ) +{ + const char* g; + + g = getenv("AUDIO_BIG_ENDIAN"); + if ( g ) + { + int i = atoi(g); + if ( i == 1 ) + { + flags |= AUDIO_BIG_ENDIAN; + } + else if ( i == 0 ) + { + flags &= ~AUDIO_BIG_ENDIAN; + } + else + { + printf("CG: bad AUDIO_BIG_ENDIAN env variable %s\n", g); + } + } + + g = getenv("SIGNED"); + if ( g ) + { + int i = atoi(g); + if ( i == 1 ) + { + flags |= SIGNED; + } + else if ( i == 0 ) + { + flags &= ~SIGNED; + } + else + { + printf("CG: bad SIGNED env variable %s\n", g); + } + } + + g = getenv("TWOS_COMPLEMENT"); + if ( g ) + { + int i = atoi(g); + if ( i == 1 ) + { + flags |= TWOS_COMPLEMENT; + } + else if ( i == 0 ) + { + flags &= ~TWOS_COMPLEMENT; + } + else + { + printf("CG: bad TWOS_COMPLEMENT env variable %s\n", g); + } + } + + g = getenv("FIXED"); + if ( g ) + { + int i = atoi(g); + if ( i == 1 ) + { + flags |= FIXED; + } + else if ( i == 0 ) + { + flags &= ~FIXED; + } + else + { + printf("CG: bad FIXED env variable %s\n", g); + } + } + + g = getenv("LEFT_ALIGNED"); + if ( g ) + { + int i = atoi(g); + if ( i == 1 ) + { + flags |= LEFT_ALIGNED; + } + else if ( i == 0 ) + { + flags &= ~LEFT_ALIGNED; + } + else + { + printf("CG: bad LEFT_ALIGNED env variable %s\n", g); + } + } + + g = getenv("RIGHT_ALIGNED"); + if ( g ) + { + int i = atoi(g); + if ( i == 1 ) + { + flags |= RIGHT_ALIGNED; + } + else if ( i == 0 ) + { + flags &= ~RIGHT_ALIGNED; + } + else + { + printf("CG: bad RIGHT_ALIGNED env variable %s\n", g); + } + } + + g = getenv("BSIZE"); + if ( g ) + { + bsize = atoi(g); + } +} + diff --git a/mpeglib/lib/util/audio/audioIO_BeOS.cpp b/mpeglib/lib/util/audio/audioIO_BeOS.cpp new file mode 100644 index 00000000..ae4cf5a1 --- /dev/null +++ b/mpeglib/lib/util/audio/audioIO_BeOS.cpp @@ -0,0 +1,227 @@ +// +// BeOS code for amp-0.7.4, (C) 1997 Andy Lo A Foe +// + + +#include <MediaKit.h> +#include <KernelKit.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "transform.h" +#include "audioIO.h" +#include "audio.h" + +// Define the streambuf size here. streambuf is used +// as a simple fit buffer. + +#define STREAMBUF_SIZE (32*1152) + +long bytes_in_streambuf; + +// streambuf definition and base indicator + +BSubscriber *the_sub; +BDACStream *the_stream; + +sem_id ok_to_read; +sem_id ok_to_write; + + +char streambuf[STREAMBUF_SIZE]; +char *readbase; + +static int au_vol = 100; + +// Define our own printout function since we are +// first writing in the streambuf (not needed, I think, +// but I don't know if the DACStream accepts a buffer +// size of 1152. Try it... + +void printout(void) +{ +if (A_WRITE_TO_FILE) { +#ifndef NO_BYTE_SWAPPING +int i,j; +short *ptr; + + if (nch==2) { + ptr=(short*)stereo_samples; + i=j=32 * 18 * 2; + } else { + ptr=(short*)mono_samples; + i=j=32 * 18; + } + + for (;i>=0;--i) + ptr[i] = ptr[i] << 8 | ptr[i] >> 8; +#endif + + if (nch==2) + fwrite(stereo_samples,1,sizeof stereo_samples,out_file); + else + fwrite(mono_samples,1,sizeof mono_samples,out_file); +} + + + if (A_AUDIO_PLAY) { + static char au_buf[STREAMBUF_SIZE]; + static int au_ptr =0, avail = 0; + static int num_smp; + static char *readbase = &au_buf[0]; + + // Write amount of samples to copy somewhere + num_smp = (nch == 2 ? sizeof stereo_samples : sizeof mono_samples); + + // Copy samples in the fit buffer + memcpy(au_buf+au_ptr,(nch == 2 ? (char *)stereo_samples : (char *)mono_samples), + num_smp); + + // Increase fit buffer pointer and available sample count + au_ptr+=num_smp; + avail+=num_smp; + + if (avail >= 4096) { // Are there enough smps to feed the stream? + audioWrite((char*)readbase,4096); // Feed it! + readbase+=4096; // Increase readbase + avail-=4096; // Decrease avail smps count + if (au_ptr == STREAMBUF_SIZE) { // At end of fit buffer? + au_ptr=0; // Reset all pointers + readbase=&au_buf[0]; + } + } + } + +} + + +// Fake Buffer functions, just to keep the sources clean, +// buffer.c should not be included in the link process... + +int AUDIO_BUFFER_SIZE; + +int +audioBufferOpen(int frequency, int stereo, int volume) +{ + audioOpen(frequency, stereo, volume); +} + + +inline void +audioBufferWrite(char *buf,int bytes) +{ + audioWrite(buf, bytes); +} + + +void +audioBufferClose() +{ + audioClose(); +} + + +int audioRead(char *buffer, int count) +{ + //printf("acquiring ok_to_read (%d bytes)\n", count); + if (acquire_sem(ok_to_read)==B_NO_ERROR) { + for (register int i=0; i < count;i++) { + *(buffer++)+=*(readbase++); + } + bytes_in_streambuf-=count; + + if (bytes_in_streambuf <= 0) { + release_sem(ok_to_write); + bytes_in_streambuf = 0; + } else { + release_sem(ok_to_read); + } + } + return (0); +} + + +bool stream_func(void *arg, char *buf, size_t count, void *header) +{ + audioRead(buf, count); + return TRUE; +} + +void audioOpen() { + readbase = &streambuf[0]; + + bytes_in_streambuf = 0; + + the_sub = new BSubscriber("amp DAC writer"); + the_stream = new BDACStream(); + + the_sub->Subscribe(the_stream); + + the_stream->SetSamplingRate(frequency); + + // Create semaphores + ok_to_read = create_sem(0, "read sem"); + ok_to_write = create_sem(1, "write sem"); + +} + +void audioInit(int sampleSize,int frequency, int stereo) +{ + + // Initialize the streambuf + bytes_in_streambuf = 0; + memset(&streambuf, 0, STREAMBUF_SIZE); + + + // Enter the stream + the_sub->EnterStream(NULL, TRUE, NULL, stream_func, NULL, TRUE); +} + + +void audioSetVolume(int volume) +{ + if (volume > 128) // This allows for a modest volume boost + volume = 128; + au_vol = volume; +} + + +void audioClose() +{ + the_sub->ExitStream(TRUE); + the_sub->Unsubscribe(); + + delete_sem(ok_to_read); + delete_sem(ok_to_write); + + delete the_sub; + delete the_stream; +} + + +// audioWrite is called from the player thread + +int audioWrite(char *buffer, int count) +{ + //printf("acquiring ok_to_write (%d bytes)\n", count); + if(acquire_sem(ok_to_write)==B_NO_ERROR) + { + memcpy(&streambuf, buffer, count); + + if (au_vol != 100) { // Handle volume scaling here + short *b=(short *)&streambuf; + for (int i=0; i < count/2; i++) { + int v=((int)b[i]*au_vol)/100; + b[i]=(v>32767) ? 32767 : ((v<-32768) ? -32768 : v); + } + } + + bytes_in_streambuf = count; + readbase = &streambuf[0]; + + release_sem(ok_to_read); + } + return 0; +} + diff --git a/mpeglib/lib/util/audio/audioIO_HPUX.cpp b/mpeglib/lib/util/audio/audioIO_HPUX.cpp new file mode 100644 index 00000000..ae07a148 --- /dev/null +++ b/mpeglib/lib/util/audio/audioIO_HPUX.cpp @@ -0,0 +1,190 @@ +/* this file is a part of amp software, (C) tomislav uzelac 1996,1997 + + Origional code by: Lutz Vieweg + Modified by: + * Andrew Richards - moved code from audio.c + + */ + + +#include <sys/audio.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/lock.h> +#include <unistd.h> +#include <stdio.h> +#include "audioIO.h" + +/* declare these static to effectively isolate the audio device */ + +static int audio_fd; + + +/* audioOpen() */ +/* should open the audio device, perform any special initialization */ +/* Set the frequency, no of channels and volume. Volume is only set if */ +/* it is not -1 */ + +void audioOpen() { + if ((audio_fd = open("/dev/audio",O_RDWR))==-1) + die(" unable to open the audio device\n"); + + DB(audio, msg("Audio device opened on %d\n",audio_fd); ) + } + + +void +audioInit(int sampleSize,int frequency, int stereo) +{ + int flags; + int failed = 0; + int volume=100; + + if ((flags = fcntl (audio_fd, F_GETFL, 0)) < 0) { + die("unable to set non-blocking mode for /dev/audio\n"); + } + flags |= O_NDELAY; + if (fcntl (audio_fd, F_SETFL, flags) < 0) { + die("unable to set non-blocking mode for /dev/audio\n"); + } + + if ( ioctl(audio_fd, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_LINEAR16BIT) < 0 || + ioctl(audio_fd, AUDIO_SET_CHANNELS, stereo ? 2 : 1) < 0 || + ioctl(audio_fd, AUDIO_SET_OUTPUT, AUDIO_OUT_SPEAKER | AUDIO_OUT_HEADPHONE + | AUDIO_OUT_LINE) < 0 || + ioctl(audio_fd, AUDIO_SET_SAMPLE_RATE, frequency) < 0) { + failed = -1; + } + if (volume != -1) { + struct audio_describe description; + struct audio_gains gains; + float fvolume = (float)volume / 100.0f; + if (ioctl(audio_fd, AUDIO_DESCRIBE, &description)) { + failed = -1; + } + if (ioctl (audio_fd, AUDIO_GET_GAINS, &gains)) { + failed = -1; + } + + gains.transmit_gain = (int)((float)description.min_transmit_gain + + (float)(description.max_transmit_gain + - description.min_transmit_gain) + * fvolume); + + /* gains.monitor_gain = description.min_monitor_gain; */ /* don't monitor ! */ + + if (ioctl (audio_fd, AUDIO_SET_GAINS, &gains)) { + failed = -1; + } + } + + if (ioctl(audio_fd, AUDIO_SET_TXBUFSIZE, 4096 * 8)) { + failed = -1; + } + if (failed) + die(" unable to setup /dev/audio\n"); +} + + +/* audioSetVolume - only code this if your system can change the volume while */ +/* playing. sets the output volume 0-100 */ + +void +audioSetVolume(int volume) +{ + struct audio_describe description; + struct audio_gains gains; + int failed = 0; + float fvolume = ((float)volume) / 100.0f; + if (ioctl(audio_fd, AUDIO_DESCRIBE, &description)) { + failed = -1; + } + if (ioctl (audio_fd, AUDIO_GET_GAINS, &gains)) { + failed = -1; +} + + gains.transmit_gain = (int)((float)description.min_transmit_gain + + (float)(description.max_transmit_gain + - description.min_transmit_gain) + * fvolume); + if (ioctl (audio_fd, AUDIO_SET_GAINS, &gains)) { + failed = -1; + } + + /* could evaluate "failed" here - but who cares? */ + + DB(audio, msg("volume set to %d%%\n",volume); ) + +} + +/* audioFlush() */ +/* should flush the audio device */ + +inline void +audioFlush() +{ + DB(audio, msg("audio: flush %d\n",audio_fd) ); +} + + +/* audioClose() */ +/* should close the audio device and perform any special shutdown */ + +void +audioClose() +{ + close(audio_fd); + DB(audio, msg("audio: closed %d\n",audio_fd) ); +} + + +/* audioWrite */ +/* writes count bytes from buffer to the audio device */ +/* returns the number of bytes actually written */ + +int audioWrite(char *buffer, int count) +{ + DB(audio, msg("audio: Writing %d bytes to audio descriptor %d\n",count,getAudioFd()) ); + return(write(audio_fd,buffer,count)); +} + + +/* Let buffer.c have the audio descriptor so it can select on it. This means */ +/* that the program is dependent on an file descriptor to work. Should really */ +/* move the select's etc (with inlines of course) in here so that this is the */ +/* ONLY file which has hardware dependent audio stuff in it */ + +int +getAudioFd() +{ + return(audio_fd); +} + +/* + Try to set the priority of this process to a value which + allows us to play without buffering, thus saving memory + and avoiding cache-misses. + If we cannot get any priority high enough to allow for + undisturbed replay (because we don't have sufficient + privilege), return a zero, otherwise, return a one. +*/ +int audioSetPriority(void) { + + /* try to lock process in physical memory, just ignore if this fails */ + plock(PROCSHLIBLOCK); + + /* try to set a realtime-priority of 64 */ + if (-1 != rtprio(0, 64)) { + DB(audio, msg("using real-time priority\n"); ) + return 1; + } + + /* try to set a nice-level of -20 */ + if (-1 != nice(-20)) { + DB(audio, msg("using nice-level -20\n"); ) + return 1; + } + + DB(audio, msg("using buffered output\n"); ) + return 0; /* need to use a buffer */ +} diff --git a/mpeglib/lib/util/audio/audioIO_IRIX.cpp b/mpeglib/lib/util/audio/audioIO_IRIX.cpp new file mode 100644 index 00000000..8498a487 --- /dev/null +++ b/mpeglib/lib/util/audio/audioIO_IRIX.cpp @@ -0,0 +1,157 @@ +/* this file is a part of amp software, (C) tomislav uzelac 1996,1997 + + Origional code by: Karl Anders Oygard + Modified by: + * Andrew Richards - moved code from audio.c + + */ +#include <assert.h> +#include <unistd.h> +#include <stdio.h> +#include <dmedia/audio.h> +#include "audioIO.h" + +/* declare these static to effectively isolate the audio device */ + +static ALport audioport; +static ALconfig audioconfig; + + +/* audioOpen() */ +/* should open the audio device, perform any special initialization */ +/* Set the frequency, no of channels and volume. Volume is only set if */ +/* it is not -1 */ + + +void audioOpen() { + printf("sorry. The audio part for irix must be fixed. \n"); +} + +void +audioInit(int sampleSize,int frequency, int stereo) +{ + ALconfig audioconfig; + audioconfig = ALnewconfig(); + + if (!audioconfig) + die("out of memory\n"); + else { + long pvbuf[] = { AL_OUTPUT_COUNT, 0, AL_MONITOR_CTL, 0, AL_OUTPUT_RATE, 0}; + + if (ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 6) < 0) + if (oserror() == AL_BAD_DEVICE_ACCESS) + die("couldn't access audio device\n"); + + if (pvbuf[1] == 0 && pvbuf[3] == AL_MONITOR_OFF) { + long al_params[] = { AL_OUTPUT_RATE, 0}; + + al_params[1] = frequency; + ALsetparams(AL_DEFAULT_DEVICE, al_params, 2); + } else + if (pvbuf[5] != frequency) + die("audio device is already in use with wrong sample output rate\n"); + + /* ALsetsampfmt(audioconfig, AL_SAMPFMT_TWOSCOMP); this is the default */ + /* ALsetwidth(audioconfig, AL_SAMPLE_16); this is the default */ + + if (!stereo) ALsetchannels(audioconfig, AL_MONO); + /* else ALsetchannels(audioconfig, AL_STEREO); this is the default */ + + ALsetqueuesize(audioconfig, AUSIZ * 2); + + audioport = ALopenport("amp", "w", audioconfig); + if (audioport == (ALport) 0) { + switch (oserror()) { + case AL_BAD_NO_PORTS: + die("system is out of ports\n"); + + case AL_BAD_DEVICE_ACCESS: + die("couldn't access audio device\n"); + + case AL_BAD_OUT_OF_MEM: + die("out of memory\n"); + } + exit(-1); + } + ALsetfillpoint(audioport, AUSIZ); + } +} + + +/* audioSetVolume - only code this if your system can change the volume while */ +/* playing. sets the output volume 0-100 */ + +void +audioSetVolume(int volume) +{ + long al_params[] = { AL_LEFT_SPEAKER_GAIN, 0, AL_RIGHT_SPEAKER_GAIN, 0}; + + al_params[1] = al_params[3] = volume * 100 / 255; + + ALsetparams(AL_DEFAULT_DEVICE, al_params, 4); +} + + +/* audioFlush() */ +/* should flush the audio device */ + +void +audioFlush() +{ + DB(audio, msg("audio: flush %d\n",audio_fd) ); +} + + +/* audioClose() */ +/* should close the audio device and perform any special shutdown */ + +void +audioClose() +{ +int write_fd; + + /* wait for all samples to be played */ + + write_fd = ALgetfd(audioport); + if (write_fd >= 0) { + fd_set write_fds; + + FD_ZERO(&write_fds); + FD_SET(write_fd, &write_fds); + + ALsetfillpoint(audioport, AUSIZ * 2); + select(write_fd + 1, NULL, &write_fds, NULL, NULL); + } + + /* now close it */ + + ALcloseport(audioport); + DB(audio, msg("audio: closed %d\n",audio_fd) ); +} + + +/* audioWrite */ +/* writes count bytes from buffer to the audio device */ +/* returns the number of bytes actually written */ + +int audioWrite(char *buffer, int count) +{ + if (ALwritesamps(audioport, buffer, count / 2) == 0) { + ALsetfillpoint(audioport, AUSIZ); + return(count); + } else + return 0; +} + +/* Let buffer.c have the audio descriptor so it can select on it. This + means that the program is dependent on an file descriptor to + work. Should really move the select's etc (with inlines of course) in + here so that this is the ONLY file which has hardware dependent audio + stuff in it. */ + +int +getAudioFd() +{ + return ALgetfd(audioport); +} + diff --git a/mpeglib/lib/util/audio/audioIO_Linux.cpp b/mpeglib/lib/util/audio/audioIO_Linux.cpp new file mode 100644 index 00000000..5ca9231c --- /dev/null +++ b/mpeglib/lib/util/audio/audioIO_Linux.cpp @@ -0,0 +1,220 @@ +/* this file is a part of amp software, (C) tomislav uzelac 1996,1997 + + Origional code by: tomislav uzelac + Modified by: + * Dan Nelson - BSD mods. + * Andrew Richards - moved code from audio.c and added mixer support etc + * Martin Vogt + */ + +/* Support for Linux and BSD sound devices */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include "audioIO.h" +#include <stdlib.h> +#include <stdio.h> + +// +// Why all these different system cannot make a standard where this +// soundcard.h file is ? +// +#if defined(HAVE_SYS_SOUNDCARD_H) + #undef AUSIZ + #undef HAVE_SYS_SOUNDCARD_H + #include <sys/soundcard.h> +#elif defined(HAVE_MACHINE_SOUNDCARD_H) + #undef AUSIZ + #include <machine/soundcard.h> +#elif defined(__NetBSD__) + #undef AUSIZ + #include <soundcard.h> +#else + // fallback: + #include <linux/soundcard.h> +#endif + + +/* optimal fragment size */ + +int AUSIZ = 0; + +// declare these static to effectively isolate the audio device + +static int audio_fd; +static int mixer_fd; +static int volumeIoctl; + + + +int audioConstruct() { + audio_fd=-1; + mixer_fd=-1; + return true; +} + + +void audioDestruct() { + +} + + + +/* + should open the audio device, perform any special initialization +*/ +int audioOpen() { + audio_fd = open ("/dev/dsp", O_WRONLY, 0); + if (audio_fd < 0) { + perror("Unable to open the audio"); + } + + // Ok here something important if your programm forks: + if (audio_fd > 0) { + if (fcntl(audio_fd,F_SETFD,true) < 0) { + perror("fcntl socket");exit(1); + } + } + + return (audio_fd > 0); +} + +inline void audioFlush() { + if (ioctl(audio_fd, SNDCTL_DSP_RESET, 0) == -1) + perror("Unable to reset audio device\n"); +} + +/* + should close the audio device and perform any special shutdown +*/ +void audioClose() { + audioFlush(); + if (close(audio_fd) < 0) { + perror("error close audiodevice:"); + } +} + + +void audioInit(int sampleSize,int frequency, int stereo, int sign, int big) { + if( sign == 0 ) + { + fprintf(stderr, + "%s, %d: expecting signed audio data, " + "initialized unsigned (ignored)\n", + __FILE__, __LINE__ ); + } + if( big != 0 ) + { + fprintf(stderr, + "%s, %d: expecting little endian audio data, " + "initialized big endian (ignored)\n", + __FILE__, __LINE__ ); + } + + int play_format=AFMT_S16_LE; + + if (sampleSize == 8) { + play_format=AFMT_S8; + } + ioctl(audio_fd,SNDCTL_DSP_RESET,NULL); + + if (ioctl(audio_fd, SNDCTL_DSP_SETFMT,&play_format) < 0) { + perror("Unable to set required audio format\n"); + } + + /* Set 1 or 2 channels */ + stereo=(stereo ? 1 : 0); + + if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0) { + perror("Unable to set stereo/mono\n"); + exit(0); + } + + /* Set the output frequency */ + if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &frequency) < 0) { + perror("Unable to set frequency"); + exit(0); + } + + if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &AUSIZ) == -1) { + perror("Unable to get fragment size\n"); + exit(0); + } +} + + +int getAudioBufferSize() { + struct audio_buf_info buf_info; + int buf=1024*65; + if (ioctl(audio_fd,SNDCTL_DSP_GETOSPACE,&buf_info) == -1) { + perror("ioctl getAudioBufferSize using default"); + } else { + buf=buf_info.bytes; + } + return buf; +} + + +int mixerOpen() { + int supportedMixers; + + if ((mixer_fd=open("/dev/mixer",O_RDWR)) == -1) { + perror("Unable to open mixer device"); + } + + // Ok here something important if your programm forks: + if (mixer_fd > 0) { + if (fcntl(mixer_fd,F_SETFD,true) < 0) { + perror("fcntl socket");exit(1); + } + } + + if (ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &supportedMixers) == -1){ + perror("Unable to get mixer info assuming master volume"); + volumeIoctl=SOUND_MIXER_WRITE_VOLUME; + } else { + if ((supportedMixers & SOUND_MASK_PCM) != 0) + volumeIoctl=SOUND_MIXER_WRITE_PCM; + else + volumeIoctl=0; + } + + return (mixer_fd > 0); +} + + +void mixerClose() { + if (mixer_fd != -1) { + close(mixer_fd); + } +} + +/* + only code this if your system can change the volume while + playing +*/ +void mixerSetVolume(int leftVolume,int rightVolume) { + int volume; + + volume=leftVolume+(rightVolume<<8); + if ((mixer_fd != -1) && (volumeIoctl!=0)) { + if (ioctl(mixer_fd, volumeIoctl, &volume) < 0) { + perror("Unable to set sound volume"); + } + } +} + + + +int audioWrite(char *buffer, int count) { + return(write(audio_fd,buffer,count)); +} + + +int getAudioFd() { + return(audio_fd); +} diff --git a/mpeglib/lib/util/audio/audioIO_SDL.cpp b/mpeglib/lib/util/audio/audioIO_SDL.cpp new file mode 100644 index 00000000..782fa388 --- /dev/null +++ b/mpeglib/lib/util/audio/audioIO_SDL.cpp @@ -0,0 +1,164 @@ +/* + audio wrapper for SDL + Copyright (C) 2000 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ +#include "../../input/bufferInputStream.h" +#include <assert.h> +#include <iostream.h> +#if defined WIN32 +#include <SDL.h> +#include <SDL_audio.h> +#else +#include <SDL/SDL.h> +#include <SDL/SDL_audio.h> +#endif + +//static SDL_AudioSpec actual; +static BufferInputStream* audioRing; +static TimeStamp* dummy; +static int lOpen=false; + + + +int audioConstruct() { + cout << "audioConstruct ********* SDL"<<endl; + if ( SDL_Init(SDL_INIT_AUDIO) < 0 ) { + fprintf(stderr, "Warning: Couldn't init SDL audio: %s\n", + SDL_GetError()); + exit(0); + } + atexit(SDL_Quit); + audioRing=new BufferInputStream(1024*65,1024*8,"audioSDL"); + audioRing->open("audioSDL"); + dummy=new TimeStamp(); + lOpen=false; + return true; +} + + +void audioDestruct() { + delete audioRing; + delete dummy; +} + + + + +int audioOpen() { + return true; +} + + +void audioClose() { + lOpen=false; + SDL_CloseAudio(); +} + + +void audioCallback(void *, Uint8 *stream, int len) { + char* startPtr; + TimeStamp* start; + int bytePos; + + int read=audioRing->readRemote(&startPtr,len); + SDL_MixAudio(stream, (Uint8*) startPtr, read, SDL_MIX_MAXVOLUME); + + audioRing->forwardReadPtr(read); + // dequeue time stamps + bytePos=audioRing->getBytePosition(); + start=audioRing->getTimeStamp(bytePos); + +} + + + +void audioInit(int sampleSize,int frequency, int stereo, int sign, int big) { + if( sign == 0 ) + { + fprintf(stderr, + "%s, %d: expecting signed audio data, " + "initialized unsigned (ignored)\n", + __FILE__, __LINE__ ); + } + if( big != 0 ) + { + fprintf(stderr, + "%s, %d: expecting little endian audio data, " + "initialized big endian (ignored)\n", + __FILE__, __LINE__ ); + } + + cout << "SDL audioInit: " + << " sampleSize:"<<sampleSize + << " frequency:"<<frequency + << " stereo:"<<stereo<<endl; + if (lOpen==true) { + cout << "SDL is buggy, because open != init -> return"<<endl; + return; + } + lOpen=true; + SDL_AudioSpec wanted; + //SDL_AudioSpec actual; + if (sampleSize == 16) { + wanted.format= AUDIO_S16LSB; + } else { + wanted.format= AUDIO_S8; + } + + wanted.freq=frequency; + wanted.channels=stereo+1; + wanted.samples = 1024; + wanted.callback = audioCallback; + wanted.userdata = NULL; + + int err=SDL_OpenAudio(&wanted, NULL); + if (err != 0) { + cout << "SDL_OpenAudio not ok"<<endl; + cout << "error is:"<<SDL_GetError()<<endl; + exit(0); + } + SDL_PauseAudio(0); + +} + + +int mixerOpen() { + return true; +} + + +void mixerClose() { +} + + +void mixerSetVolume(int volumeLeft,int volumeRight) { + cout << "volumeLeft:"<<volumeLeft + << " volumeRight:"<<volumeRight<<endl; +} + + +int audioWrite(char *buffer, int count) { + + audioRing->write(buffer,count,dummy); + + + return count; +} + + +int getAudioFd() { + return false; +} + + +int getAudioBufferSize() { + int buf=1024*65; + return buf; +} diff --git a/mpeglib/lib/util/audio/audioIO_SunOS.cpp b/mpeglib/lib/util/audio/audioIO_SunOS.cpp new file mode 100644 index 00000000..4e9958a1 --- /dev/null +++ b/mpeglib/lib/util/audio/audioIO_SunOS.cpp @@ -0,0 +1,167 @@ +/* this file is a part of amp software, (C) tomislav uzelac 1996,1997 + + Origional code by: tomislav uzelac + Modified by: + * Andrew Richards - moved code from audio.c + * Jim Crumley - ported some code from other audioIO_'s + + */ + +#include <sys/types.h> +#include <sys/stropts.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <sys/audioio.h> +#include "audioIO.h" +#include <iostream.h> + +/* declare these static to effectively isolate the audio device */ + +static int audio_fd; +static audio_info_t auinfo; + + +int audioConstruct(){ + audio_fd=-1; + return true; +} + +void audioDestruct() { + +} + + +/* audioOpen() */ +/* should open the audio device and perform any special initialization */ +/* returns the file descriptior of the audio device */ + +int audioOpen() { + AUDIO_INITINFO(&auinfo); + + if ((audio_fd = open("/dev/audio",O_RDWR))==-1) { + perror("unable to open the audio device"); + } + // Ok here something important if your programm forks: + if (audio_fd > 0) { + if (fcntl(audio_fd,F_SETFD,true) < 0) { + perror("fcntl socket");exit(1); + } + } + + DB(audio, msg("Audio device opened on %d\n",audio_fd) ); + return (audio_fd > 0); +} + +/* audioFlush() */ +/* should flush the audio device */ + +inline void audioFlush() { + DB(audio, msg("audio: flush %d\n",audio_fd) ); +} + + +/* audioClose() */ +/* should close the audio device and perform any special shutdown */ + +void audioClose() { + close(audio_fd); +} + + +/** + Audio init assumes that the audiodevice is open. It initializes + it to the given values +*/ + +void audioInit(int sampleSize ,int frequency, int stereo,int sign, int big){ + + if (ioctl(audio_fd,AUDIO_GETINFO,&auinfo)<0) + perror("Unable to get audio info"); + + auinfo.play.precision=sampleSize; + auinfo.play.encoding=AUDIO_ENCODING_LINEAR; + auinfo.play.channels=(stereo ? 2 : 1); + DB(audio, msg("setting sample rate to %d Hz",frequency) ); + auinfo.play.sample_rate=frequency; + if (ioctl(audio_fd,AUDIO_SETINFO,&auinfo)<0) + perror("Unable to set audio info"); + +} + +/* + only code this if your system can change the volume while + playing +*/ + + +int getAudioBufferSize() { + int buf; + if (ioctl(audio_fd,AUDIO_GETINFO,&auinfo) == -1) { + perror("ioctl getAudioBufferSize using default"); + buf=1024*65; + } else { + buf=auinfo.play.buffer_size; + } + return buf; +} + + +void mixerSetVolume(int leftVolume,int rightVolume) { + int volume; + + volume=(leftVolume+rightVolume)/2; + auinfo.play.gain=(volume*255)/100; + + // now normalize to values 0...32 + leftVolume=(32*leftVolume)/100; + rightVolume=(32*rightVolume)/100; + + // eg : leftVolume=32, rightVolume=32 => balance=32 + // eg : leftVolume=0, rightVolume=32 => balance=64 + // eg : leftVolume=32, rightVolume=0 => balance=0 + + //cout << "leftVolume:"<<leftVolume<<endl; + //cout << "rightVolume:"<<rightVolume<<endl; + int balance=leftVolume-rightVolume+32; + //cout << "balance:"<<balance<<endl; + //someone should fix the volume on solaris + balance=0; + + auinfo.play.balance=(uchar_t)balance; + if (ioctl(audio_fd,AUDIO_SETINFO,&auinfo)<0) + perror("Unable to set sound volume"); +} + + + + +int mixerOpen() { + return true; +} + +void mixerClose() { +} + + + + +/* audioWrite */ +/* writes count bytes from buffer to the audio device */ +/* returns the number of bytes actually written */ + +int audioWrite(char *buffer, int count) +{ + return(write(audio_fd,buffer,count)); +} + +/* Let buffer.c have the audio descriptor so it can select on it. This means */ +/* that the program is dependent on an file descriptor to work. Should really */ +/* move the select's etc (with inlines of course) in here so that this is the */ +/* ONLY file which has hardware dependent audio stuff in it */ + +int +getAudioFd() +{ + return(audio_fd); +} diff --git a/mpeglib/lib/util/audio/dspWrapper.cpp b/mpeglib/lib/util/audio/dspWrapper.cpp new file mode 100644 index 00000000..cd9afa57 --- /dev/null +++ b/mpeglib/lib/util/audio/dspWrapper.cpp @@ -0,0 +1,193 @@ +/* + a wrapper for the audioDevice. + Copyright (C) 1998 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + +#include "dspWrapper.h" +#include "audioIO.h" + + +#include "../../frame/pcmFrame.h" +#include "../../frame/floatFrame.h" + +#include <iostream> + +using namespace std; + +DSPWrapper::DSPWrapper() { + currentFormat=new PCMFrame(0); + lopenDevice=false; + lopenMixer=false; + + audioConstruct(); +} + +DSPWrapper::~DSPWrapper() { + if (lopenDevice) { + audioClose(); + } + if (lopenMixer) { + mixerClose(); + } + audioDestruct(); + delete currentFormat; +} + + +int DSPWrapper::isOpenDevice() { + return lopenDevice; +} + +int DSPWrapper::openDevice() { + if (lopenDevice==true) { + return true; + } + lopenDevice=audioOpen(); + return lopenDevice; +} + +int DSPWrapper::closeDevice() { + if (isOpenDevice() == true) { + audioClose(); + currentFormat->setFrameFormat(-1,-1); + lopenDevice=false; + } + return true; +} + + +int DSPWrapper::isOpenMixer() { + return lopenMixer; +} + + +int DSPWrapper::getAudioBufferSize() { + return ::getAudioBufferSize(); +} + + +int DSPWrapper::openMixer() { + lopenMixer=mixerOpen(); + return lopenMixer; +} + +int DSPWrapper::closeMixer() { + if (isOpenMixer() == true) { + mixerClose(); + lopenMixer=false; + } + return true; +} + + +int DSPWrapper::audioPlay(char *buf, int len) { + return audioWrite(buf,len); +} + +int DSPWrapper::audioSetup(int stereo,int sampleSize,int lSigned, + int lBigEndian,int freq) { + + + if (isOpenDevice()==false) { + cout << "device not open"<<endl; + exit(-1); + } + /* + cout << "sampleSize:"<<sampleSize<<endl; + cout << "freq:"<<freq<<endl; + cout << "stereo:"<<stereo<<endl; + cout << "lSigned:"<<lSigned<<endl; + cout << "lBigEndian:"<<lBigEndian<<endl; + */ + audioInit(sampleSize,freq,stereo,lSigned,lBigEndian); + if (currentFormat->getSampleSize() != sampleSize) { + cout << "FIXME: pcmFrame with sampleSize:"<<sampleSize<<endl; + } + currentFormat->setFrameFormat(stereo,freq); + return true; +} + +int DSPWrapper::audioSetup(AudioFrame* audioFrame) { + if (audioFrame == NULL) { + cout << "audioFrame NULL: DSPWrapper:audioSetup"<<endl; + exit(0); + } + if(audioFrame->isFormatEqual(currentFormat)==false) { + audioSetup(audioFrame->getStereo(),audioFrame->getSampleSize(), + audioFrame->getSigned(),audioFrame->getBigEndian(), + audioFrame->getFrequenceHZ()); + } + return true; +} + + +int DSPWrapper::audioPlay(PCMFrame* pcmFrame) { + if (pcmFrame == NULL) { + cout << "pcmFrame NULL: DSPWrapper:audioPlay"<<endl; + exit(0); + } + if(pcmFrame->isFormatEqual(currentFormat)==false) { + audioSetup(pcmFrame->getStereo(),pcmFrame->getSampleSize(), + pcmFrame->getSigned(),pcmFrame->getBigEndian(), + pcmFrame->getFrequenceHZ()); + } + int len=pcmFrame->getLen()*2; + int played=audioPlay((char*)pcmFrame->getData(),len); + return (len == played); +} + + +// +// Misuse our internal currentFormat for the float->int conversion. +// + +int DSPWrapper::audioPlay(FloatFrame* floatFrame) { + if (floatFrame == NULL) { + cout << "floatFrame NULL: DSPWrapper:audioPlay"<<endl; + exit(0); + } + if(floatFrame->isFormatEqual(currentFormat)==false) { + audioSetup(floatFrame->getStereo(),floatFrame->getSampleSize(), + floatFrame->getSigned(),floatFrame->getBigEndian(), + floatFrame->getFrequenceHZ()); + } + + int tmpLen=currentFormat->getLen(); + if (tmpLen < floatFrame->getLen()) { + delete currentFormat; + currentFormat=new PCMFrame(floatFrame->getLen()); + floatFrame->copyFormat(currentFormat); + } + currentFormat->clearrawdata(); + currentFormat->putFloatData(floatFrame->getData(),floatFrame->getLen()); + return audioPlay(currentFormat); +} + +void DSPWrapper::audioFlush() { + closeDevice(); +} + + +void DSPWrapper::setVolume(float leftPercent,float rightPercent) { + if (isOpenMixer()) { + mixerSetVolume((int)leftPercent,(int)rightPercent); + } else { + cout << "cannot set Mixer settings:not open!"<<endl; + } +} + + +void DSPWrapper::print() { + cout<<"lopenDevice:"<<lopenDevice<<endl; + cout<<"lopenMixer:"<<lopenMixer<<endl; + currentFormat->print("currentFormat"); + +} diff --git a/mpeglib/lib/util/audio/dspWrapper.h b/mpeglib/lib/util/audio/dspWrapper.h new file mode 100644 index 00000000..f323096d --- /dev/null +++ b/mpeglib/lib/util/audio/dspWrapper.h @@ -0,0 +1,75 @@ +/* + a wrapper for the audioDevice. + Copyright (C) 1998 Martin Vogt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as published by + the Free Software Foundation. + + For more information look at the file COPYRIGHT in this package + + */ + + + +#ifndef _DSPWRAPPER_H +#define _DSPWRAPPER_H + +class AudioFrame; +class PCMFrame; +class FloatFrame; +#include <kdemacros.h> + +/** + This class wraps the platform specific /dev/dsp implementation. + The only unusal thing is, that it supports each order of + init/open. + i) you can first init the device and the open + ii) you can first open the device and the init it + The implementation takes care that the calls are forwarded + in the right order to the /dev/dsp implementation. + (means: before the init it, we need to open it) + But a caller can do it in both orders. +*/ + +class KDE_EXPORT DSPWrapper { + + int lopenDevice; + int lopenMixer; + PCMFrame* currentFormat; + + + public: + DSPWrapper(); + ~DSPWrapper(); + + int openDevice(); + int closeDevice(); + int isOpenDevice(); + + int openMixer(); + int closeMixer(); + int isOpenMixer(); + + int getAudioBufferSize(); + void setVolume(float leftPercent,float rightPercent); + + int audioSetup(int stereo,int sampleSize,int lSigned, + int lBigEndian,int freq); + int audioSetup(AudioFrame* audioFrame); + + int audioPlay(char *buffer, int size); + int audioPlay(PCMFrame* pcmFrame); + int audioPlay(FloatFrame* floatFrame); + void audioFlush(); + + int isEqual(int samplesize,int speed,int stereo,int lSigned,int lBigEndian); + int write(char* buf,int len); + void print(); +}; + +#endif + + + + |