LPCNet meets Codec 2

The previous post described my attempts to come up to speed with NN based speech synthesis, with the kind help of Jean-Marc Valin and his LPCNet system.

As an exercise, I have adapted LPCNet to use Codec 2 features, and have managed to synthesise high quality speech at a sample rate of 8kHz. Here are the output speech samples:

Sample original LPCNet Codec 2
cq_ref Listen Listen
hts1a Listen Listen
hts2a Listen Listen
mmt1 Listen Listen
morig Listen Listen
speech_orig Listen Listen

I’m happy with all of the samples except cq_ref. That sample has a lot of low freq energy (like the pitch fundamental) which may not have been well represented in the training database. mmt1 has some artefacts, but this system already does better than any other low rate codec on this sample.

This is not quite a quantised speech codec, as I used unquantised Codec 2 parameters (10 Line Spectral Pairs, pitch, energy, and a binary voicing flag). However it does show how LPCNet (and indeed NN synthesis in general) can be trained to use different sets of input features, and the system I have built is close to an open source version of the Codec 2/NN system presented by Kleijn et al.

Why 8kHz rather than the higher quality 16 kHz? Well LPCNet requires a set of Linear Prediction Coefficients (LPCs). The LPCs dumped by Codec 2 are sampled at 8kHz. It’s possible, but not straight forward, to resample the LPC spectra at 16 kHz, but I chose to avoid that step for now.


My initial attempts led to good quality speech using samples from within the training database, but poor quality on speech samples (like the venerable hts1a) from outside the training database. In Machine Learning land, this suggests “not enough training data”. So I dug up an old TIMIT speech sample database, and did a bunch of filtering on my speech samples to simulate what I have seen from microphones in my Codec 2 adventures. It’s all described in gory detail here (Training Tips section). Then, much to my surprise, it worked! Clean, good quality speech from all sorts of samples.

Further Work

  • Add code to generate 16 kHz LPCs from 8 kHz LPCs and try for 16 kHz synthesised speech
  • Use quantised Codec 2 parameters from say Codec 2 2400 or 1300 and see how it sounds.
  • Help Jean-Marc convert LPCNet to C and get it running in real time on commodity hardware.
  • Make a real world, over the air contact using NN based speech synthesis and FreeDV.
  • A computationally large part of the LPCNet (and indeed any *Net speech synthesis system) is dedicated to handling periodic pitch information. The harmonic sinusoidal model used in Codec 2 can remove this information and hence much of the CPU load. So a dramatic further reduction in the number of weights (and hence CPU load) is possible, although this may result in some quality reduction. Another way of looking at this (as highlighted by Jean-Marc’s LPCNet paper) is “how do we model the excitation” in source/filter type speech systems.
  • The Kleijn et al paper had the remarkable result that we can synthesise high quality speech from low bit rate Codec 2 features. What is quality trade off between the bit rate of the features and the speech quality? How coarsely can we quantise the speech features and still get high quality speech? How much of the quality is due to the NN, and how much the speech features?

Reading Further

Jean Marc’s blog post on LPCNet, including links to LPCNet source code and his ICASSP 2019 paper.
WaveNet and Codec 2
Source Code for my Codec 2 version of LPCNet

LPCNet – Open Source Neural Net Speech Synthesis

Jean-Marc Valin has been working on Neural Network (NN) based speech synthesis in his project called LPCNet. It has similar speech quality to Wavenet, but is based on an architecture called WaveRNN, and includes many new innovations.

Jean-Marc’s work is aimed at reducing the synthesis CPU load down to the level of a modern CPU, for example a mobile phone or Raspberry Pi, and he has made significant progress in that direction.

As well as being useful for his research – this code is a working, open source reference system for Neural Net (NN) based synthesis projects. He has also written an ICASSP 2019 paper on LPCNet, which explains many of the finer details of NN speech synthesis. Fantastic resources for other people coming up to speed in NN synthesis. Well done Jean-Marc!

Over the past few weeks Jean-Marc has kindly answered many NN-noob questions from me. I have used the answers to comment his code and add to his README. There are still many aspects of how this code works that I do not understand. However I can drive his software well enough to synthesise high quality speech:

The first sample was from inside the training database, the second outside.

The network is driven by some speech codec like parameters, but it’s not actually running as a speech codec at present. However it’s a great starting point for high quality speech (de)coding, or indeed speech synthesis.

