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 );
342 waveOutReset( hWaveOut );
345 /* ------------------------------------------------------------ */
346 /* OpenBSD 2.3 this should be very close to SUN Audio */
347 /* ------------------------------------------------------------ */
349 #elif defined(__OpenBSD__)
350 void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
355 fd = ::open ( device, O_RDWR ) ;
359 perror ( "slDSP: open" ) ;
365 if( ::ioctl( fd, AUDIO_GETINFO, &ainfo) == -1)
367 perror("slDSP: open - getinfo");
376 ainfo.play.sample_rate = _rate;
377 ainfo.play.precision = _bps;
378 ainfo.play.channels = _stereo ? 2 : 1;
380 ainfo.play.encoding = AUDIO_ENCODING_ULINEAR;
382 if( :: ioctl(fd, AUDIO_SETINFO, &ainfo) == -1)
384 perror("slDSP: open - setinfo");
400 // I could not change the size,
401 // so let's try this ...
403 init_bytes = 1024 * 8;
415 int slDSP::getDriverBufferSize ()
422 // HW buffer is 0xffff on my box
423 //return ainfo.play.buffer_size;
428 void slDSP::getBufferInfo ()
433 if( ::ioctl( fd, AUDIO_GETINFO, &ainfo) < 0)
435 perror ( "slDSP: getBufferInfo" ) ;
440 if( ::ioctl( fd, AUDIO_GETOOFFS, &audio_offset ) < 0)
442 perror ( "slDSP: getBufferInfo" ) ;
449 void slDSP::write ( void *buffer, size_t length )
451 if ( error || length <= 0 )
454 int nwritten = ::write ( fd, (const char *) buffer, length ) ;
457 perror ( "slDSP: write" ) ;
458 else if ( nwritten != length )
459 perror ( "slDSP: short write" ) ;
461 counter ++; /* hmmm */
465 float slDSP::secondsRemaining ()
471 float slDSP::secondsUsed ()
474 * original formula from Steve:
475 * -----------------------------
477 * int samples_used = init_bytes - buff_info.bytes ;
479 * | +--- current available
481 * +---------------- available space
484 * sample_used contains the number of bytes which are
485 * "used" or in the DSP "pipeline".
496 //This is wrong: this is the hw queue in the kernel !
497 //samples_used = ainfo.play.buffer_size - audio_offset.offset ;
499 // This is: all data written minus where we are now in the queue
504 samples_used = ( counter * init_bytes ) - audio_offset.samples;
506 if ( stereo ) samples_used /= 2 ;
507 if ( bps == 16 ) samples_used /= 2 ;
509 return (float) samples_used / (float) rate ;
515 if ( !error) ::ioctl ( fd, AUDIO_FLUSH , 0 ) ;
523 /* ------------------------------------------------------------ */
525 /* ------------------------------------------------------------ */
529 void slDSP::open ( char *device, int _rate, int _stereo, int _bps )
533 perror ( "slDSP: supports only 8bit audio for sgi" ) ;
538 init_bytes = 1024 * 8;
540 config = ALnewconfig();
542 ALsetchannels ( config, _stereo ? AL_STEREO : AL_MONO );
543 ALsetwidth ( config, _bps == 8 ? AL_SAMPLE_8 : AL_SAMPLE_16 );
544 ALsetqueuesize( config, init_bytes );
546 port = ALopenport( device, "w", config );
550 perror ( "slDSP: open" ) ;
555 long params[2] = {AL_OUTPUT_RATE, 0 };
559 if ( ALsetparams(AL_DEFAULT_DEVICE, params, 2) != 0 )
561 perror ( "slDSP: open - ALsetparams" ) ;
580 ALcloseport ( port );
581 ALfreeconfig( config );
587 int slDSP::getDriverBufferSize ()
592 return ALgetqueuesize( config );
595 void slDSP::getBufferInfo ()
602 void slDSP::write ( void *buffer, size_t length )
604 char *buf = (char *)buffer;
607 if ( error || length <= 0 )
610 // Steve: is this a problem ??
612 for ( i = 0; i < length; i ++ )
613 buf[i] = buf[i] >> 1;
615 ALwritesamps(port, (void *)buf, length );
619 float slDSP::secondsRemaining ()
626 samples_remain = ALgetfillable(port);
628 if ( stereo ) samples_remain /= 2 ;
629 if ( bps == 16 ) samples_remain /= 2 ;
631 return (float) samples_remain / (float) rate ;
635 float slDSP::secondsUsed ()
642 samples_used = ALgetfilled(port);
644 if ( stereo ) samples_used /= 2 ;
645 if ( bps == 16 ) samples_used /= 2 ;
647 return (float) samples_used / (float) rate ;
656 /* found this in the header file - but no description
657 * or example for the long parameter.
660 // ALflush(ALport, long);