checkin from browser
authorClaus Gittinger <cg@exept.de>
Mon, 20 Nov 2000 22:12:19 +0100
changeset 923 cfb86334aebf
parent 922 2439a81a0530
child 924 4d262097b161
checkin from browser
SoundStream.st
--- a/SoundStream.st	Mon Nov 20 19:03:51 2000 +0100
+++ b/SoundStream.st	Mon Nov 20 22:12:19 2000 +0100
@@ -1081,12 +1081,6 @@
         ]
     ].
 %{
-    int f = __intVal(fd);
-    int __fmt = 0, __fmtWant;
-    union {
-        unsigned short us;
-        unsigned char ub[2];
-    } u;
     OBJ sym = aSymbol;
 
     if (__INST(audioFormat) == sym) {
@@ -1095,6 +1089,13 @@
 
 #if defined(DEV_AUDIO)
     if (__isSmallInteger(fd)) {
+        int f = __intVal(fd);
+        int __fmt = 0, __fmtWant;
+        union {
+            unsigned short us;
+            unsigned char ub[2];
+        } u;
+
         if (__isSymbol(sym)) {
             if (sym == @symbol(U16)) {
                 u.us = 0x1234;
@@ -1227,19 +1228,22 @@
         ]
     ].
 %{
-    int f = __intVal(fd);
-    int __nCh = 0;
 
 #if defined(DEV_AUDIO)
     if (__isSmallInteger(fd) && __isSmallInteger(nChannels)) {
-        __nCh = __intVal(nChannels);
+        int f = __intVal(fd);
+        int __nCh = __intVal(nChannels);
 
 # if defined(SNDCTL_DSP_STEREO)
         if ((__nCh == 1) || (__nCh == 2)) {
             int __stereo = (__nCh == 2) ? 1 : 0;
 
             if (ioctl(f, SNDCTL_DSP_STEREO, &__stereo) >= 0) {
-                __INST(numberOfChannels) = nChannels;
+                if (__stereo == 0) {
+                    __INST(numberOfChannels) = __MKSMALLINT(1);
+                } else {
+                    __INST(numberOfChannels) = __MKSMALLINT(2);
+                }
                 RETURN (self);
             }
         }
@@ -1324,16 +1328,13 @@
         ]
     ].
 %{
-    int f = __intVal(fd);
-    int __rate = 0;
-    int __rateWant;
-
 #if defined(DEV_AUDIO) 
     if (__isSmallInteger(fd) && __isSmallInteger(hz)) {
-        __rate = __intVal(hz);
+        int f = __intVal(fd);
+        int __rate = __intVal(hz);
+        int __rateWant = __rate;
 
 # if defined(SNDCTL_DSP_SPEED)
-        __rateWant = __rate;
         if (ioctl(f, SNDCTL_DSP_SPEED, &__rate) >= 0) {
             if (__rate != __rateWant) {
                 fprintf(stderr, "SoundStream [warning]: actual rate is %d\n", __rate);
@@ -1344,7 +1345,6 @@
         }
 # else
 #  if defined(SOUND_PCM_WRITE_RATE)
-        __rateWant = __rate;
         if (ioctl(f, SOUND_PCM_WRITE_RATE, &__rate) >= 0) {
             if (__rate != __rateWant) {
                 fprintf(stderr, "SoundStream [warning]: actual rate is %d\n", __rate);
@@ -1748,27 +1748,27 @@
     char *cp;
 
     if ((port = __INST(alPort)) != nil) {
-	if (__INST(mode) != @symbol(readonly)) {
-	    if (__bothSmallInteger(count, start)) {
-		cnt = __intVal(count);
-		offs = __intVal(start) - 1;
-		p = __ALportVal(port);
+        if (__INST(mode) != @symbol(readonly)) {
+            if (__bothSmallInteger(count, start)) {
+                cnt = __intVal(count);
+                offs = __intVal(start) - 1;
+                p = __ALportVal(port);
 
-		/*
-		 * compute number of samples
-		 */
-		objSize = _Size(anObject) - OHDR_SIZE;
-		if ( (offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs)) ) {
-		    cp = (char *)__InstPtr(anObject) + OHDR_SIZE + offs;
-		    if (__INST(bitsPerSample) == __MKSMALLINT(16))
-			nSamp = cnt / 2;
-		    else
-			nSamp = cnt;
-		    ALwritesamps(p, cp, cnt);
-		    RETURN ( count );
-		}
-	    }
-	}
+                /*
+                 * compute number of samples
+                 */
+                objSize = _Size(anObject) - OHDR_SIZE;
+                if ( (offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs)) ) {
+                    cp = (char *)__InstPtr(anObject) + OHDR_SIZE + offs;
+                    if (__INST(bitsPerSample) == __MKSMALLINT(16))
+                        nSamp = cnt / 2;
+                    else
+                        nSamp = cnt;
+                    ALwritesamps(p, cp, cnt);
+                    RETURN ( count );
+                }
+            }
+        }
     }
   }
 #endif /* SGI_AUDIO */
@@ -1792,15 +1792,15 @@
       int cnt, offs;
 
       if ((oDSBuffer = __INST(pDSBuffer)) != nil) {
-	  t_pDSBuffer = __DSBufferVal(oDSBuffer);
+          t_pDSBuffer = __DSBufferVal(oDSBuffer);
       }
       if ((oDirectSound = __INST(pDirectSound)) != nil) {
-	  t_pDirectSound = __DirectSoundVal(oDirectSound);
+          t_pDirectSound = __DirectSoundVal(oDirectSound);
       }
 
       if (!t_pDSBuffer || !t_pDirectSound) {
-	  fprintf(stderr, "SoundStream not open!\n");
-	  RETURN (0);
+          fprintf(stderr, "SoundStream not open!\n");
+          RETURN (0);
       }
       t_cbBufOffset = __intVal(__INST(bufferOffset));
       t_cbBufSize = __intVal(__INST(bufferSize));
@@ -1812,47 +1812,47 @@
       // Should be playing, right?
       hr = IDirectSoundBuffer_GetStatus(t_pDSBuffer, &status );
       if (!(status && DSBSTATUS_PLAYING)) {
-	  fprintf(stderr, "Buffer not playing!\n");
-	  RETURN (0);
+          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);
+          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))));
+          // 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);
+          // 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);
+          // 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);
 
@@ -1869,7 +1869,7 @@
     OBJ oWaveHandle;
 
     if ((oWaveHandle = __INST(waveHandle)) == nil) {
-	RETURN(0);
+        RETURN(0);
     }
     t_waveHandle = __WaveHandleVal(oWaveHandle);
 
@@ -1878,50 +1878,50 @@
     buf = (short *)__InstPtr(anObject) + OHDR_SIZE + offs;
 
     while (dataLen > 0) {
-	if (free_list == NULL && total_buffers < MAXBUF) {
-	    /* Expand available buffer space */
-	    bp = (struct buf *)malloc(sizeof(struct buf));
-	    total_buffers++;
-	} else {
-	    if (free_list == NULL) {
-		/* We must wait for a free buffer */
-		while (free_list == NULL) {
-		    WaitForSingleObject(free_buffer_event, INFINITE);
-		}
-	    }
-	    EnterCriticalSection(&free_list_lock);
-	    bp = free_list;
-	    free_list = free_list->next;
-	    --free_buffers;
-	    LeaveCriticalSection(&free_list_lock);
-	    r = waveOutUnprepareHeader(t_waveHandle, &bp->hdr, sizeof(WAVEHDR));
-	    if (r != 0) {
-		printf("waveOutUnprepareHeader\n");
-		RETURN(self);
-	    }
-	}
-	len = min(dataLen, DATALEN);
-	bp->hdr.lpData = (char *)bp->data;
-	bp->hdr.dwBufferLength = len;
-	bp->hdr.dwBytesRecorded = len;
-	bp->hdr.dwUser = (DWORD)bp;
-	bp->hdr.dwFlags = 0;
-	bp->hdr.dwLoops = 0;
-	r = waveOutPrepareHeader(t_waveHandle, &bp->hdr, sizeof(WAVEHDR));
-	if (r != 0) {
-	    printf("waveOutPrepareHeader\n");
-	    RETURN(self);
-	}
-	for (i = 0; i < len; i++) {
-	    bp->data[i] = buf[i];
-	}
-	r = waveOutWrite(t_waveHandle, &bp->hdr, sizeof(WAVEHDR));
-	if (r != 0) {
-	    printf("waveOutWrite\n");
-	    RETURN(self);
-	}
-	buf += len;
-	dataLen -= len;
+        if (free_list == NULL && total_buffers < MAXBUF) {
+            /* Expand available buffer space */
+            bp = (struct buf *)malloc(sizeof(struct buf));
+            total_buffers++;
+        } else {
+            if (free_list == NULL) {
+                /* We must wait for a free buffer */
+                while (free_list == NULL) {
+                    WaitForSingleObject(free_buffer_event, INFINITE);
+                }
+            }
+            EnterCriticalSection(&free_list_lock);
+            bp = free_list;
+            free_list = free_list->next;
+            --free_buffers;
+            LeaveCriticalSection(&free_list_lock);
+            r = waveOutUnprepareHeader(t_waveHandle, &bp->hdr, sizeof(WAVEHDR));
+            if (r != 0) {
+                printf("waveOutUnprepareHeader\n");
+                RETURN(self);
+            }
+        }
+        len = min(dataLen, DATALEN);
+        bp->hdr.lpData = (char *)bp->data;
+        bp->hdr.dwBufferLength = len;
+        bp->hdr.dwBytesRecorded = len;
+        bp->hdr.dwUser = (DWORD)bp;
+        bp->hdr.dwFlags = 0;
+        bp->hdr.dwLoops = 0;
+        r = waveOutPrepareHeader(t_waveHandle, &bp->hdr, sizeof(WAVEHDR));
+        if (r != 0) {
+            printf("waveOutPrepareHeader\n");
+            RETURN(self);
+        }
+        for (i = 0; i < len; i++) {
+            bp->data[i] = buf[i];
+        }
+        r = waveOutWrite(t_waveHandle, &bp->hdr, sizeof(WAVEHDR));
+        if (r != 0) {
+            printf("waveOutWrite\n");
+            RETURN(self);
+        }
+        buf += len;
+        dataLen -= len;
     }
     RETURN (count);
   }