How I trained

My GTX1060 GPU isn’t quite up to spec, so for training I had to reduce the batch_size to 16, and run for 60 epochs. I used the TSP speech database discussed in the LPCNet README, and followed Jean-Marc’s suggestion of resampling it twice (once at +5% Fs, once at -5% Fs), to get 3x the training data. It took 14 hours for me to train. Synthesis runs 10 times slower than real time on my GPU, however much of this is overhead. If the Keras code was ported to C – it would be close to real time on a modern laptop/phone CPU.


Jean Marc’s blog post on LPCNet, including links to LPCNet source code and his ICASSP 2019 paper.
WaveNet and Codec 2
FFTNet, some good figures that helped me get my head around the idea of sampling a probability distribution.

Simple Keras “Hello World” Example – Mean Removal

Inspired by the Wavenet work with Codec 2 I’m dipping my toe into the word of Deep Learning (DL) using Keras. I’ve read Deep Learning with Python (quite an enjoyable read) and set up a Linux box with a GTX graphics card that is making my teenage sons weep with jealousy.

So after a couple of days of messing about here is my first “hello world” Keras example: mean_removal.py. It might be helpful for other Keras noobs. Assuming you have all the packages installed, it runs with either Python 2:

$ python mean_removal.py

Or Python 3:

$ python3 mean_removal.py

It removes the mean from vectors, using just a single layer regression model. The script runs OK on a regular PC without a chunky graphics card.

So I start by generating vectors from random numbers with a zero mean. I then add a random offset to each sample in the vector. Here are 5 vectors with random offsets added to them:

The Keras script is then trained to estimate and remove the offsets, so the output vectors look like:

Estimating the offset is the same as finding the “mean” of the vector. Yes I know we can do that with a “mean” function, but where’s the fun in that!

Here are some other plots that show the training and validation measures, and error metrics at the output:

The last two plots show pretty much all of the offset is removed and it restores the original (non offset) vectors with just a tiny bit of noise. I had to wind back the learning rate to get it to converge without “NAN” losses, possibly as I’m using fairly big input numbers. I’m familiar with the idea of learning rate from NLMS adaptive filters, such as those used for my work in echo cancellation.

Deep Learning for Codec 2

My initial ambitions for DL are somewhat more modest than the sample-by-sample synthesis used in the Wavenet work. I have some problems with Vector Quantisation (VQ) in the low rate Codec 2 modes. The VQ is used to compactly describe the speech spectrum, which carries the intelligibility of the signal.

The VQ gets upset with different microphones, speakers, or minor spectral shaping like gentle high pass/low pass filtering. This shaping often causes a poor vector to be chosen, which results in crappy speech quality. The current VQ error measure can’t tell the difference between spectral features that matter and those that don’t.

So I’d like to try DL to address those issues, and train a system to say “look, this speech and this speech are actually the same. Yes I know one of them has a 3dB/octave low pass filter, please ignore that”.

As emphasised in the text book above, some feature extraction can help with DL problems. For my first pass I’ll be working on parameters extracted by the Codec 2 model (like a compact version of the speech spectrum) rather than speech samples like Wavenet. This will reduce my CPU load significantly, at the expense of speech quality, which will be limited by the unquantised Codec 2 model. But that’s OK as a first step. A notch or two up on Codec 2 at 700 bit/s would be very useful, especially if it can run on a CPU from the first two decades of the 21st century.

Mean Removal on Speech Vectors

So to get started with Keras I chose mean removal. The mean level or constant offset is like the volume or energy in a speech signal, its the simplest form of spectral shaping I could imagine. I trained and tested it with vectors of random numbers, using numbers in the range of the speech spectral samples that Codec 2 plays with.

It’s a bit like an equaliser, vectors with arbitrary spectral shaping go in, “flat” unshaped vectors come out. They can then be sent to a Vector Quantiser. There are probably smarter ways to do this, but I need to start somewhere.

So as a next step I tried offset removal with vectors that represent the spectrum of 40ms speech frame:

This is pretty cool – the network was trained on random numbers but works well with real speech frames. You can also see the spectral slope I mentioned above, the speech energy gradually falls off at high frequencies. This doesn’t affect the intelligibility of the speech but tends to upset traditional Vector Quantisers. Especially mine.

