first attempt in win32 audio
authorClaus Gittinger <cg@exept.de>
Mon, 21 Dec 1998 12:43:58 +0100
changeset 712 9e853d04f52b
parent 711 487b2bff9d31
child 713 85912db3ad19
first attempt in win32 audio
SoundStr.st
SoundStream.st
--- a/SoundStr.st	Thu Dec 17 14:24:26 1998 +0100
+++ b/SoundStr.st	Mon Dec 21 12:43:58 1998 +0100
@@ -11,7 +11,9 @@
 "
 
 FileStream subclass:#SoundStream
-	instanceVariableNames:'sampleRate numberOfChannels bitsPerSample audioFormat'
+	instanceVariableNames:'sampleRate numberOfChannels bitsPerSample audioFormat
+			       alPort 
+			       pDirectSound pDSBuffer cbBufOffset cbBufSize'
 	classVariableNames:'UnsupportedOperationSignal'
 	poolDictionaries:''
 	category:'Streams-External'
@@ -27,7 +29,7 @@
 
 #ifdef IRIS_AUDIO
 # include <audio.h>
-# define _ALportVal(o)  (ALport)(__externalAddressVal(o))
+# define __ALportVal(o)  (ALport)(__externalAddressVal(o))
 #endif
 
 #ifdef LINUX
@@ -42,6 +44,67 @@
 #ifdef DEV_AUDIO
 # include <stdio.h>
 #endif
+
+#ifdef WIN32
+
+# define _WIN32
+
+# undef INT
+# undef Array
+# undef Number
+# undef Method
+# undef Point
+# undef Rectangle
+# undef Block
+# undef String
+# undef Message
+# undef Object
+# undef Context
+
+/* # include <stdarg.h> /* */
+# include <stdio.h> /* */
+# include <windows.h>
+# define CINTERFACE
+# include "dsound.h"
+
+# ifdef __DEF_Array
+#  define Array __DEF_Array
+# endif
+# ifdef __DEF_Number
+#  define Number __DEF_Number
+# endif
+# ifdef __DEF_Method
+#  define Method __DEF_Method
+# endif
+# ifdef __DEF_Point
+#  define Point __DEF_Point
+# endif
+# ifdef __DEF_Block
+#  define Block __DEF_Block
+# endif
+# ifdef __DEF_String
+#  define String __DEF_String
+# endif
+# ifdef __DEF_Message
+#  define Message __DEF_Message
+# endif
+# ifdef __DEF_Object
+#  define Object __DEF_Object
+# endif
+# ifdef __DEF_Context
+#  define Context __DEF_Context
+# endif
+
+# define INT int
+
+# define __DirectSoundVal(o) (LPDIRECTSOUND)(__externalAddressVal(o))
+# define __DSBufferVal(o)    (LPDIRECTSOUNDBUFFER)(__externalAddressVal(o))
+
+# define RT_BUFFER_SIZE 4096
+# define NBUFS          4
+
+#endif
+
 %}
 ! !
 
@@ -82,9 +145,9 @@
 
 initialize
     UnsupportedOperationSignal isNil ifTrue:[
-        UnsupportedOperationSignal := StreamErrorSignal newSignalMayProceed:false.
-        UnsupportedOperationSignal nameClass:self message:#unsupportedOperationSignal.
-        UnsupportedOperationSignal notifierString:'unsupported operation'.
+	UnsupportedOperationSignal := StreamErrorSignal newSignalMayProceed:false.
+	UnsupportedOperationSignal nameClass:self message:#unsupportedOperationSignal.
+	UnsupportedOperationSignal notifierString:'unsupported operation'.
     ]
 ! !
 
@@ -124,7 +187,7 @@
     "Modified: / 12.12.1997 / 16:51:38 / cg"
 !
 
-writing16BitStero
+writing16BitStereo
     "just an example, has never been tried (I also
      have no samples for this ... leave it as an exercise)"
 
@@ -202,32 +265,10 @@
     "/
     "/ fallback for non-integral argument
     "/
-    sign := 0.
-    (absVal := a16bitSignedValue asInteger) < 0 ifTrue:[
-	(absVal <= -32256) ifTrue:[
-	    ^ 0
-	].
-	absVal := absVal negated.
-	sign := 16r80
-    ] ifFalse:[
-	absVal >= 32256 ifTrue:[
-	    ^ 128
-	]
+    a16bitSignedValue isInteger ifFalse:[
+	^ self uLawToLinear16:a16bitSignedValue asInteger
     ].
-
-    exp := #[
-	      0 1 2 2 3 3 3 3 4 4 4 4 4 4 4 4
-	      5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
-	      6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
-	      6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
-	      7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
-	      7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
-	      7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
-	      7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 
-	   ] at:(absVal bitShift:-1)+1.
-    mantissa := (absVal bitShift:(exp+3) negated) bitAnd:16r0F.
-    byte := ((sign bitOr:(exp bitShift:4)) bitOr:mantissa) bitInvert bitAnd:16rFF.
-    ^ byte
+    ^ 0
 
     "
      SoundStream uLawToLinear16:(SoundStream linear16ToUlaw:0)    
@@ -513,12 +554,18 @@
 !SoundStream class methodsFor:'default values'!
 
 defaultAudioFormat
+    OperatingSystem getOSType = 'win32' ifTrue:[
+	^ #S16 
+    ].
     ^ #U8 
 !
 
 defaultBitsPerSample
     "minimum, supported by all audio systems"
 
+    OperatingSystem getOSType = 'win32' ifTrue:[
+	^ 16 
+    ].
     ^ 8
 !
 
@@ -642,8 +689,8 @@
 
     fd := self fileDescriptor.
     fd isNil ifTrue:[
-        self error.
-        ^ nil
+	self error.
+	^ nil
     ].
 %{
     int f = __intVal(fd);
@@ -653,45 +700,43 @@
     int __channels = 0;
 
 #if defined(DEV_AUDIO) 
-# if defined(LINUX)
-#  if defined(SNDCTL_DSP_GETBLKSIZE)
-    if (ioctl(f, SNDCTL_DSP_GETBLKSIZE, &__blockSize) >= 0) {
-        blockSize = __MKSMALLINT(__blockSize);
-    }
-#  endif
-#  if defined(SNDCTL_DSP_CHANNELS)
-    if (ioctl(f, SNDCTL_DSP_CHANNELS, &__channels) >= 0) {
-        channels = __MKSMALLINT(__channels);
-    }
-#  endif
-#  if defined(SNDCTL_DSP_STEREO)
-    if (ioctl(f, SNDCTL_DSP_STEREO, &__stereo) >= 0) {
-        stereo = __MKSMALLINT(__stereo);
-    }
-#  endif
-#  if defined(SNDCTL_DSP_SPEED)
-    if (ioctl(f, SNDCTL_DSP_SPEED, &__speed) >= 0) {
-        speed = __MKSMALLINT(__speed);
-    }
-#  endif
-# else
     channels = __MKSMALLINT(1);
     stereo = __MKSMALLINT(0);
     speed = __MKSMALLINT(8000);
-# endif /* LINUX */
+
+# if defined(SNDCTL_DSP_GETBLKSIZE)
+    if (ioctl(f, SNDCTL_DSP_GETBLKSIZE, &__blockSize) >= 0) {
+	blockSize = __MKSMALLINT(__blockSize);
+    }
+# endif
+# if defined(SNDCTL_DSP_CHANNELS)
+    if (ioctl(f, SNDCTL_DSP_CHANNELS, &__channels) >= 0) {
+	channels = __MKSMALLINT(__channels);
+    }
+# endif
+# if defined(SNDCTL_DSP_STEREO)
+    if (ioctl(f, SNDCTL_DSP_STEREO, &__stereo) >= 0) {
+	stereo = __MKSMALLINT(__stereo);
+    }
+# endif
+# if defined(SNDCTL_DSP_SPEED)
+    if (ioctl(f, SNDCTL_DSP_SPEED, &__speed) >= 0) {
+	speed = __MKSMALLINT(__speed);
+    }
+# endif
 #endif /* DEV_AUDIO */
 %}.
     blockSize notNil ifTrue:[
-        Transcript show:'blockSize: '; showCR:blockSize
+	Transcript show:'blockSize: '; showCR:blockSize
     ].
     speed notNil ifTrue:[
-        Transcript show:'speed: '; showCR:speed
+	Transcript show:'speed: '; showCR:speed
     ].
     channels notNil ifTrue:[
-        Transcript show:'channels: '; showCR:channels
+	Transcript show:'channels: '; showCR:channels
     ].
     stereo notNil ifTrue:[
-        Transcript show:'stereo: '; showCR:stereo
+	Transcript show:'stereo: '; showCR:stereo
     ].
 
     Transcript show:'audioFormats: '; showCR:(self supportedAudioFormats).
@@ -705,21 +750,19 @@
     "initialize for least common mode"
 
     buffered := false.
-    bitsPerSample := 8.
-    audioFormat := #U8.
-    numberOfChannels := 1.
-    sampleRate := 8000.
+    bitsPerSample := self class defaultBitsPerSample.
+    audioFormat := self class defaultAudioFormat.
+    numberOfChannels := self class defaultNumberOfChannels.
+    sampleRate := self class defaultSampleRate.
+    pathName := nil.
 
