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 |
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 ) { |
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 |