146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL - Simple DirectMedia Layer 346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Copyright (C) 1997-2006 Sam Lantinga 446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is free software; you can redistribute it and/or 646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner modify it under the terms of the GNU Lesser General Public 746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License as published by the Free Software Foundation; either 846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner version 2.1 of the License, or (at your option) any later version. 946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is distributed in the hope that it will be useful, 1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner but WITHOUT ANY WARRANTY; without even the implied warranty of 1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Lesser General Public License for more details. 1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner You should have received a copy of the GNU Lesser General Public 1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License along with this library; if not, write to the Free Software 1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Carsten Griwodz 2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner griff@kom.tu-darmstadt.de 2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner based on linux/SDL_dspaudio.c by Sam Lantinga 2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/ 2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h" 2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Allow access to a raw mixing buffer */ 2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <errno.h> 2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <unistd.h> 3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <fcntl.h> 3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/time.h> 3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/ioctl.h> 3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/stat.h> 3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_timer.h" 3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_audio.h" 3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_audiomem.h" 3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_audio_c.h" 3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_audiodev_c.h" 4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_paudio.h" 4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DEBUG_AUDIO 1 4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* A conflict within AIX 4.3.3 <sys/> headers and probably others as well. 4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * I guess nobody ever uses audio... Shame over AIX header files. */ 4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/machine.h> 4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#undef BIG_ENDIAN 4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/audio.h> 4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The tag name used by paud audio */ 5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define Paud_DRIVER_NAME "paud" 5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Open the audio device for playback, and don't block if busy */ 5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) */ 5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define OPEN_FLAGS O_WRONLY 5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Audio driver functions */ 5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int Paud_OpenAudio(_THIS, SDL_AudioSpec *spec); 5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Paud_WaitAudio(_THIS); 6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Paud_PlayAudio(_THIS); 6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint8 *Paud_GetAudioBuf(_THIS); 6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Paud_CloseAudio(_THIS); 6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Audio driver bootstrap functions */ 6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int Audio_Available(void) 6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int fd; 6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int available; 7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner available = 0; 7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); 7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( fd >= 0 ) { 7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner available = 1; 7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner close(fd); 7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(available); 7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Audio_DeleteDevice(SDL_AudioDevice *device) 8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(device->hidden); 8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(device); 8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic SDL_AudioDevice *Audio_CreateDevice(int devindex) 8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_AudioDevice *this; 8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Initialize all variables that we clean on shutdown */ 9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); 9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( this ) { 9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memset(this, 0, (sizeof *this)); 9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->hidden = (struct SDL_PrivateAudioData *) 9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_malloc((sizeof *this->hidden)); 9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (this == NULL) || (this->hidden == NULL) ) { 9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_OutOfMemory(); 9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( this ) { 10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(this); 10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(0); 10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memset(this->hidden, 0, (sizeof *this->hidden)); 10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_fd = -1; 10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Set the function pointers */ 10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->OpenAudio = Paud_OpenAudio; 10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->WaitAudio = Paud_WaitAudio; 11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->PlayAudio = Paud_PlayAudio; 11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->GetAudioBuf = Paud_GetAudioBuf; 11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->CloseAudio = Paud_CloseAudio; 11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->free = Audio_DeleteDevice; 11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return this; 11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 11946be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerAudioBootStrap Paud_bootstrap = { 12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Paud_DRIVER_NAME, "AIX Paudio", 12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Audio_Available, Audio_CreateDevice 12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}; 12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* This function waits until it is possible to write a full sound buffer */ 12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Paud_WaitAudio(_THIS) 12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fd_set fdset; 12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* See if we need to use timed audio synchronization */ 13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( frame_ticks ) { 13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Use timer for general audio synchronization */ 13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sint32 ticks; 13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; 13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ticks > 0 ) { 13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Delay(ticks); 13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_buffer paud_bufinfo; 14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Use select() for audio synchronization */ 14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner struct timeval timeout; 14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner FD_ZERO(&fdset); 14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner FD_SET(audio_fd, &fdset); 14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0 ) { 14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_AUDIO 14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr, "Couldn't get audio buffer information\n"); 14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner timeout.tv_sec = 10; 15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner timeout.tv_usec = 0; 15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner long ms_in_buf = paud_bufinfo.write_buf_time; 15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner timeout.tv_sec = ms_in_buf/1000; 15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ms_in_buf = ms_in_buf - timeout.tv_sec*1000; 15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner timeout.tv_usec = ms_in_buf*1000; 15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_AUDIO 15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf( stderr, 15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner "Waiting for write_buf_time=%ld,%ld\n", 16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner timeout.tv_sec, 16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner timeout.tv_usec ); 16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_AUDIO 16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr, "Waiting for audio to get ready\n"); 16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( select(audio_fd+1, NULL, &fdset, NULL, &timeout) <= 0 ) { 16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner const char *message = "Audio timeout - buggy audio driver? (disabled)"; 17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* 17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * In general we should never print to the screen, 17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * but in this case we have no other way of letting 17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * the user know what happened. 17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message); 17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->enabled = 0; 17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Don't try to close - may hang */ 17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_fd = -1; 17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_AUDIO 18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr, "Done disabling audio\n"); 18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_AUDIO 18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr, "Ready!\n"); 18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Paud_PlayAudio(_THIS) 19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int written; 19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Write the audio data, checking for EAGAIN on broken audio drivers */ 19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner do { 19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner written = write(audio_fd, mixbuf, mixlen); 19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (written < 0) && ((errno == 0) || (errno == EAGAIN)) ) { 19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Delay(1); /* Let a little CPU time go by */ 19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } while ( (written < 0) && 20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)) ); 20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* If timer synchronization is enabled, set the next write frame */ 20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( frame_ticks ) { 20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner next_frame += frame_ticks; 20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* If we couldn't write, assume fatal error for now */ 20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( written < 0 ) { 20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->enabled = 0; 21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_AUDIO 21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr, "Wrote %d bytes of audio data\n", written); 21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint8 *Paud_GetAudioBuf(_THIS) 21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return mixbuf; 21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Paud_CloseAudio(_THIS) 22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( mixbuf != NULL ) { 22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_FreeAudioMem(mixbuf); 22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner mixbuf = NULL; 22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( audio_fd >= 0 ) { 22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner close(audio_fd); 22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_fd = -1; 23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int Paud_OpenAudio(_THIS, SDL_AudioSpec *spec) 23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner char audiodev[1024]; 23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int format; 23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int bytes_per_sample; 23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint16 test_format; 23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_init paud_init; 24046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_buffer paud_bufinfo; 24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_status paud_status; 24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_control paud_control; 24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_change paud_change; 24446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Reset the timer synchronization flag */ 24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner frame_ticks = 0.0; 24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 24846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Open the audio device */ 24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); 25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( audio_fd < 0 ) { 25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); 25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 25546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* 25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * We can't set the buffer size - just ask the device for the maximum 25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * that we can have. 25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 25946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0 ) { 26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Couldn't get audio buffer information"); 26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 26246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner mixbuf = NULL; 26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( spec->channels > 1 ) 26746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner spec->channels = 2; 26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner else 26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner spec->channels = 1; 27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* 27246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Fields in the audio_init structure: 27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * 27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Ignored by us: 27546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * 27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.loadpath[LOAD_PATH]; * DSP code to load, MWave chip only? 27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.slot_number; * slot number of the adapter 27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.device_id; * adapter identification number 27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * 28046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Input: 28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * 28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.srate; * the sampling rate in Hz 28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.bits_per_sample; * 8, 16, 32, ... 28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.bsize; * block size for this rate 28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.mode; * ADPCM, PCM, MU_LAW, A_LAW, SOURCE_MIX 28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.channels; * 1=mono, 2=stereo 28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.flags; * FIXED - fixed length data 28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * LEFT_ALIGNED, RIGHT_ALIGNED (var len only) 28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * TWOS_COMPLEMENT - 2's complement data 29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * SIGNED - signed? comment seems wrong in sys/audio.h 29146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * BIG_ENDIAN 29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.operation; * PLAY, RECORD 29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * 29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Output: 29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * 29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.flags; * PITCH - pitch is supported 29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * INPUT - input is supported 29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * OUTPUT - output is supported 29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * MONITOR - monitor is supported 30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * VOLUME - volume is supported 30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * VOLUME_DELAY - volume delay is supported 30246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * BALANCE - balance is supported 30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * BALANCE_DELAY - balance delay is supported 30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * TREBLE - treble control is supported 30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * BASS - bass control is supported 30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * BESTFIT_PROVIDED - best fit returned 30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * LOAD_CODE - DSP load needed 30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.rc; * NO_PLAY - DSP code can't do play requests 30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * NO_RECORD - DSP code can't do record requests 31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * INVALID_REQUEST - request was invalid 31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * CONFLICT - conflict with open's flags 31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * * OVERLOADED - out of DSP MIPS or memory 31346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * paud.position_resolution; * smallest increment for position 31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.srate = spec->freq; 31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.mode = PCM; 31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.operation = PLAY; 31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.channels = spec->channels; 32046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Try for a closest match on audio format */ 32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format = 0; 32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( test_format = SDL_FirstAudioFormat(spec->format); 32446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ! format && test_format; ) { 32546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_AUDIO 32646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr, "Trying format 0x%4.4x\n", test_format); 32746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 32846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch ( test_format ) { 32946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case AUDIO_U8: 33046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bytes_per_sample = 1; 33146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.bits_per_sample = 8; 33246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.flags = TWOS_COMPLEMENT | FIXED; 33346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format = 1; 33446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 33546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case AUDIO_S8: 33646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bytes_per_sample = 1; 33746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.bits_per_sample = 8; 33846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.flags = SIGNED | 33946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner TWOS_COMPLEMENT | FIXED; 34046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format = 1; 34146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 34246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case AUDIO_S16LSB: 34346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bytes_per_sample = 2; 34446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.bits_per_sample = 16; 34546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.flags = SIGNED | 34646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner TWOS_COMPLEMENT | FIXED; 34746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format = 1; 34846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 34946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case AUDIO_S16MSB: 35046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bytes_per_sample = 2; 35146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.bits_per_sample = 16; 35246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.flags = BIG_ENDIAN | 35346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SIGNED | 35446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner TWOS_COMPLEMENT | FIXED; 35546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format = 1; 35646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 35746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case AUDIO_U16LSB: 35846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bytes_per_sample = 2; 35946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.bits_per_sample = 16; 36046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.flags = TWOS_COMPLEMENT | FIXED; 36146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format = 1; 36246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 36346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case AUDIO_U16MSB: 36446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner bytes_per_sample = 2; 36546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.bits_per_sample = 16; 36646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.flags = BIG_ENDIAN | 36746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner TWOS_COMPLEMENT | FIXED; 36846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format = 1; 36946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 37046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 37146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 37246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 37346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ! format ) { 37446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner test_format = SDL_NextAudioFormat(); 37546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 37646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 37746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( format == 0 ) { 37846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_AUDIO 37946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr, "Couldn't find any hardware audio formats\n"); 38046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 38146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Couldn't find any hardware audio formats"); 38246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 38346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 38446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner spec->format = test_format; 38546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 38646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* 38746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * We know the buffer size and the max number of subsequent writes 38846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * that can be pending. If more than one can pend, allow the application 38946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * to do something like double buffering between our write buffer and 39046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * the device's own buffer that we are filling with write() anyway. 39146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * 39246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * We calculate spec->samples like this because SDL_CalculateAudioSpec() 39346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * will give put paud_bufinfo.write_buf_cap (or paud_bufinfo.write_buf_cap/2) 39446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * into spec->size in return. 39546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 39646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( paud_bufinfo.request_buf_cap == 1 ) 39746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { 39846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner spec->samples = paud_bufinfo.write_buf_cap 39946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner / bytes_per_sample 40046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner / spec->channels; 40146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 40246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner else 40346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { 40446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner spec->samples = paud_bufinfo.write_buf_cap 40546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner / bytes_per_sample 40646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner / spec->channels 40746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner / 2; 40846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 40946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_init.bsize = bytes_per_sample * spec->channels; 41046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 41146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_CalculateAudioSpec(spec); 41246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 41346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* 41446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * The AIX paud device init can't modify the values of the audio_init 41546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * structure that we pass to it. So we don't need any recalculation 41646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * of this stuff and no reinit call as in linux dsp and dma code. 41746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * 41846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * /dev/paud supports all of the encoding formats, so we don't need 41946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * to do anything like reopening the device, either. 42046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 42146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ioctl(audio_fd, AUDIO_INIT, &paud_init) < 0 ) { 42246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch ( paud_init.rc ) 42346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { 42446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 1 : 42546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Couldn't set audio format: DSP can't do play requests"); 42646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 42746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 42846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 2 : 42946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Couldn't set audio format: DSP can't do record requests"); 43046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 43146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 43246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 4 : 43346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Couldn't set audio format: request was invalid"); 43446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 43546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 43646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 5 : 43746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Couldn't set audio format: conflict with open's flags"); 43846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 43946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 44046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 6 : 44146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Couldn't set audio format: out of DSP MIPS or memory"); 44246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 44346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 44446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default : 44546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Couldn't set audio format: not documented in sys/audio.h"); 44646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 44746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 44846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 44946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 45046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 45146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Allocate mixing buffer */ 45246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner mixlen = spec->size; 45346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); 45446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( mixbuf == NULL ) { 45546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 45646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 45746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memset(mixbuf, spec->silence, spec->size); 45846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 45946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* 46046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Set some paramters: full volume, first speaker that we can find. 46146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Ignore the other settings for now. 46246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 46346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_change.input = AUDIO_IGNORE; /* the new input source */ 46446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_change.output = OUTPUT_1; /* EXTERNAL_SPEAKER,INTERNAL_SPEAKER,OUTPUT_1 */ 46546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */ 46646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_change.volume = 0x7fffffff; /* volume level [0-0x7fffffff] */ 46746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */ 46846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_change.balance = 0x3fffffff; /* the new balance */ 46946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */ 47046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_change.treble = AUDIO_IGNORE; /* the new treble state */ 47146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_change.bass = AUDIO_IGNORE; /* the new bass state */ 47246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */ 47346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 47446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_control.ioctl_request = AUDIO_CHANGE; 47546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_control.request_info = (char*)&paud_change; 47646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 ) { 47746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_AUDIO 47846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr, "Can't change audio display settings\n" ); 47946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 48046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 48146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 48246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* 48346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Tell the device to expect data. Actual start will wait for 48446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * the first write() call. 48546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 48646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_control.ioctl_request = AUDIO_START; 48746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner paud_control.position = 0; 48846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 ) { 48946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_AUDIO 49046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fprintf(stderr, "Can't start audio play\n" ); 49146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 49246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Can't start audio play"); 49346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 49446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 49546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 49646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Check to see if we need to use select() workaround */ 49746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { char *workaround; 49846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner workaround = SDL_getenv("SDL_DSP_NOSELECT"); 49946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( workaround ) { 50046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner frame_ticks = (float)(spec->samples*1000)/spec->freq; 50146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner next_frame = SDL_GetTicks()+frame_ticks; 50246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 50346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 50446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 50546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Get the parent process id (we're the parent of the audio thread) */ 50646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner parent = getpid(); 50746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 50846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* We're ready to rock and roll. :-) */ 50946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return 0; 51046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 51146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 512