Now that I have something super-basic working, the next step is to train and test networks to deal with some non-trivial spectral shaping.

Reading Further

Deep Learning with Python
WaveNet and Codec 2
Codec 2 700C, the current Codec 2 700 bit/s mode. With better VQ we can improve on this.
Codec 2 at 450 bit/s, some fine work from Thomas and Stefan, that uses a form of machine learning to synthesise 16 kHz speech from 8 kHz inputs.
FreeDV 700D, the recently released FreeDV mode that uses Codec 2 700C. A FreeDV Mode also includes a modem, FEC, protocol.
RNNoise: Learning Noise Suppression, Jean-Marc’s DL network for noise reduction. Thanks Jean-Marc for the brainstorming emails!

Self Driving Cars

I’m a believer in self driving car technology, and predict it will have enormous effects, for example:

  1. Our cars currently spend most of the time doing nothing. They could be out making money for us as taxis while we are at work.
  2. How much infrastructure and frustration (home garage, driveways, car parks, finding a park) do we devote to cars that are standing still? We could park them a few km away in a “car hive” and arrange to have them turn up only when we need them.
  3. I can make interstate trips laying down sleeping or working.
  4. Electric cars can recharge themselves.
  5. It throws personal car ownership into question. I can just summon a car on my smart phone then send the thing away when I’m finished. No need for parking, central maintenance. If they are electric, and driverless, then very low running costs.
  6. It will decimate the major cause of accidental deaths, saving untold misery. Imagine if your car knew the GPS coordinates of every car within 1000m, even if outside of visual range, like around a corner. No more t-boning, or even car doors opening in the path of my bike.
  7. Speeding and traffic fines go away, which will present a revenue problem for governments like mine that depend on the statistical likelihood of people accidentally speeding.
  8. My red wine consumption can set impressive new records as the car can drive me home and pour me into bed.

I think the time will come when computers do a lot better than we can at driving. The record of these cars in the US is impressive. The record for humans in car accidents dismal (a leading case of death).

We already have driverless planes (autopilot, anti-collision radar, autoland), that do a pretty good job with up to 500 lives at a time.

I can see a time (say 20 years) when there will be penalties (like a large insurance excess) if a human is at the wheel during an accident. Meat bags like me really shouldn’t be in control of 1000kg of steel hurtling along at 60 km/hr. Incidentally that’s 144.5 kJ of kinetic energy. A 9mm bullet exits a pistol with 0.519 kJ of energy. No wonder cars hurt people.

However many people are concerned about “blue screens of death”. I recently had an email exchange on a mailing list, here are some key points for and against:

  1. The cars might be hacked. My response is that computers and micro-controllers have been in cars for 30 years. Hacking of safety critical systems (ABS or EFI or cruise control) is unheard of. However unlike a 1980’s EFI system, self driving cars will have operating systems and connectivity, so this does need to be addressed. The technology will (initially at least) be closed source, increasing the security risk. Here is a recent example of a modern car being hacked.
  2. Planes are not really “driverless”, they have controls and pilots present. My response is that long distance commercial aircraft are under autonomous control for the majority of their flying hours, even if manual controls are present. Given the large number of people on board an aircraft it is of course prudent to have manual control/pilot back up, even if rarely used.
  3. The drivers of planes are sometimes a weak link. As we saw last year and on Sep 11 2001, there are issues when a malicious pilot gains control. Human error is also behind a large number of airplane incidents, and most car accidents. It was noted that software has been behind some airplane accidents too – a fair point.
  4. Compared to aircraft the scale is much different for cars (billions rather than 1000s). The passenger payload is also very different (1.5 people in a car on average?), and the safety record of cars much much worse – it’s crying out for improvement via automation. So I think automation of cars will eventually be a public safety issue (like vaccinations) and controls will disappear.
  5. Insurance companies may refuse a claim if the car is driverless. My response is that insurance companies will look at the actuarial data as that’s how they make money. So far all of the accidents involving Google driverless cars have been caused by meat bags, not silicon.

I have put my money where my mouth is and invested in a modest amount of Google shares based on my belief in this technology. This is also an ethical buy for me. I’d rather have some involvement in an exciting future that saves lives and makes the a world a better place than invest in banks and mining companies which don’t.

Degrowth Economy

Just read this article: Life in a de-growth economy and why you might actually enjoy it.

