SoundStream.st
changeset 5425 17cec979acdf
parent 5424 9f874a72681c
child 5426 c9d3c51e1b53
equal deleted inserted replaced
5424:9f874a72681c 5425:17cec979acdf
   618 
   618 
   619 documentation
   619 documentation
   620 "
   620 "
   621     Preliminary (unfinished) interface to an audio device.
   621     Preliminary (unfinished) interface to an audio device.
   622     Currently works with
   622     Currently works with
   623         LINUXs
   623 	LINUXs
   624         SUNs (and other) /dev/audio driver
   624 	SUNs (and other) /dev/audio driver
   625         IRIX (indy).
   625 	IRIX (indy).
   626         PORTAUDIO (osx).
   626 	PORTAUDIO (osx).
   627     On iris, the default setup is for 8 bit mono
   627     On iris, the default setup is for 8 bit mono
   628     so I can play the standard sound files I have here.
   628     so I can play the standard sound files I have here.
   629     It needs much more work, for stereo, different sampling rates etc.
   629     It needs much more work, for stereo, different sampling rates etc.
   630 
   630 
   631     This is an experimental class - its interface & implementation may change in the future.
   631     This is an experimental class - its interface & implementation may change in the future.
   632 
   632 
   633     [author:]
   633     [author:]
   634         Claus Gittinger
   634 	Claus Gittinger
   635 "
   635 "
   636 ! !
   636 ! !
   637 
   637 
   638 !SoundStream class methodsFor:'initialization'!
   638 !SoundStream class methodsFor:'initialization'!
   639 
   639 
   653 
   653 
   654 !SoundStream class methodsFor:'instance creation'!
   654 !SoundStream class methodsFor:'instance creation'!
   655 
   655 
   656 determineConcreteClass
   656 determineConcreteClass
   657     self allSubclassesDo:[:each |
   657     self allSubclassesDo:[:each |
   658         each isAbstract ifFalse:[
   658 	each isAbstract ifFalse:[
   659             each isSupported ifTrue:[
   659 	    each isSupported ifTrue:[
   660                 ^ each
   660 		^ each
   661             ]
   661 	    ]
   662         ]
   662 	]
   663     ].
   663     ].
   664     ^ nil
   664     ^ nil
   665 
   665 
   666     "
   666     "
   667      self determineConcreteClass
   667      self determineConcreteClass
   668     "
   668     "
   669 !
   669 !
   670 
   670 
   671 new
   671 new
   672     self == SoundStream ifTrue:[
   672     self == SoundStream ifTrue:[
   673         ConcreteClass isNil ifTrue:[
   673 	ConcreteClass isNil ifTrue:[
   674             ConcreteClass := self determineConcreteClass.
   674 	    ConcreteClass := self determineConcreteClass.
   675             ConcreteClass isNil ifTrue:[
   675 	    ConcreteClass isNil ifTrue:[
   676                 OpenError raiseErrorString:'missing sound support'.
   676 		OpenError raiseErrorString:'missing sound support'.
   677             ].
   677 	    ].
   678         ].
   678 	].
   679         ^ ConcreteClass new.
   679 	^ ConcreteClass new.
   680     ].
   680     ].
   681     ^ self basicNew initialize
   681     ^ self basicNew initialize
   682 
   682 
   683     "
   683     "
   684      SoundStream new
   684      SoundStream new
   734 
   734 
   735     |newStream|
   735     |newStream|
   736 
   736 
   737     newStream := self new.
   737     newStream := self new.
   738     (newStream supportedAudioFormats includesAny:#(S16 U16)) ifFalse:[
   738     (newStream supportedAudioFormats includesAny:#(S16 U16)) ifFalse:[
   739         OpenError raiseRequestErrorString:'sound system does not support 16bit audio'
   739 	OpenError raiseRequestErrorString:'sound system does not support 16bit audio'
   740     ].
   740     ].
   741     newStream bitsPerSample:16.
   741     newStream bitsPerSample:16.
   742     newStream openForWriting isNil ifTrue:[^nil].
   742     newStream openForWriting isNil ifTrue:[^nil].
   743     ^ newStream
   743     ^ newStream
   744 
   744 
   754 
   754 
   755     |newStream|
   755     |newStream|
   756 
   756 
   757     newStream := self new.
   757     newStream := self new.
   758     (newStream supportedAudioFormats includesAny:#(S16 U16)) ifFalse:[
   758     (newStream supportedAudioFormats includesAny:#(S16 U16)) ifFalse:[
   759         OpenError raiseRequestErrorString:'sound system does not support 16bit audio'
   759 	OpenError raiseRequestErrorString:'sound system does not support 16bit audio'
   760     ].
   760     ].
   761     newStream bitsPerSample:16.
   761     newStream bitsPerSample:16.
   762     newStream numberOfChannels:2.
   762     newStream numberOfChannels:2.
   763     newStream openForWriting isNil ifTrue:[^nil].
   763     newStream openForWriting isNil ifTrue:[^nil].
   764     ^ newStream
   764     ^ newStream
   771 writingFloat
   771 writingFloat
   772     |newStream|
   772     |newStream|
   773 
   773 
   774     newStream := self new.
   774     newStream := self new.
   775     (newStream supportedAudioFormats includes:#F32) ifFalse:[
   775     (newStream supportedAudioFormats includes:#F32) ifFalse:[
   776         OpenError raiseRequestErrorString:'sound system does not support float audio'
   776 	OpenError raiseRequestErrorString:'sound system does not support float audio'
   777     ].
   777     ].
   778     newStream setAudioFormat:#F32.
   778     newStream setAudioFormat:#F32.
   779     newStream numberOfChannels:1.
   779     newStream numberOfChannels:1.
   780     newStream openForWriting isNil ifTrue:[^nil].
   780     newStream openForWriting isNil ifTrue:[^nil].
   781     ^ newStream
   781     ^ newStream
   786 writingFloatStereo
   786 writingFloatStereo
   787     |newStream|
   787     |newStream|
   788 
   788 
   789     newStream := self new.
   789     newStream := self new.
   790     (newStream supportedAudioFormats includes:#F32) ifFalse:[
   790     (newStream supportedAudioFormats includes:#F32) ifFalse:[
   791         OpenError raiseRequestErrorString:'sound system does not support float audio'
   791 	OpenError raiseRequestErrorString:'sound system does not support float audio'
   792     ].
   792     ].
   793     newStream setAudioFormat:#F32.
   793     newStream setAudioFormat:#F32.
   794     newStream numberOfChannels:2.
   794     newStream numberOfChannels:2.
   795     newStream openForWriting isNil ifTrue:[^nil].
   795     newStream openForWriting isNil ifTrue:[^nil].
   796     ^ newStream
   796     ^ newStream
  3486     openAttributes := attributeSpec.
  3486     openAttributes := attributeSpec.
  3487 %{
  3487 %{
  3488 #ifdef SUPPORT_JACKAUDIO
  3488 #ifdef SUPPORT_JACKAUDIO
  3489     jack_options_t options = JackNullOption;
  3489     jack_options_t options = JackNullOption;
  3490     jack_client_t *client;
  3490     jack_client_t *client;
       
  3491     jack_port_t *output_port;
  3491     struct jackStreamData* streamData;
  3492     struct jackStreamData* streamData;
  3492     int nChannels, sampleRate, bytesPerSample;
  3493     int nChannels, sampleRate, bytesPerSample;
  3493 #   define FRAMES_PER_BUFFER 128
  3494 #   define FRAMES_PER_BUFFER 128
  3494 
  3495 
  3495     ok = false;
  3496     ok = false;
  3496 
  3497 
  3497     if (__isSmallInteger(__INST(numberOfChannels))) {
  3498     if (__isSmallInteger(__INST(numberOfChannels))) {
  3498         nChannels = __intVal(__INST(numberOfChannels));
  3499 	nChannels = __intVal(__INST(numberOfChannels));
  3499     } else {
  3500     } else {
  3500         nChannels = 1;
  3501 	nChannels = 1;
  3501     }
  3502     }
  3502 
  3503 
  3503     if (__INST(audioFormat) == @symbol(F32)) {
  3504     if (__INST(audioFormat) == @symbol(F32)) {
  3504         bytesPerSample = 4;
  3505 	bytesPerSample = 4;
  3505     } else {
  3506     } else {
  3506         fprintf(stderr, "SoundStream [warning]: only f32 supported with jack\n");
  3507 	fprintf(stderr, "SoundStream [warning]: only f32 supported with jack\n");
  3507         errorStringOrNil = __MKSTRING("audioFormat must be f32 with jack");
  3508 	errorStringOrNil = __MKSTRING("audioFormat must be f32 with jack");
  3508         goto out;
  3509 	goto out;
  3509     }
       
  3510 
       
  3511     if (__isSmallInteger(__INST(sampleRate))) {
       
  3512         sampleRate = __intVal(__INST(sampleRate));
       
  3513     } else {
       
  3514         fprintf(stderr, "SoundStream [warning]: using default sampleRate 8000\n");
       
  3515         sampleRate = 8000;
       
  3516     }
  3510     }
  3517 
  3511 
  3518     streamData = (struct jackStreamData*)malloc(sizeof(struct jackStreamData));
  3512     streamData = (struct jackStreamData*)malloc(sizeof(struct jackStreamData));
  3519     if (streamData == NULL) {
  3513     if (streamData == NULL) {
  3520         fprintf(stderr, "SoundStream [warning]: failed to allocate jackStream\n");
  3514 	fprintf(stderr, "SoundStream [warning]: failed to allocate jackStream\n");
  3521         errorStringOrNil = __MKSTRING("failed to allocate jackStream");
  3515 	errorStringOrNil = __MKSTRING("failed to allocate jackStream");
  3522         goto out;
  3516 	goto out;
  3523     }
  3517     }
  3524 
  3518 
  3525     if ((client = jack_client_open ("stx", JackNullOption, NULL)) == 0) {
  3519     if ((client = jack_client_open ("stx", JackNullOption, NULL)) == 0) {
  3526         fprintf(stderr, "SoundStream [warning]: client_open\n");
  3520 	fprintf(stderr, "SoundStream [warning]: JACK server not running?\n");
  3527         free(streamData);
  3521 	free(streamData);
  3528         errorStringOrNil = __MKSTRING("client_open");
  3522 	errorStringOrNil = __MKSTRING("JACK server not running");
  3529         goto out;
  3523 	goto out;
  3530     }
  3524     }
  3531     jack_set_process_callback (client, jack_callback, 0);
  3525     jack_set_process_callback (client, jack_callback, 0);
  3532 
  3526 
       
  3527     output_port = jack_port_register (client, "stx_out", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
       
  3528     sampleRate = jack_get_sample_rate (client);
       
  3529     __INST(sampleRate) = __MKSMALLINT(sampleRate);
       
  3530     // if (__isSmallInteger(__INST(sampleRate))) {
       
  3531     //     sampleRate = __intVal(__INST(sampleRate));
       
  3532     // } else {
       
  3533     //     fprintf(stderr, "SoundStream [warning]: using default sampleRate 8000\n");
       
  3534     //     sampleRate = 8000;
       
  3535     // }
       
  3536 
  3533     streamData->jack_client = client;
  3537     streamData->jack_client = client;
       
  3538     streamData->jack_output_port = output_port;
  3534     INITLOCK(streamData->lock);
  3539     INITLOCK(streamData->lock);
  3535     streamData->readOffset = 0;
  3540     streamData->readOffset = 0;
  3536     streamData->bytesPerSample = bytesPerSample;
  3541     streamData->bytesPerSample = bytesPerSample;
  3537     streamData->nChannels = nChannels;
  3542     streamData->nChannels = nChannels;
  3538 
  3543 
  3540     streamData->lastBuffer = NULL;
  3545     streamData->lastBuffer = NULL;
  3541     streamData->freeList = NULL;
  3546     streamData->freeList = NULL;
  3542     streamData->hasFinished = 0;
  3547     streamData->hasFinished = 0;
  3543 
  3548 
  3544     {
  3549     {
  3545         OBJ t;
  3550 	OBJ t;
  3546         t = __MKEXTERNALADDRESS(streamData); __INST(handle1) = t; __STORE(self, t);
  3551 	t = __MKEXTERNALADDRESS(streamData); __INST(handle1) = t; __STORE(self, t);
  3547     }
  3552     }
  3548     __INST(binary) = true;
  3553     __INST(binary) = true;
  3549 
  3554 
  3550 //    paErr = Pa_SetStreamFinishedCallback( stream, &paStreamFinished );
  3555 //    paErr = Pa_SetStreamFinishedCallback( stream, &paStreamFinished );
  3551 //    if( paErr != paNoError ) {
  3556 //    if( paErr != paNoError ) {
  3559 out:;
  3564 out:;
  3560 #endif /* SUPPORT_JACKAUDIO */
  3565 #endif /* SUPPORT_JACKAUDIO */
  3561 
  3566 
  3562 %}.
  3567 %}.
  3563     ok == false ifTrue:[
  3568     ok == false ifTrue:[
  3564         lastErrorString := errorStringOrNil.
  3569 	lastErrorString := errorStringOrNil.
  3565         lastErrorNumber := error ? -1.
  3570 	lastErrorNumber := error ? -1.
  3566         self openError:error.
  3571 	self openError:error.
  3567         "normally not reached"
  3572 	"normally not reached"
  3568         ^ nil.
  3573 	^ nil.
  3569     ].
  3574     ].
  3570     self registerForFinalization.
  3575     self registerForFinalization.
  3571 !
  3576 !
  3572 
  3577 
  3573 reopenStream
  3578 reopenStream
  3579 !SoundStream::JackAudio methodsFor:'queries'!
  3584 !SoundStream::JackAudio methodsFor:'queries'!
  3580 
  3585 
  3581 supportedAudioFormats
  3586 supportedAudioFormats
  3582     "return a collection of supported audio formats.
  3587     "return a collection of supported audio formats.
  3583      possibly returned symbols are:
  3588      possibly returned symbols are:
  3584         U8        unsigned 8bit samples
  3589 	U8        unsigned 8bit samples
  3585         S8        signed 8bit samples
  3590 	S8        signed 8bit samples
  3586         U16       unsigned 16bit samples in native format
  3591 	U16       unsigned 16bit samples in native format
  3587         U16_LE    unsigned 16bit big endian samples
  3592 	U16_LE    unsigned 16bit big endian samples
  3588         U16_BE    unsigned 16bit big endian samples
  3593 	U16_BE    unsigned 16bit big endian samples
  3589         S16       signed 16bit little endian samples in native format
  3594 	S16       signed 16bit little endian samples in native format
  3590         S16_LE    signed 16bit little endian samples
  3595 	S16_LE    signed 16bit little endian samples
  3591         S16_BE    signed 16bit big endian samples
  3596 	S16_BE    signed 16bit big endian samples
  3592         S24       signed 24bit little endian samples in native format
  3597 	S24       signed 24bit little endian samples in native format
  3593         S24_LE    signed 24bit little endian samples
  3598 	S24_LE    signed 24bit little endian samples
  3594         S24_BE    signed 24bit big endian samples
  3599 	S24_BE    signed 24bit big endian samples
  3595         S32       signed 32bit little endian samples in native format
  3600 	S32       signed 32bit little endian samples in native format
  3596         S32_LE    signed 32bit little endian samples
  3601 	S32_LE    signed 32bit little endian samples
  3597         S32_BE    signed 32bit big endian samples
  3602 	S32_BE    signed 32bit big endian samples
  3598         F32       float samples
  3603 	F32       float samples
  3599         MPEG      audio mpeg encoded
  3604 	MPEG      audio mpeg encoded
  3600         MU_LAW    u-law encoded 8bit samples
  3605 	MU_LAW    u-law encoded 8bit samples
  3601         A_LAW     a-law encoded 8bit samples
  3606 	A_LAW     a-law encoded 8bit samples
  3602         IMA_ADPCM adpcm encoded
  3607 	IMA_ADPCM adpcm encoded
  3603      the set of returned symbols depends on the underlying sound hardware.
  3608      the set of returned symbols depends on the underlying sound hardware.
  3604     "
  3609     "
  3605 
  3610 
  3606     ^ #(F32)
  3611     ^ #(F32)
  3607 
  3612