SoundStream.st
changeset 121 606a3ccd3682
parent 112 3e18f2cfe430
child 152 89d93f115cb8
--- 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"
 ! !
+