How to use the software build environment

Getting the Village Telco (Mesh Potato) Software

The Mesh-Potato build environment is available at the Village Telco project site at Sourceforge now. It is a snapshot of the current OpenWRT Kamikaze development trunk (bleeding edge) that we are working on. Changes will be merged back to OpenWRT later.

Using a Subversion client program the environment can be checked out with the command:

 svn co villagetelco 

It is also possible to get the code and to monitor the changes with a browser here

The download of the build environment will consume about 350 MByte of hard drive space, a fully compiled environment consumes 3,6 GByte.

Building Linux for the Mesh Potato

Of course you don't have to compile anything if you just want to flash our firmware or use the software packages for the Mesh-Potato. Firmware images and software packages will be available from [1], or [2]

Note: Never compile as superuser/root. You'll be warned when you compile the build system initially, but once you finished compiling, it won't warn you again. Compiling as root will mess up permissions in /tmp and /var on your host system. Applications like Gnome or KDE won't start until you fix the permissions.

There are currently two ways to compile the build environment.

Note: It is necessary to have a internet connection while compiling because the build system will download the sources for most components. The compile process will take a while, even if you have a decent internet connection. You are going to compile a Linux kernel, GCC and many other things. Depending on the speed of your workstation it can take a few hours.

Automated build

The simple, and therefore recommended method is to use a little script that automatically performs all the necessary steps for you - well, almost all.

Note: Running the "from-scratch" version of the script is only necessary if you compile the build environment for the first time from scratch - hence the name. On the command line change into the Villagetelco directory. Then perform:


After a while a interactive ncurses-based menu will show up. Confirm the selected CPU platform by pressing the return key. You can select, add or remove packages - but actually you don't have to, if you are happy with the default Mesh-Potato firmware image. Use the tab, arrow and return keys to navigate. Once you are done, save the configuration, even if you did not make any changes. The script will continue until the build is finished, without any further interaction required.

You should only run the from-scratch script if you just made a fresh check-out of the Villagetelco build environment. The process of downloading and building everything will take quite a while.

On a fast PC (2.5 GHz Intel Core2) with fast Internet connection it will take about one hour, using both CPU cores. In order to use both cores edit the line "make V=99" in the script and change it to "make -j 2 V=99".

In order to rebuild the firmware after an svn update or after you made your own additions / changes run:


The advantage of the build-potato-firmware scripts is that they generate the Mesh-Potato command-line-interface banner against the latest SVN version from Sourceforge and make sure the revision number shown in the LUCI web interface is in sync, too. In order to do that we need to recompile LUCI, just to update the correct revision number. This takes some extra compile time. If you don't worry about the displayed revision number you don't need to go that way.

Manual build

Once you have checked the SVN repository out, enter the Villagetelco directory and run

 ./scripts/feeds update 


Then run

   ./scripts/feeds install -a 

These commands will include additional packages like the BATMAN mesh routing daemon and the Luci web interface. Then start the command:

 make menuconfig 

A comfortable Ncurses based menu will pop up that allows you to customize the configuration of firmware images and select / deselect packages. Save the configuration, even if you did not make any changes.

Finally the build process can be kicked off by issuing:

 make V=99 

Note that for subsequent rebuilds only this step is required:

 make V=99 

The output of the build process for the Mesh Potato are two files:


To generate the combined (kernel and rootfs) firmware image, perform:

cd scripts

Refer to Mesh Potato Firmware How To for flashing information.

Compiling / recompiling a single software package

In the villagetelco directory execute the command:

 make package/packagename/{clean,compile,install} V=99 

Some packages are stored in the ./package/feeds/ subdirectories. In this case you have to provide the path.

 make package/feeds/subdirectory/packagename/{clean,compile,install} V=99 

After the compiling process is finished the new software package is stored in the ./bin/packages/mips directory.

Creating a customized Asterisk Mesh-Potato configuration package

Setting up Asterisk isn't exactly trivial. In order to make the distribution of Asterisk configuration settings easier, we have created a Asterisk-Mesh-Potato-Configuration package. Let's assume you are a VOIP service provider named Freephone. In the villagetelco build environment change to the package directory. Copy the directory asterisk-mesh-potato-configuration into the same package directory to a new name, for example asterisk-mesh-potato-configuration-freephone.