I like the idea of a steady state economy. Simple maths shows how stupid endless growth is. And yet our politicians cling to it. We will get a steady state, energy neutral economy one day. It’s just a question of if we are forced, or if it’s managed.

Some thoughts on the article above:

  • I don’t agree that steady state implies localisation. Trade and specialisation and wonderful inventions. It’s more efficient if I write your speech coding software than you working it out. It’s for more efficient for a farmer to grow food than me messing about in my back yard. What is missing is a fossil fuel free means of transport to sustain trade and transportation of goods from where they are efficiently produced to where they are consumed.
  • Likewise local food production like they do in Cuba. Better to grow lots of food on a Cuban farm, they just lack an efficient way to transport it.
  • I have some problems with “organic” food production in the backyard, or my neighbours backyard. To me it’s paying more for chemically identical food to what I buy in the supermarket. Modern, scientific, food production has it’s issues, but these can be solved by science. On a small scale, sure, gardening is fun, and it would be great to meet people in communal gardens. However it’s no way to feed a hungry world.
  • Likewise this articles vision of us repairing/recycling clothing. New is still fine, as long as it’s resource-neutral, e.g. cotton manufactured into jeans using solar powered factories, and transported to my shopping mall in an electric vehicle. Or synthetic fibres from bio-fuels or GM bacteria.
  • Software costs zero to upgrade but can improve our standard of living. So there can be “growth” in some sense at no expense in resources. You can use my speech codec and conserve resources (energy for transmission and radio spectrum). I can send you that software over the Internet, so we don’t need an aircraft to ship you a black box or even a CD.

I live by some anti-growth, anti-consumer principles. I drive an electric car that is a based on a 25 year old recycled petrol car chassis. I don’t have a fossil fuel intensive commute. I use my bike more than my car.

I work part time from home mainly on volunteer work. My work is developing software that I can give away to help people. This software (for telecommunications) will in turn remove the need for expensive radio hardware, save power, and yet improve telecommunications.

I live inexpensively compared to my peers who are paying large mortgages due to the arbitrarily high price of land here, and other costs I have managed to avoid or simply say no to. No great luck or financial acumen at work here, although my parents taught me the useful habit of spending less than I earn. I’m not a very good consumer!

I don’t aspire to a larger home in a nice area or more gadgets. That would just mean more house work and maintenance and expense and less time on helping people with my work. In fact I aspire to a smaller home, and less gadgets (I keep throwing stuff out). I am renting at the moment as the real estate prices here are spiralling upwards and I don’t want to play that game. Renting will allow me to down-shift even further when my children are a little older. I have no debt, and no real desire to make more money, a living wage is fine. Although I do have investments and savings which I like tracking on spreadsheets.

I am typing this on a laptop made in 2008. I bought a second, identical one a few years later for $300 and swap parts between them so I always have a back up.

I do however burn a lot of fossil fuel in air travel. My home uses 11 kWhr/day of electricity, which, considering this includes my electric car and hence all my “fuel” costs, is not bad.


In the past I have written about why I think economic growth is evil. There is a lot of great information on this topic such as this physics based argument on why we will cook (literally!) in a few hundred years if we keep increasing energy use. The Albert Bartlett lectures on exponential growth are also awesome.

Hybrid Optical-Microwave Communications

A few weeks ago I visited the ITR at the University of South Australia, where I studied some time ago. My former PhD superviser, Bill Cowley is part of a team working on a interesting new hybrid optical/microwave communications scheme.

Their reasoning is that spectrum is becoming more and more congested. Free Space Optical (FSO) communications offers a great way to increase bandwidth. Free space means sending light signals through the air rather than through a fibre, for example over a distance of 10km. Like Wifi, but at higher (optical) frequencies, and with potentially enormous bandwidth for data.

The have a really neat trick – combining the FSO link with a regular microwave link, with Forward Error Correction (FEC) applied across the combined channels. This makes a system that is more robust than either link alone. The two channels have complimentary properties. For example if cloud affect the FSO link, the microwave link will be less affected.

I think this is a really novel idea. Normally FEC bits are sent through the same channel, e.g. on a CD extra bits on the disk are used to protect the music recording on the same disk from errors (like a scratch). On your cell phone both the speech data and the error protection bits pass through the same radio channel. With this scheme it’s like a DVD is combined with a CD to protect against bit errors.

