diff -r ddec037c4b4c -r a45ac92afbc8 SoundStream.st --- a/SoundStream.st Thu Dec 22 17:14:07 2005 +0100 +++ b/SoundStream.st Thu Dec 22 17:55:51 2005 +0100 @@ -13,7 +13,7 @@ "{ Package: 'stx:libbasic2' }" FileStream subclass:#SoundStream - instanceVariableNames:'sampleRate numberOfChannels bitsPerSample audioFormat alPort + instanceVariableNames:'sampleRate numberOfChannels bitsPerSample audioFormat handle1 handle2 bufferOffset bufferSize' classVariableNames:'UnsupportedOperationSignal' poolDictionaries:'' @@ -23,68 +23,92 @@ !SoundStream primitiveDefinitions! %{ +#ifdef WIN32 +# define xxxUSE_WIN32_DIRECTSOUND +#endif #ifdef IRIS # ifndef IRIX5 -# define IRIS_AUDIO +# define USE_IRIS_AUDIO +# endif +#endif + +#ifndef USE_IRIS_AUDIO +# ifndef USE_ALSA_AUDIO +# ifdef LINUX +# define USE_DEV_AUDIO +# endif +# endif +#endif + +#ifdef USE_IRIS_AUDIO +# define IRIS_AUDIO +# include +# define __ALportVal(o) (ALport)(__externalAddressVal(o)) +# define alPort handle1 +#endif + +#ifdef USE_ALSA_AUDIO +# ifdef LINUX +# define ALSA_AUDIO +# include +# define MAX_NR_OF_CHANNELS 8 +# define DEBUG_SOUND +# define readHandle handle1 +# define writeHandle handle2 # endif #endif -#ifdef IRIS_AUDIO -# include -# define __ALportVal(o) (ALport)(__externalAddressVal(o)) -#endif +#ifdef USE_DEV_AUDIO +# ifdef LINUX +# include +# include +# define DEV_AUDIO_DEFAULT_FREQ (8000) +# define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384) +# define DEV_AUDIO +# endif -#ifdef LINUX -# include -# include -# define DEV_AUDIO_DEFAULT_FREQ (8000) -# define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384) -# define DEV_AUDIO -#endif - -#ifdef FREEBSD -# include -# include -# include -# include -# define DEV_AUDIO_DEFAULT_FREQ (8000) -# define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384) -# define DEV_AUDIO -#endif +# ifdef FREEBSD +# include +# include +# include +# include +# define DEV_AUDIO_DEFAULT_FREQ (8000) +# define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384) +# define DEV_AUDIO +# endif -#if defined(sunos) || defined(solaris) -# include -# ifdef solaris -# include -# else -# include +# if defined(sunos) || defined(solaris) +# include +# ifdef solaris +# include +# else +# include +# endif +# define DEV_AUDIO_DEFAULT_FREQ (8000) +# define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384) +# define DEV_AUDIO # endif -# define DEV_AUDIO_DEFAULT_FREQ (8000) -# define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384) -# define DEV_AUDIO -#endif -#if defined(hpux) -# include -# include -# include -# include -# include -# include -# define DEV_AUDIO_DEFAULT_FREQ (22050) -# define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384) -# define DEV_AUDIO -#endif +# if defined(hpux) +# include +# include +# include +# include +# include +# include +# define DEV_AUDIO_DEFAULT_FREQ (22050) +# define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384) +# define DEV_AUDIO +# endif +#endif /* USE_DEV_AUDIO */ #ifndef WIN32 # ifndef O_WRONLY # include # endif -# ifndef EINTR -# include -# endif +# include #endif #ifdef WIN32 @@ -112,7 +136,8 @@ # include /* */ # include -# ifdef USE_DIRECTSOUND +# ifdef USE_WIN32_DIRECTSOUND +# define WIN32_DIRECTSOUND # define CINTERFACE # include "dsound.h" # define __DirectSoundVal(o) (LPDIRECTSOUND)(__externalAddressVal(o)) @@ -126,6 +151,7 @@ # else /* USE WAVE... */ +# define WIN32_WAVE # define __WaveHandleVal(o) (HWAVEOUT)(__externalAddressVal(o)) # define MAXBUF 10 /* Maximum number of buffers */ # define DATALEN 2048 /* Size of wave data buffer */ @@ -193,13 +219,18 @@ #endif /* WIN32 */ +#ifdef DEBUG_SOUND +# define DPRINTF(x) printf x +#else +# define DPRINTF(x) /* as nothing */ +#endif + %} ! ! !SoundStream primitiveFunctions! %{ -#ifdef WIN32 -# ifndef USE_DIRECTSOUND +#ifdef WIN32_WAVE static void CALLBACK waveCallBack(HWAVE waveHandle, UINT msg, DWORD inst, DWORD p1, DWORD p2) @@ -215,8 +246,7 @@ } } -# endif -#endif +#endif /* WIN32_WAVE */ %} ! ! @@ -856,58 +886,55 @@ if (0) { } + else if (__INST(audioFormat) == @symbol(MU_LAW)) { # ifdef AFMT_MU_LAW - else if (__INST(audioFormat) == @symbol(MU_LAW)) { __format = AFMT_MU_LAW; +# endif } -# endif + else if (__INST(audioFormat) == @symbol(A_LAW)) { # ifdef AFMT_A_LAW - else if (__INST(audioFormat) == @symbol(A_LAW)) { __format = AFMT_A_LAW; +# endif } -# endif + else if (__INST(audioFormat) == @symbol(IMA_ADPCM)) { # ifdef AFMT_IMA_ADPCM - else if (__INST(audioFormat) == @symbol(IMA_ADPCM)) { __format = AFMT_IMA_ADPCM; +# endif } -# endif + else if (__INST(audioFormat) == @symbol(U8)) { # ifdef AFMT_U8 - else if (__INST(audioFormat) == @symbol(U8)) { __format = AFMT_U8; +# endif } -# endif + else if (__INST(audioFormat) == @symbol(S16_LE)) { # ifdef AFMT_S16_LE - else if (__INST(audioFormat) == @symbol(S16_LE)) { __format = AFMT_S16_LE; +# endif } -# endif + else if (__INST(audioFormat) == @symbol(S16_BE)) { # ifdef AFMT_S16_BE - else if (__INST(audioFormat) == @symbol(S16_BE)) { __format = AFMT_S16_BE; +# endif } -# endif -# ifdef AFMT_S8 else if (__INST(audioFormat) == @symbol(S8)) { +# ifdef AFMT_S8 __format = AFMT_S8; - } # endif -# ifdef AFMT_U16_LE - else if (__INST(audioFormat) == @symbol(U16_LE)) { - __format = AFMT_U16_LE; } + else if (__INST(audioFormat) == @symbol(U16_LE)) { +# ifdef AFMT_U16_LE + __format = AFMT_U16_LE; # endif -# ifdef AFMT_U16_BE + } else if (__INST(audioFormat) == @symbol(U16_BE)) { +# ifdef AFMT_U16_BE __format = AFMT_U16_BE; +# endif } -# endif + else if (__INST(audioFormat) == @symbol(MPEG)) { # ifdef AFMT_MPEG - else if (__INST(audioFormat) == @symbol(MPEG)) { __format = AFMT_MPEG; - } # endif - else { - __format = -1; } #if defined(DEV_AUDIO) @@ -1070,7 +1097,7 @@ } # endif } -#endif +#endif /* DEV_AUDIO */ %}. ^ UnsupportedOperationSignal raise @@ -1547,11 +1574,9 @@ ALcloseport(__ALportVal(port)); } RETURN (self); -#endif +#endif /* IRIS_AUDIO */ -#ifdef WIN32 -# ifdef USE_DIRECTSOUND - +#ifdef WIN32_DIRECTSOUND OBJ oDirectSound, oDSBuffer; LPDIRECTSOUND t_pDirectSound; LPDIRECTSOUNDBUFFER t_pDSBuffer; @@ -1571,7 +1596,10 @@ IDirectSound_Release(t_pDirectSound); } } -# else + RETURN (self); +#endif /* WIN32_DIRECTSOUND */ + +#ifdef WIN32_WAVE struct buf *bp, *next; int r; HWAVEOUT t_waveHandle; @@ -1580,20 +1608,20 @@ if ((oWaveHandle = __INST(waveHandle)) != nil) { t_waveHandle = __WaveHandleVal(oWaveHandle); -# ifdef NO_WAIT_IN_CLOSE +# ifdef NO_WAIT_IN_CLOSE /* Force cancellation of any pending buffers */ (void)waveOutReset(t_waveHandle); -# endif +# endif /* Wait until all pending buffers have been freed */ while (free_buffers < total_buffers) { WaitForSingleObject(free_buffer_event, INFINITE); } -# ifndef NO_WAIT_IN_CLOSE +# ifndef NO_WAIT_IN_CLOSE /* Force cancellation of any pending buffers */ (void)waveOutReset(t_waveHandle); -# endif +# endif /* Close the device */ if ((r = waveOutClose(t_waveHandle)) != 0) { @@ -1614,9 +1642,8 @@ __INST(waveHandle) = nil; } -# endif RETURN (self); -#endif +# endif /* WIN32_WAVE */ #if defined(DEV_AUDIO) OBJ fp; @@ -1667,22 +1694,22 @@ } } RETURN(self); -#endif +#endif /* IRIS_AUDIO */ #if defined(DEV_AUDIO) if (__isSmallInteger(fd)) { int f = __intVal(fd); /* ... */ } -#endif +#endif /* DEV_AUDIO */ %}. "dont know how to wait on non-iris systems" ^ self ! isOpen - alPort notNil ifTrue:[^ true]. handle1 notNil ifTrue:[^ true]. + handle2 notNil ifTrue:[^ true]. ^ filePointer notNil ! @@ -1720,10 +1747,9 @@ } } } -#endif +#endif /* IRIS_AUDIO */ #if defined(DEV_AUDIO) -#include /* * redefine to work around a bug in the linux sound driver; * if a write is interrupted (EINTR), it is not defined, how many @@ -1782,7 +1808,7 @@ } } } -#endif +#endif /* DEV_AUDIO */ %}. OperatingSystem getOSType = 'irix' ifFalse:[ @@ -1834,94 +1860,95 @@ } } } -#endif /* SGI_AUDIO */ +#endif /* IRIS_AUDIO */ -#ifdef WIN32 -# ifdef USE_DIRECTSOUND +#ifdef WIN32_DIRECTSOUND { - 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; + 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 ((oDSBuffer = __INST(pDSBuffer)) != nil) { + t_pDSBuffer = __DSBufferVal(oDSBuffer); + } + if ((oDirectSound = __INST(pDirectSound)) != nil) { + t_pDirectSound = __DirectSoundVal(oDirectSound); + } - if (!t_pDSBuffer || !t_pDirectSound) { - fprintf(stderr, "SoundStream not open!\n"); - RETURN (0); - } - t_cbBufOffset = __intVal(__INST(bufferOffset)); - t_cbBufSize = __intVal(__INST(bufferSize)); + if (!t_pDSBuffer || !t_pDirectSound) { + fprintf(stderr, "SoundStream not open!\n"); + RETURN (0); + } + t_cbBufOffset = __intVal(__INST(bufferOffset)); + t_cbBufSize = __intVal(__INST(bufferSize)); - cnt = __intVal(count); - offs = __intVal(start) - 1; - buf = (short *)__InstPtr(anObject) + OHDR_SIZE + offs; + 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)) { + fprintf(stderr, "Buffer not playing!\n"); + RETURN (0); + } - // Should be playing, right? - hr = IDirectSoundBuffer_GetStatus(t_pDSBuffer, &status ); - if (!(status && DSBSTATUS_PLAYING)) { - fprintf(stderr, "Buffer not playing!\n"); - RETURN (0); - } + // Sleep until we have enough room in buffer. + hr = IDirectSoundBuffer_GetCurrentPosition(t_pDSBuffer, &playPos, &safePos ); + if( hr != DS_OK ) { + fprintf(stderr, "Cannot get position!\n"); + RETURN (0); + } + if( playPos < t_cbBufOffset ) playPos += t_cbBufSize; - // Sleep until we have enough room in buffer. - hr = IDirectSoundBuffer_GetCurrentPosition(t_pDSBuffer, &playPos, &safePos ); - if( hr != DS_OK ) { - fprintf(stderr, "Cannot get position!\n"); - RETURN (0); - } - if( playPos < t_cbBufOffset ) playPos += t_cbBufSize; + endWrite = t_cbBufOffset + (cnt * 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)))); - endWrite = t_cbBufOffset + (cnt * 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 ); + // 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 ) { - fprintf(stderr, "Cannot get position!\n"); - RETURN (0); - } - if( playPos < t_cbBufOffset ) playPos += t_cbBufSize; // unwrap offset - } + // Wake up, find out where we are now + hr = IDirectSoundBuffer_GetCurrentPosition(t_pDSBuffer, &playPos, &safePos ); + if( hr != DS_OK ) { + fprintf(stderr, "Cannot get position!\n"); + RETURN (0); + } + if( playPos < t_cbBufOffset ) playPos += t_cbBufSize; // unwrap offset + } - // Lock free space in the DS - hr = IDirectSoundBuffer_Lock(t_pDSBuffer, t_cbBufOffset, cnt * 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); + // Lock free space in the DS + hr = IDirectSoundBuffer_Lock(t_pDSBuffer, t_cbBufOffset, cnt * 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(buffferOffset) = __MKSMALLINT(t_cbBufOffset); + // 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(buffferOffset) = __MKSMALLINT(t_cbBufOffset); - RETURN (count); + RETURN (count); } -# else +#endif /* WIN32_DIRECTSOUND */ + +#ifdef WIN32_WAVE { struct buf *bp; int len, i, r; @@ -1988,11 +2015,9 @@ } RETURN (count); } -# endif -#endif /* WIN32 */ +#endif /* WIN32_WAVE */ #if defined(DEV_AUDIO) -#include /* * redefine to work around a bug in the linux sound driver; * if a write is interrupted (EINTR), it is not defined, how many @@ -2052,7 +2077,7 @@ } } } -#endif +#endif /* DEV_AUDIO */ %}. ^ super nextPutBytes:count from:anObject startingAt:start @@ -2134,8 +2159,7 @@ } #endif /* IRIS_AUDIO */ -#ifdef WIN32 -# ifdef USE_DIRECTSOUND +#ifdef WIN32_DIRECTSOUND { HRESULT result; LPDIRECTSOUND t_pDirectSound; @@ -2252,7 +2276,9 @@ ok = true; goto out; } -# else /* !USE_DIRECTSOUND */ +#endif /* WIN32_DIRECTSOUND */ + +#ifdef WIN32_WAVE { PCMWAVEFORMAT waveFormat; int r; @@ -2297,7 +2323,7 @@ t = __MKEXTERNALADDRESS(t_waveHandle); __INST(waveHandle) = t; __STORE(self, t); } -#if 0 +# if 0 /* * HACK: If we immediately start writing valid audio data to the device * then the sound is choppy in the beginning. Writing a null packet to @@ -2312,67 +2338,66 @@ } audioWrite(null, DATALEN); } -#endif /* 0 */ +# endif /* 0 */ ok = true; goto out; } -# endif /* !USE_DIRECTSOUND */ -#endif /* WIN32 */ +#endif /* !WIN32_DIRECTSOUND */ #ifdef DEV_AUDIO - { - int __fd; - int __mode; - FILE *f; + { + int __fd; + int __mode; + FILE *f; - if (strcmp(__stringVal(aMode), "w") == 0) { - __mode = O_WRONLY; - } else if (strcmp(__stringVal(aMode), "r") == 0) { - __mode = O_RDONLY; - } else { - __mode = O_RDWR; - } - do { - __BEGIN_INTERRUPTABLE__ - __fd = open((char *) __stringVal(__INST(pathName)), __mode /* |O_NDELAY */); - __END_INTERRUPTABLE__ - } while ((__fd < 0) && (__threadErrno == EINTR)); + if (strcmp(__stringVal(aMode), "w") == 0) { + __mode = O_WRONLY; + } else if (strcmp(__stringVal(aMode), "r") == 0) { + __mode = O_RDONLY; + } else { + __mode = O_RDWR; + } + do { + __BEGIN_INTERRUPTABLE__ + __fd = open((char *) __stringVal(__INST(pathName)), __mode /* |O_NDELAY */); + __END_INTERRUPTABLE__ + } while ((__fd < 0) && (__threadErrno == EINTR)); - if (__fd >= 0) { - /* - * make it a FILE * - */ - f = fdopen(__fd, __stringVal(aMode)); - if (! f) { - __BEGIN_INTERRUPTABLE__ - close(__fd); - __END_INTERRUPTABLE__ - ok = false; - goto out; - } - setbuf(f, NULL); - __INST(buffered) = false; - __INST(filePointer) = __MKOBJ(f); - __STORESELF(filePointer); + if (__fd >= 0) { + /* + * make it a FILE * + */ + f = fdopen(__fd, __stringVal(aMode)); + if (! f) { + __BEGIN_INTERRUPTABLE__ + close(__fd); + __END_INTERRUPTABLE__ + ok = false; + goto out; + } + setbuf(f, NULL); + __INST(buffered) = false; + __INST(filePointer) = __MKOBJ(f); + __STORESELF(filePointer); #if defined(PCM_ENABLE_OUTPUT) && defined(PCM_ENABLE_INPUT) # if defined(SNDCTL_DSP_SETTRIGGER) - if (__mode == O_RDWR) { - int enable_bits = ~(PCM_ENABLE_OUTPUT|PCM_ENABLE_INPUT); + if (__mode == O_RDWR) { + int enable_bits = ~(PCM_ENABLE_OUTPUT|PCM_ENABLE_INPUT); - if (ioctl(__fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) == -1) - { - fprintf(stderr, "can't request synchronous start of fullduplex operation"); - } - } + if (ioctl(__fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) == -1) + { + fprintf(stderr, "can't request synchronous start of fullduplex operation"); + } + } # endif #endif - ok = true; - goto out; - } - } + ok = true; + goto out; + } + } +#endif /* DEV_AUDIO */ -#endif /* DEV_AUDIO */ out:; %}. ok == false ifTrue:[ @@ -2662,7 +2687,7 @@ !SoundStream class methodsFor:'documentation'! version - ^ '$Header: /cvs/stx/stx/libbasic2/SoundStream.st,v 1.67 2005-05-31 18:49:10 cg Exp $' + ^ '$Header: /cvs/stx/stx/libbasic2/SoundStream.st,v 1.68 2005-12-22 16:55:51 cg Exp $' ! ! SoundStream initialize!