Speak Freely for Windows
Workarounds for driver bugs
One of the special joys of working with Windows is the never-ending
challenge of discovering and working around ratty bugs in crummy
drivers. With Windows late to arrive with a resounding thud in the
worlds of networking and multimedia, Speak Freely finds itself close
to the frontier, as it were, where frequent raids by marauding bands
of byte bandits are the price one pays for the privilege of
pioneering. The defensive programmer finds himself transcending that
time-proven style of software development and becoming truly paranoid,
always looking over his shoulder for the next incoming arrow of
misfortune. This is, after all, a system on which functions such as
GetTextMetrics() can return an error status.
The Options/Workarounds menu tree allows you to select workarounds for
various errors in audio and network drivers. In an ideal world none
of these would be needed, but in an ideal world Windows wouldn't
exist. All workaround settings are remembered from session to
session. Workarounds can be selected only when no connections are
active, and some workarounds take effect only when Speak Freely is
restarted; a message box will appear to let you know if this is the
Available workarounds are described in the following paragraphs, along
with suggestions as to when enabling them may be necessary.
- Assume Half-duplex
- Assumes the sound card is half-duplex without requiring it to fail
an output open while input is open. Accommodates cards which are
actually half-duplex but don't indicate so by failing when one
attempts to open input and output simultaneously. Also handles cards
which crash the system or application when you try to open them in
- Assume 11025 Samples/sec
- Assumes the card is capable only of 11025 samples per second mode,
not our preferred 8000 samples per second. Permits correct operation
on cards which don't fail when opened with a sample rate of 8000
samples per second but which can't actually run at that rate.
- Set Maximum Volume on Ring
- If this item is checked, when the first packet of a remote ring request is
received, the output volume is set (if the sound card has that capability) to
maximum. If other programs on your machine mute the speaker or turn down the
volume to a low level, enabling this item may keep you from missing a call. But
beware: some sound cards don't correctly handle setting the output volume--I've
even encountered one which mutes the microphone when output volume is
changed! So if you enable this mode, be sure to run some tests to make sure it's
behaving as intended on your machine.
- Always Bind Socket
- When a network socket is created for transmitting sound, there's
no reason to bind it to an address, but some network drivers are
reputed to fail if a socket isn't bound. Checking this menu item
binds transmit sockets to persuade such feeble minded networks to let
us use them.
- Never Connect Outbound Socket
- Don't connect() the output sockets. This implies we'll
always use sendto() to write to those sockets. Clears "Use
send(), Not sendto()" mode if set. Some WINSOCK implementations,
notably Microsoft's own in Windows NT and Windows 95, blatantly
diverge from the Berkeley sockets practice of treating
connect() on a datagram socket as merely specifying a default
address, not prohibiting subsequent use of sendto() with an
explicit address. Checking this item disables the call on
connect() entirely, just in case there's some driver which
becomes entirely befuddled if it is used.
- Use send(), Not sendto()
- Always use send() to write to outbound sockets; don't
wait for a sendto() to fail first. Accommodates drivers
where a sendto() on a connected socket crashes the
application or system. Clears "Never Connect Outbound Socket" mode if
set. We normally auto-detect the failure of sendto() on a
connected socket and fall back to send(). This item allows
entirely bypassing the sendto() just in case it wreaks havoc
when used on a connected socket.
- Multicast TTL Argument Is char
- The arguments for the multicast
setsockopt() calls IP_MULTICAST_TTL and
IP_MULTICAST_LOOP are documented as type char in
every Unix Socket implementation I've seen. The
Windows Socket 1.1
specification does not contain these calls, as multicast was not a
part of WINSOCK at the time.
application note on
multicast support in Windows NT (and now Windows 95) shows the
argument for these two calls as int and, sure enough, if you
pass a char the call errors with WSAEFAULT (bad address).
Speak Freely conforms to the Microsoft specification and passes
int arguments to these two calls but, just in case there's a
more Unix-like WINSOCK out there which requires a char
argument, provides you this workaround to use char instead. Even
though we're running on a little-endian machine, since the length of
the argument is passed in the setsockopt() call, the two
cases are distinguishable.
- Disable Output Overflow Recovery
- Some versions of Winsock appear to crash the machine rather than throwing
away UDP packets when the user selects a compression mode which transmits
faster than the outbound network connection can accommodate. Speak Freely
attempts to detect this and discard packets itself when this situation occurs, since
losing data is better than a hung machine. The mechanism used to detect and
recover from output overflow ventures into poorly-lit regions of Winsock where I
suspect may lurk many bugs in various implementations, given how many of the
easy things so many manage to get wrong. This workaround turns off output
overflow detection and recovery code for such buggy Winsocks, running the risk
of a crash due to output overflow if they are also buggy in that regard.
- Disable Message Loop Insurance
- If the selected compression and encryption modes (or the modes in packets being
received) exceed the ability of the CPU to process in real time, there's a risk Speak
Freely will hang Windows since sound buffers or packets from the network,
combined with the computing to process them, result in Speak Freely never going
idle and relinquishing control to other applications. To avoid this, there's a
mechanism in Speak Freely which detects if 350 milliseconds or more have
elapsed since the last opportunity for other applications to run and, if so, explicitly
yields control to any waiting application(s). On slower machines, the very
mechanism which saves them from hanging may, itself, cause pauses in sound.
So, you can disable the message loop check (restoring the potential for a hang), if
necessary, with this workaround. Don't disable it until you're confident your
machine is working well with the compression and encryption modes you've
- Get Host Name Synchronously
- When you enter a numeric IP address (for example, 127.112.201.14) rather than a
host name, Speak Freely attempts to look up the host name to display it in the
connection window. It does this the recommended way, with the non-blocking call
WSAAsyncGetHostByAddr. Unfortunately, this does not work correctly on every
Winsock. The one that comes with Sun Select PC-NFS 5.1, for example, returns
the correct results but plants a time bomb that can explode when you finally exit
Speak Freely. This workaround uses the blocking call gethostbyaddr() which does
not seem to trigger the bomb. Not that it works perfectly--it forgets to null terminate
the host string it returns, but that's just ugly, not catastrophic. If the Winsock
identifies itself as PC-NFS, this workaround is enabled by default.
- No Speak Freely Heartbeat
- Disable the periodic Speak Freely protocol heartbeat on the control channel. This
is primarily intended as a last resort if the (less than 1%) added bandwidth
saturates a close to the edge connection, and also in case the control channel
packets awake something horrid lurking on the next higher port.
- Large RTP Protocol Packets
- Uses Speak Freely's preferred packet sizes for GSM and LPC compression rather
than those typically sent by RTP programs. Most RTP programs were developed on
fast workstations with high bandwidth network connectivity. Speak Freely users
generally have slower machines and network links which benefit from larger packets.
Try this if the person you're talking to reports halting audio in RTP protocol.
- Disable VAT Protocol Detection
- VAT protocol will never be automatically selected as a result of receiving a
message on the control channel which resembles a VAT control message. Enable
this if you never receive VAT protocol messages and are annoyed at how long it
takes to identify the protocol of encrypted RTP messages.
- Disable RTP Protocol Detection
- RTP protocol will never be automatically selected as a result of receiving a
message on the control channel which resembles a RTP control message. Enable
this if you never receive RTP protocol messages and are annoyed at how long it
takes to identify the protocol of encrypted VAT messages.
- No Encryption of RTP Control Packets
- RTP control packets can, according to the standard, be sent either encrypted or in
the clear. Most RTP programs I've encountered encrypt their control packets, so
this is the default Speak Freely sends (it accepts both encrypted and clear
packets). If you set this workaround, control packets are sent in the clear.