SoundStream.st
changeset 1583 a45ac92afbc8
parent 1556 8a78c9a5a8f7
child 1839 c10cd58ec334
equal deleted inserted replaced
1582:ddec037c4b4c 1583:a45ac92afbc8
    11 "
    11 "
    12 
    12 
    13 "{ Package: 'stx:libbasic2' }"
    13 "{ Package: 'stx:libbasic2' }"
    14 
    14 
    15 FileStream subclass:#SoundStream
    15 FileStream subclass:#SoundStream
    16 	instanceVariableNames:'sampleRate numberOfChannels bitsPerSample audioFormat alPort
    16 	instanceVariableNames:'sampleRate numberOfChannels bitsPerSample audioFormat
    17 		handle1 handle2 bufferOffset bufferSize'
    17 		handle1 handle2 bufferOffset bufferSize'
    18 	classVariableNames:'UnsupportedOperationSignal'
    18 	classVariableNames:'UnsupportedOperationSignal'
    19 	poolDictionaries:''
    19 	poolDictionaries:''
    20 	category:'Streams-External'
    20 	category:'Streams-External'
    21 !
    21 !
    22 
    22 
    23 !SoundStream primitiveDefinitions!
    23 !SoundStream primitiveDefinitions!
    24 %{
    24 %{
    25 
    25 
       
    26 #ifdef WIN32
       
    27 # define xxxUSE_WIN32_DIRECTSOUND
       
    28 #endif
    26 
    29 
    27 #ifdef IRIS
    30 #ifdef IRIS
    28 # ifndef IRIX5
    31 # ifndef IRIX5
    29 #  define IRIS_AUDIO
    32 #  define USE_IRIS_AUDIO
    30 # endif
    33 # endif
    31 #endif
    34 #endif
    32 
    35 
    33 #ifdef IRIS_AUDIO
    36 #ifndef USE_IRIS_AUDIO
       
    37 # ifndef USE_ALSA_AUDIO
       
    38 #  ifdef LINUX
       
    39 #   define USE_DEV_AUDIO
       
    40 #  endif
       
    41 # endif
       
    42 #endif
       
    43 
       
    44 #ifdef USE_IRIS_AUDIO
       
    45 # define IRIS_AUDIO
    34 # include <audio.h>
    46 # include <audio.h>
    35 # define __ALportVal(o)  (ALport)(__externalAddressVal(o))
    47 # define __ALportVal(o)  (ALport)(__externalAddressVal(o))
       
    48 # define alPort handle1
    36 #endif
    49 #endif
    37 
    50 
    38 #ifdef LINUX
    51 #ifdef USE_ALSA_AUDIO
    39 # include <stdio.h>
    52 # ifdef LINUX
    40 # include <sys/soundcard.h>
    53 #  define ALSA_AUDIO
    41 # define DEV_AUDIO_DEFAULT_FREQ (8000)
    54 #  include <alsa/asoundlib.h>
    42 # define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384)
    55 #  define MAX_NR_OF_CHANNELS 8
    43 # define DEV_AUDIO
    56 #  define DEBUG_SOUND
       
    57 #  define readHandle handle1
       
    58 #  define writeHandle handle2
       
    59 # endif
    44 #endif
    60 #endif
    45 
    61 
    46 #ifdef FREEBSD
    62 #ifdef USE_DEV_AUDIO
    47 # include <stdio.h>
    63 # ifdef LINUX
    48 # include <sys/time.h>
    64 #  include <stdio.h>
    49 # include <sys/ioctl.h>
    65 #  include <sys/soundcard.h>
    50 # include <machine/pcaudioio.h>
    66 #  define DEV_AUDIO_DEFAULT_FREQ (8000)
    51 # define DEV_AUDIO_DEFAULT_FREQ (8000)
    67 #  define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384)
    52 # define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384)
    68 #  define DEV_AUDIO
    53 # define DEV_AUDIO
    69 # endif
    54 #endif
    70 
    55 
    71 # ifdef FREEBSD
    56 #if defined(sunos) || defined(solaris)
    72 #  include <stdio.h>
    57 # include <stdio.h>
    73 #  include <sys/time.h>
    58 # ifdef solaris
    74 #  include <sys/ioctl.h>
    59 #  include <sys/audioio.h>
    75 #  include <machine/pcaudioio.h>
    60 # else
    76 #  define DEV_AUDIO_DEFAULT_FREQ (8000)
    61 #  include <sun/audioio.h>
    77 #  define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384)
    62 # endif
    78 #  define DEV_AUDIO
    63 # define DEV_AUDIO_DEFAULT_FREQ (8000)
    79 # endif
    64 # define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384)
    80 
    65 # define DEV_AUDIO
    81 # if defined(sunos) || defined(solaris)
    66 #endif
    82 #  include <stdio.h>
    67 
    83 #  ifdef solaris
    68 #if defined(hpux)
    84 #   include <sys/audioio.h>
    69 # include <stdio.h>
    85 #  else
    70 # include <sys/ioctl.h>
    86 #   include <sun/audioio.h>
    71 # include <sys/inode.h>
    87 #  endif
    72 # include <sys/audio.h>
    88 #  define DEV_AUDIO_DEFAULT_FREQ (8000)
    73 # include <sys/time.h>
    89 #  define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384)
    74 # include <unistd.h>
    90 #  define DEV_AUDIO
    75 # define DEV_AUDIO_DEFAULT_FREQ (22050)
    91 # endif
    76 # define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384)
    92 
    77 # define DEV_AUDIO
    93 # if defined(hpux)
    78 #endif
    94 #  include <stdio.h>
       
    95 #  include <sys/ioctl.h>
       
    96 #  include <sys/inode.h>
       
    97 #  include <sys/audio.h>
       
    98 #  include <sys/time.h>
       
    99 #  include <unistd.h>
       
   100 #  define DEV_AUDIO_DEFAULT_FREQ (22050)
       
   101 #  define DEV_AUDIO_DEFAULT_BUFFERSIZE (16384)
       
   102 #  define DEV_AUDIO
       
   103 # endif
       
   104 #endif /* USE_DEV_AUDIO */
    79 
   105 
    80 #ifndef WIN32
   106 #ifndef WIN32
    81 # ifndef O_WRONLY
   107 # ifndef O_WRONLY
    82 #  include <sys/fcntl.h>
   108 #  include <sys/fcntl.h>
    83 # endif
   109 # endif
    84 
   110 
    85 # ifndef EINTR
   111 # include <errno.h>
    86 #  include <errno.h>
       
    87 # endif
       
    88 #endif
   112 #endif
    89 
   113 
    90 #ifdef WIN32
   114 #ifdef WIN32
    91 
   115 
    92 # define _WIN32
   116 # define _WIN32
   110 
   134 
   111 /* # include <stdarg.h> /* */
   135 /* # include <stdarg.h> /* */
   112 # include <stdio.h> /* */
   136 # include <stdio.h> /* */
   113 # include <windows.h>
   137 # include <windows.h>
   114 
   138 
   115 # ifdef USE_DIRECTSOUND
   139 # ifdef USE_WIN32_DIRECTSOUND
       
   140 #  define WIN32_DIRECTSOUND
   116 #  define CINTERFACE
   141 #  define CINTERFACE
   117 #  include "dsound.h"
   142 #  include "dsound.h"
   118 #  define __DirectSoundVal(o) (LPDIRECTSOUND)(__externalAddressVal(o))
   143 #  define __DirectSoundVal(o) (LPDIRECTSOUND)(__externalAddressVal(o))
   119 #  define __DSBufferVal(o)    (LPDIRECTSOUNDBUFFER)(__externalAddressVal(o))
   144 #  define __DSBufferVal(o)    (LPDIRECTSOUNDBUFFER)(__externalAddressVal(o))
   120 
   145 
   124 #  define pDirectSound handle1
   149 #  define pDirectSound handle1
   125 #  define pDSBuffer    handle2
   150 #  define pDSBuffer    handle2
   126 
   151 
   127 # else /* USE WAVE... */
   152 # else /* USE WAVE... */
   128 
   153 
       
   154 #  define WIN32_WAVE
   129 #  define __WaveHandleVal(o)    (HWAVEOUT)(__externalAddressVal(o))
   155 #  define __WaveHandleVal(o)    (HWAVEOUT)(__externalAddressVal(o))
   130 #  define MAXBUF      10        /* Maximum number of buffers */
   156 #  define MAXBUF      10        /* Maximum number of buffers */
   131 #  define DATALEN     2048      /* Size of wave data buffer */
   157 #  define DATALEN     2048      /* Size of wave data buffer */
   132 
   158 
   133 struct buf {
   159 struct buf {
   191 
   217 
   192 # define INT int
   218 # define INT int
   193 
   219 
   194 #endif /* WIN32 */
   220 #endif /* WIN32 */
   195 
   221 
       
   222 #ifdef DEBUG_SOUND
       
   223 # define DPRINTF(x) printf x
       
   224 #else
       
   225 # define DPRINTF(x) /* as nothing */
       
   226 #endif
       
   227 
   196 %}
   228 %}
   197 ! !
   229 ! !
   198 
   230 
   199 !SoundStream primitiveFunctions!
   231 !SoundStream primitiveFunctions!
   200 %{
   232 %{
   201 #ifdef WIN32
   233 #ifdef WIN32_WAVE
   202 # ifndef USE_DIRECTSOUND
       
   203 
   234 
   204 static void CALLBACK
   235 static void CALLBACK
   205 waveCallBack(HWAVE waveHandle, UINT msg, DWORD inst, DWORD p1, DWORD p2)
   236 waveCallBack(HWAVE waveHandle, UINT msg, DWORD inst, DWORD p1, DWORD p2)
   206 {
   237 {
   207     if (msg == MM_WOM_DONE) {
   238     if (msg == MM_WOM_DONE) {
   213 	SetEvent(free_buffer_event);
   244 	SetEvent(free_buffer_event);
   214 	LeaveCriticalSection(&free_list_lock);
   245 	LeaveCriticalSection(&free_list_lock);
   215     }
   246     }
   216 }
   247 }
   217 
   248 
   218 # endif
   249 #endif /* WIN32_WAVE */
   219 #endif
       
   220 
   250 
   221 %}
   251 %}
   222 ! !
   252 ! !
   223 
   253 
   224 !SoundStream class methodsFor:'documentation'!
   254 !SoundStream class methodsFor:'documentation'!
   854     int __stereo = __channels > 1;
   884     int __stereo = __channels > 1;
   855     int __format = -1;
   885     int __format = -1;
   856 
   886 
   857     if (0) {
   887     if (0) {
   858     }
   888     }
       
   889     else if (__INST(audioFormat) == @symbol(MU_LAW)) {
   859 #  ifdef AFMT_MU_LAW
   890 #  ifdef AFMT_MU_LAW
   860     else if (__INST(audioFormat) == @symbol(MU_LAW)) {
       
   861 	__format = AFMT_MU_LAW;
   891 	__format = AFMT_MU_LAW;
   862     }
       
   863 #  endif
   892 #  endif
       
   893     }
       
   894     else if (__INST(audioFormat) == @symbol(A_LAW)) {
   864 #  ifdef AFMT_A_LAW
   895 #  ifdef AFMT_A_LAW
   865     else if (__INST(audioFormat) == @symbol(A_LAW)) {
       
   866 	__format = AFMT_A_LAW;
   896 	__format = AFMT_A_LAW;
   867     }
       
   868 #  endif
   897 #  endif
       
   898     }
       
   899     else if (__INST(audioFormat) == @symbol(IMA_ADPCM)) {
   869 #  ifdef AFMT_IMA_ADPCM
   900 #  ifdef AFMT_IMA_ADPCM
   870     else if (__INST(audioFormat) == @symbol(IMA_ADPCM)) {
       
   871 	__format = AFMT_IMA_ADPCM;
   901 	__format = AFMT_IMA_ADPCM;
   872     }
       
   873 #  endif
   902 #  endif
       
   903     }
       
   904     else if (__INST(audioFormat) == @symbol(U8)) {
   874 #  ifdef AFMT_U8
   905 #  ifdef AFMT_U8
   875     else if (__INST(audioFormat) == @symbol(U8)) {
       
   876 	__format = AFMT_U8;
   906 	__format = AFMT_U8;
   877     }
       
   878 #  endif
   907 #  endif
       
   908     }
       
   909     else if (__INST(audioFormat) == @symbol(S16_LE)) {
   879 #  ifdef AFMT_S16_LE
   910 #  ifdef AFMT_S16_LE
   880     else if (__INST(audioFormat) == @symbol(S16_LE)) {
       
   881 	__format = AFMT_S16_LE;
   911 	__format = AFMT_S16_LE;
   882     }
       
   883 #  endif
   912 #  endif
       
   913     }
       
   914     else if (__INST(audioFormat) == @symbol(S16_BE)) {
   884 #  ifdef AFMT_S16_BE
   915 #  ifdef AFMT_S16_BE
   885     else if (__INST(audioFormat) == @symbol(S16_BE)) {
       
   886 	__format = AFMT_S16_BE;
   916 	__format = AFMT_S16_BE;
   887     }
       
   888 #  endif
   917 #  endif
       
   918     }
       
   919     else if (__INST(audioFormat) == @symbol(S8)) {
   889 #  ifdef AFMT_S8
   920 #  ifdef AFMT_S8
   890     else if (__INST(audioFormat) == @symbol(S8)) {
       
   891 	__format = AFMT_S8;
   921 	__format = AFMT_S8;
   892     }
       
   893 #  endif
   922 #  endif
       
   923     }
       
   924     else if (__INST(audioFormat) == @symbol(U16_LE)) {
   894 #  ifdef AFMT_U16_LE
   925 #  ifdef AFMT_U16_LE
   895     else if (__INST(audioFormat) == @symbol(U16_LE)) {
       
   896 	__format = AFMT_U16_LE;
   926 	__format = AFMT_U16_LE;
   897     }
       
   898 #  endif
   927 #  endif
       
   928     }
       
   929     else if (__INST(audioFormat) == @symbol(U16_BE)) {
   899 #  ifdef AFMT_U16_BE
   930 #  ifdef AFMT_U16_BE
   900     else if (__INST(audioFormat) == @symbol(U16_BE)) {
       
   901 	__format = AFMT_U16_BE;
   931 	__format = AFMT_U16_BE;
   902     }
       
   903 #  endif
   932 #  endif
       
   933     }
       
   934     else if (__INST(audioFormat) == @symbol(MPEG)) {
   904 #  ifdef AFMT_MPEG
   935 #  ifdef AFMT_MPEG
   905     else if (__INST(audioFormat) == @symbol(MPEG)) {
       
   906 	__format = AFMT_MPEG;
   936 	__format = AFMT_MPEG;
   907     }
       
   908 #  endif
   937 #  endif
   909     else {
       
   910 	__format = -1;
       
   911     }
   938     }
   912 
   939 
   913 #if defined(DEV_AUDIO)
   940 #if defined(DEV_AUDIO)
   914     channels = nil;
   941     channels = nil;
   915     blockSize = nil;
   942     blockSize = nil;
  1068 	if (ioctl(f, SNDCTL_DSP_RESET, &__dummy) >= 0) {
  1095 	if (ioctl(f, SNDCTL_DSP_RESET, &__dummy) >= 0) {
  1069 	    RETURN (self);
  1096 	    RETURN (self);
  1070 	}
  1097 	}
  1071 # endif
  1098 # endif
  1072     }
  1099     }
  1073 #endif
  1100 #endif /* DEV_AUDIO */
  1074 %}.
  1101 %}.
  1075     ^ UnsupportedOperationSignal raise
  1102     ^ UnsupportedOperationSignal raise
  1076 
  1103 
  1077     "
  1104     "
  1078      self writing resetSoundCard; dumpSettings; close
  1105      self writing resetSoundCard; dumpSettings; close
  1545     if ((port = __INST(alPort)) != nil) {
  1572     if ((port = __INST(alPort)) != nil) {
  1546 	__INST(alPort) = nil;
  1573 	__INST(alPort) = nil;
  1547 	ALcloseport(__ALportVal(port));
  1574 	ALcloseport(__ALportVal(port));
  1548     }
  1575     }
  1549     RETURN (self);
  1576     RETURN (self);
  1550 #endif
  1577 #endif /* IRIS_AUDIO */
  1551 
  1578 
  1552 #ifdef WIN32
  1579 #ifdef WIN32_DIRECTSOUND
  1553 # ifdef USE_DIRECTSOUND
       
  1554 
       
  1555     OBJ oDirectSound, oDSBuffer;
  1580     OBJ oDirectSound, oDSBuffer;
  1556     LPDIRECTSOUND       t_pDirectSound;
  1581     LPDIRECTSOUND       t_pDirectSound;
  1557     LPDIRECTSOUNDBUFFER t_pDSBuffer;
  1582     LPDIRECTSOUNDBUFFER t_pDSBuffer;
  1558 
  1583 
  1559     if ((oDSBuffer = __INST(pDSBuffer)) != nil) {
  1584     if ((oDSBuffer = __INST(pDSBuffer)) != nil) {
  1569 	t_pDirectSound = __DirectSoundVal(oDirectSound);
  1594 	t_pDirectSound = __DirectSoundVal(oDirectSound);
  1570 	if (t_pDirectSound) {
  1595 	if (t_pDirectSound) {
  1571 	    IDirectSound_Release(t_pDirectSound);
  1596 	    IDirectSound_Release(t_pDirectSound);
  1572 	}
  1597 	}
  1573     }
  1598     }
  1574 # else
  1599     RETURN (self);
       
  1600 #endif /* WIN32_DIRECTSOUND */
       
  1601 
       
  1602 #ifdef WIN32_WAVE
  1575     struct buf *bp, *next;
  1603     struct buf *bp, *next;
  1576     int r;
  1604     int r;
  1577     HWAVEOUT t_waveHandle;
  1605     HWAVEOUT t_waveHandle;
  1578     OBJ oWaveHandle;
  1606     OBJ oWaveHandle;
  1579 
  1607 
  1580     if ((oWaveHandle = __INST(waveHandle)) != nil) {
  1608     if ((oWaveHandle = __INST(waveHandle)) != nil) {
  1581 	t_waveHandle = __WaveHandleVal(oWaveHandle);
  1609 	t_waveHandle = __WaveHandleVal(oWaveHandle);
  1582 
  1610 
  1583 #  ifdef NO_WAIT_IN_CLOSE
  1611 # ifdef NO_WAIT_IN_CLOSE
  1584 	/* Force cancellation of any pending buffers */
  1612 	/* Force cancellation of any pending buffers */
  1585 	(void)waveOutReset(t_waveHandle);
  1613 	(void)waveOutReset(t_waveHandle);
  1586 #  endif
  1614 # endif
  1587 
  1615 
  1588 	/* Wait until all pending buffers have been freed */
  1616 	/* Wait until all pending buffers have been freed */
  1589 	while (free_buffers < total_buffers) {
  1617 	while (free_buffers < total_buffers) {
  1590 	    WaitForSingleObject(free_buffer_event, INFINITE);
  1618 	    WaitForSingleObject(free_buffer_event, INFINITE);
  1591 	}
  1619 	}
  1592 
  1620 
  1593 #  ifndef NO_WAIT_IN_CLOSE
  1621 # ifndef NO_WAIT_IN_CLOSE
  1594 	/* Force cancellation of any pending buffers */
  1622 	/* Force cancellation of any pending buffers */
  1595 	(void)waveOutReset(t_waveHandle);
  1623 	(void)waveOutReset(t_waveHandle);
  1596 #  endif
  1624 # endif
  1597 
  1625 
  1598 	/* Close the device */
  1626 	/* Close the device */
  1599 	if ((r = waveOutClose(t_waveHandle)) != 0) {
  1627 	if ((r = waveOutClose(t_waveHandle)) != 0) {
  1600 	    printf("waveOutClose\n");
  1628 	    printf("waveOutClose\n");
  1601 	    RETURN(self);
  1629 	    RETURN(self);
  1612 
  1640 
  1613 	LeaveCriticalSection(&free_list_lock);
  1641 	LeaveCriticalSection(&free_list_lock);
  1614 
  1642 
  1615 	__INST(waveHandle) = nil;
  1643 	__INST(waveHandle) = nil;
  1616     }
  1644     }
  1617 # endif
       
  1618     RETURN (self);
  1645     RETURN (self);
  1619 #endif
  1646 # endif /* WIN32_WAVE */
  1620 
  1647 
  1621 #if defined(DEV_AUDIO)
  1648 #if defined(DEV_AUDIO)
  1622     OBJ fp;
  1649     OBJ fp;
  1623     int fd;
  1650     int fd;
  1624     FILE *f;
  1651     FILE *f;
  1665 	while (ALgetfilled(p) > 0) {
  1692 	while (ALgetfilled(p) > 0) {
  1666 	    sginap(1);
  1693 	    sginap(1);
  1667 	}
  1694 	}
  1668     }
  1695     }
  1669     RETURN(self);
  1696     RETURN(self);
  1670 #endif
  1697 #endif /* IRIS_AUDIO */
  1671 
  1698 
  1672 #if defined(DEV_AUDIO)
  1699 #if defined(DEV_AUDIO)
  1673     if (__isSmallInteger(fd)) {
  1700     if (__isSmallInteger(fd)) {
  1674 	int f = __intVal(fd);
  1701 	int f = __intVal(fd);
  1675 	/* ... */
  1702 	/* ... */
  1676     }
  1703     }
  1677 #endif
  1704 #endif /* DEV_AUDIO */
  1678 %}.
  1705 %}.
  1679     "dont know how to wait on non-iris systems"
  1706     "dont know how to wait on non-iris systems"
  1680     ^ self
  1707     ^ self
  1681 !
  1708 !
  1682 
  1709 
  1683 isOpen
  1710 isOpen
  1684     alPort notNil ifTrue:[^ true].
       
  1685     handle1 notNil ifTrue:[^ true].
  1711     handle1 notNil ifTrue:[^ true].
       
  1712     handle2 notNil ifTrue:[^ true].
  1686     ^ filePointer notNil
  1713     ^ filePointer notNil
  1687 !
  1714 !
  1688 
  1715 
  1689 nextBytes:count into:anObject startingAt:start
  1716 nextBytes:count into:anObject startingAt:start
  1690     "read the next count bytes into an object and return the number of
  1717     "read the next count bytes into an object and return the number of
  1718 		}
  1745 		}
  1719 	    }
  1746 	    }
  1720 	}
  1747 	}
  1721     }
  1748     }
  1722   }
  1749   }
  1723 #endif
  1750 #endif /* IRIS_AUDIO */
  1724 
  1751 
  1725 #if defined(DEV_AUDIO)
  1752 #if defined(DEV_AUDIO)
  1726 #include <errno.h>
       
  1727    /*
  1753    /*
  1728     * redefine to work around a bug in the linux sound driver;
  1754     * redefine to work around a bug in the linux sound driver;
  1729     * if a write is interrupted (EINTR), it is not defined, how many
  1755     * if a write is interrupted (EINTR), it is not defined, how many
  1730     * bytes have been read from the device.
  1756     * bytes have been read from the device.
  1731     *
  1757     *
  1780 		}
  1806 		}
  1781 		RETURN (count);
  1807 		RETURN (count);
  1782 	    }
  1808 	    }
  1783 	}
  1809 	}
  1784     }
  1810     }
  1785 #endif
  1811 #endif /* DEV_AUDIO */
  1786 
  1812 
  1787 %}.
  1813 %}.
  1788     OperatingSystem getOSType = 'irix' ifFalse:[
  1814     OperatingSystem getOSType = 'irix' ifFalse:[
  1789 	OperatingSystem getOSType = 'win32' ifFalse:[
  1815 	OperatingSystem getOSType = 'win32' ifFalse:[
  1790 	    ^ super nextPutBytes:count from:anObject startingAt:start
  1816 	    ^ super nextPutBytes:count from:anObject startingAt:start
  1832 		}
  1858 		}
  1833 	    }
  1859 	    }
  1834 	}
  1860 	}
  1835     }
  1861     }
  1836   }
  1862   }
  1837 #endif /* SGI_AUDIO */
  1863 #endif /* IRIS_AUDIO */
  1838 
  1864 
  1839 #ifdef WIN32
  1865 #ifdef WIN32_DIRECTSOUND
  1840 # ifdef USE_DIRECTSOUND
       
  1841   {
  1866   {
  1842       HRESULT hr;
  1867     HRESULT hr;
  1843       DWORD status;
  1868     DWORD status;
  1844       LPVOID lpbuf1 = NULL;
  1869     LPVOID lpbuf1 = NULL;
  1845       LPVOID lpbuf2 = NULL;
  1870     LPVOID lpbuf2 = NULL;
  1846       DWORD dwsize1 = 0;
  1871     DWORD dwsize1 = 0;
  1847       DWORD dwsize2 = 0;
  1872     DWORD dwsize2 = 0;
  1848       DWORD playPos, safePos, endWrite;
  1873     DWORD playPos, safePos, endWrite;
  1849       DWORD millis;
  1874     DWORD millis;
  1850       OBJ oDirectSound, oDSBuffer;
  1875     OBJ oDirectSound, oDSBuffer;
  1851       LPDIRECTSOUND       t_pDirectSound = (LPDIRECTSOUND)0;
  1876     LPDIRECTSOUND       t_pDirectSound = (LPDIRECTSOUND)0;
  1852       LPDIRECTSOUNDBUFFER t_pDSBuffer = (LPDIRECTSOUNDBUFFER)0;
  1877     LPDIRECTSOUNDBUFFER t_pDSBuffer = (LPDIRECTSOUNDBUFFER)0;
  1853       int t_cbBufOffset, t_cbBufSize;
  1878     int t_cbBufOffset, t_cbBufSize;
  1854       short *buf;
  1879     short *buf;
  1855       int cnt, offs;
  1880     int cnt, offs;
  1856 
  1881 
  1857       if ((oDSBuffer = __INST(pDSBuffer)) != nil) {
  1882     if ((oDSBuffer = __INST(pDSBuffer)) != nil) {
  1858 	  t_pDSBuffer = __DSBufferVal(oDSBuffer);
  1883 	t_pDSBuffer = __DSBufferVal(oDSBuffer);
  1859       }
  1884     }
  1860       if ((oDirectSound = __INST(pDirectSound)) != nil) {
  1885     if ((oDirectSound = __INST(pDirectSound)) != nil) {
  1861 	  t_pDirectSound = __DirectSoundVal(oDirectSound);
  1886 	t_pDirectSound = __DirectSoundVal(oDirectSound);
  1862       }
  1887     }
  1863 
  1888 
  1864       if (!t_pDSBuffer || !t_pDirectSound) {
  1889     if (!t_pDSBuffer || !t_pDirectSound) {
  1865 	  fprintf(stderr, "SoundStream not open!\n");
  1890 	fprintf(stderr, "SoundStream not open!\n");
  1866 	  RETURN (0);
  1891 	RETURN (0);
  1867       }
  1892     }
  1868       t_cbBufOffset = __intVal(__INST(bufferOffset));
  1893     t_cbBufOffset = __intVal(__INST(bufferOffset));
  1869       t_cbBufSize = __intVal(__INST(bufferSize));
  1894     t_cbBufSize = __intVal(__INST(bufferSize));
  1870 
  1895 
  1871       cnt = __intVal(count);
  1896     cnt = __intVal(count);
  1872       offs = __intVal(start) - 1;
  1897     offs = __intVal(start) - 1;
  1873       buf = (short *)__InstPtr(anObject) + OHDR_SIZE + offs;
  1898     buf = (short *)__InstPtr(anObject) + OHDR_SIZE + offs;
  1874 
  1899 
  1875       // Should be playing, right?
  1900     // Should be playing, right?
  1876       hr = IDirectSoundBuffer_GetStatus(t_pDSBuffer, &status );
  1901     hr = IDirectSoundBuffer_GetStatus(t_pDSBuffer, &status );
  1877       if (!(status && DSBSTATUS_PLAYING)) {
  1902     if (!(status && DSBSTATUS_PLAYING)) {
  1878 	  fprintf(stderr, "Buffer not playing!\n");
  1903 	fprintf(stderr, "Buffer not playing!\n");
  1879 	  RETURN (0);
  1904 	RETURN (0);
  1880       }
  1905     }
  1881 
  1906 
  1882       // Sleep until we have enough room in buffer.
  1907     // Sleep until we have enough room in buffer.
  1883       hr = IDirectSoundBuffer_GetCurrentPosition(t_pDSBuffer, &playPos, &safePos );
  1908     hr = IDirectSoundBuffer_GetCurrentPosition(t_pDSBuffer, &playPos, &safePos );
  1884       if( hr != DS_OK ) {
  1909     if( hr != DS_OK ) {
  1885 	  fprintf(stderr, "Cannot get position!\n");
  1910 	fprintf(stderr, "Cannot get position!\n");
  1886 	  RETURN (0);
  1911 	RETURN (0);
  1887       }
  1912     }
  1888       if( playPos < t_cbBufOffset ) playPos += t_cbBufSize;
  1913     if( playPos < t_cbBufOffset ) playPos += t_cbBufSize;
  1889 
  1914 
  1890       endWrite = t_cbBufOffset + (cnt * sizeof(short));
  1915     endWrite = t_cbBufOffset + (cnt * sizeof(short));
  1891       while ( playPos < endWrite ) {
  1916     while ( playPos < endWrite ) {
  1892 	  // Calculate number of milliseconds until we will have room, as
  1917 	// Calculate number of milliseconds until we will have room, as
  1893 	  // time = distance * (milliseconds/second) / ((bytes/sample) * (samples/second)),
  1918 	// time = distance * (milliseconds/second) / ((bytes/sample) * (samples/second)),
  1894 	  // rounded up.
  1919 	// rounded up.
  1895 	  millis = (DWORD) (1.0 + ((endWrite - playPos) * 1000.0) / ( sizeof(short) * __intVal(__INST(sampleRate))));
  1920 	millis = (DWORD) (1.0 + ((endWrite - playPos) * 1000.0) / ( sizeof(short) * __intVal(__INST(sampleRate))));
  1896 
  1921 
  1897 	  // Sleep for that long
  1922 	// Sleep for that long
  1898 	  Sleep( millis );
  1923 	Sleep( millis );
  1899 
  1924 
  1900 	  // Wake up, find out where we are now
  1925 	// Wake up, find out where we are now
  1901 	  hr = IDirectSoundBuffer_GetCurrentPosition(t_pDSBuffer, &playPos, &safePos );
  1926 	hr = IDirectSoundBuffer_GetCurrentPosition(t_pDSBuffer, &playPos, &safePos );
  1902 	  if( hr != DS_OK ) {
  1927 	if( hr != DS_OK ) {
  1903 	      fprintf(stderr, "Cannot get position!\n");
  1928 	    fprintf(stderr, "Cannot get position!\n");
  1904 	      RETURN (0);
  1929 	    RETURN (0);
  1905 	  }
  1930 	}
  1906 	  if( playPos < t_cbBufOffset ) playPos += t_cbBufSize; // unwrap offset
  1931 	if( playPos < t_cbBufOffset ) playPos += t_cbBufSize; // unwrap offset
  1907       }
  1932     }
  1908 
  1933 
  1909       // Lock free space in the DS
  1934     // Lock free space in the DS
  1910       hr = IDirectSoundBuffer_Lock(t_pDSBuffer, t_cbBufOffset, cnt * sizeof(short), &lpbuf1, &dwsize1, &lpbuf2, &dwsize2, 0);
  1935     hr = IDirectSoundBuffer_Lock(t_pDSBuffer, t_cbBufOffset, cnt * sizeof(short), &lpbuf1, &dwsize1, &lpbuf2, &dwsize2, 0);
  1911       if (hr == DS_OK) {
  1936     if (hr == DS_OK) {
  1912 	  // Copy the buffer into the DS
  1937 	// Copy the buffer into the DS
  1913 	  CopyMemory(lpbuf1, buf, dwsize1);
  1938 	CopyMemory(lpbuf1, buf, dwsize1);
  1914 	  if(NULL != lpbuf2) CopyMemory(lpbuf2, buf+dwsize1, dwsize2);
  1939 	if(NULL != lpbuf2) CopyMemory(lpbuf2, buf+dwsize1, dwsize2);
  1915 
  1940 
  1916 	  // Update our buffer offset and unlock sound buffer
  1941 	// Update our buffer offset and unlock sound buffer
  1917 	  t_cbBufOffset = (t_cbBufOffset + dwsize1 + dwsize2) % t_cbBufSize;
  1942 	t_cbBufOffset = (t_cbBufOffset + dwsize1 + dwsize2) % t_cbBufSize;
  1918 	  IDirectSoundBuffer_Unlock(t_pDSBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);
  1943 	IDirectSoundBuffer_Unlock(t_pDSBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);
  1919       }
  1944     }
  1920       __INST(buffferOffset) = __MKSMALLINT(t_cbBufOffset);
  1945     __INST(buffferOffset) = __MKSMALLINT(t_cbBufOffset);
  1921 
  1946 
  1922       RETURN (count);
  1947     RETURN (count);
  1923   }
  1948   }
  1924 # else
  1949 #endif /* WIN32_DIRECTSOUND */
       
  1950 
       
  1951 #ifdef WIN32_WAVE
  1925   {
  1952   {
  1926     struct buf *bp;
  1953     struct buf *bp;
  1927     int len, i, r;
  1954     int len, i, r;
  1928     int dataLen, offs;
  1955     int dataLen, offs;
  1929     char *buf;
  1956     char *buf;
  1986 	buf += len;
  2013 	buf += len;
  1987 	dataLen -= len;
  2014 	dataLen -= len;
  1988     }
  2015     }
  1989     RETURN (count);
  2016     RETURN (count);
  1990   }
  2017   }
  1991 # endif
  2018 #endif /* WIN32_WAVE */
  1992 #endif /* WIN32 */
       
  1993 
  2019 
  1994 #if defined(DEV_AUDIO)
  2020 #if defined(DEV_AUDIO)
  1995 #include <errno.h>
       
  1996    /*
  2021    /*
  1997     * redefine to work around a bug in the linux sound driver;
  2022     * redefine to work around a bug in the linux sound driver;
  1998     * if a write is interrupted (EINTR), it is not defined, how many
  2023     * if a write is interrupted (EINTR), it is not defined, how many
  1999     * bytes have been written to the device.
  2024     * bytes have been written to the device.
  2000     * I.e. a retry of the write may lead to ever-playing without ever
  2025     * I.e. a retry of the write may lead to ever-playing without ever
  2050 		}
  2075 		}
  2051 		RETURN (count);
  2076 		RETURN (count);
  2052 	    }
  2077 	    }
  2053 	}
  2078 	}
  2054     }
  2079     }
  2055 #endif
  2080 #endif /* DEV_AUDIO */
  2056 
  2081 
  2057 %}.
  2082 %}.
  2058     ^ super nextPutBytes:count from:anObject startingAt:start
  2083     ^ super nextPutBytes:count from:anObject startingAt:start
  2059 !
  2084 !
  2060 
  2085 
  2132     ok = true;
  2157     ok = true;
  2133     goto out;
  2158     goto out;
  2134   }
  2159   }
  2135 #endif /* IRIS_AUDIO */
  2160 #endif /* IRIS_AUDIO */
  2136 
  2161 
  2137 #ifdef WIN32
  2162 #ifdef WIN32_DIRECTSOUND
  2138 # ifdef USE_DIRECTSOUND
       
  2139   {
  2163   {
  2140     HRESULT result;
  2164     HRESULT result;
  2141     LPDIRECTSOUND       t_pDirectSound;
  2165     LPDIRECTSOUND       t_pDirectSound;
  2142     LPDIRECTSOUNDBUFFER t_pDSBuffer, t_pDSPrimeBuffer;
  2166     LPDIRECTSOUNDBUFFER t_pDSBuffer, t_pDSPrimeBuffer;
  2143     WAVEFORMATEX        wfFormat;
  2167     WAVEFORMATEX        wfFormat;
  2250 	t = __MKEXTERNALADDRESS(t_pDirectSound); __INST(pDirectSound) = t; __STORE(self, t);
  2274 	t = __MKEXTERNALADDRESS(t_pDirectSound); __INST(pDirectSound) = t; __STORE(self, t);
  2251     }
  2275     }
  2252     ok = true;
  2276     ok = true;
  2253     goto out;
  2277     goto out;
  2254   }
  2278   }
  2255 # else /* !USE_DIRECTSOUND */
  2279 #endif /* WIN32_DIRECTSOUND */
       
  2280 
       
  2281 #ifdef WIN32_WAVE
  2256   {
  2282   {
  2257     PCMWAVEFORMAT waveFormat;
  2283     PCMWAVEFORMAT waveFormat;
  2258     int r;
  2284     int r;
  2259     HWAVEOUT t_waveHandle;
  2285     HWAVEOUT t_waveHandle;
  2260     OBJ oWaveHandle;
  2286     OBJ oWaveHandle;
  2295 	OBJ t;
  2321 	OBJ t;
  2296 
  2322 
  2297 	t = __MKEXTERNALADDRESS(t_waveHandle); __INST(waveHandle) = t; __STORE(self, t);
  2323 	t = __MKEXTERNALADDRESS(t_waveHandle); __INST(waveHandle) = t; __STORE(self, t);
  2298     }
  2324     }
  2299 
  2325 
  2300 #if 0
  2326 # if 0
  2301     /*
  2327     /*
  2302      * HACK: If we immediately start writing valid audio data to the device
  2328      * HACK: If we immediately start writing valid audio data to the device
  2303      * then the sound is choppy in the beginning. Writing a null packet to
  2329      * then the sound is choppy in the beginning. Writing a null packet to
  2304      * to the device first seems to fix this problem although I have no idea
  2330      * to the device first seems to fix this problem although I have no idea
  2305      * why - DAC
  2331      * why - DAC
  2310 	for (i = 0; i < DATALEN; i++) {
  2336 	for (i = 0; i < DATALEN; i++) {
  2311 	    null[i] = 127;
  2337 	    null[i] = 127;
  2312 	}
  2338 	}
  2313 	audioWrite(null, DATALEN);
  2339 	audioWrite(null, DATALEN);
  2314     }
  2340     }
  2315 #endif /* 0 */
  2341 # endif /* 0 */
  2316     ok = true;
  2342     ok = true;
  2317     goto out;
  2343     goto out;
  2318   }
  2344   }
  2319 # endif /* !USE_DIRECTSOUND */
  2345 #endif /* !WIN32_DIRECTSOUND */
  2320 #endif /* WIN32 */
       
  2321 
  2346 
  2322 #ifdef DEV_AUDIO
  2347 #ifdef DEV_AUDIO
  2323 	{
  2348   {
  2324 	    int __fd;
  2349       int __fd;
  2325 	    int __mode;
  2350       int __mode;
  2326 	    FILE *f;
  2351       FILE *f;
  2327 
  2352 
  2328 	    if (strcmp(__stringVal(aMode), "w") == 0) {
  2353       if (strcmp(__stringVal(aMode), "w") == 0) {
  2329 		__mode = O_WRONLY;
  2354 	  __mode = O_WRONLY;
  2330 	    } else if (strcmp(__stringVal(aMode), "r") == 0) {
  2355       } else if (strcmp(__stringVal(aMode), "r") == 0) {
  2331 		__mode = O_RDONLY;
  2356 	  __mode = O_RDONLY;
  2332 	    } else {
  2357       } else {
  2333 		__mode = O_RDWR;
  2358 	  __mode = O_RDWR;
  2334 	    }
  2359       }
  2335 	    do {
  2360       do {
  2336 		__BEGIN_INTERRUPTABLE__
  2361 	  __BEGIN_INTERRUPTABLE__
  2337 		__fd = open((char *) __stringVal(__INST(pathName)), __mode /* |O_NDELAY */);
  2362 	  __fd = open((char *) __stringVal(__INST(pathName)), __mode /* |O_NDELAY */);
  2338 		__END_INTERRUPTABLE__
  2363 	  __END_INTERRUPTABLE__
  2339 	    } while ((__fd < 0) && (__threadErrno == EINTR));
  2364       } while ((__fd < 0) && (__threadErrno == EINTR));
  2340 
  2365 
  2341 	    if (__fd >= 0) {
  2366       if (__fd >= 0) {
  2342 		/*
  2367 	  /*
  2343 		 * make it a FILE *
  2368 	   * make it a FILE *
  2344 		 */
  2369 	   */
  2345 		f = fdopen(__fd, __stringVal(aMode));
  2370 	  f = fdopen(__fd, __stringVal(aMode));
  2346 		if (! f) {
  2371 	  if (! f) {
  2347 		    __BEGIN_INTERRUPTABLE__
  2372 	      __BEGIN_INTERRUPTABLE__
  2348 		    close(__fd);
  2373 	      close(__fd);
  2349 		    __END_INTERRUPTABLE__
  2374 	      __END_INTERRUPTABLE__
  2350 		    ok = false;
  2375 	      ok = false;
  2351 		    goto out;
  2376 	      goto out;
  2352 		}
  2377 	  }
  2353 		setbuf(f, NULL);
  2378 	  setbuf(f, NULL);
  2354 		__INST(buffered) = false;
  2379 	  __INST(buffered) = false;
  2355 		__INST(filePointer) = __MKOBJ(f);
  2380 	  __INST(filePointer) = __MKOBJ(f);
  2356 		__STORESELF(filePointer);
  2381 	  __STORESELF(filePointer);
  2357 
  2382 
  2358 #if defined(PCM_ENABLE_OUTPUT) && defined(PCM_ENABLE_INPUT)
  2383 #if defined(PCM_ENABLE_OUTPUT) && defined(PCM_ENABLE_INPUT)
  2359 # if defined(SNDCTL_DSP_SETTRIGGER)
  2384 # if defined(SNDCTL_DSP_SETTRIGGER)
  2360 		if (__mode == O_RDWR) {
  2385 	  if (__mode == O_RDWR) {
  2361 		    int enable_bits = ~(PCM_ENABLE_OUTPUT|PCM_ENABLE_INPUT);
  2386 	      int enable_bits = ~(PCM_ENABLE_OUTPUT|PCM_ENABLE_INPUT);
  2362 
  2387 
  2363 		    if (ioctl(__fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) == -1)
  2388 	      if (ioctl(__fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) == -1)
  2364 		    {
  2389 	      {
  2365 			fprintf(stderr, "can't request synchronous start of fullduplex operation");
  2390 		  fprintf(stderr, "can't request synchronous start of fullduplex operation");
  2366 		    }
  2391 	      }
  2367 		}
  2392 	  }
  2368 # endif
  2393 # endif
  2369 #endif
  2394 #endif
  2370 		ok = true;
  2395 	  ok = true;
  2371 		goto out;
  2396 	  goto out;
  2372 	    }
  2397       }
  2373 	}
  2398   }
  2374 
       
  2375 #endif /* DEV_AUDIO */
  2399 #endif /* DEV_AUDIO */
       
  2400 
  2376 out:;
  2401 out:;
  2377 %}.
  2402 %}.
  2378     ok == false ifTrue:[
  2403     ok == false ifTrue:[
  2379 	self openError.
  2404 	self openError.
  2380 	"not reached"
  2405 	"not reached"
  2660 ! !
  2685 ! !
  2661 
  2686 
  2662 !SoundStream class methodsFor:'documentation'!
  2687 !SoundStream class methodsFor:'documentation'!
  2663 
  2688 
  2664 version
  2689 version
  2665     ^ '$Header: /cvs/stx/stx/libbasic2/SoundStream.st,v 1.67 2005-05-31 18:49:10 cg Exp $'
  2690     ^ '$Header: /cvs/stx/stx/libbasic2/SoundStream.st,v 1.68 2005-12-22 16:55:51 cg Exp $'
  2666 ! !
  2691 ! !
  2667 
  2692 
  2668 SoundStream initialize!
  2693 SoundStream initialize!