-    '/dev/audio' asFilename exists ifTrue:[
-	"/
-	"/ sunos or linux
-	"/
-	pathName := '/dev/audio'.
-    ].
-
-    OperatingSystem getOSType = 'irix' ifTrue:[
-	"no device, use special library calls"
-	pathName := nil.
+    OperatingSystem getOSType ~= 'win32' ifTrue:[
+	'/dev/audio' asFilename exists ifTrue:[
+	    "/
+	    "/ sunos or linux
+	    "/
+	    pathName := '/dev/audio'.
+	].
     ].
 
     "Created: 17.11.1995 / 17:28:14 / cg"
@@ -730,21 +773,25 @@
 
     |fd|
 
-    fd := self fileDescriptor.
-    fd isNil ifTrue:[
-	self error.
-	^ nil
+    filePointer notNil ifTrue:[
+	fd := self fileDescriptor.
+	fd isNil ifTrue:[
+	    self error.
+	    ^ nil
+	]
     ].
 %{
     int f = __intVal(fd);
     int __dummy;
 
-#if defined(DEV_AUDIO) && defined(LINUX)
+#if defined(DEV_AUDIO)
+    if (__isSmallInteger(fd)) {
 # if defined(SNDCTL_DSP_RESET)
-    if (ioctl(f, SNDCTL_DSP_RESET, &__dummy) >= 0) {
-	RETURN (self);
+	if (ioctl(f, SNDCTL_DSP_RESET, &__dummy) >= 0) {
+	    RETURN (self);
+	}
+# endif
     }
-# endif
 #endif
 %}.
     ^ UnsupportedOperationSignal raise
@@ -760,82 +807,111 @@
 
     |fd|
 
-    fd := self fileDescriptor.
-    fd isNil ifTrue:[
-        self error.
-        ^ nil
+    filePointer notNil ifTrue:[
+	fd := self fileDescriptor.
+	fd isNil ifTrue:[
+	    self error.
+	    ^ nil
+	]
     ].
 %{
     int f = __intVal(fd);
     int __fmt = 0, __fmtWant;
     union {
-        unsigned short us;
-        unsigned char ub[2];
+	unsigned short us;
+	unsigned char ub[2];
     } u;
     OBJ sym = aSymbol;
 
-#if defined(DEV_AUDIO) && defined(LINUX)
-    if (__isSymbol(sym)) {
-        if (sym == @symbol(U16)) {
-            u.us = 0x1234;
-            if (u.ub[0] == 0x34) {
+#if defined(DEV_AUDIO)
+    if (__isSmallInteger(fd)) {
+	if (__isSymbol(sym)) {
+	    if (sym == @symbol(U16)) {
+		u.us = 0x1234;
+		if (u.ub[0] == 0x34) {
 /* printf("U16_LE\n"); */
-                sym = @symbol(U16_LE);
-            } else {
+		    sym = @symbol(U16_LE);
+		} else {
 /* printf("U16_BE\n"); */
-                sym = @symbol(U16_BE);
-            }
-        } else if (sym == @symbol(S16)) {
-            u.us = 0x1234;
-            if (u.ub[0] == 0x34) {
+		    sym = @symbol(U16_BE);
+		}
+	    } else if (sym == @symbol(S16)) {
+		u.us = 0x1234;
+		if (u.ub[0] == 0x34) {
 /* printf("S16_LE\n"); */
-               sym = @symbol(S16_LE);
-            } else {
+		   sym = @symbol(S16_LE);
+		} else {
 /* printf("S16_BE\n"); */
-               sym = @symbol(S16_BE);
-            }
-        }
+		   sym = @symbol(S16_BE);
+		}
+	    }
 
-        if (sym == @symbol(MU_LAW)) {
-            __fmt = AFMT_MU_LAW;
-        } else if (sym == @symbol(A_LAW)) {
-            __fmt = AFMT_A_LAW;
-        } else if (sym == @symbol(IMA_ADPCM)) {
-            __fmt = AFMT_IMA_ADPCM;
-        } else if (sym == @symbol(U8)) {
-            __fmt = AFMT_U8;
-        } else if (sym == @symbol(S8)) {
-            __fmt = AFMT_S8;
-        } else if (sym == @symbol(U16_LE)) {
-            __fmt = AFMT_U16_LE;
-        } else if (sym == @symbol(U16_BE)) {
-            __fmt = AFMT_U16_BE;
-        } else if (sym == @symbol(S16_LE)) {
-            __fmt = AFMT_S16_LE;
-        } else if (sym == @symbol(S16_BE)) {
-            __fmt = AFMT_S16_BE;
-        } else if (sym == @symbol(MPEG)) {
-            __fmt = AFMT_MPEG;
-        } else {
-            fprintf(stderr, "bad format: %s\n", __stringVal(sym));
-            goto bad;
-        }
+	    if (0) {
+#ifdef AFMT_MU_LAW
+	    } else if (sym == @symbol(MU_LAW)) {
+		__fmt = AFMT_MU_LAW;
+#endif
+#ifdef AFMT_A_LAW
+	    } else if (sym == @symbol(A_LAW)) {
+		__fmt = AFMT_A_LAW;
+#endif
+#ifdef AFMT_IMA_ADPCM
+	    } else if (sym == @symbol(IMA_ADPCM)) {
+		__fmt = AFMT_IMA_ADPCM;
+#endif
+#ifdef AFMT_U8
+	    } else if (sym == @symbol(U8)) {
+		__fmt = AFMT_U8;
+#endif
+#ifdef AFMT_S8
+	    } else if (sym == @symbol(S8)) {
+		__fmt = AFMT_S8;
+#endif
+#ifdef AFMT_U16_LE
+	    } else if (sym == @symbol(U16_LE)) {
+		__fmt = AFMT_U16_LE;
+#endif
+#ifdef AFMT_U16_BE
+	    } else if (sym == @symbol(U16_BE)) {
+		__fmt = AFMT_U16_BE;
+#endif
+#ifdef AFMT_S16_LE
+	    } else if (sym == @symbol(S16_LE)) {
+		__fmt = AFMT_S16_LE;
+#endif
+#ifdef AFMT_S16_BE
+	    } else if (sym == @symbol(S16_BE)) {
+		__fmt = AFMT_S16_BE;
+#endif
+#ifdef AFMT_MPEG
+	    } else if (sym == @symbol(MPEG)) {
+		__fmt = AFMT_MPEG;
+#endif
+	    } else {
+		fprintf(stderr, "bad format: %s\n", __stringVal(sym));
+		goto bad;
+	    }
+	}
+
+	__fmtWant = __fmt;
+
+#ifdef SNDCTL_DSP_SETFMT
+	if (ioctl(f, SNDCTL_DSP_SETFMT, &__fmt) >= 0) {
+	    if (__fmt == __fmtWant) {
+		__INST(audioFormat) = sym;
+		RETURN (self);
+	    } else {
+		/* fprintf(stderr, "want: %x; got: %x\n", __fmtWant, __fmt); */
+	    }
+	} else {
+		/* fprintf(stderr, "got err-return from setFmp %x\n", __fmt); */
+	}
+#endif /* SNDCTL_DSP_SETFMT */
+
+bad: ;
     }
-
-    __fmtWant = __fmt;
+#endif /* DEV_AUDIO */
 
-    if (ioctl(f, SNDCTL_DSP_SETFMT, &__fmt) >= 0) {
-        if (__fmt == __fmtWant) {
-            __INST(audioFormat) = sym;
-            RETURN (self);
-        } else {
-            /* fprintf(stderr, "want: %x; got: %x\n", __fmtWant, __fmt); */
-        }
-    } else {
-            /* fprintf(stderr, "got err-return from setFmp %x\n", __fmt); */
-    }
-bad: ;
-#endif
 %}.
     ^ UnsupportedOperationSignal raise
 
@@ -852,17 +928,19 @@
 
     |fd|
 
-    fd := self fileDescriptor.
-    fd isNil ifTrue:[
-	self error.
-	^ nil
+    filePointer notNil ifTrue:[
+	fd := self fileDescriptor.
+	fd isNil ifTrue:[
+	    self error.
+	    ^ nil
+	]
     ].
 %{
     int f = __intVal(fd);
     int __nCh = 0;
 
-#if defined(DEV_AUDIO) && defined(LINUX)
-    if (__isSmallInteger(nChannels)) {
+#if defined(DEV_AUDIO) && defined(SOUND_PCM_WRITE_CHANNELS)
+    if (__isSmallInteger(fd) && __isSmallInteger(nChannels)) {
 	__nCh = __intVal(nChannels);
 	if (ioctl(f, SOUND_PCM_WRITE_CHANNELS, &__nCh) >= 0) {
 	    __INST(numberOfChannels) = nChannels;
@@ -886,17 +964,19 @@
 
     |fd|
 
-    fd := self fileDescriptor.
-    fd isNil ifTrue:[
-	self error.
-	^ nil
+    filePointer notNil ifTrue:[
+	fd := self fileDescriptor.
+	fd isNil ifTrue:[
+	    self error.
+	    ^ nil
+	]
     ].
 %{
     int f = __intVal(fd);
     int __blockSize = 0;
 
-#if defined(DEV_AUDIO) && defined(LINUX)
-    if (__isSmallInteger(blockSize)) {
+#if defined(DEV_AUDIO) && defined(SNDCTL_DSP_SETFRAGMENT)
+    if (__isSmallInteger(fd) && __isSmallInteger(blockSize)) {
 	__blockSize = __intVal(blockSize);
 	if (ioctl(f, SNDCTL_DSP_SETFRAGMENT, &__blockSize) >= 0) {
 	    /* __INST(blockSize) = blockSize; */
@@ -914,18 +994,20 @@
 
     |fd|
 
-    fd := self fileDescriptor.
-    fd isNil ifTrue:[
-	self error.
-	^ nil
+    filePointer notNil ifTrue:[
+	fd := self fileDescriptor.
+	fd isNil ifTrue:[
+	    self error.
+	    ^ nil
+	]
     ].
 %{
     int f = __intVal(fd);
     int __rate = 0;
     int __rateWant;
 
-#if defined(DEV_AUDIO) && defined(LINUX)
-    if (__isSmallInteger(hz)) {
+#if defined(DEV_AUDIO) && defined(SOUND_PCM_WRITE_RATE)
+    if (__isSmallInteger(fd) && __isSmallInteger(hz)) {
 	__rate = __rateWant = __intVal(hz);
 	if (ioctl(f, SOUND_PCM_WRITE_RATE, &__rate) >= 0) {
 	    if (__rate != __rateWant) {
@@ -961,6 +1043,7 @@
 	S16_LE    signed 16bit little endian samples
 	S16_BE    signed 16bit big endian samples
 	MPEG      audio mpeg encoded
+	PCM       pcm
     "
 
     |fd audioFormatMask
@@ -969,7 +1052,7 @@
      supports_IMA_ADPCM supports_U8
      supports_S16_LE supports_S16_BE
      supports_S8 supports_U16_LE
-     supports_U16_BE supports_MPEG|
+     supports_U16_BE supports_MPEG supports_PCM|
 
     fd := self fileDescriptor.
     fd isNil ifTrue:[
@@ -981,23 +1064,43 @@
     int __audioFormatMask = 0;
 
 #if defined(DEV_AUDIO)
-# if defined(LINUX)
+    supports_MU_LAW = true;
+
+# if defined(SNDCTL_DSP_GETFMTS)
     if (ioctl(f, SNDCTL_DSP_GETFMTS, &__audioFormatMask) >= 0) {
 	audioFormatMask = __MKSMALLINT(__audioFormatMask);
 
+#  ifdef AFMT_MU_LAW
 	supports_MU_LAW = (__audioFormatMask & AFMT_MU_LAW) ? true : false;
+#  endif
+#  ifdef AFMT_A_LAW
 	supports_A_LAW = (__audioFormatMask & AFMT_A_LAW) ? true : false;
+#  endif
+#  ifdef AFMT_IMA_ADPCM
 	supports_IMA_ADPCM = (__audioFormatMask & AFMT_IMA_ADPCM) ? true : false;
+#  endif
+#  ifdef AFMT_U8
 	supports_U8 = (__audioFormatMask & AFMT_U8) ? true : false;
+#  endif
+#  ifdef AFMT_S16_LE
 	supports_S16_LE = (__audioFormatMask & AFMT_S16_LE) ? true : false;
+#  endif
+#  ifdef AFMT_S16_BE
 	supports_S16_BE = (__audioFormatMask & AFMT_S16_BE) ? true : false;
+#  endif
+#  ifdef AFMT_S8
 	supports_S8 = (__audioFormatMask & AFMT_S8) ? true : false;
+#  endif
+#  ifdef AFMT_U16_LE
 	supports_U16_LE = (__audioFormatMask & AFMT_U16_LE) ? true : false;
+#  endif
+#  ifdef AFMT_U16_BE
 	supports_U16_BE = (__audioFormatMask & AFMT_U16_BE) ? true : false;
+#  endif
+#  ifdef AFMT_MPEG
 	supports_MPEG = (__audioFormatMask & AFMT_MPEG) ? true : false;
+#  endif
     }
-# else
-    supports_MU_LAW = true;
 # endif
 
 #endif /* DEV_AUDIO */
@@ -1007,6 +1110,10 @@
     supports_U16_BE = true;
 #endif
 
+#ifdef WIN32
+    supports_S16_LE = true;
+#endif
+
 %}.
     supportedFormats := IdentitySet new.
     supports_MU_LAW ifTrue:[
@@ -1057,10 +1164,13 @@
 
 !SoundStream methodsFor:'redefined'!
 
-close
+XXclose
     OperatingSystem getOSType = 'irix' ifTrue:[
 	^ self closeFile
     ].
+    OperatingSystem getOSType = 'win32' ifTrue:[
+	^ self closeFile
+    ].
 
     super close
 
@@ -1075,9 +1185,32 @@
 #ifdef IRIS_AUDIO
     OBJ port;
 
-    if ((port = __INST(filePointer)) != nil) {
-        __INST(filePointer) = nil;
-        ALcloseport(_ALportVal(port));
+    if ((port = __INST(alPort)) != nil) {
+	__INST(alPort) = nil;
+	ALcloseport(__ALportVal(port));
+    }
+    RETURN (self);
+#endif
+
+#ifdef WIN32
+    OBJ oDirectSound, oDSBuffer;
+    LPDIRECTSOUND       t_pDirectSound;
+    LPDIRECTSOUNDBUFFER t_pDSBuffer;
+
+    if ((oDSBuffer = __INST(pDSBuffer)) != nil) {
+	__INST(pDSBuffer) = nil;
+	t_pDSBuffer = __DSBufferVal(oDSBuffer);
+	if (t_pDSBuffer) {
+	    IDirectSoundBuffer_Stop(t_pDSBuffer);
+	    IDirectSoundBuffer_Release(t_pDSBuffer);
+	}
+    }
+    if ((oDirectSound = __INST(pDirectSound)) != nil) {
+	__INST(pDirectSound) = nil;
+	t_pDirectSound = __DirectSoundVal(oDirectSound);
+	if (t_pDirectSound) {
+	    IDirectSound_Release(t_pDirectSound);
+	}
     }
     RETURN (self);
 #endif
@@ -1119,10 +1252,11 @@
     fd := self fileDescriptor.
 %{ 
 #ifdef IRIS_AUDIO
+    OPJ port;
     ALport p;
 
-    if (__INST(filePointer) != nil) {
-	p = _ALportVal(__INST(filePointer));
+    if ((port = __INST(alPort)) != nil) {
+	p = __ALportVal(port);
 	while (ALgetfilled(p) > 0) {
 	    sginap(1);
 	}
@@ -1130,7 +1264,7 @@
     RETURN(self);
 #endif
 
-#if defined(DEV_AUDIO) && defined(LINUX)
+#if defined(DEV_AUDIO)
     if (__isSmallInteger(fd)) {
 	int f = __intVal(fd);
 	/* ... */
@@ -1141,6 +1275,12 @@
     ^ self
 !
 
+isOpen
+    alPort notNil ifTrue:[^ true].
+    pDirectSound notNil ifTrue:[^ true].
+    ^ filePointer notNil
+!
+
 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.
@@ -1149,24 +1289,26 @@
 %{
 #ifdef IRIS_AUDIO
   {
+    OBJ port;
     ALport p;
-    int cnt, offs;
+    int cnt, offs, nSamp;
     int objSize;
     char *cp;
 
-    if (__INST(filePointer) != nil) {
+    if ((port = __INST(alPort)) != nil) {
 	if (__INST(mode) != _writeonly) {
 	    if (__bothSmallInteger(count, start)) {
-		cnt = _intVal(count);
-		offs = _intVal(start) - 1;
-		p = _ALportVal(__INST(filePointer));
+		cnt = __intVal(count);
+		offs = __intVal(start) - 1;
+		p = __ALportVal(port);
 		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);
+			nSamp = cnt / 2;
 		    else
-			ALreadsamps(p, cp, cnt);
+			nSamp = cnt;
+		    ALreadsamps(p, cp, nSamp);
 		    RETURN ( __MKSMALLINT(cnt) );
 		}
 	    }
@@ -1176,7 +1318,9 @@
 #endif
 %}.
     OperatingSystem getOSType = 'irix' ifFalse:[
-	^ super nextPutBytes:count from:anObject startingAt:start
+	OperatingSystem getOSType = 'win32' ifFalse:[
+	    ^ super nextPutBytes:count from:anObject startingAt:start
+	].
     ].
     filePointer isNil ifTrue:[^ self errorNotOpen].
     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
@@ -1192,17 +1336,18 @@
 %{
 #ifdef IRIS_AUDIO
   {
+    OBJ port;
     ALport p;
-    int cnt, offs;
+    int cnt, offs, nSamp;
     int objSize;
     char *cp;
 
-    if (__INST(filePointer) != nil) {
+    if ((port = __INST(alPort)) != nil) {
 	if (__INST(mode) != @symbol(readonly)) {
 	    if (__bothSmallInteger(count, start)) {
-		cnt = _intVal(count);
-		offs = _intVal(start) - 1;
-		p = _ALportVal(__INST(filePointer));
+		cnt = __intVal(count);
+		offs = __intVal(start) - 1;
+		p = __ALportVal(port);
 
 		/*
 		 * compute number of samples
@@ -1211,16 +1356,99 @@
 		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);
+			nSamp = cnt / 2;
 		    else
-			ALwritesamps(p, cp, cnt);
+			nSamp = cnt;
+		    ALwritesamps(p, cp, cnt);
 		    RETURN ( count );
 		}
 	    }
 	}
     }
   }
-#endif
+#endif /* SGI_AUDIO */
+
+#ifdef WIN32
+  {
+      HRESULT hr;
+      DWORD status;
+      LPVOID lpbuf1 = NULL;
+      LPVOID lpbuf2 = NULL;
+      DWORD dwsize1 = 0;
+      DWORD dwsize2 = 0;
+      DWORD playPos, safePos, endWrite;
+      DWORD millis;
+      OBJ oDirectSound, oDSBuffer;
+      LPDIRECTSOUND       t_pDirectSound = (LPDIRECTSOUND)0;
+      LPDIRECTSOUNDBUFFER t_pDSBuffer = (LPDIRECTSOUNDBUFFER)0;
+      int t_cbBufOffset, t_cbBufSize;
+      short *buf;
+      int cnt, offs;
+
+      if ((oDSBuffer = __INST(pDSBuffer)) != nil) {
+	  t_pDSBuffer = __DSBufferVal(oDSBuffer);
+      }
+      if ((oDirectSound = __INST(pDirectSound)) != nil) {
+	  t_pDirectSound = __DirectSoundVal(oDirectSound);
+      }
+
+      if (!t_pDSBuffer || !t_pDirectSound) {
+	  RETURN (0);
+      }
+      t_cbBufOffset = __intVal(__INST(cbBufOffset));
+      t_cbBufSize = __intVal(__INST(cbBufSize));
+
+      cnt = __intVal(count);
+      offs = __intVal(start) - 1;
+      buf = (short *)__InstPtr(anObject) + OHDR_SIZE + offs;
+
+      // Should be playing, right?
+      hr = IDirectSoundBuffer_GetStatus(t_pDSBuffer, &status );
+      if (!(status && DSBSTATUS_PLAYING)) {
+	  printf("Buffer not playing!\n");
+      }
+
+      // Sleep until we have enough room in buffer.
+      hr = IDirectSoundBuffer_GetCurrentPosition(t_pDSBuffer, &playPos, &safePos );
+      if( hr != DS_OK ) {
+	  RETURN (0);
+      }
+      if( playPos < t_cbBufOffset ) playPos += t_cbBufSize; 
+
+      endWrite = t_cbBufOffset + RT_BUFFER_SIZE * sizeof(short);
+      while ( playPos < endWrite ) {
+	  // Calculate number of milliseconds until we will have room, as
+	  // time = distance * (milliseconds/second) / ((bytes/sample) * (samples/second)),
+	  // rounded up.
+	  millis = (DWORD) (1.0 + ((endWrite - playPos) * 1000.0) / ( sizeof(short) * __intVal(__INST(sampleRate))));
+
+	  // Sleep for that long
+	  Sleep( millis );
+
+	  // Wake up, find out where we are now
+	  hr = IDirectSoundBuffer_GetCurrentPosition(t_pDSBuffer, &playPos, &safePos );
+	  if( hr != DS_OK ) {
+	      RETURN (0);
+	  }
+	  if( playPos < t_cbBufOffset ) playPos += t_cbBufSize; // unwrap offset
+      }
+
+      // Lock free space in the DS
+      hr = IDirectSoundBuffer_Lock(t_pDSBuffer, t_cbBufOffset, RT_BUFFER_SIZE * sizeof(short), &lpbuf1, &dwsize1, &lpbuf2, &dwsize2, 0);
+      if (hr == DS_OK) {
+	  // Copy the buffer into the DS
+	  CopyMemory(lpbuf1, buf, dwsize1);
+	  if(NULL != lpbuf2) CopyMemory(lpbuf2, buf+dwsize1, dwsize2);
+
+	  // Update our buffer offset and unlock sound buffer
+	  t_cbBufOffset = (t_cbBufOffset + dwsize1 + dwsize2) % t_cbBufSize;
+	  IDirectSoundBuffer_Unlock(t_pDSBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);
+      }
+      __INST(cbBufOffset) = __MKSMALLINT(t_cbBufOffset);
+
+      RETURN (0);
+  }
+#endif /* WIN32 */
 
 #if defined(DEV_AUDIO)
    /*
@@ -1243,18 +1471,18 @@
 	f = __FILEVal(fp);
 	if (__INST(mode) != @symbol(readonly)) {
 	    if (__bothSmallInteger(count, start)) {
-		cnt = _intVal(count);
-		offs = _intVal(start) - 1;
+		cnt = __intVal(count);
+		offs = __intVal(start) - 1;
 
 		objSize = _Size(anObject) - OHDR_SIZE;
 		if ( (offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs)) ) {
 		    do {
-		        cp = (char *)__InstPtr(anObject) + OHDR_SIZE + offs;
+			cp = (char *)__InstPtr(anObject) + OHDR_SIZE + offs;
 
 			n = cnt;
 			if (n > 4096) n = 4096;
 # ifdef LINUX
-		        sigsetmask(~0);
+			sigsetmask(~0);
 # endif
 			if (__INST(buffered) == true) {
 			    n = fwrite(cp, 1, n, f);
@@ -1263,7 +1491,7 @@
 			    n = write(fd, cp, n);
 			}
 # ifdef LINUX
-		        sigsetmask(0);
+			sigsetmask(0);
 # endif
 			__BEGIN_INTERRUPTABLE__
 			__END_INTERRUPTABLE__
@@ -1283,23 +1511,35 @@
     ^ super nextPutBytes:count from:anObject startingAt:start
 !
 
+openForReading
+    |rslt|
+
+    mode := #readonly.
+    didWrite := false.
+    (rslt :=  self openWithMode:ReadMode) notNil ifTrue:[
+	Lobby register:self
+    ].
+    ^ rslt
+!
+
 openForWriting
     "open the file writeonly.
      If the file does not exist its an error, return nil; 
      otherwise return the receiver."
 
+    |rslt|
+
     mode := #writeonly.
     didWrite := true.
-    ^ self openWithMode:WriteMode
+    (rslt := self openWithMode:WriteMode) notNil ifTrue:[
+	Lobby register:self
+    ].
+    ^ rslt
 
     "Created: / 15.12.1997 / 13:13:56 / cg"
 !
 
 openWithMode:aMode
-    ((aMode = 'r') or:[aMode = 'w']) ifFalse:[
-	self error:'invalid mode'.
-	^ nil
-    ].
 %{
 #ifdef IRIS_AUDIO
   {
@@ -1322,14 +1562,16 @@
 	ALsetwidth(config, AL_SAMPLE_8);
 
     if (__isSmallInteger(__INST(sampleRate)))
-	params[3] = params[5] = _intVal(__INST(sampleRate));
+	params[3] = params[5] = __intVal(__INST(sampleRate));
 
     ALsetparams(AL_DEFAULT_DEVICE, params, 6);
     p = ALopenport("smallchat", (char *)_stringVal(aMode), config);
     if (p) {
-	__INST(filePointer) = __MKEXTERNALADDRESS(p);
+	OBJ t;
+
+	__INST(alPort) = t = __MKEXTERNALADDRESS(p); __STORE(self, t);
     } else {
-	__INST(filePointer) = nil;
+	__INST(alPort) = nil;
 	RETURN (nil);
     }
     __INST(binary) = true;
@@ -1368,7 +1610,125 @@
     ALfreeconfig(config);
     RETURN (self);
   }
+#endif /* SGI_AUDIO */
+
+#ifdef WIN32
+  {
+    HRESULT result;
+    LPDIRECTSOUND       t_pDirectSound;
+    LPDIRECTSOUNDBUFFER t_pDSBuffer, t_pDSPrimeBuffer;
+    WAVEFORMATEX        wfFormat;
+    DSBUFFERDESC        dsbdDesc, primarydsbDesc;
+    BYTE                *pDSBuffData;
+    int                 t_cbBufSize;
+    int                 dwDataLen;
+
+    /* Create the DS object */
+    if ((result = DirectSoundCreate(NULL, &t_pDirectSound, NULL)) != DS_OK) {
+	fprintf(stderr,"SoundStream: Cannot open default sound device!!\n");
+	RETURN (nil);
+    }
+
+    /* Define the wave format structure */
+    wfFormat.wFormatTag = WAVE_FORMAT_PCM;
+    wfFormat.nChannels = __intVal(__INST(numberOfChannels));
+    wfFormat.nSamplesPerSec = __intVal(__INST(sampleRate));
+    wfFormat.wBitsPerSample = __intVal(__INST(bitsPerSample));
+    wfFormat.nBlockAlign = wfFormat.nChannels * wfFormat.wBitsPerSample / 8;
+    wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign;
+    wfFormat.cbSize = 0;
+#if 0
+    /* Setup the primary DS buffer description */
+    ZeroMemory(&primarydsbDesc, sizeof(DSBUFFERDESC));
+    primarydsbDesc.dwSize = sizeof(DSBUFFERDESC);
+    primarydsbDesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
+    primarydsbDesc.dwBufferBytes = 0;
+    primarydsbDesc.lpwfxFormat = NULL;
+
+    /* Create the primary DS buffer */
+    if ((result = IDirectSound_CreateSoundBuffer(t_pDirectSound, &primarydsbDesc,
+						 &t_pDSPrimeBuffer, NULL)) != DS_OK) {
+	fprintf(stderr,"SoundStream: Cannot get the primary DS buffer address!\n");
+	IDirectSound_Release(t_pDirectSound);
+	RETURN (nil);
+    }
+
+    /* Set the primary DS buffer sound format.  We have to do this because
+       the default primary buffer is 8-bit, 22kHz! */
+    if ((result = IDirectSoundBuffer_SetFormat(t_pDSPrimeBuffer, &wfFormat)) != DS_OK) {
+	fprintf(stderr,"SoundStream: Cannot set the primary DS buffer to proper sound format (%x) (%d)!\n", result, result);
+	IDirectSoundBuffer_Stop(t_pDSPrimeBuffer);
+	IDirectSoundBuffer_Release(t_pDSPrimeBuffer);
+	IDirectSound_Release(t_pDirectSound);
+	RETURN (nil);
+    }
 #endif
+
+    /* Setup the secondary DS buffer description */
+    t_cbBufSize = RT_BUFFER_SIZE * sizeof(short) * NBUFS;
+    __INST(cbBufSize) = __MKSMALLINT(t_cbBufSize);
+
+    ZeroMemory(&dsbdDesc, sizeof(DSBUFFERDESC));
+    dsbdDesc.dwSize = sizeof(DSBUFFERDESC);
+    dsbdDesc.dwFlags = DSBCAPS_GLOBALFOCUS;
+    dsbdDesc.dwBufferBytes = t_cbBufSize;
+    dsbdDesc.lpwfxFormat = &wfFormat;
+
+    /* Create the secondary DS buffer */
+    if ((result = IDirectSound_CreateSoundBuffer(t_pDirectSound, &dsbdDesc, &t_pDSBuffer, NULL)) != DS_OK) {
+	fprintf(stderr,"SoundStream: couldn't create sound buffer!\n");
+	IDirectSoundBuffer_Stop(t_pDSPrimeBuffer);
+	IDirectSoundBuffer_Release(t_pDSPrimeBuffer);
+	IDirectSound_Release(t_pDirectSound);
+	RETURN (nil);
+    }
+
+    /* Lock the DS buffer */
+    if ((result = IDirectSoundBuffer_Lock(t_pDSBuffer, 0, t_cbBufSize, (LPLPVOID)&pDSBuffData,
+					  &dwDataLen, NULL, NULL, 0)) != DS_OK) {
+	fprintf(stderr,"SoundStream: couldn't lock sound buffer!\n");
+	IDirectSoundBuffer_Stop(t_pDSBuffer);
+	IDirectSoundBuffer_Stop(t_pDSPrimeBuffer);
+	IDirectSoundBuffer_Release(t_pDSPrimeBuffer);
+	IDirectSound_Release(t_pDirectSound);
+	RETURN (nil);
+    }
+
+    /* Zero the DS buffer */
+    ZeroMemory(pDSBuffData, dwDataLen);
+
+    /* Unlock the DS buffer */
+    if ((result = IDirectSoundBuffer_Unlock(t_pDSBuffer, pDSBuffData, dwDataLen, NULL, 0)) != DS_OK) {
+	fprintf(stderr,"SoundStream: couldn't unlock sound buffer!\n");
+	IDirectSoundBuffer_Stop(t_pDSBuffer);
+	IDirectSoundBuffer_Stop(t_pDSPrimeBuffer);
+	IDirectSoundBuffer_Release(t_pDSPrimeBuffer);
+	IDirectSound_Release(t_pDirectSound);
+	RETURN (nil);
+    }
+
+    __INST(cbBufOffset) = __MKSMALLINT(0);  // reset last write position to start of buffer
+
+    /* Start the buffer playback */
+    if ((result = IDirectSoundBuffer_Play(t_pDSBuffer, 0, 0, DSBPLAY_LOOPING ) != DS_OK)) {
+	fprintf(stderr,"SoundStream: couldn't play sound buffer!\n");
+	IDirectSoundBuffer_Stop(t_pDSBuffer);
+	IDirectSoundBuffer_Stop(t_pDSPrimeBuffer);
+	IDirectSoundBuffer_Release(t_pDSPrimeBuffer);
+	IDirectSound_Release(t_pDirectSound);
+	RETURN (nil);
+    }
+
+    {
+	OBJ t;
+
+	__INST(pDSBuffer) = t = __MKEXTERNALADDRESS(t_pDSBuffer); __STORE(self, t);
+	__INST(pDirectSound) = t = __MKEXTERNALADDRESS(t_pDirectSound); __STORE(self, t);
+    }
+    RETURN (self);
+  }
+#endif /* WIN32 */
+
 %}.
     "its a regular file open (i.e. /dev/audio) "
     ^ super openWithMode:aMode
@@ -1405,15 +1765,15 @@
 
     scale := freq * 2 * (Float pi).
     1 to:numSamples do:[:i |
-        val := (scale * i / numSamples) sin.
-        val := (val * 16r7FFF) rounded bitAnd:16rFFFF.
-        buffer at:i put:val
+	val := (scale * i / numSamples) sin.
+	val := (val * 16r7FFF) rounded bitAnd:16rFFFF.
+	buffer at:i put:val
     ].
 
     oldFormat := audioFormat.
     self setAudioFormat:#S16.
     1 to:3 do:[:s |
-        self nextPutBytes:(numSamples*2) from:buffer startingAt:1
+	self nextPutBytes:(numSamples*2) from:buffer startingAt:1
     ].
     self setAudioFormat:oldFormat.
 
@@ -1443,15 +1803,15 @@
 
     scale := freq * 2 * (Float pi).
     1 to:numSamples do:[:i |
-        val := (scale * i / numSamples) sin.
-        val := (val * 127 + 128) rounded.
-        buffer at:i put:val
+	val := (scale * i / numSamples) sin.
+	val := (val * 127 + 128) rounded.
+	buffer at:i put:val
     ].
 
     oldFormat := audioFormat.
     self setAudioFormat:#U8.
     1 to:3 do:[:s |
-        self nextPutBytes:numSamples from:buffer startingAt:1
+	self nextPutBytes:numSamples from:buffer startingAt:1
     ].
     self setAudioFormat:oldFormat.
 
@@ -1494,15 +1854,15 @@
 
     scale := freq * 2 * (Float pi).
     1 to:numSamples do:[:i |
-        val := (scale * i / numSamples) sin.
-        val := (val * 16r7FFF) rounded.
-        buffer at:i put:(self class linear16ToUlaw:val)
+	val := (scale * i / numSamples) sin.
+	val := (val * 16r7FFF) rounded.
+	buffer at:i put:(self class linear16ToUlaw:val)
     ].
 
     oldFormat := audioFormat.
     self setAudioFormat:#MU_LAW.
     1 to:3 do:[:s |
-        self nextPutBytes:numSamples from:buffer startingAt:1
+	self nextPutBytes:numSamples from:buffer startingAt:1
     ].
     self setAudioFormat:oldFormat.
 
@@ -1521,5 +1881,5 @@
 !SoundStream class methodsFor:'documentation'!
 
 version
-^ '$Header: /cvs/stx/stx/libbasic2/Attic/SoundStr.st,v 1.33 1998-02-08 00:45:12 cg Exp $'! !
+^ '$Header: /cvs/stx/stx/libbasic2/Attic/SoundStr.st,v 1.34 1998-12-21 11:43:58 cg Exp $'! !
 SoundStream initialize!
--- a/SoundStream.st	Thu Dec 17 14:24:26 1998 +0100
+++ b/SoundStream.st	Mon Dec 21 12:43:58 1998 +0100
@@ -11,7 +11,9 @@
 "
 
 FileStream subclass:#SoundStream
-	instanceVariableNames:'sampleRate numberOfChannels bitsPerSample audioFormat'
+	instanceVariableNames:'sampleRate numberOfChannels bitsPerSample audioFormat
+			       alPort 
+			       pDirectSound pDSBuffer cbBufOffset cbBufSize'
 	classVariableNames:'UnsupportedOperationSignal'
 	poolDictionaries:''
 	category:'Streams-External'
@@ -27,7 +29,7 @@
 
 #ifdef IRIS_AUDIO
 # include <audio.h>
-# define _ALportVal(o)  (ALport)(__externalAddressVal(o))
+# define __ALportVal(o)  (ALport)(__externalAddressVal(o))
 #endif
 
 #ifdef LINUX
@@ -42,6 +44,67 @@
 #ifdef DEV_AUDIO
 # include <stdio.h>
 #endif
+
+#ifdef WIN32
+
+# define _WIN32
+
+# undef INT
+# undef Array
+# undef Number
+# undef Method
+# undef Point
+# undef Rectangle
+# undef Block
+# undef String
+# undef Message
+# undef Object
+# undef Context
+
+/* # include <stdarg.h> /* */
+# include <stdio.h> /* */
+# include <windows.h>
+# define CINTERFACE
+# include "dsound.h"
+
+# ifdef __DEF_Array
+#  define Array __DEF_Array
+# endif
+# ifdef __DEF_Number
+#  define Number __DEF_Number
+# endif
+# ifdef __DEF_Method
+#  define Method __DEF_Method
+# endif
+# ifdef __DEF_Point
+#  define Point __DEF_Point
+# endif
+# ifdef __DEF_Block
+#  define Block __DEF_Block
+# endif
+# ifdef __DEF_String
+#  define String __DEF_String
+# endif
+# ifdef __DEF_Message
+#  define Message __DEF_Message
+# endif
+# ifdef __DEF_Object
+#  define Object __DEF_Object
+# endif
+# ifdef __DEF_Context
+#  define Context __DEF_Context
+# endif
+
+# define INT int
+
+# define __DirectSoundVal(o) (LPDIRECTSOUND)(__externalAddressVal(o))
+# define __DSBufferVal(o)    (LPDIRECTSOUNDBUFFER)(__externalAddressVal(o))
+
+# define RT_BUFFER_SIZE 4096
+# define NBUFS          4
+
+#endif
+
 %}
 ! !
 
@@ -82,9 +145,9 @@
 
 initialize
     UnsupportedOperationSignal isNil ifTrue:[
-        UnsupportedOperationSignal := StreamErrorSignal newSignalMayProceed:false.
-        UnsupportedOperationSignal nameClass:self message:#unsupportedOperationSignal.
-        UnsupportedOperationSignal notifierString:'unsupported operation'.
+	UnsupportedOperationSignal := StreamErrorSignal newSignalMayProceed:false.
+	UnsupportedOperationSignal nameClass:self message:#unsupportedOperationSignal.
+	UnsupportedOperationSignal notifierString:'unsupported operation'.
     ]
 ! !
 
@@ -124,7 +187,7 @@
     "Modified: / 12.12.1997 / 16:51:38 / cg"
 !
 
-writing16BitStero
+writing16BitStereo
     "just an example, has never been tried (I also
      have no samples for this ... leave it as an exercise)"
 
@@ -202,32 +265,10 @@
     "/
     "/ fallback for non-integral argument
     "/
-    sign := 0.
-    (absVal := a16bitSignedValue asInteger) < 0 ifTrue:[
-	(absVal <= -32256) ifTrue:[
-	    ^ 0
-	].
-	absVal := absVal negated.
-	sign := 16r80
-    ] ifFalse:[
-	absVal >= 32256 ifTrue:[
-	    ^ 128
-	]
+    a16bitSignedValue isInteger ifFalse:[
+	^ self uLawToLinear16:a16bitSignedValue asInteger
     ].
-
-    exp := #[
-	      0 1 2 2 3 3 3 3 4 4 4 4 4 4 4 4
-	      5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
-	      6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
-	      6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
-	      7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
-	      7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
-	      7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
-	      7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 
-	   ] at:(absVal bitShift:-1)+1.
-    mantissa := (absVal bitShift:(exp+3) negated) bitAnd:16r0F.
-    byte := ((sign bitOr:(exp bitShift:4)) bitOr:mantissa) bitInvert bitAnd:16rFF.
-    ^ byte
+    ^ 0
 
     "
      SoundStream uLawToLinear16:(SoundStream linear16ToUlaw:0)    
@@ -513,12 +554,18 @@
 !SoundStream class methodsFor:'default values'!
 
 defaultAudioFormat
+    OperatingSystem getOSType = 'win32' ifTrue:[
+	^ #S16 
+    ].
     ^ #U8 
 !
 
 defaultBitsPerSample
     "minimum, supported by all audio systems"
 
+    OperatingSystem getOSType = 'win32' ifTrue:[
+	^ 16 
+    ].
     ^ 8
 !
 
@@ -642,8 +689,8 @@
 
     fd := self fileDescriptor.
     fd isNil ifTrue:[
-        self error.
-        ^ nil
+	self error.
+	^ nil
     ].
 %{
     int f = __intVal(fd);
@@ -653,45 +700,43 @@
     int __channels = 0;
 
 #if defined(DEV_AUDIO) 
-# if defined(LINUX)
-#  if defined(SNDCTL_DSP_GETBLKSIZE)
-    if (ioctl(f, SNDCTL_DSP_GETBLKSIZE, &__blockSize) >= 0) {
-        blockSize = __MKSMALLINT(__blockSize);
-    }
-#  endif
-#  if defined(SNDCTL_DSP_CHANNELS)
-    if (ioctl(f, SNDCTL_DSP_CHANNELS, &__channels) >= 0) {
-        channels = __MKSMALLINT(__channels);
-    }
-#  endif
-#  if defined(SNDCTL_DSP_STEREO)
-    if (ioctl(f, SNDCTL_DSP_STEREO, &__stereo) >= 0) {
-        stereo = __MKSMALLINT(__stereo);
-    }
-#  endif
-#  if defined(SNDCTL_DSP_SPEED)
-    if (ioctl(f, SNDCTL_DSP_SPEED, &__speed) >= 0) {
-        speed = __MKSMALLINT(__speed);
-    }
-#  endif
-# else
     channels = __MKSMALLINT(1);
     stereo = __MKSMALLINT(0);
     speed = __MKSMALLINT(8000);
-# endif /* LINUX */
+
+# if defined(SNDCTL_DSP_GETBLKSIZE)
+    if (ioctl(f, SNDCTL_DSP_GETBLKSIZE, &__blockSize) >= 0) {
+	blockSize = __MKSMALLINT(__blockSize);
+    }
+# endif
+# if defined(SNDCTL_DSP_CHANNELS)
+    if (ioctl(f, SNDCTL_DSP_CHANNELS, &__channels) >= 0) {
+	channels = __MKSMALLINT(__channels);
+    }
+# endif
+# if defined(SNDCTL_DSP_STEREO)
+    if (ioctl(f, SNDCTL_DSP_STEREO, &__stereo) >= 0) {
+	stereo = __MKSMALLINT(__stereo);
+    }
+# endif
+# if defined(SNDCTL_DSP_SPEED)
+    if (ioctl(f, SNDCTL_DSP_SPEED, &__speed) >= 0) {
+	speed = __MKSMALLINT(__speed);
+    }
+# endif
 #endif /* DEV_AUDIO */
 %}.
     blockSize notNil ifTrue:[
-        Transcript show:'blockSize: '; showCR:blockSize
+	Transcript show:'blockSize: '; showCR:blockSize
     ].
     speed notNil ifTrue:[
-        Transcript show:'speed: '; showCR:speed
+	Transcript show:'speed: '; showCR:speed
     ].
     channels notNil ifTrue:[
-        Transcript show:'channels: '; showCR:channels
+	Transcript show:'channels: '; showCR:channels
     ].
     stereo notNil ifTrue:[
-        Transcript show:'stereo: '; showCR:stereo
+	Transcript show:'stereo: '; showCR:stereo
     ].
 
     Transcript show:'audioFormats: '; showCR:(self supportedAudioFormats).
@@ -705,21 +750,19 @@
     "initialize for least common mode"
 
     buffered := false.
-    bitsPerSample := 8.
-    audioFormat := #U8.
-    numberOfChannels := 1.
-    sampleRate := 8000.
+    bitsPerSample := self class defaultBitsPerSample.
+    audioFormat := self class defaultAudioFormat.
+    numberOfChannels := self class defaultNumberOfChannels.
+    sampleRate := self class defaultSampleRate.
+    pathName := nil.
 
-    '/dev/audio' asFilename exists ifTrue:[
-	"/
-	"/ sunos or linux
-	"/
-	pathName := '/dev/audio'.
-    ].
-
-    OperatingSystem getOSType = 'irix' ifTrue:[
-	"no device, use special library calls"
-	pathName := nil.
+    OperatingSystem getOSType ~= 'win32' ifTrue:[
+	'/dev/audio' asFilename exists ifTrue:[
+	    "/
+	    "/ sunos or linux
+	    "/
+	    pathName := '/dev/audio'.
+	].
     ].
 
     "Created: 17.11.1995 / 17:28:14 / cg"
@@ -730,21 +773,25 @@
 
     |fd|
 
-    fd := self fileDescriptor.
-    fd isNil ifTrue:[
-	self error.
-	^ nil
+    filePointer notNil ifTrue:[
+	fd := self fileDescriptor.
+	fd isNil ifTrue:[
+	    self error.
+	    ^ nil
+	]
     ].
 %{
     int f = __intVal(fd);
     int __dummy;
 
-#if defined(DEV_AUDIO) && defined(LINUX)
+#if defined(DEV_AUDIO)
+    if (__isSmallInteger(fd)) {
 # if defined(SNDCTL_DSP_RESET)
-    if (ioctl(f, SNDCTL_DSP_RESET, &__dummy) >= 0) {
-	RETURN (self);
+	if (ioctl(f, SNDCTL_DSP_RESET, &__dummy) >= 0) {
+	    RETURN (self);
+	}
+# endif
     }
-# endif
 #endif
 %}.
     ^ UnsupportedOperationSignal raise
@@ -760,82 +807,111 @@
 
     |fd|
 
-    fd := self fileDescriptor.
-    fd isNil ifTrue:[
-        self error.
-        ^ nil
+    filePointer notNil ifTrue:[
+	fd := self fileDescriptor.
+	fd isNil ifTrue:[
+	    self error.
+	    ^ nil
+	]
     ].
 %{
     int f = __intVal(fd);
     int __fmt = 0, __fmtWant;
     union {
-        unsigned short us;
-        unsigned char ub[2];
+	unsigned short us;
+	unsigned char ub[2];
     } u;
     OBJ sym = aSymbol;
 
-#if defined(DEV_AUDIO) && defined(LINUX)
-    if (__isSymbol(sym)) {
-        if (sym == @symbol(U16)) {
-            u.us = 0x1234;
-            if (u.ub[0] == 0x34) {
+#if defined(DEV_AUDIO)
+    if (__isSmallInteger(fd)) {
+	if (__isSymbol(sym)) {
+	    if (sym == @symbol(U16)) {
+		u.us = 0x1234;
+		if (u.ub[0] == 0x34) {
 /* printf("U16_LE\n"); */
-                sym = @symbol(U16_LE);
-            } else {
+		    sym = @symbol(U16_LE);
+		} else {
 /* printf("U16_BE\n"); */
-                sym = @symbol(U16_BE);
-            }
-        } else if (sym == @symbol(S16)) {
-            u.us = 0x1234;
-            if (u.ub[0] == 0x34) {
+		    sym = @symbol(U16_BE);
+		}
+	    } else if (sym == @symbol(S16)) {
+		u.us = 0x1234;
+		if (u.ub[0] == 0x34) {
 /* printf("S16_LE\n"); */
-               sym = @symbol(S16_LE);
-            } else {
+		   sym = @symbol(S16_LE);
+		} else {
 /* printf("S16_BE\n"); */
-               sym = @symbol(S16_BE);
-            }
-        }
+		   sym = @symbol(S16_BE);
+		}
+	    }
 
-        if (sym == @symbol(MU_LAW)) {
-            __fmt = AFMT_MU_LAW;
-        } else if (sym == @symbol(A_LAW)) {
-            __fmt = AFMT_A_LAW;
-        } else if (sym == @symbol(IMA_ADPCM)) {
-            __fmt = AFMT_IMA_ADPCM;
-        } else if (sym == @symbol(U8)) {
-            __fmt = AFMT_U8;
-        } else if (sym == @symbol(S8)) {
-            __fmt = AFMT_S8;
-        } else if (sym == @symbol(U16_LE)) {
-            __fmt = AFMT_U16_LE;
-        } else if (sym == @symbol(U16_BE)) {
-            __fmt = AFMT_U16_BE;
-        } else if (sym == @symbol(S16_LE)) {
-            __fmt = AFMT_S16_LE;
-        } else if (sym == @symbol(S16_BE)) {
-            __fmt = AFMT_S16_BE;
-        } else if (sym == @symbol(MPEG)) {
-            __fmt = AFMT_MPEG;
-        } else {
-            fprintf(stderr, "bad format: %s\n", __stringVal(sym));
-            goto bad;
-        }
+	    if (0) {
+#ifdef AFMT_MU_LAW
+	    } else if (sym == @symbol(MU_LAW)) {
+		__fmt = AFMT_MU_LAW;
+#endif
+#ifdef AFMT_A_LAW
+	    } else if (sym == @symbol(A_LAW)) {
+		__fmt = AFMT_A_LAW;
+#endif
+#ifdef AFMT_IMA_ADPCM
+	    } else if (sym == @symbol(IMA_ADPCM)) {
+		__fmt = AFMT_IMA_ADPCM;
+#endif
+#ifdef AFMT_U8
+	    } else if (sym == @symbol(U8)) {
+		__fmt = AFMT_U8;
+#endif
+#ifdef AFMT_S8
+	    } else if (sym == @symbol(S8)) {
+		__fmt = AFMT_S8;
+#endif
+#ifdef AFMT_U16_LE
+	    } else if (sym == @symbol(U16_LE)) {
+		__fmt = AFMT_U16_LE;
+#endif
+#ifdef AFMT_U16_BE
+	    } else if (sym == @symbol(U16_BE)) {
+		__fmt = AFMT_U16_BE;
+#endif
+#ifdef AFMT_S16_LE
+	    } else if (sym == @symbol(S16_LE)) {
+		__fmt = AFMT_S16_LE;
+#endif
+#ifdef AFMT_S16_BE
+	    } else if (sym == @symbol(S16_BE)) {
+		__fmt = AFMT_S16_BE;
+#endif
+#ifdef AFMT_MPEG
+	    } else if (sym == @symbol(MPEG)) {
+		__fmt = AFMT_MPEG;
+#endif
+	    } else {
+		fprintf(stderr, "bad format: %s\n", __stringVal(sym));
+		goto bad;
+	    }
+	}
+
+	__fmtWant = __fmt;
+
+#ifdef SNDCTL_DSP_SETFMT
+	if (ioctl(f, SNDCTL_DSP_SETFMT, &__fmt) >= 0) {
+	    if (__fmt == __fmtWant) {
+		__INST(audioFormat) = sym;
+		RETURN (self);
+	    } else {
+		/* fprintf(stderr, "want: %x; got: %x\n", __fmtWant, __fmt); */
+	    }
+	} else {
+		/* fprintf(stderr, "got err-return from setFmp %x\n", __fmt); */
+	}
+#endif /* SNDCTL_DSP_SETFMT */
+
+bad: ;
     }
-
-    __fmtWant = __fmt;
+#endif /* DEV_AUDIO */
 
-    if (ioctl(f, SNDCTL_DSP_SETFMT, &__fmt) >= 0) {
-        if (__fmt == __fmtWant) {
-            __INST(audioFormat) = sym;
-            RETURN (self);
-        } else {
-            /* fprintf(stderr, "want: %x; got: %x\n", __fmtWant, __fmt); */
-        }
-    } else {
-            /* fprintf(stderr, "got err-return from setFmp %x\n", __fmt); */
-    }
-bad: ;
-#endif
 %}.
     ^ UnsupportedOperationSignal raise
 
@@ -852,17 +928,19 @@
 
     |fd|
 
-    fd := self fileDescriptor.
-    fd isNil ifTrue:[
-	self error.
-	^ nil
+    filePointer notNil ifTrue:[
+	fd := self fileDescriptor.
+	fd isNil ifTrue:[
+	    self error.
+	    ^ nil
+	]
     ].
 %{
     int f = __intVal(fd);
     int __nCh = 0;
 
-#if defined(DEV_AUDIO) && defined(LINUX)
-    if (__isSmallInteger(nChannels)) {
+#if defined(DEV_AUDIO) && defined(SOUND_PCM_WRITE_CHANNELS)
+    if (__isSmallInteger(fd) && __isSmallInteger(nChannels)) {
 	__nCh = __intVal(nChannels);
 	if (ioctl(f, SOUND_PCM_WRITE_CHANNELS, &__nCh) >= 0) {
 	    __INST(numberOfChannels) = nChannels;
@@ -886,17 +964,19 @@
 
     |fd|
 
-    fd := self fileDescriptor.
-    fd isNil ifTrue:[
-	self error.
-	^ nil
+    filePointer notNil ifTrue:[
+	fd := self fileDescriptor.
+	fd isNil ifTrue:[
+	    self error.
+	    ^ nil
+	]
     ].
 %{
     int f = __intVal(fd);
     int __blockSize = 0;
 
-#if defined(DEV_AUDIO) && defined(LINUX)
-    if (__isSmallInteger(blockSize)) {
+#if defined(DEV_AUDIO) && defined(SNDCTL_DSP_SETFRAGMENT)
+    if (__isSmallInteger(fd) && __isSmallInteger(blockSize)) {
 	__blockSize = __intVal(blockSize);
 	if (ioctl(f, SNDCTL_DSP_SETFRAGMENT, &__blockSize) >= 0) {
 	    /* __INST(blockSize) = blockSize; */
@@ -914,18 +994,20 @@
 
     |fd|
 
-    fd := self fileDescriptor.
-    fd isNil ifTrue:[
-	self error.
-	^ nil
+    filePointer notNil ifTrue:[
+	fd := self fileDescriptor.
+	fd isNil ifTrue:[
+	    self error.
+	    ^ nil
+	]
     ].
 %{
     int f = __intVal(fd);
     int __rate = 0;
     int __rateWant;
 
-#if defined(DEV_AUDIO) && defined(LINUX)
-    if (__isSmallInteger(hz)) {
+#if defined(DEV_AUDIO) && defined(SOUND_PCM_WRITE_RATE)
+    if (__isSmallInteger(fd) && __isSmallInteger(hz)) {
 	__rate = __rateWant = __intVal(hz);
 	if (ioctl(f, SOUND_PCM_WRITE_RATE, &__rate) >= 0) {
 	    if (__rate != __rateWant) {
@@ -961,6 +1043,7 @@
 	S16_LE    signed 16bit little endian samples
 	S16_BE    signed 16bit big endian samples
 	MPEG      audio mpeg encoded
+	PCM       pcm
     "
 
     |fd audioFormatMask
@@ -969,7 +1052,7 @@
      supports_IMA_ADPCM supports_U8
      supports_S16_LE supports_S16_BE
      supports_S8 supports_U16_LE
-     supports_U16_BE supports_MPEG|
+     supports_U16_BE supports_MPEG supports_PCM|
 
     fd := self fileDescriptor.
     fd isNil ifTrue:[
@@ -981,23 +1064,43 @@
     int __audioFormatMask = 0;
 
 #if defined(DEV_AUDIO)
-# if defined(LINUX)
+    supports_MU_LAW = true;
+
+# if defined(SNDCTL_DSP_GETFMTS)
     if (ioctl(f, SNDCTL_DSP_GETFMTS, &__audioFormatMask) >= 0) {
 	audioFormatMask = __MKSMALLINT(__audioFormatMask);
 
+#  ifdef AFMT_MU_LAW
 	supports_MU_LAW = (__audioFormatMask & AFMT_MU_LAW) ? true : false;
+#  endif
+#  ifdef AFMT_A_LAW
 	supports_A_LAW = (__audioFormatMask & AFMT_A_LAW) ? true : false;
+#  endif
+#  ifdef AFMT_IMA_ADPCM
 	supports_IMA_ADPCM = (__audioFormatMask & AFMT_IMA_ADPCM) ? true : false;
+#  endif
+#  ifdef AFMT_U8
 	supports_U8 = (__audioFormatMask & AFMT_U8) ? true : false;
+#  endif
+#  ifdef AFMT_S16_LE
 	supports_S16_LE = (__audioFormatMask & AFMT_S16_LE) ? true : false;
+#  endif
+#  ifdef AFMT_S16_BE
 	supports_S16_BE = (__audioFormatMask & AFMT_S16_BE) ? true : false;
+#  endif
+#  ifdef AFMT_S8
 	supports_S8 = (__audioFormatMask & AFMT_S8) ? true : false;
+#  endif
+#  ifdef AFMT_U16_LE
 	supports_U16_LE = (__audioFormatMask & AFMT_U16_LE) ? true : false;
+#  endif
+#  ifdef AFMT_U16_BE
 	supports_U16_BE = (__audioFormatMask & AFMT_U16_BE) ? true : false;
+#  endif
+#  ifdef AFMT_MPEG
 	supports_MPEG = (__audioFormatMask & AFMT_MPEG) ? true : false;
+#  endif
     }
-# else
-    supports_MU_LAW = true;
 # endif
 
 #endif /* DEV_AUDIO */
@@ -1007,6 +1110,10 @@
     supports_U16_BE = true;
 #endif
 
+#ifdef WIN32
+    supports_S16_LE = true;
+#endif
+
 %}.
     supportedFormats := IdentitySet new.
     supports_MU_LAW ifTrue:[
@@ -1057,10 +1164,13 @@
 
 !SoundStream methodsFor:'redefined'!
 
-close
+XXclose
     OperatingSystem getOSType = 'irix' ifTrue:[
 	^ self closeFile
     ].
+    OperatingSystem getOSType = 'win32' ifTrue:[
+	^ self closeFile
+    ].
 
     super close
 
@@ -1075,9 +1185,32 @@
 #ifdef IRIS_AUDIO
     OBJ port;
 
-    if ((port = __INST(filePointer)) != nil) {
-        __INST(filePointer) = nil;
-        ALcloseport(_ALportVal(port));
+    if ((port = __INST(alPort)) != nil) {
+	__INST(alPort) = nil;
+	ALcloseport(__ALportVal(port));
+    }
+    RETURN (self);
+#endif
+
+#ifdef WIN32
+    OBJ oDirectSound, oDSBuffer;
+    LPDIRECTSOUND       t_pDirectSound;
+    LPDIRECTSOUNDBUFFER t_pDSBuffer;
+
+    if ((oDSBuffer = __INST(pDSBuffer)) != nil) {
+	__INST(pDSBuffer) = nil;
+	t_pDSBuffer = __DSBufferVal(oDSBuffer);
+	if (t_pDSBuffer) {
+	    IDirectSoundBuffer_Stop(t_pDSBuffer);
+	    IDirectSoundBuffer_Release(t_pDSBuffer);
+	}
+    }
+    if ((oDirectSound = __INST(pDirectSound)) != nil) {
+	__INST(pDirectSound) = nil;
+	t_pDirectSound = __DirectSoundVal(oDirectSound);
+	if (t_pDirectSound) {
+	    IDirectSound_Release(t_pDirectSound);
+	}
     }
     RETURN (self);
 #endif
@@ -1119,10 +1252,11 @@
     fd := self fileDescriptor.
 %{ 
 #ifdef IRIS_AUDIO
+    OPJ port;
     ALport p;
 
-    if (__INST(filePointer) != nil) {
-	p = _ALportVal(__INST(filePointer));
+    if ((port = __INST(alPort)) != nil) {
+	p = __ALportVal(port);
 	while (ALgetfilled(p) > 0) {
 	    sginap(1);
 	}
@@ -1130,7 +1264,7 @@
     RETURN(self);
 #endif
 
-#if defined(DEV_AUDIO) && defined(LINUX)
+#if defined(DEV_AUDIO)
     if (__isSmallInteger(fd)) {
 	int f = __intVal(fd);
 	/* ... */
@@ -1141,6 +1275,12 @@
     ^ self
 !
 
+isOpen
+    alPort notNil ifTrue:[^ true].
+    pDirectSound notNil ifTrue:[^ true].
+    ^ filePointer notNil
+!
+
 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.
@@ -1149,24 +1289,26 @@
 %{
 #ifdef IRIS_AUDIO
   {
+    OBJ port;
     ALport p;
-    int cnt, offs;
+    int cnt, offs, nSamp;
     int objSize;
     char *cp;
 
-    if (__INST(filePointer) != nil) {
+    if ((port = __INST(alPort)) != nil) {
 	if (__INST(mode) != _writeonly) {
 	    if (__bothSmallInteger(count, start)) {
-		cnt = _intVal(count);
-		offs = _intVal(start) - 1;
-		p = _ALportVal(__INST(filePointer));
+		cnt = __intVal(count);
+		offs = __intVal(start) - 1;
+		p = __ALportVal(port);
 		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);
+			nSamp = cnt / 2;
 		    else
-			ALreadsamps(p, cp, cnt);
+			nSamp = cnt;
+		    ALreadsamps(p, cp, nSamp);
 		    RETURN ( __MKSMALLINT(cnt) );
 		}
 	    }
@@ -1176,7 +1318,9 @@
 #endif
 %}.
     OperatingSystem getOSType = 'irix' ifFalse:[
-	^ super nextPutBytes:count from:anObject startingAt:start
+	OperatingSystem getOSType = 'win32' ifFalse:[
+	    ^ super nextPutBytes:count from:anObject startingAt:start
+	].
     ].
     filePointer isNil ifTrue:[^ self errorNotOpen].
     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
@@ -1192,17 +1336,18 @@
 %{
 #ifdef IRIS_AUDIO
   {
+    OBJ port;
     ALport p;
-    int cnt, offs;
+    int cnt, offs, nSamp;
     int objSize;
     char *cp;
 
-    if (__INST(filePointer) != nil) {
+    if ((port = __INST(alPort)) != nil) {
 	if (__INST(mode) != @symbol(readonly)) {
 	    if (__bothSmallInteger(count, start)) {
-		cnt = _intVal(count);
-		offs = _intVal(start) - 1;
-		p = _ALportVal(__INST(filePointer));
+		cnt = __intVal(count);
+		offs = __intVal(start) - 1;
+		p = __ALportVal(port);
 
 		/*
 		 * compute number of samples
@@ -1211,16 +1356,99 @@
 		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);
+			nSamp = cnt / 2;
 		    else
-			ALwritesamps(p, cp, cnt);
+			nSamp = cnt;
+		    ALwritesamps(p, cp, cnt);
 		    RETURN ( count );
 		}
 	    }
 	}
     }
   }
-#endif
+#endif /* SGI_AUDIO */
+
+#ifdef WIN32
+  {
+      HRESULT hr;
+      DWORD status;
+      LPVOID lpbuf1 = NULL;
+      LPVOID lpbuf2 = NULL;
+      DWORD dwsize1 = 0;
+      DWORD dwsize2 = 0;
+      DWORD playPos, safePos, endWrite;
+      DWORD millis;
+      OBJ oDirectSound, oDSBuffer;
+      LPDIRECTSOUND       t_pDirectSound = (LPDIRECTSOUND)0;
+      LPDIRECTSOUNDBUFFER t_pDSBuffer = (LPDIRECTSOUNDBUFFER)0;
+      int t_cbBufOffset, t_cbBufSize;
+      short *buf;
+      int cnt, offs;
+
+      if ((oDSBuffer = __INST(pDSBuffer)) != nil) {
+	  t_pDSBuffer = __DSBufferVal(oDSBuffer);
+      }
+      if ((oDirectSound = __INST(pDirectSound)) != nil) {
+	  t_pDirectSound = __DirectSoundVal(oDirectSound);
+      }
+
+      if (!t_pDSBuffer || !t_pDirectSound) {
+	  RETURN (0);
+      }
+      t_cbBufOffset = __intVal(__INST(cbBufOffset));
+      t_cbBufSize = __intVal(__INST(cbBufSize));
+
+      cnt = __intVal(count);
+      offs = __intVal(start) - 1;
+      buf = (short *)__InstPtr(anObject) + OHDR_SIZE + offs;
+
+      // Should be playing, right?
+      hr = IDirectSoundBuffer_GetStatus(t_pDSBuffer, &status );
+      if (!(status && DSBSTATUS_PLAYING)) {
+	  printf("Buffer not playing!\n");
+      }
+
+      // Sleep until we have enough room in buffer.
+      hr = IDirectSoundBuffer_GetCurrentPosition(t_pDSBuffer, &playPos, &safePos );
+      if( hr != DS_OK ) {
+	  RETURN (0);
+      }
+      if( playPos < t_cbBufOffset ) playPos += t_cbBufSize; 
+
+      endWrite = t_cbBufOffset + RT_BUFFER_SIZE * sizeof(short);
+      while ( playPos < endWrite ) {
+	  // Calculate number of milliseconds until we will have room, as
+	  // time = distance * (milliseconds/second) / ((bytes/sample) * (samples/second)),
+	  // rounded up.
+	  millis = (DWORD) (1.0 + ((endWrite - playPos) * 1000.0) / ( sizeof(short) * __intVal(__INST(sampleRate))));
+
+	  // Sleep for that long
+	  Sleep( millis );
+
+	  // Wake up, find out where we are now
+	  hr = IDirectSoundBuffer_GetCurrentPosition(t_pDSBuffer, &playPos, &safePos );
+	  if( hr != DS_OK ) {
+	      RETURN (0);
+	  }
+	  if( playPos < t_cbBufOffset ) playPos += t_cbBufSize; // unwrap offset
+      }
+
+      // Lock free space in the DS
+      hr = IDirectSoundBuffer_Lock(t_pDSBuffer, t_cbBufOffset, RT_BUFFER_SIZE * sizeof(short), &lpbuf1, &dwsize1, &lpbuf2, &dwsize2, 0);
+      if (hr == DS_OK) {
+	  // Copy the buffer into the DS
+	  CopyMemory(lpbuf1, buf, dwsize1);
+	  if(NULL != lpbuf2) CopyMemory(lpbuf2, buf+dwsize1, dwsize2);
+
+	  // Update our buffer offset and unlock sound buffer
+	  t_cbBufOffset = (t_cbBufOffset + dwsize1 + dwsize2) % t_cbBufSize;
+	  IDirectSoundBuffer_Unlock(t_pDSBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);
+      }
+      __INST(cbBufOffset) = __MKSMALLINT(t_cbBufOffset);
+
+      RETURN (0);
+  }
+#endif /* WIN32 */
 
 #if defined(DEV_AUDIO)
    /*
@@ -1243,18 +1471,18 @@
 	f = __FILEVal(fp);
 	if (__INST(mode) != @symbol(readonly)) {
 	    if (__bothSmallInteger(count, start)) {
-		cnt = _intVal(count);
-		offs = _intVal(start) - 1;
+		cnt = __intVal(count);
+		offs = __intVal(start) - 1;
 
 		objSize = _Size(anObject) - OHDR_SIZE;
 		if ( (offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs)) ) {
 		    do {
-		        cp = (char *)__InstPtr(anObject) + OHDR_SIZE + offs;
+			cp = (char *)__InstPtr(anObject) + OHDR_SIZE + offs;
 
 			n = cnt;
 			if (n > 4096) n = 4096;
 # ifdef LINUX
-		        sigsetmask(~0);
+			sigsetmask(~0);
 # endif
 			if (__INST(buffered) == true) {
 			    n = fwrite(cp, 1, n, f);
@@ -1263,7 +1491,7 @@
 			    n = write(fd, cp, n);
 			}
 # ifdef LINUX
-		        sigsetmask(0);
+			sigsetmask(0);
 # endif
 			__BEGIN_INTERRUPTABLE__
 			__END_INTERRUPTABLE__
@@ -1283,23 +1511,35 @@
     ^ super nextPutBytes:count from:anObject startingAt:start
 !
 
+openForReading
+    |rslt|
+
+    mode := #readonly.
+    didWrite := false.
+    (rslt :=  self openWithMode:ReadMode) notNil ifTrue:[
+	Lobby register:self
+    ].
+    ^ rslt
+!
+
 openForWriting
     "open the file writeonly.
      If the file does not exist its an error, return nil; 
      otherwise return the receiver."
 
+    |rslt|
+
     mode := #writeonly.
     didWrite := true.
-    ^ self openWithMode:WriteMode
+    (rslt := self openWithMode:WriteMode) notNil ifTrue:[
+	Lobby register:self
+    ].
+    ^ rslt
 
     "Created: / 15.12.1997 / 13:13:56 / cg"
 !
 
 openWithMode:aMode
-    ((aMode = 'r') or:[aMode = 'w']) ifFalse:[
-	self error:'invalid mode'.
-	^ nil
-    ].
 %{
 #ifdef IRIS_AUDIO
   {
@@ -1322,14 +1562,16 @@
 	ALsetwidth(config, AL_SAMPLE_8);
 
     if (__isSmallInteger(__INST(sampleRate)))
-	params[3] = params[5] = _intVal(__INST(sampleRate));
+	params[3] = params[5] = __intVal(__INST(sampleRate));
 
     ALsetparams(AL_DEFAULT_DEVICE, params, 6);
     p = ALopenport("smallchat", (char *)_stringVal(aMode), config);
     if (p) {
-	__INST(filePointer) = __MKEXTERNALADDRESS(p);
+	OBJ t;
+
+	__INST(alPort) = t = __MKEXTERNALADDRESS(p); __STORE(self, t);
     } else {
-	__INST(filePointer) = nil;
+	__INST(alPort) = nil;
 	RETURN (nil);
     }
     __INST(binary) = true;
@@ -1368,7 +1610,125 @@
     ALfreeconfig(config);
     RETURN (self);
   }
+#endif /* SGI_AUDIO */
+
+#ifdef WIN32
+  {
+    HRESULT result;
+    LPDIRECTSOUND       t_pDirectSound;
+    LPDIRECTSOUNDBUFFER t_pDSBuffer, t_pDSPrimeBuffer;
+    WAVEFORMATEX        wfFormat;
+    DSBUFFERDESC        dsbdDesc, primarydsbDesc;
+    BYTE                *pDSBuffData;
+    int                 t_cbBufSize;
+    int                 dwDataLen;
+
+    /* Create the DS object */
+    if ((result = DirectSoundCreate(NULL, &t_pDirectSound, NULL)) != DS_OK) {
+	fprintf(stderr,"SoundStream: Cannot open default sound device!!\n");
+	RETURN (nil);
+    }
+
+    /* Define the wave format structure */
+    wfFormat.wFormatTag = WAVE_FORMAT_PCM;
+    wfFormat.nChannels = __intVal(__INST(numberOfChannels));
+    wfFormat.nSamplesPerSec = __intVal(__INST(sampleRate));
+    wfFormat.wBitsPerSample = __intVal(__INST(bitsPerSample));
+    wfFormat.nBlockAlign = wfFormat.nChannels * wfFormat.wBitsPerSample / 8;
+    wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign;
+    wfFormat.cbSize = 0;
+#if 0
+    /* Setup the primary DS buffer description */
+    ZeroMemory(&primarydsbDesc, sizeof(DSBUFFERDESC));
+    primarydsbDesc.dwSize = sizeof(DSBUFFERDESC);
+    primarydsbDesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
+    primarydsbDesc.dwBufferBytes = 0;
+    primarydsbDesc.lpwfxFormat = NULL;
+
+    /* Create the primary DS buffer */
+    if ((result = IDirectSound_CreateSoundBuffer(t_pDirectSound, &primarydsbDesc,
+						 &t_pDSPrimeBuffer, NULL)) != DS_OK) {
+	fprintf(stderr,"SoundStream: Cannot get the primary DS buffer address!\n");
+	IDirectSound_Release(t_pDirectSound);
+	RETURN (nil);
+    }
+
+    /* Set the primary DS buffer sound format.  We have to do this because
+       the default primary buffer is 8-bit, 22kHz! */
+    if ((result = IDirectSoundBuffer_SetFormat(t_pDSPrimeBuffer, &wfFormat)) != DS_OK) {
+	fprintf(stderr,"SoundStream: Cannot set the primary DS buffer to proper sound format (%x) (%d)!\n", result, result);
+	IDirectSoundBuffer_Stop(t_pDSPrimeBuffer);
+	IDirectSoundBuffer_Release(t_pDSPrimeBuffer);
+	IDirectSound_Release(t_pDirectSound);
+	RETURN (nil);
+    }
 #endif
+
+    /* Setup the secondary DS buffer description */
+    t_cbBufSize = RT_BUFFER_SIZE * sizeof(short) * NBUFS;
+    __INST(cbBufSize) = __MKSMALLINT(t_cbBufSize);
+
+    ZeroMemory(&dsbdDesc, sizeof(DSBUFFERDESC));
+    dsbdDesc.dwSize = sizeof(DSBUFFERDESC);
+    dsbdDesc.dwFlags = DSBCAPS_GLOBALFOCUS;
+    dsbdDesc.dwBufferBytes = t_cbBufSize;
+    dsbdDesc.lpwfxFormat = &wfFormat;
+
+    /* Create the secondary DS buffer */
+    if ((result = IDirectSound_CreateSoundBuffer(t_pDirectSound, &dsbdDesc, &t_pDSBuffer, NULL)) != DS_OK) {
+	fprintf(stderr,"SoundStream: couldn't create sound buffer!\n");
+	IDirectSoundBuffer_Stop(t_pDSPrimeBuffer);
+	IDirectSoundBuffer_Release(t_pDSPrimeBuffer);
+	IDirectSound_Release(t_pDirectSound);
+	RETURN (nil);
+    }
+
+    /* Lock the DS buffer */
+    if ((result = IDirectSoundBuffer_Lock(t_pDSBuffer, 0, t_cbBufSize, (LPLPVOID)&pDSBuffData,
+					  &dwDataLen, NULL, NULL, 0)) != DS_OK) {
+	fprintf(stderr,"SoundStream: couldn't lock sound buffer!\n");
+	IDirectSoundBuffer_Stop(t_pDSBuffer);
+	IDirectSoundBuffer_Stop(t_pDSPrimeBuffer);
+	IDirectSoundBuffer_Release(t_pDSPrimeBuffer);
+	IDirectSound_Release(t_pDirectSound);
+	RETURN (nil);
+    }
+
+    /* Zero the DS buffer */
+    ZeroMemory(pDSBuffData, dwDataLen);
+
+    /* Unlock the DS buffer */
+    if ((result = IDirectSoundBuffer_Unlock(t_pDSBuffer, pDSBuffData, dwDataLen, NULL, 0)) != DS_OK) {
+	fprintf(stderr,"SoundStream: couldn't unlock sound buffer!\n");
+	IDirectSoundBuffer_Stop(t_pDSBuffer);
+	IDirectSoundBuffer_Stop(t_pDSPrimeBuffer);
+	IDirectSoundBuffer_Release(t_pDSPrimeBuffer);
+	IDirectSound_Release(t_pDirectSound);
+	RETURN (nil);
+    }
+
+    __INST(cbBufOffset) = __MKSMALLINT(0);  // reset last write position to start of buffer
+
+    /* Start the buffer playback */
+    if ((result = IDirectSoundBuffer_Play(t_pDSBuffer, 0, 0, DSBPLAY_LOOPING ) != DS_OK)) {
+	fprintf(stderr,"SoundStream: couldn't play sound buffer!\n");
+	IDirectSoundBuffer_Stop(t_pDSBuffer);
+	IDirectSoundBuffer_Stop(t_pDSPrimeBuffer);
+	IDirectSoundBuffer_Release(t_pDSPrimeBuffer);
+	IDirectSound_Release(t_pDirectSound);
+	RETURN (nil);
+    }
+
+    {
+	OBJ t;
+
+	__INST(pDSBuffer) = t = __MKEXTERNALADDRESS(t_pDSBuffer); __STORE(self, t);
+	__INST(pDirectSound) = t = __MKEXTERNALADDRESS(t_pDirectSound); __STORE(self, t);
+    }
+    RETURN (self);
+  }
+#endif /* WIN32 */
+
 %}.
     "its a regular file open (i.e. /dev/audio) "
     ^ super openWithMode:aMode
@@ -1405,15 +1765,15 @@
 
     scale := freq * 2 * (Float pi).
     1 to:numSamples do:[:i |
-        val := (scale * i / numSamples) sin.
-        val := (val * 16r7FFF) rounded bitAnd:16rFFFF.
-        buffer at:i put:val
+	val := (scale * i / numSamples) sin.
+	val := (val * 16r7FFF) rounded bitAnd:16rFFFF.
+	buffer at:i put:val
     ].
 
     oldFormat := audioFormat.
     self setAudioFormat:#S16.
     1 to:3 do:[:s |
-        self nextPutBytes:(numSamples*2) from:buffer startingAt:1
+	self nextPutBytes:(numSamples*2) from:buffer startingAt:1
     ].
     self setAudioFormat:oldFormat.
 
@@ -1443,15 +1803,15 @@
 
     scale := freq * 2 * (Float pi).
     1 to:numSamples do:[:i |
-        val := (scale * i / numSamples) sin.
-        val := (val * 127 + 128) rounded.
-        buffer at:i put:val
+	val := (scale * i / numSamples) sin.
+	val := (val * 127 + 128) rounded.
+	buffer at:i put:val
     ].
 
     oldFormat := audioFormat.
     self setAudioFormat:#U8.
     1 to:3 do:[:s |
-        self nextPutBytes:numSamples from:buffer startingAt:1
+	self nextPutBytes:numSamples from:buffer startingAt:1
     ].
     self setAudioFormat:oldFormat.
 
@@ -1494,15 +1854,15 @@
 
     scale := freq * 2 * (Float pi).
     1 to:numSamples do:[:i |
-        val := (scale * i / numSamples) sin.
-        val := (val * 16r7FFF) rounded.
-        buffer at:i put:(self class linear16ToUlaw:val)
+	val := (scale * i / numSamples) sin.
+	val := (val * 16r7FFF) rounded.
+	buffer at:i put:(self class linear16ToUlaw:val)
     ].
 
     oldFormat := audioFormat.
     self setAudioFormat:#MU_LAW.
     1 to:3 do:[:s |
-        self nextPutBytes:numSamples from:buffer startingAt:1
+	self nextPutBytes:numSamples from:buffer startingAt:1
     ].
     self setAudioFormat:oldFormat.
 
@@ -1521,5 +1881,5 @@
 !SoundStream class methodsFor:'documentation'!
 
 version
-^ '$Header: /cvs/stx/stx/libbasic2/SoundStream.st,v 1.33 1998-02-08 00:45:12 cg Exp $'! !
+^ '$Header: /cvs/stx/stx/libbasic2/SoundStream.st,v 1.34 1998-12-21 11:43:58 cg Exp $'! !
 SoundStream initialize!