Here is a picture of the optical part of the link, in a small room on the top of the ITR building:

The ‘receiver’ on the left hand side is a home-brew design based on 150mm Fresnel lens; the telescope of the right is a 125mm Meade which can either be used in visible wavelengths (via the web cam directly behind the scope) or at 1550 nm (detector and IR camera attached to the T splitter). The link extends over a 12km path to a site in the Adelaide Hills.

More information on the ITR’s FSO page. Thanks Bill for showing me the system and providing information for this post.

Baboons, Mesh networks, and Community

At both Village Telco Workshops I had the pleasure of meeting David Carman and Antoine van Gelder, who founded and now administer the Scarborough Wireless User Group (SWUG). Scarborough is located almost on the southern tip of Africa, on the edge of Cape Town, South Africa.

SWUG uses a mesh network to provide Internet access to people in Scarborough, as DSL is largely unavailable. DSL is connected at one edge of the mesh, and is then distributed throughout Scarborough and some neighboring villages. Users buy their own routers and local youth have been trained to flash and install the routers as mesh nodes.

The mesh network also provides connectivity to those who couldn’t otherwise afford it, and to kids whose parents don’t wish to pay for Internet. The result is wider access which promotes greater community participation in local applications.

Subscription payments are voluntary, with paying traffic prioritized over non-paying. This has worked surprisingly well to ensure that everyone gets access and we are able to afford sufficient bandwidth. The accounting system is fully automated (using bank deposit email notifications), so administration is hands-free and anonymous. The accounting system removes what would otherwise be a serious admin burden. It uses pmacct and changes iptables rules on the fly.

David has installed several communication forums (including phpbb, mediawiki, argwatch). Mailman is most effective. Email is the preferred modality for the naive user and mailman works well for the naive moderator. However the kids on the mesh appear to be using Facebook to organise themselves!

SWUG has lead David and Antoine into some interesting projects.

They have written a very cool application called ArgusWatch to track incursions of Baboons into the community! The Baboons have a habit of sneaking into peoples homes and making a big mess. One thing that fascinates me is how “local” this application is. We are used to most web apps having a global audience. Makes me think there must be many very useful, very local applications that could be written to address local community issues.

David has become skilled at real world mesh network issues like Wifi propagation and is a strong contributor to the Village Telco project. Antoine has been very busy building Afrimesh, a GUI for the Village Telco that is now running on the Mesh Potato. Funny how these community projects change the direction of our lives. I started out messing around with Asterisk on a DSP chip in 2005 and some how I now build Mesh Potatoes!

Talking to David got me thinking about mesh networks and community.

Now a community used to be something local, for example I might get together with other parents from my daughters school and work together to get a school crossing installed. Local people with a common interest working together. A social organization with social aims, compared to say a business organisation that has business goals.

Then the Internet came along and widely dispersed people with common interests could be connected. So now we have widely separated people with a common interest working together. A good example ais the Open Hardware projects I have been working on as part of the Free Telephony Project. Individuals from Canada, China, Bulgaria, Australia working together to develop complex telephony hardware designs. Together we built leading edge IP-PBX technology – as good or better than products coming from giant hardware companies. One example is the BlackfinOne – a community built open hardware Linux board, forerunner to the IP04:

Mesh networks close the circle. A mesh network depends on neighbors working together. My Internet comes via my neighbor’s router. There is a dependency that encourages people to work together and help each other (even if only by leaving their router on). So just like the first example we have local people working together, but this time facilitated by Internet technology. SWUG is a social enterprise that outperforms the incumbent Telco in delivery of broadband to the people of Scarborough.

In my travels to East Timor I found an interesting counter-example. East Timor has very little local Internet infrastructure and very little local content. Most of the Internet traffic goes straight up a satellite dish to ISPs in other countries. I found no examples of IP traffic going from a browser to a web server in East Timor – it all left the country as a first step. As you can image the cost of accessing information on the Internet is prohibitive ($5-10/hour where people would be lucky to earn that in a week). I wonder what that does to a community?


Thanks David Carman for checking this post and providing additional details of SWUG.

Kjell Aleklett Lecture

Yesterday I took a much needed break from Mesh Potato hacking and pedaled into Adelaide University to see a lecture by Kjell Aleklett, who is the president of the Association for the Study of Peak Oil and Gas who is visiting Australia this week.

