diff options
Diffstat (limited to 'mpeglib/lib/util/audio/audioIO_AIX.cpp')
-rw-r--r-- | mpeglib/lib/util/audio/audioIO_AIX.cpp | 533 |
1 files changed, 533 insertions, 0 deletions
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); + } +} + |