cd package
cp -r asterisk-mesh-potato-configuration asterisk-mesh-potato-configuration-freephone 

We need to get rid of the hidden .svn directories.

 cd asterisk-mesh-potato-configuration-freephone
rm -fr `find -name .svn` 

Now edit the Makefile. Change the package name so it matches the new name. Enter a version number.

Adapt the Asterisk configuration files, stored in the files subdirectory according to your needs.

Go back to the villagetelco root directory.


 make package/asterisk-mesh-potato-configuration-freephone/{compile,install} V=99 

After the compilation process is finished, the new package is stored in ./bin/packages/mips. Note that this package will overwrite the default Asterisk configuration files when you install it on a Mesh-Potato. Therefore the opkg package manager will complain about the conflict and refuse to install the new configuration package. You can override this behavior using the opkg command on the command line, using the --force-overwrite switch.

opkg install --force-overwrite asterisk-mesh-potato-configuration-freephone_<package-version>.ipk 

Asterisk Configuration and Testing

(this section a work in progress)

Steps to setup and test Asterisk on a Nanostation2 or equivalent.

1. Install Speex. In this case we use the opkgs you have built locally (rather than the web-based opkg repository).

scp libspeex
opkg install libspeex
scp codec_speex
opkg install codec_speex

2. Add a SIP device (e.g. SIP phone or ATA), add this code to the bottom of /etc/asterisk/sip.conf using vi:

user=sipguest     ****
secret=sipguest   ****
callerid=YourName ****