@@ -1929,6 +1929,7 @@
 #endif /* WIN32 */
 
 #if defined(DEV_AUDIO)
+#include <errno.h>
    /*
     * redefine to work around a bug in the linux sound driver;
     * if a write is interrupted (EINTR), it is not defined, how many
@@ -1946,42 +1947,47 @@
     int fd;
 
     if ((fp = __INST(filePointer)) != nil) {
-	f = __FILEVal(fp);
-	if (__INST(mode) != @symbol(readonly)) {
-	    if (__bothSmallInteger(count, start)) {
-		cnt = __intVal(count);
-		offs = __intVal(start) - 1;
+        f = __FILEVal(fp);
+        if (__INST(mode) != @symbol(readonly)) {
+            if (__bothSmallInteger(count, start)) {
+                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;
+                objSize = _Size(anObject) - OHDR_SIZE;
+                if ( (offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs)) ) {
+                    do {
+                        cp = (char *)__InstPtr(anObject) + OHDR_SIZE + offs;
 
-			n = cnt;
-			if (n > 4096) n = 4096;
+                        n = cnt;
+                        if (n > 4096) n = 4096;
 # ifdef LINUX
-			sigsetmask(~0);
+                        sigsetmask(~0);
 # endif
-			if (__INST(buffered) == true) {
-			    n = fwrite(cp, 1, n, f);
-			} else {
-			    fd = fileno(f);
-			    n = write(fd, cp, n);
-			}
+                        if (__INST(buffered) == true) {
+                            n = fwrite(cp, 1, n, f);
+                        } else {
+                            fd = fileno(f);
+                            n = write(fd, cp, n);
+                        }
 # ifdef LINUX
-			sigsetmask(0);
+                        sigsetmask(0);
 # endif
-			__BEGIN_INTERRUPTABLE__
-			__END_INTERRUPTABLE__
-			if (n > 0) {
-			    offs += n;
-			    cnt -= n;
-			}
-		    } while (cnt);
-		}
-		RETURN (count);
-	    }
-	}
+                        __BEGIN_INTERRUPTABLE__
+                        __END_INTERRUPTABLE__
+                        if (n > 0) {
+                            offs += n;
+                            cnt -= n;
+                        } else {
+                            if (n < 0) {
+                                fprintf(stderr, "write error: %d\n", __threadErrno);
+                                RETURN (count);
+                            }
+                        }
+                    } while (cnt);
+                }
+                RETURN (count);
+            }
+        }
     }
 #endif
 
@@ -2292,7 +2298,7 @@
             do {
                 __BEGIN_INTERRUPTABLE__
                 __threadErrno = 0;
-                __fd = open((char *) __stringVal(__INST(pathName)), __mode|O_NDELAY);
+                __fd = open((char *) __stringVal(__INST(pathName)), __mode /* |O_NDELAY */);
                 __END_INTERRUPTABLE__
             } while ((__fd < 0) && (__threadErrno == EINTR));
 
