--- a/SoundStream.st Mon Nov 13 22:41:15 1995 +0100
+++ b/SoundStream.st Fri Nov 17 17:54:08 1995 +0100
@@ -17,6 +17,21 @@
category:'Streams-External'
!
+!SoundStream primitiveDefinitions!
+%{
+#ifdef IRIS
+# ifndef IRIX5
+# define IRIS_AUDIO
+# endif
+#endif
+
+#ifdef IRIS_AUDIO
+# include <audio.h>
+# define _ALportVal(o) (ALport)(__MKCP(o))
+#endif
+%}
+! !
+
!SoundStream class methodsFor:'documentation'!
copyright
@@ -33,10 +48,6 @@
"
!
-version
- ^ '$Header: /cvs/stx/stx/libbasic2/SoundStream.st,v 1.17 1995-11-11 15:21:53 cg Exp $'
-!
-
documentation
"
Interface to audio device.
@@ -48,23 +59,10 @@
see companion classes VocBrowser and VocView in fileIn-directory for
how to use this class.
"
-! !
-
-!SoundStream primitiveDefinitions!
+!
-%{
-#ifdef IRIS
-# ifndef IRIX5
-# define IRIS_AUDIO
-# endif
-#endif
-
-#ifdef IRIS_AUDIO
-# include <audio.h>
-# define _ALportVal(o) (ALport)(__MKCP(o))
-#endif
-%}
-! !
+version
+^ '$Header: /cvs/stx/stx/libbasic2/SoundStream.st,v 1.18 1995-11-17 16:54:08 cg Exp $'! !
!SoundStream class methodsFor:'instance creation'!
@@ -81,16 +79,20 @@
|newStream|
OperatingSystem getCPUType = '386' ifTrue:[
- "soundblaster special kludge to avoid click"
- RampOff isNil ifTrue:[
- self generateRamp
- ]
+ "soundblaster special kludge to avoid click"
+ RampOff isNil ifTrue:[
+ self generateRamp
+ ]
].
newStream := (self basicNew) initialize.
newStream openForWriting isNil ifTrue:[^nil].
^ newStream
- "SoundStream writing"
+ "
+ SoundStream writing
+ "
+
+ "Created: 17.11.1995 / 17:25:42 / cg"
!
writing16BitStero
@@ -112,37 +114,6 @@
"SoundStream writing16BitStereo"
! !
-!SoundStream class methodsFor:'default values'!
-
-defaultSampleRate
- "minimum, supported by all audio systems"
-
- ^ 8000
-!
-
-defaultBitsPerSample
- "minimum, supported by all audio systems"
-
- ^ 8
-!
-
-defaultNumberOfChannels
- "minimum, supported by all audio systems"
-
- ^ 1
-!
-
-defaultMode
- ^ #linear "planned is at least uLaw"
-!
-
-blockSize
- "a good chunk size to read soundstream.
- Some devices may force a specific size ..."
-
- ^ 2048 "about 1/4 of a second"
-! !
-
!SoundStream class methodsFor:'conversion tables'!
uLawToLinear:uLawValue
@@ -408,6 +379,81 @@
) at:(uLawValue + 1)
! !
+!SoundStream class methodsFor:'default values'!
+
+blockSize
+ "a good chunk size to read soundstream.
+ Some devices may force a specific size ..."
+
+ ^ 2048 "about 1/4 of a second"
+!
+
+defaultBitsPerSample
+ "minimum, supported by all audio systems"
+
+ ^ 8
+!
+
+defaultMode
+ ^ #linear "planned is at least uLaw"
+!
+
+defaultNumberOfChannels
+ "minimum, supported by all audio systems"
+
+ ^ 1
+!
+
+defaultSampleRate
+ "minimum, supported by all audio systems"
+
+ ^ 8000
+! !
+
+!SoundStream class methodsFor:'playing'!
+
+playSoundFile:aFilename
+ |inStream soundStream count totalCount buffer startTime playTime delayedTime waitTime|
+
+ inStream := aFilename asFilename readStream.
+ inStream isNil ifTrue:[^ self].
+
+ soundStream := self writing.
+ soundStream isNil ifTrue:[^ self].
+ soundStream buffered:false.
+
+ startTime := AbsoluteTime now.
+ totalCount := 0.
+
+ buffer := ByteArray new:4096.
+ [(count := inStream nextBytesInto:buffer) > 0] whileTrue:[
+ totalCount := totalCount + count.
+ soundStream nextPutBytes:count from:buffer.
+ ].
+
+ inStream close.
+ soundStream commit.
+
+ "/
+ "/ at least the linux audio driver behaves funny, if we close too early ...
+ "/
+ playTime := totalCount / soundStream sampleRate.
+ delayedTime := (AbsoluteTime now - startTime).
+ waitTime := playTime - delayedTime + 0.1.
+
+ (Delay forSeconds:waitTime) wait.
+
+ soundStream close.
+
+ "
+ SoundStream playSoundFile:'/usr/local/lib/sounds/laugh.snd'
+ SoundStream playSoundFile:'/usr/local/lib/sounds/spacemusic.snd'
+ "
+
+ "Created: 17.11.1995 / 17:25:30 / cg"
+ "Modified: 17.11.1995 / 17:45:40 / cg"
+! !
+
!SoundStream class methodsFor:'private'!
generateRamp
@@ -427,8 +473,67 @@
"SoundStream generateRamp"
! !
+!SoundStream methodsFor:'catching invalid methods'!
+
+pathName:filename
+ "catch pathname access - its fixed here"
+
+ self shouldNotImplement
+!
+
+pathName:filename in:aDirectory
+ "catch pathname access - its fixed here"
+
+ self shouldNotImplement
+! !
+
+!SoundStream methodsFor:'instance release'!
+
+closeFile
+ "a stream has been collected - close the file"
+
+ OperatingSystem getOSType = 'irix' ifFalse:[
+ ^ super closeFile
+ ].
+%{
+#ifdef IRIS_AUDIO
+ ALcloseport(_ALportVal(_INST(filePointer)));
+#endif
+%}
+! !
+
!SoundStream methodsFor:'mode setting'!
+bitsPerSample
+ "return the number of bits per sample - usually 8"
+
+ ^ bitsPerSample
+!
+
+bitsPerSample:aNumber
+ "set the number of bits per sample"
+
+ bitsPerSample := aNumber
+!
+
+numberOfChannels
+ "return the number of channels (1 or 2; usually 1)"
+
+ ^ numberOfChannels
+!
+
+numberOfChannels:aNumber
+ "set the number of channels"
+
+ numberOfChannels := aNumber
+!
+
+sampleRate
+ "return the sample rate"
+
+ ^ sampleRate
+!
+
sampleRate:aNumber
"set the sample rate in hertz - on some
devices, this is a nop"
@@ -448,50 +553,6 @@
"could change using ALibrary ...for now, it is fix"
sampleRate := aNumber.
].
-!
-
-sampleRate
- "return the sample rate"
-
- ^ sampleRate
-!
-
-numberOfChannels
- "return the number of channels (1 or 2; usually 1)"
-
- ^ numberOfChannels
-!
-
-numberOfChannels:aNumber
- "set the number of channels"
-
- numberOfChannels := aNumber
-!
-
-bitsPerSample
- "return the number of bits per sample - usually 8"
-
- ^ bitsPerSample
-!
-
-bitsPerSample:aNumber
- "set the number of bits per sample"
-
- bitsPerSample := aNumber
-! !
-
-!SoundStream methodsFor:'catching invalid methods'!
-
-pathName:filename
- "catch pathname access - its fixed here"
-
- self shouldNotImplement
-!
-
-pathName:filename in:aDirectory
- "catch pathname access - its fixed here"
-
- self shouldNotImplement
! !
!SoundStream methodsFor:'private'!
@@ -504,23 +565,144 @@
numberOfChannels := 1.
sampleRate := 8000.
- OperatingSystem getOSType = 'sunos' ifTrue:[
- pathName := '/dev/audio'.
+ '/dev/audio' asFilename exists ifTrue:[
+ "/
+ "/ sunos or linux
+ "/
+ pathName := '/dev/audio'.
].
OperatingSystem getOSType = 'irix' ifTrue:[
- "no device, use special library calls"
- pathName := nil.
+ "no device, use special library calls"
+ pathName := nil.
].
- OperatingSystem getCPUType = '386' ifTrue:[
- "this code assumes a PD sound-blaster driver .."
- pathName := '/dev/sbdsp'
- ]
+"/ OperatingSystem getCPUType = '386' ifTrue:[
+"/ "this code assumes a PD sound-blaster driver .."
+"/ pathName := '/dev/sbdsp'
+"/ ]
+
+ "Created: 17.11.1995 / 17:28:14 / cg"
! !
!SoundStream methodsFor:'redefined'!
+close
+ OperatingSystem getOSType = 'irix' ifTrue:[
+ ^ self closeFile
+ ].
+
+"/ (mode == #writeonly) ifTrue:[
+"/ "special handling of close on sound blaster,
+"/ turn off voice but continue playing a ramp
+"/ to avoid audible click"
+"/
+"/ OperatingSystem getCPUType = '386' ifTrue:[
+"/ "assume sound-blaster device"
+"/ self ioctl:2 "DSP_IOCTL_VOICE" with:0.
+"/
+"/ "OperatingSystem sleep:3. "
+"/ "add a ramp to zero to prevent click-off"
+"/ super nextPutBytes:(RampOff size) from:RampOff
+"/ ]
+"/ ].
+ super close
+
+ "Created: 17.11.1995 / 17:27:26 / cg"
+ "Modified: 17.11.1995 / 17:47:13 / cg"
+!
+
+nextBytes:count into:anObject startingAt:start
+ "read the next count bytes into an object and return the number of
+ bytes read or nil on error.
+ Use with ByteArrays only."
+
+%{
+#ifdef IRIS_AUDIO
+ {
+ ALport p;
+ int cnt, offs;
+ int objSize;
+ char *cp;
+
+ if (_INST(filePointer) != nil) {
+ if (_INST(mode) != _writeonly) {
+ if (__bothSmallInteger(count, start)) {
+ cnt = _intVal(count);
+ offs = _intVal(start) - 1;
+ p = _ALportVal(_INST(filePointer));
+ objSize = _Size(anObject) - OHDR_SIZE;
+ if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
+ cp = (char *)_InstPtr(anObject) + OHDR_SIZE + offs;
+ if (_INST(bitsPerSample) == _MKSMALLINT(16))
+ ALreadsamps(p, cp, cnt / 2);
+ else
+ ALreadsamps(p, cp, cnt);
+ RETURN ( _MKSMALLINT(cnt) );
+ }
+ }
+ }
+ }
+ }
+#endif
+%}
+.
+ OperatingSystem getOSType = 'irix' ifFalse:[
+ ^ super nextPutBytes:count from:anObject startingAt:start
+ ].
+ filePointer isNil ifTrue:[^ self errorNotOpen].
+ (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
+ self primitiveFailed
+!
+
+nextPutBytes:count from:anObject startingAt:start
+ "write count bytes from an object starting at index start.
+ return the number of bytes written or nil on error.
+ Redefined, since IRIS audio library cannot be used with stdio.
+ (at least I dont know). Use with ByteArrays only."
+
+%{
+#ifdef IRIS_AUDIO
+ {
+ ALport p;
+ int cnt, offs;
+ int objSize;
+ char *cp;
+
+ if (_INST(filePointer) != nil) {
+ if (_INST(mode) != _readonly) {
+ if (__bothSmallInteger(count, start)) {
+ cnt = _intVal(count);
+ offs = _intVal(start) - 1;
+ p = _ALportVal(_INST(filePointer));
+
+ /*
+ * compute number of samples
+ */
+ objSize = _Size(anObject) - OHDR_SIZE;
+ if ( (offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs)) ) {
+ cp = (char *)_InstPtr(anObject) + OHDR_SIZE + offs;
+ if (_INST(bitsPerSample) == _MKSMALLINT(16))
+ ALwritesamps(p, cp, cnt / 2);
+ else
+ ALwritesamps(p, cp, cnt);
+ RETURN ( _MKSMALLINT(cnt) );
+ }
+ }
+ }
+ }
+ }
+#endif
+%}
+.
+ OperatingSystem getOSType = 'irix' ifFalse:[
+ ^ super nextPutBytes:count from:anObject startingAt:start
+ ].
+ filePointer isNil ifTrue:[^ self errorNotOpen].
+ (mode == #readonly) ifTrue:[^ self errorReadOnly].
+ self primitiveFailed
+!
+
openWithMode:aMode
OperatingSystem getOSType = 'irix' ifFalse:[
"its a regular file open"
@@ -604,119 +786,6 @@
^ self
!
-close
- OperatingSystem getOSType = 'irix' ifTrue:[
- ^ self closeFile
- ].
-
- (mode == #writeonly) ifTrue:[
- "special handling of close on sound blaster,
- turn off voice but continue playing a ramp
- to avoid audible click"
-
- OperatingSystem getCPUType = '386' ifTrue:[
- "assume sound-blaster device"
- self ioctl:2 "DSP_IOCTL_VOICE" with:0.
-
- "OperatingSystem sleep:3. "
- "add a ramp to zero to prevent click-off"
- super nextPutBytes:(RampOff size) from:RampOff
- ]
- ].
- super close
-!
-
-nextPutBytes:count from:anObject startingAt:start
- "write count bytes from an object starting at index start.
- return the number of bytes written or nil on error.
- Redefined, since IRIS audio library cannot be used with stdio.
- (at least I dont know). Use with ByteArrays only."
-
-%{
-#ifdef IRIS_AUDIO
- {
- ALport p;
- int cnt, offs;
- int objSize;
- char *cp;
-
- if (_INST(filePointer) != nil) {
- if (_INST(mode) != _readonly) {
- if (__bothSmallInteger(count, start)) {
- cnt = _intVal(count);
- offs = _intVal(start) - 1;
- p = _ALportVal(_INST(filePointer));
-
- /*
- * compute number of samples
- */
- objSize = _Size(anObject) - OHDR_SIZE;
- if ( (offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs)) ) {
- cp = (char *)_InstPtr(anObject) + OHDR_SIZE + offs;
- if (_INST(bitsPerSample) == _MKSMALLINT(16))
- ALwritesamps(p, cp, cnt / 2);
- else
- ALwritesamps(p, cp, cnt);
- RETURN ( _MKSMALLINT(cnt) );
- }
- }
- }
- }
- }
-#endif
-%}
-.
- OperatingSystem getOSType = 'irix' ifFalse:[
- ^ super nextPutBytes:count from:anObject startingAt:start
- ].
- filePointer isNil ifTrue:[^ self errorNotOpen].
- (mode == #readonly) ifTrue:[^ self errorReadOnly].
- self primitiveFailed
-!
-
-nextBytes:count into:anObject startingAt:start
- "read the next count bytes into an object and return the number of
- bytes read or nil on error.
- Use with ByteArrays only."
-
-%{
-#ifdef IRIS_AUDIO
- {
- ALport p;
- int cnt, offs;
- int objSize;
- char *cp;
-
- if (_INST(filePointer) != nil) {
- if (_INST(mode) != _writeonly) {
- if (__bothSmallInteger(count, start)) {
- cnt = _intVal(count);
- offs = _intVal(start) - 1;
- p = _ALportVal(_INST(filePointer));
- objSize = _Size(anObject) - OHDR_SIZE;
- if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
- cp = (char *)_InstPtr(anObject) + OHDR_SIZE + offs;
- if (_INST(bitsPerSample) == _MKSMALLINT(16))
- ALreadsamps(p, cp, cnt / 2);
- else
- ALreadsamps(p, cp, cnt);
- RETURN ( _MKSMALLINT(cnt) );
- }
- }
- }
- }
- }
-#endif
-%}
-.
- OperatingSystem getOSType = 'irix' ifFalse:[
- ^ super nextPutBytes:count from:anObject startingAt:start
- ].
- filePointer isNil ifTrue:[^ self errorNotOpen].
- (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
- self primitiveFailed
-!
-
synchronizeOutput
"wait until all sound has been played"
@@ -739,21 +808,6 @@
^ self
! !
-!SoundStream methodsFor:'instance release'!
-
-closeFile
- "a stream has been collected - close the file"
-
- OperatingSystem getOSType = 'irix' ifFalse:[
- ^ super closeFile
- ].
-%{
-#ifdef IRIS_AUDIO
- ALcloseport(_ALportVal(_INST(filePointer)));
-#endif
-%}
-! !
-
!SoundStream methodsFor:'sine wave generation'!
tuneTone
@@ -780,3 +834,4 @@
"SoundStream writing tuneTone"
! !
+