Couple of important points that I took away:

  1. Kjell explained the physical process by which oil percolates through porous stone to oil wells – he then made the point that economists think that oil flows are propelled by money, not physical processes. In other words economists (and therefore governments) think money can overcome physical supply problems. Oops.
  2. The estimates of greenhouse gas emissions and hence global warming are based on continued growth of fossil fuel use. However these estimates do not take into account the actual peaking of oil, gas, and coal supplies. When the limited supply situation of fossil fuels are modeled, greenhouse emissions are constant over the next 50 years. If fossil fuel supply is limited, you limit huge increases in carbon dioxide concentrations.
  3. All current economic models assume unlimited future growth. Growth requires fossil fuels, which are reaching the limits of physical supply. For example if our population increases, we need a new suburb, and new cars to handle commuting. So if fossil fuels are limited, this means that from now on economic growth will be curtailed. No economic growth means the current economic systems break.


My original post on Peak Oil.

Some thoughts on our obsession with economic growth.

East Timor – OLPC Pilot

One of the main reasons for the February East Timor trip was to assist the Seaton OLPC group investigate a possible OLPC pilot later this year. Here are some thoughts based on my experiences with the OLPC in East Timor:

  1. Everyone we met who saw and played the XO’s (teachers, students of all ages) “got it” – they worked out how to drive the laptops quickly and could see great benefit to Timor. Their eyes lit up with the possibilities!
  2. Education is generally of a poor standard, is non-compulsory and it not widely encouraged by parents. If students don’t want to go, they don’t go and no one really cares. However education would greatly benefit Timor and help resolve some of the nasty social and violence problems lurking under the surface (75% unemployment, afternoon drunkenness of teenagers, teenage pregnancy and resulting high birth rate).
  3. School is boring in Timor. It is taught in Portuguese (to students whose native language is Tetun) with inadequate books (not enough and poor quality) via rote learning. XOs would make it fun.
  4. I have no doubt teachers and students alike would quickly come up to speed with XOs. Where we need to work is on integrating the XO into teaching – for example lesson plans for the next 6 months that can be agreed upon with the teachers.
  5. Cultural: There is a family pecking order in society of Father-Mother-then children in descending age order. For example Dad eats first and young children get whats left over. This means if an XO is taken home, a child’s bigger brother will be within his rights to grab it for himself. This may be a good thing (spreading laptop usage around the family) as long as it makes it back to school. Will the XO be valued and cared for in the home? Possibly – it may be viewed as a status symbol like satellite TV or a mobile phone. Status is big there – a person with no income will have a mobile phone. They will sleep on a dirt floor, have no proper kitchen or toilet but have satellite TV – a big dish standing next to a Gilligan’s Island type hut made of palm leaves.
  6. I have no doubt that introducing these laptops to classrooms will be very beneficial to students and teachers alike. The XO will literally change the course of the lives it touches. We should work together to make a pilot deployment happen ASAP.


East Timor – We really do have road rules now!
East Timor – Cultural and IT

Prototype Village Telco Raided

Dabba are a South African company that have been operating a prototype Village Telco network in the Orange Farm township near Johannesburg. It’s fair to say that Dabba inspired much of the Village Telco project. They use unlicensed 2.4 GHz spectrum to run VOIP over Wifi links. The result is disadvantaged people get a telephone at a reasonable cost.

A few days ago the South African communications regulator (ICASA) confiscated Dabba’s Wifi equipment with zero notice. Just stompted in and took it, apparently based on a complaint by the incumbent South African Telco (Telkom) regarding interference. There has been no explanation by ICASA of the actual technical problem, and no evidence of any interference. The Wifi equipment was type approved (this means samples have been rigorously tested to prove they do not interfere with other services).

Dabba was proving Internet and Phone service to a skills development centre, an aids orphanage, and an Internet cafe. On line communities are outraged. Given the amount of evidence provided it sounds like Telkom made an unsubstantiated claim and the regulator jumped in prematurely using a very heavy hand.

The good news is that Rael from Dabba is determined to rebuild the network ASAP – well done Rael and I hope we get some clarity (or an apology) from ICASA soon.


ICASA – Stealing from AIDS Orphans

IT Web article

Village Telco Google Group Thread on Dabba Wifi Confiscation