@@ -2328,27 +2334,43 @@
     "output some tone for some time
      in S16 audioFormat - a test method"
 
-    |buffer numSamples val scale|
+    |buffer numSamples val scale isUnsigned|
+
+    (audioFormat startsWith:#U16) ifFalse:[
+        (audioFormat startsWith:#S16) ifFalse:[
+            self error:'must be in 16bit mode' mayProceed:true.
+            ^ self
+        ]
+    ].
 
     numSamples := (self sampleRate * seconds) truncated.
     buffer := WordArray new:numSamples.
 
     "fill it with a sine wave"
 
+    isUnsigned := audioFormat startsWith:#U16.
+
     scale := freq * 2 * (Float pi).
     1 to:numSamples do:[:i |
-	val := (scale * i / self sampleRate) sin.
-	val := (val * 16r7FFF) rounded bitAnd:16rFFFF.
-	audioFormat == #U16 ifTrue:[
-	    val := val + 32768
-	].
-	buffer at:i put:val
+        val := (scale * i / self sampleRate) sin.
+        val := (val * 16r7FFF) rounded bitAnd:16rFFFF.
+        isUnsigned ifTrue:[
+            val := val + 32768
+        ].
+        buffer at:i put:val
     ].
 
     self nextPutBytes:(numSamples*2) from:buffer startingAt:1
 
     "
