# HG changeset patch # User Claus Gittinger # Date 914240638 -3600 # Node ID 9e853d04f52bda5ef755f013844c54817ab679d4 # Parent 487b2bff9d31a52dab0dfe63d9e9ce0b2450a233 first attempt in win32 audio diff -r 487b2bff9d31 -r 9e853d04f52b SoundStr.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 -# define _ALportVal(o) (ALport)(__externalAddressVal(o)) +# define __ALportVal(o) (ALport)(__externalAddressVal(o)) #endif #ifdef LINUX @@ -42,6 +44,67 @@ #ifdef DEV_AUDIO # include #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 /* */ +# include /* */ +# include +# 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! diff -r 487b2bff9d31 -r 9e853d04f52b SoundStream.st --- 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 -# define _ALportVal(o) (ALport)(__externalAddressVal(o)) +# define __ALportVal(o) (ALport)(__externalAddressVal(o)) #endif #ifdef LINUX @@ -42,6 +44,67 @@ #ifdef DEV_AUDIO # include #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 /* */ +# include /* */ +# include +# 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!