4 static int init_bytes ;
6 #ifdef SL_USING_OSS_AUDIO
8 /* ------------------------------------------------------------ */
9 /* OSSAUDIO - Linux, FreeBSD, etc */
10 /* ------------------------------------------------------------ */
12 void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
14 fd = ::open ( device, O_WRONLY ) ;
18 perror ( "slDSP: open" ) ;
30 /* Set up a driver fragment size of 1024 (ie 2^10) */
32 ioctl ( SNDCTL_DSP_SETFRAGMENT, 0x7FFF000A ) ;
34 stereo = ioctl ( SOUND_PCM_WRITE_CHANNELS, _stereo ? 2 : 1 ) >= 2 ;
35 bps = ioctl ( SOUND_PCM_WRITE_BITS, _bps ) ;
36 rate = ioctl ( SOUND_PCM_WRITE_RATE, _rate ) ;
39 init_bytes = buff_info.bytes ;
51 int slDSP::getDriverBufferSize ()
57 return buff_info.fragsize ;
60 void slDSP::getBufferInfo ()
65 if ( ::ioctl ( fd, SNDCTL_DSP_GETOSPACE, & buff_info ) < 0 )
67 perror ( "slDSP: getBufferInfo" ) ;
74 void slDSP::write ( void *buffer, size_t length )
76 if ( error || length <= 0 )
79 int nwritten = ::write ( fd, (const char *) buffer, length ) ;
82 perror ( "slDSP: write" ) ;
84 if ( nwritten != length )
85 perror ( "slDSP: short write" ) ;
89 float slDSP::secondsRemaining ()
96 int samples_left = buff_info.fragments * buff_info.fragsize ;
98 if ( stereo ) samples_left /= 2 ;
99 if ( bps == 16 ) samples_left /= 2 ;
100 return (float) samples_left / (float) rate ;
104 float slDSP::secondsUsed ()
111 int samples_used = init_bytes - buff_info.bytes ;
113 if ( stereo ) samples_used /= 2 ;
114 if ( bps == 16 ) samples_used /= 2 ;
115 return (float) samples_used / (float) rate ;
121 if ( !error) ::ioctl ( fd, SOUND_PCM_SYNC , 0 ) ;
126 if ( !error) ::ioctl ( fd, SOUND_PCM_RESET, 0 ) ;
133 /* ------------------------------------------------------------ */
135 /* ------------------------------------------------------------ */
137 static void wperror(MMRESULT num)
139 char buffer[0xff]; // yes, this is hardcoded :-)
141 waveOutGetErrorText( num, buffer, sizeof(buffer)-1);
143 fprintf( stderr, "SlDSP: %s\n", buffer );
149 void CALLBACK waveOutProc( HWAVEOUT hwo, UINT uMsg,
150 DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )
161 waveOutUnprepareHeader( (HWAVEOUT)dwParam1,
162 (LPWAVEHDR)dwParam2, sizeof( WAVEHDR ));
168 void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
176 Format.wFormatTag = WAVE_FORMAT_PCM;
177 Format.nChannels = _stereo ? 2 : 1;
178 Format.nSamplesPerSec = _rate;
179 Format.wBitsPerSample = _bps;
180 Format.nBlockAlign = 1;
181 Format.nAvgBytesPerSec = _rate * Format.nChannels;
184 result = waveOutOpen( & hWaveOut, WAVE_MAPPER, & Format, NULL,
185 0L, WAVE_FORMAT_QUERY );
187 if ( result != MMSYSERR_NOERROR )
200 // Now the hwaveouthandle "should" be valid
202 if ( ( result = waveOutOpen( & hWaveOut, WAVE_MAPPER,
203 (WAVEFORMATEX *)& Format, (DWORD)waveOutProc,
204 0L, CALLBACK_FUNCTION )) != MMSYSERR_NOERROR )
231 if ( hWaveOut != NULL )
233 waveOutClose( hWaveOut );
238 int slDSP::getDriverBufferSize ()
248 void slDSP::getBufferInfo ()
254 void slDSP::write ( void *buffer, size_t length )
258 if ( error || length <= 0 )
261 wavehdr[curr_header].lpData = (LPSTR) buffer;
262 wavehdr[curr_header].dwBufferLength = (long) length;
263 wavehdr[curr_header].dwBytesRecorded = 0L;
264 wavehdr[curr_header].dwUser = NULL;
265 wavehdr[curr_header].dwFlags = 0;
266 wavehdr[curr_header].dwLoops = 0;
267 wavehdr[curr_header].lpNext = NULL;
268 wavehdr[curr_header].reserved = 0;
271 result = waveOutPrepareHeader( hWaveOut, & wavehdr[curr_header],
274 if ( result != MMSYSERR_NOERROR )
280 result = waveOutWrite(hWaveOut, & wavehdr[curr_header],
282 if ( result != MMSYSERR_NOERROR )
290 curr_header = ( curr_header + 1 ) % 3;
294 float slDSP::secondsRemaining ()
303 float slDSP::secondsUsed ()
312 mmt.wType = TIME_BYTES;
314 result = waveOutGetPosition( hWaveOut, &mmt, sizeof( mmt ));
316 if ( mmt.u.cb == 0 || counter == 0)
319 samples_used = ( init_bytes * counter ) - mmt.u.cb;
321 if ( stereo ) samples_used /= 2 ;
322 if ( bps == 16 ) samples_used /= 2 ;
324 samp_time = (float) samples_used / (float) rate ;
326 //printf("%0.2f position=%ld total written=%ld\n",
327 // samp_time, mmt.u.cb, init_bytes * counter );
339 waveOutReset( hWaveOut );
342 /* ------------------------------------------------------------ */
343 /* OpenBSD 2.3 this should be very close to SUN Audio */
344 /* ------------------------------------------------------------ */
346 #elif defined(__OpenBSD__)
347 void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
352 fd = ::open ( device, O_RDWR ) ;
356 perror ( "slDSP: open" ) ;
362 if( ::ioctl( fd, AUDIO_GETINFO, &ainfo) == -1)
364 perror("slDSP: open - getinfo");
373 ainfo.play.sample_rate = _rate;
374 ainfo.play.precision = _bps;
375 ainfo.play.channels = _stereo ? 2 : 1;
377 ainfo.play.encoding = AUDIO_ENCODING_ULINEAR;
379 if( :: ioctl(fd, AUDIO_SETINFO, &ainfo) == -1)
381 perror("slDSP: open - setinfo");
397 // I could not change the size,
398 // so let's try this ...
400 init_bytes = 1024 * 8;
412 int slDSP::getDriverBufferSize ()
419 // HW buffer is 0xffff on my box
420 //return ainfo.play.buffer_size;
425 void slDSP::getBufferInfo ()
430 if( ::ioctl( fd, AUDIO_GETINFO, &ainfo) < 0)
432 perror ( "slDSP: getBufferInfo" ) ;
437 if( ::ioctl( fd, AUDIO_GETOOFFS, &audio_offset ) < 0)
439 perror ( "slDSP: getBufferInfo" ) ;
446 void slDSP::write ( void *buffer, size_t length )
448 if ( error || length <= 0 )
451 int nwritten = ::write ( fd, (const char *) buffer, length ) ;
454 perror ( "slDSP: write" ) ;
455 else if ( nwritten != length )
456 perror ( "slDSP: short write" ) ;
458 counter ++; /* hmmm */
462 float slDSP::secondsRemaining ()
468 float slDSP::secondsUsed ()
471 * original formula from Steve:
472 * -----------------------------
474 * int samples_used = init_bytes - buff_info.bytes ;
476 * | +--- current available
478 * +---------------- available space
481 * sample_used contains the number of bytes which are
482 * "used" or in the DSP "pipeline".
493 //This is wrong: this is the hw queue in the kernel !
494 //samples_used = ainfo.play.buffer_size - audio_offset.offset ;
496 // This is: all data written minus where we are now in the queue
501 samples_used = ( counter * init_bytes ) - audio_offset.samples;
503 if ( stereo ) samples_used /= 2 ;
504 if ( bps == 16 ) samples_used /= 2 ;
506 return (float) samples_used / (float) rate ;
512 if ( !error) ::ioctl ( fd, AUDIO_FLUSH , 0 ) ;
520 /* ------------------------------------------------------------ */
522 /* ------------------------------------------------------------ */
526 void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
530 perror ( "slDSP: supports only 8bit audio for sgi" ) ;
535 init_bytes = 1024 * 8;
537 config = ALnewconfig();
539 ALsetchannels ( config, _stereo ? AL_STEREO : AL_MONO );
540 ALsetwidth ( config, _bps == 8 ? AL_SAMPLE_8 : AL_SAMPLE_16 );
541 ALsetqueuesize( config, init_bytes );
543 port = ALopenport( device, "w", config );
547 perror ( "slDSP: open" ) ;
552 long params[2] = {AL_OUTPUT_RATE, 0 };
556 if ( ALsetparams(AL_DEFAULT_DEVICE, params, 2) != 0 )
558 perror ( "slDSP: open - ALsetparams" ) ;
577 ALcloseport ( port );
578 ALfreeconfig( config );
584 int slDSP::getDriverBufferSize ()
589 return ALgetqueuesize( config );
592 void slDSP::getBufferInfo ()
599 void slDSP::write ( void *buffer, size_t length )
601 char *buf = (char *)buffer;
604 if ( error || length <= 0 )
607 // Steve: is this a problem ??
609 for ( i = 0; i < length; i ++ )
610 buf[i] = buf[i] >> 1;
612 ALwritesamps(port, (void *)buf, length );
616 float slDSP::secondsRemaining ()
623 samples_remain = ALgetfillable(port);
625 if ( stereo ) samples_remain /= 2 ;
626 if ( bps == 16 ) samples_remain /= 2 ;
628 return (float) samples_remain / (float) rate ;
632 float slDSP::secondsUsed ()
639 samples_used = ALgetfilled(port);
641 if ( stereo ) samples_used /= 2 ;
642 if ( bps == 16 ) samples_used /= 2 ;
644 return (float) samples_used / (float) rate ;
650 /* found this in the header file - but no description
651 * or example for the long parameter.
654 // ALflush(ALport, long);