Change the lines marked **** to match your SIP device and desired caller ID. 3. Add a dial-plan entry so we can check the SIP device. Add this code to the [defaults] section of /etc/asterisk/extensions.conf. Note to find this section easily use the vi search feature, e.g. type /[def at the vi command line.

exten => 2060,1,Answer()
exten => 2060,2,Oslec()

This says that extension 2060 will answer the call and then run the Oslec test application.

4. The automated Asterisk start up script does not start Asterisk correctly, so kill the partially started Asterisk and start Asterisk manually from the command line:

killall -9 asterisk asterisk -vvvc.

To stop Asterisk:

CLI> stop now

5. Check that Speex and GSM have loaded:

CLI> show translation

Look for entries in the SIP and GSM columns, these show the time taken to process 1000ms of speech.

6. Set a faily high debug level and check that the 2060 dial-plan has been loaded OK:

CLI> set verbose 5 CLI> show dialplan default

7. Now try dialing extension 2060 on your SIP device. If everything is working then you won't hear much, perhaps a little echo if you yell. Pressing keys on your phones allows you to control the test application:

  • 1 - Turn on the echo canceller
  • 2 - Turn off the echo canceller
  • 3 - Reset the echo canceller (which forces it to re-converge)

Flashing a Ubiquity Nanostation 2

1. Hold reset button on the Nanostation 2 and apply power. I used a bent paper clip to access reset. Release reset after 10 seconds.

2. Check you can ping the Nanostation 2 boot loader on

3. Use tftp on your host to flash the Nanostation2:

   $ cd bin
   $ tftp
   tftp> bin
   tftp> put openwrt-atheros-ubnt2-squashfs.bin
   Sent 3277208 bytes in 20.4 seconds
   tftp> quit

4. Wait for the light show to finish on the signal LEDs and it will reboot into OpenWRT.

5. You can telnet to the Nanostation 2 on

6. It is recommended to use the "passwd" command now, to set a password for the router. This will disable telnet and enable SSH & SCP.

7. To edit the network parameters (IP, gateway, DNS) of the Nanostation 2:

root@OpenWrt:/# vi /etc/config/network

Installing Packages

Check that your Nanostation 2 is connected to the Internet and can reach the package repository:

root@OpenWrt:/# ping

Grab the list of available packages:

root@OpenWrt:/# opkg update
root@OpenWrt:/# opkg list

Code Development

Building Asterisk

This is a bit slow (also builds ipkg which is not really necessary in many cases). Is there a faster way?

[villagetelco]$ make package/feeds/potato/asterisk-1.4.x/compile V=99

To install (in build_dir/mips/root-atheros/)

[villagetelco]$ make package/feeds/potato/asterisk-1.4.x/install V=99

The OpenWRT files used to build Asterisk (Makefile, patches, etc) are in villagetelco/feeds/potato/net/asterisk-1.4.x/

Building Oslec

  • Using 'make menuconfig' enable Oslec from the Network menu.
  • The first time Oslec is selected
make V=99
  • Then use the following:
make package/oslec/clean V=99
make package/oslec/compile V=99
make package/oslec/install V=99

You can then re-install Oslec using opkg, or just scp the binary you wish to test.

Building Speex

  • Speex should already be enabled in the build system as it is used by Asterisk. The output of the Speex build process is a shared library which is used by the Asterisk codec
  • Use the following commands:
make package/feeds/packages/speex/clean V=99
make package/feeds/packages/speex/compile V=99
make package/feeds/packages/speex/install V=99
  • To test on the target:
$ scp build_dir/mips/speex-1.2beta3.2/libspeex/.libs/ root@nanostation2:/usr/lib

Configuring an x86 Asterisk box

  1. [Download speex-1.2beta3.tar.gz], ./configure & make install (Note check you don't already have an earlier version of Speex, if so delete it)
  2. [Download asterisk-1.4.4 ]
  3. tar xvzf asterisk-1.4.4.tar.gz
  4. cd asterisk-1.4.4
  5. ./configure and check Speex is found. You can see this in the ./configure output or do a "make menuconfig" and check under codecs that Speex is enabled.
  6. To support 8 kbit/s Speex some patches are required. Apply patches 035, 040, 045 from villagetelco/feeds/potato/net/asterisk-1.4.x/ to Asterisk (patch -p1 might be useful to remove the asterisk-1.4.11 prefix from the patches).
  7. make
  8. become root
  9. make install && make samples
  10. You need to run as root, test using same methods as NS2 Asterisk above, i.e. configure a SIP device and try to

make a call. On the x86 we don't have the Oslec test application so use this dialplan in /etc/asterisk/extensions.conf:

exten => 2060,1,Answer()
exten => 2060,2,Echo()

Configuring SIP/Speex trunk between x86 and NS2

1. Place this code at the end of /etc/asterisk/sip.conf on both the x86 and the NS2.

host= ****

Adjust the IP **** to match the other end of the SIP trunk. The "disallow=all" and "allow=speex" lines force the trunk to only use the Speex codec. If this line is changed to "allow=gsm" then the use of GSM will be forced.

2. Place the following dialplan entry in the [default] section of the x86 Asterisk box:

exten => 2050,1,Dial(SIP/ast/2060)

So dialing 2050 on a phone connected to the x86 box will put a call through the SIP trunk to the NS2, where it will dial 2060 (and hence run the Oslec test application).

3. Restarts Asterisk at both ends:

CLI> stop now
root# asterisk -vvvc

4. Check the SIP trunks are running:

CLI> sip show peers

You should see "ast" listed on both the x86 and the NS2.

Configuring Load Test


The purpose of this test is to prove that a Potato is capable of performing all of the processing required (mesh routing, Asterisk, speech codec and echo canceller). This is a significant project risk as the low cost CPUs targeted for the Mesh Potato have relatively low clock speeds (180MHz) and small caches.

Pass Conditions

The worst case CPU load condition occurs when a Potato is required to route X calls from other nodes in the mesh network while simultaneously originating a single phone call of it's own. (i.e. Asterisk, a speech codec, and a line echo canceller).

The test passes if the potato under test can successfully process a simulated Asterisk call while routing X calls over the mesh. The Asterisk call is simulated by running Asterisk, a speech codec, and an echo canceller. As FXS hardware is not available, we simply echo the received audio back to the caller via a special Asterisk application that also exercises the Oslec echo canceller.

We decided on X=15, based on the following model:

  • A Village Telco mesh network with 500 nodes
  • An activity factor of 10%, so 50 nodes are active at one time.
  • At the centre of the network is a mast with three Nanostation 2s, each which services 120 degrees and one third of the nodes, arranged on three sub-networks with different Wifi frequencies
  • This means around 15 calls/sub-net (16.7 actually, but we chose 15) at our nominal 50 call load.
  • So the _worst_ case is a node that has to pass the traffic of all other calls on the sub-net, in addition to processing it's own call. For example this might be the only node that can see the central Nanostation 2.

Of course many models are possible, but we had to take an educated guess at one to make some meaningful loads tests of the proto-potato software.

Configuring the Mesh Network

Load test.png

All of the x86 and Nanostation boxes were connected to the same physical LAN. IP-aliasing was used to set up the different Ethernet sub-nets illustrated above. Each Nanostation and x86 box also had a 192.168.1.x IP (not illustrated) to allow easy access for configuration and administration.

1/ Three Ubiquity Nanostation 2 and two x86 Asterisk boxes are required. Flash via Nanostation A, B & C with the Nanostation 2 image (from SVN revision 27). This will have an initial IP of

2/ Install (un tar) this conf file tar ball on each Nanostation. This provides config information for the mesh network. Some manual configuration is required on each Nanostation.

This is the network and wireless configuration files for Nanostation A. Note that ipaddr and gateway is different for each Nanostation as per the figure above. Optionally set dns for your LAN (this speeds up Asterisk booting on Nanostation B). Make sure all of the ssid entries are the same.

root@OpenWrt:/etc/config# cat network

config 'interface' 'loopback'
        option 'ifname' 'lo'
        option 'proto' 'static'
        option 'ipaddr' ''
        option 'netmask' ''

config 'interface' 'lan'
        option 'ifname' 'eth0'
        option 'proto' 'static'
        option 'netmask' ''
        option 'dns' ''
        option 'gateway' ''
        option 'ipaddr' ''
root@OpenWrt:/etc/config# cat wireless
config wifi-device  wifi0
        option type     atheros
        option channel  10

config wifi-iface
        option device   wifi0
        option network  lan
        option mode     adhoc
        option ssid     potato
        option encryption none

Here is the meshnetwork start up file used for the tests. Note the ip alias line setting up eth0:0 to be on the 192.168.1 network. This allows

root@OpenWrt:/etc/init.d# cat meshnetwork
sleep 2
iwconfig ath0 essid potato
iwconfig ath0 channel 10
iwconfig ath0 ap 02:CA:FF:EE:BA:BE
iwpriv ath0 bgscan 0
ifconfig ath0
ifconfig eth0:0 netmask
batmand -a ath0

3/ Reboot and check the various interfaces:

root@OpenWrt:~# ifconfig
ath0      Link encap:Ethernet  HWaddr 00:15:6D:A7:F2:A4
          inet addr:  Bcast:  Mask:
          RX packets:8388 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2632 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:810778 (791.7 KiB)  TX bytes:315422 (308.0 KiB)

eth0      Link encap:Ethernet  HWaddr 00:15:6D:A8:F2:A4
          inet addr:  Bcast:  Mask:
          RX packets:360 errors:0 dropped:0 overruns:0 frame:0
          TX packets:576 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:26822 (26.1 KiB)  TX bytes:30002 (29.2 KiB)
          Interrupt:4 Base address:0x1000

eth0:0    Link encap:Ethernet  HWaddr 00:15:6D:A8:F2:A4
          inet addr:  Bcast:  Mask:
          Interrupt:4 Base address:0x1000

See if you can ping the other Nanostations on the mesh network:

root@OpenWrt:~# ping
PING ( 56 data bytes
64 bytes from seq=0 ttl=64 time=5.759 ms
64 bytes from seq=1 ttl=64 time=5.092 ms

Batman can also give you some statistics:

root@OpenWrt:~# batmand -c -d 1

  Originator  (#/255)         Nexthop [outgoingIF]:   Potential nexthops ... [B.A.T.M.A.N. 0.3-beta, MainIF/IP: ath0/, UT: 0d 0h18m]     (230) [      ath0]: (230) (184)     (245) [      ath0]: (245) (214)

4/ To maximise the traffic through B we need to Force mesh to take A-B-C path (removing any direct links between A&C in the mesh) using iptables rule on A:

iptables -A INPUT -m mac --mac-source (mac address of Nanostation C) -j DROP

It is sufficient to add this iptables rule to only one NS2 (either A or C), because this forces batmand to see the link A <-> C as completely asymmetric - and hence ignore it completely.

While setting up this firewall rule run"

batmand -c -d 1

in another telnet session and watch the path change.

5/ Set up the network on x86 Asterisk boxes A & C. (Note David actually used an IP04 for Asterisk C, but any x86 box should be OK). All of the codec transcoding only occurs on Asterisk A so this should be the fastest box. Asterisk A & C should be connected to the LAN and have have their Ethernet interfaces configured with the IPs in the figure above.

Set up the Ethernet interfaces and routes as follows. If eth0 is already used set up an IP alias (e.g. use eth0:0 or eth0:1 instead of eth0).

(Asterisk A):

$ ifconfig eth0 netmask
$ route add -net gw
$ route add -net gw

(Asterisk B):

$ ifconfig eth0:1 netmask
$ route add -net gw

Check routes by pinging:

(Asterisk A):

$ ping
$ ping

(Asterisk B):

$ ping

Check that mesh network routes packets from A-C via B:

(Asterisk A):

$ ping -R
PING ( 56(124) bytes of data.
64 bytes from icmp_seq=1 ttl=61 time=5.28 ms

$ traceroute
traceroute to (, 30 hops max, 40 byte packets
 1 (  1.241 ms  0.798 ms  0.770 ms
 2 (  2.550 ms  2.576 ms  3.820 ms
 3 (  4.717 ms  4.168 ms  4.340 ms
 4 (  5.719 ms  4.488 ms  4.443 ms

Configuring Asterisk

1/ Install Asterisk on x86 A & C as per Configuring an x86 Asterisk box. Connect a SIP device (ATA or SIP phone) to Asterisk A and check you can make calls to Asterisk A from the SIP phone. An example sip.conf fragment for the SIP device is in Asterisk Configuration and Testing above.

2/ Lets set up a SIP trunk between Asterisk A and Asterisk C.

(Asterisk A), to the bottom of /etc/asterisk/sip.conf add:



The first trunk (ast) is used to route calls between Asterisk A to Asterisk C. We will use this to load X=15 calls on the mesh network. The second trunk (potato) is used to route calls between Asterisk A and simulated potato B, this will just carry a single call to exercise Asterisk on the potato.

The allow=gsm:80 selects just the GSM codec using 80ms RTP packets. We are using GSM for initial testing as it uses less CPU than Speex.

We also need some dialplan entries for Asterisk A, place this code in the [default] section of /etc/asterisk/extensions.conf:

exten => 2008,1,Background(demo-instruct)
exten => 2008,2,Goto(2008,1)

exten => 2050,1,Dial(SIP/ast/600)
exten => 2065,1,Dial(SIP/ast/2008)
exten => 2070,1,Dial(SIP/potato/600)

Extension 2008 provides a source of audio for when we set up simulated calls. Extension 2050 is used to dial extension 600 on Asterisk C, and 2070 is used to dial extension 600 on potato B.

(Asterisk C), to the bottom of /etc/asterisk/sip.conf add:


This implements the SIP trunk between Asterisk A & C. We also need to set up extensions 600 and 2008 in the dial plan of Asterisk C (/etc/asterisk/extensions.conf):

exten => 600,1,Answer
exten => 600,2,Echo()
exten => 2008,1,Background(demo-instruct)
exten => 2008,2,Goto(2008,1)

3/ Start Asterisk on box Asterisk A & C:

# asterisk
# asterisk -r

(You could also use "asterisk -vvvvc" for non-daemon mode). Check that the SIP trunk is working:

ip04*CLI> sip show peers
Name/username              Host            Dyn Nat ACL Port     Status 
ast/ast                            5060     OK (5 ms) 

Now try to make a call between Asterisk A and C. Using your SIP device, dial 2050. The call should go through and you should hear your voice echoed back to you. You can see the status of the call on either Asterisk box:

ip04*CLI> sip show channels
Peer             User/ANR    Call ID      Seq (Tx/Rx)  Form  Hold     Last Message       ast         212175e7236  00101/00103  gsm   No       Rx: ACK
1 active SIP channel

When you dial 2008 you should hear an Asterisk prompt played to you, by Asterisk A.

When you dial 2065 you should hear an Asterisk prompt played to you, by Asterisk C via the SIP trunk.

"set verbose 5" can be useful to track down any problems.

4/ Configuring Potato (Nanostation) B. Set up a SIP trunk and dialplan entry:

exten => 600,1,Answer
exten => 600,2,Oslec

The Oslec application is like "Echo" above, however it runs the Oslec echo canceller, loading the Atheros CPU. Now start Asterisk on the Nanostation and check the SIP trunk (Note: Asterisk may take a minute to start, especially if you don't have DNS set up):

# killall -9 asterisk
# asterisk -vvvc
*CLI> sip show peers
Name/username              Host            Dyn Nat ACL Port     Status 
potato/potato                      5060     OK (6 ms) 
1 sip peers [Monitored: 1 online, 0 offline Unmonitored: 0 online, 0 offline]

Try making a test call to the potato using your SIP device via Asterisk A, by dialling 2070. The Oslec test application responds to 3 command that you can dial on your phone keypad:

  • 1 switches on the echo canceller (default). When you talk into your phone you should hear very silence coming back if the echo canceller is working. The Oslec application uses the maximum CPU in this mode, which is what we want for load testing.
  • 2 switches off the echo canceller. You will hear you voice being echoed back to you. The Oslec application uses minimal CPU in this mode.
  • 3 resets the echo canceller states (filter coefficients). If in mode 1 when you press 3 you will hear echo for a short time before the echo canceller converges again.

5/ Finally we can perform the load test!

Set up 15 SIP calls across the mesh from the Asterisk A CLI:

bunny*CLI> originate SIP/ast/600 extension 2008

This connects extension 600 on Asterisk C to the stored prompt on extension 2008, creating a SIP call with full duplex audio across the mesh. Repeat the above "originate" step 15 times, then check how many calls are running:

ip04*CLI> show channels

Running iptraf (or the tool of your choice) on Asterisk A can show the packets and bits flowing across the LAN:

Iptraf load test.png

Now place a call from your SIP device to the Potato B, by dialling 2070. Run the Oslec Application, and check the speech quality of the returned audio (e.g. for break up). Hang up and try dialling 2050 or 2065, check the audio quality. Ideally the audio quality should be high, with no break up of audio.

If you have two line SIP phone (or an extra SIP device), try setting up simultaneous calls to Asterisk C and Potato B.


With 15 SIP/gsm or 15 SIP/Speex calls being routed through Potato B plus one GSM (or Speex) call to Potato B, the speech quality of the test calls was fine. No evidence of audio break up or CPU overload. The loadav of Potato B was around 0.7 after several hours of continuous operation.

These results were achieved using 80ms RTP packets. With the default 20ms packets the Potato B command line response was very slow, and loadav quite high, suggesting CPU overload.

We also increased the number of simultaneous calls up to 45 using GSM with 80ms audio payload per package. Sound quality degraded but still seemed usable with some clicking sounds. The CPU load on the DIR-300 that Elektra used for the tests was mainly caused by soft interrupts (~77% of the total load, read with the command top), which are triggered by the WiFi interface for every incoming and outgoing packet.

Even with GSM at 80ms the voice data payload embedded in the UDP packets is merely 144 Bytes. The total packet size on the ethernet interface of Asterisk-PC A was 186 Byte. Increasing the length of audio data would reduce the number of interrupts and the overhead on the WiFi layer / radio channel. The MAC protocol of WiFi cards has to coordinate time slots for every transmission using CSMA/CA (Carrier Sense Multiple Access/Collision Avoidance).

  • Before a card can transmit, it has to listen to the radio channel to see whether it is in use.
  • If it doesn't detect a signal it will transmit the packet.
  • If it detects a signal, it will wait until the current signal has stopped. Then further wait for another random time interval (contention window) which is (0-15 * 20us) slot size (or 50us slot size depending on the modulation/bitrate). If the channel is still idle after the contention window is finished it can transmit. If there is a signal on the channel during the contention window it will again wait for the signal to end, calculate a random contention window a.s.o.

Hence with many short packets on the channel we will lose capacity for CSMA/CA and increase jitter - because it can happen that a card has to wait for multiple contention windows before it can transmit. So in order to increase stability and robustness, reduce jitter longer audio pieces are preferable.

Further we have experimented with longer audio chunks (100ms, 120ms, 180ms, 200ms). With 100ms audio chunks the situation improved and the number of calls increased. Audio was still usable with 53 calls. However CPU load went up when we increased the length to more than 100ms, there seems to be a software problem with longer audio chunks using GSM. (Not yet tested with Speex).