-     SoundStream writing playSine16:440 forSeconds:3; close
+     SoundStream writing setAudioFormat:#S16; playSine16:440 forSeconds:2; close
+     SoundStream writing setAudioFormat:#S16; playSine16:880 forSeconds:2; close
+     SoundStream writing setAudioFormat:#S16; playSine16:1760 forSeconds:2; close
+     SoundStream writing setAudioFormat:#S16; playSine16:3520 forSeconds:2; close
+     SoundStream writing tuneTone:440; close
+
+     SoundStream writing setAudioFormat:#U16; playSine16:880 forSeconds:2; close
+     SoundStream writing setAudioFormat:#U16_LE; playSine16:880 forSeconds:2; close
     "
 
     "Modified: / 31.1.1999 / 12:12:41 / cg"
@@ -2381,6 +2403,8 @@
      SoundStream writing setSampleRate:10000; tuneTone; close
      SoundStream writing setSampleRate:20000; tuneTone; close
      SoundStream writing setSampleRate:40000; tuneTone; close
+
+     SoundStream writing setSampleRate:40000; dumpSettings; close
      SoundStream writing setSampleRate:20000; dumpSettings; close
     "
 
@@ -2392,6 +2416,13 @@
 
     |buffer numSamples val scale oldFormat|
 
+    (audioFormat startsWith:#U16) ifFalse:[
+        (audioFormat startsWith:#S16) ifFalse:[
+            self error:'must be in 16bit mode' mayProceed:true.
+            ^ self
+        ]
+    ].
+
     "allocate memory for 1sec playing time"
     numSamples := self sampleRate.
     buffer := WordArray new:numSamples.
@@ -2400,18 +2431,18 @@
 
     scale := freq * 2 * (Float pi).
     1 to:numSamples do:[:i |
-	val := (scale * i / numSamples) sin.
-	val := (val * 16r7FFF) rounded bitAnd:16rFFFF.
-	audioFormat == #U16 ifTrue:[
-	    val := val + 32768
-	].
-	buffer at:i put:val
+        val := (scale * i / numSamples) sin.
+        val := (val * 16r7FFF) rounded bitAnd:16rFFFF.
+        audioFormat == #U16 ifTrue:[
+            val := val + 32768
+        ].
+        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.
 
@@ -2433,6 +2464,13 @@
 
     |buffer numSamples val scale oldFormat|
 
+    (audioFormat == #U8) ifFalse:[
+        (audioFormat == #S8) ifFalse:[
+            self error:'must be in 8bit mode' mayProceed:true.
+            ^ self
+        ]
+    ].
+
     "allocate memory for 1sec playing time"
     numSamples := self sampleRate.
     buffer := ByteArray new:numSamples.
@@ -2441,15 +2479,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.
 
@@ -2481,24 +2519,41 @@
 !
 
 tuneTone:freq
-    audioFormat == #S16 ifTrue:[
-	^ self tuneTone16:freq
-    ].
-    audioFormat == #U16 ifTrue:[
-	^ self tuneTone16:freq
+    ((audioFormat startsWith:#S16) 
+    or:[audioFormat startsWith:#U16]) ifTrue:[
+        ^ self tuneTone16:freq
     ].
     audioFormat == #MU_LAW ifTrue:[
-	^ self tuneToneMU:freq
+        ^ self tuneToneMU:freq
     ].
     self tuneTone8:freq
 
     "
      SoundStream writing tuneTone:880; close
+     SoundStream writing setSampleRate:4000; tuneTone:440; close
      SoundStream writing setSampleRate:4000; tuneTone:880; close
+     SoundStream writing setSampleRate:8000; tuneTone:440; close
      SoundStream writing setSampleRate:8000; tuneTone:880; close
+     SoundStream writing setSampleRate:10000; tuneTone:440; close
      SoundStream writing setSampleRate:10000; tuneTone:880; close
+
+     SoundStream writing setSampleRate:20000; tuneTone:440; close
      SoundStream writing setSampleRate:20000; tuneTone:880; close
+
+     SoundStream writing setSampleRate:40000; tuneTone:440; close
      SoundStream writing setSampleRate:40000; tuneTone:880; close
+     SoundStream writing setSampleRate:40000; tuneTone:1760; close
+     SoundStream writing setSampleRate:40000; tuneTone:3520; close
+     SoundStream writing setSampleRate:40000; tuneTone:7020; close
+     SoundStream writing setSampleRate:40000; tuneTone:14040; close
+
+     SoundStream writing setSampleRate:44100; tuneTone:440; close
+     SoundStream writing setSampleRate:44100; tuneTone:880; close
+     SoundStream writing setSampleRate:44100; tuneTone:1760; close
+     SoundStream writing setSampleRate:44100; tuneTone:3520; close
+     SoundStream writing setSampleRate:44100; tuneTone:7020; close
+     SoundStream writing setSampleRate:44100; tuneTone:14040; close
+
      SoundStream writing setSampleRate:20000; dumpSettings; close
     "
 
@@ -2545,6 +2600,6 @@
 !SoundStream class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic2/SoundStream.st,v 1.52 2000-11-20 18:03:51 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic2/SoundStream.st,v 1.53 2000-11-20 21:12:19 cg Exp $'
 ! !
 SoundStream initialize!