Rádio é algo com que eu gostaria de ter brincado mais. Por diversas razões, esse interesse está sempre enterrado lá no fundo das coisas por fazer um dia, e pelo andar da carruagem talvez nunca chegue a fazê-lo. Vou me consolando com código Morse e ouvindo ondas curtas, e NDBs aeronáuticos.
Para um sinal, uma informação útil, viajar sobre ondas de rádio, ela precisa ser modulada. Modular é transpor o sinal para uma banda de freqüência e formato compatíveis com o meio de transmissão. As técnicas de modulação são unha e carne com telecomunicações e teoria da informação, e é possível brincar com modulação, ou pelo menos simulá-la, num computador. Não sou um engenheiro de telecomunicações, mas o tema me interessa assim mesmo. A simplicidade do processo faz parecer "milagre".
Neste artigo, vou ilustrar as técnicas de AM — modulação de amplitude ou, como preferem os locutores de rádio da velha guarda, amplitude modulada. Nosso meio de transmissão é o arquivo de áudio WAV. Para começar, precisamos de um sinal de banda-base, isto é, algum áudio que preencha toda a banda desde 0Hz. Gravei minha própria (e desagradável) voz para este fim:
A largura de banda ou espectro de freqüências deste áudio é:
A parte amarela do espectro é a mais relevante, já que o eixo Y é logarítmico (dB). Um sinal 30 decibels mais fraco é 1000 vezes mais fraco. O espectro acima de 5000Hz é basicamente "ruído digital", não é a voz. Nas próximas figuras, vou cortar fora a parte baixa do gráfico. (Se você for curioso, ou não confia nos meus gráficos, você pode fazer o download dos arquivos WAV e analisar o espectro no seu aplicativo predileto.)
A modulação AM exige que o sinal seja restrito em largura de banda, de modo que o sinal modulado também "caiba" numa faixa de freqüência de rádio. Assim, precisamos aplicar um filtro passa-baixas no meu arquivo de voz, e definimos a freqüência de corte em 1000Hz. O resultado é a mesma voz, porém com menos qualidade.
O espectro deste sinal filtrado é o seguinte:
Fiz uso do plug-in de filtro passa-baixas do Audacity, que não é perfeito mas é suficiente para ilustrar nossa modulação. Em outros artigos, implementarei um filtro do zero, em Python.
Modulação de amplitude é matematicamente muito simples: basta multiplicar o sinal original por uma onda senoidal contínua, conhecida como portadora. No nosso caso, escolhi uma portadora de 3000Hz, bem acima do corte do sinal original que foi 1000Hz. O ruído da portadora pura parece um assobio:
O resultado da modulação (voz multiplicada pela portadora) é:
Note que é quase impossível entender a palavra falada no áudio modulado. Para ser preciso, este tipo de modulação é denominado AM-SC (AM-Suppressed Carrier, ou Modulação de Amplitude com Portadora Suprimida), por uma razão que vou esclarecer mais adiante.
A modulação pega minha voz, cuja banda era 0-1000Hz, e move para 2000-4000Hz. Além de deslocada, a banda dobrou, porque a modulação AM cria realmente duas "cópias" do sinal original: uma na banda 2000-3000Hz e outra na banda 3000-4000Hz. Assim sendo, a modulação AM "desperdiça" banda porque o sinal modulado ocupa duas vezes mais banda:
Ainda assim, a modulação AM é muito útil, porque ela permite "mover" o sinal sonoro para freqüências que se prestam à transmissão eletromagnética (bastaria escolher uma portadora na faixa de 1MHz). Mais importante, a modulação permite que múltiplos sinais sejam alocados e transmitidos num mesmo meio de transmissão (no caso do rádio, é o "ar", compartilhado por todos os rádios), cada um ocupando sua banda, e cada um pode ser recuperado separadamente.
Como disse, a modulação acima foi AM-SC, que não é utilizada pelas radiodifusoras. A modulação AM para radiodifusão tem o seguinte som:
Nesta modalidade de AM, podemos ouvir a portadora, que não podíamos em AM-SC. O espectro AM de radiodifusão é semelhante ao AM-SC porém possui um "pico" exatamente em cima da freqüência da portadora:
O seguinte programa escrito em Python gerou as modulações AM e AM-SC:
#!/usr/bin/env python import wave, struct, math baseband = wave.open("paralelepipedo_lopass.wav", "r") amsc = wave.open("amsc.wav", "w") am = wave.open("am.wav", "w") carrier = wave.open("carrier3000.wav", "w") for f in [am, amsc, carrier]: f.setnchannels(1) f.setsampwidth(2) f.setframerate(44100) for n in range(0, baseband.getnframes()): base = struct.unpack('h', baseband.readframes(1))[0] / 32768.0 carrier_sample = math.cos(3000.0 * (n / 44100.0) * math.pi * 2) signal_am = signal_amsc = base * carrier_sample signal_am += carrier_sample signal_am /= 2 amsc.writeframes(struct.pack('h', signal_amsc * 32767)) am.writeframes(struct.pack('h', signal_am * 32767)) carrier.writeframes(struct.pack('h', carrier_sample * 32767))
O modulador AM-SC multiplica o sinal original (devidamente limitado em banda por algum filtro) pela portadora, que é uma simples onda senoidal.
A modulação AM de radiodifusão é igual a AM-SC, mas a portadora é adicionada ao resultado final. Isto permite que o receptor AM seja mais simples e barato, conforme veremos.
Muito bem, é hora de provar que podemos recuperar a voz original a partir dos áudios modulados. O demodulador AM-SC é tão simples quanto o modulador: o sinal é novamente multiplicado pela mesma portadora — técnica denominada "detecção por produto". O resultado é passado por um filtro passa-baixas.
Estes são os áudios demodulados, primeiro sem a filtragem final:
E com a filtragem final:
Para quem prefere ver a modulação acontecendo no domínio do tempo, segue as formas de onda da modulação AM-SC. Azul é o sinal original, vermelho é a portadora, roxo é o sinal modulado, verde é o sinal demodulado no receptor.
Note que o sinal modulado AM-SC tem um "envoltório" ou "envelope", ou seja, os picos de onda guardam uma relação com o sinal original, como se fossem envolvidos por ele.
A demodulação AM-SC é igual à modulação, exceto pela filtragem final compulsória. Multiplicar um sinal duas vezes pela mesma portadora transfere o áudio de volta para a sua banda original (0-1000Hz) e cria uma nova cópia em torno de 6000Hz, que deve ser filtrada.
Este é o código do demodulador AM-SC:
modulated = wave.open("amsc.wav", "r") demod_amsc_ok = wave.open("demod_amsc_ok.wav", "w") demod_amsc_nok = wave.open("demod_amsc_nok.wav", "w") demod_amsc_nok2 = wave.open("demod_amsc_nok2.wav", "w") for f in [demod_amsc_ok, demod_amsc_nok, demod_amsc_nok2]: f.setnchannels(1) f.setsampwidth(2) f.setframerate(44100) for n in range(0, modulated.getnframes()): signal = struct.unpack('h', modulated.readframes(1))[0] / 32768.0 carrier = math.cos(3000.0 * (n / 44100.0) * math.pi * 2) carrier_phased = math.sin(3000.0 * (n / 44100.0) * math.pi * 2) carrier_freq = math.cos(3100.0 * (n / 44100.0) * math.pi * 2) base = signal * carrier base_nok = signal * carrier_phased base_nok2 = signal * carrier_freq demod_amsc_ok.writeframes(struct.pack('h', base * 32767)) demod_amsc_nok.writeframes(struct.pack('h', base_nok * 32767)) demod_amsc_nok2.writeframes(struct.pack('h', base_nok2 * 32767))
A nova cópia do sinal em 6000Hz é indesejada, pode ser considerada ruído, e confunde alguns leitores. Eles simulam a demodulação numa planilha Excel e não entendem de onde vem esse componente de alta freqüência.
A figura a seguir mostra o espectro do áudio AM-SC demodulado, antes da filtragem passa-baixas. A parte amarela é a "parte boa":
É interessante usar um pouco de matemática para esclarecer este ponto. Isto aplica-se a AM e também a QAM. O sinal original de áudio, representado pela função f(t), é modulado (multiplicado) por uma cossenóide (a portadora). Assim, o sinal transmitido é f(t).cos(c.t).
A demodulação transforma novamente o sinal para f(t).cos(c.t).cos(c.t). Se relembramos das identidades trigonométricas do colegial, podemos converter a última forma para f(t).[1+cos(2.c.t)] e finalmente para f(t)+[f(t).cos(2.c.t)].
Agora está claro (se você manja de fórmulas) que o sinal demodulado é uma soma de duas partes: o áudio f(t) original (que nós queremos) e o mesmo áudio modulado por uma portadora de 6000Hz (que é indesejável).
Como a freqüência da portadora em aplicações reais é muito mais alta que a largura de banda do sinal base, a parte indesejável cai numa freqüência tão alta que é fácil livrar-se dela usando um filtro passa-baixas extremamente simples. E mesmo que não fosse removida, ninguém ouviria.
Um pequeno grande problema da demodulação AM-SC: a onda da portadora gerada no lado receptor precisa ser exatamente igual à do transmissor, tanto em freqüência quanto em fase. Qualquer diferença destrói a demodulação.
No código Python exibido antes, simulei dois problemas de demodulação: portadora com fase errada (90 graus atrasada) e com freqüência errada (100Hz acima). Os resultados são muito ruins conforme você pode ouvir abaixo (já filtrados). A portadora fora de fase simplesmente não encontra o áudio original; freqüência errada distorce a ponto de tornar incompreensível:
A bem da verdade, uma portadora com desvio menor que 90 graus ainda detectaria o sinal, embora com volume menor (quanto menor o desvio, maior o volume). Assim sendo, podemos usar um demodulador de quadratura (I/Q) que usa duas portadoras defasadas de 90 graus. A combinação dos sinais detectados será sempre o sinal com volume total. Mas a frequência dessas portadoras ainda precisa ser exata.
A modulação AM-SC não fornece uma referência para sincronizar a portadora, o que torna difícil gerar a portadora com as qualidades necessárias. Talvez por conta disso, AM-SC é pouco empregado na prática (*) enquanto AM é amplamente usado.
A propósito, vamos ver como funciona um receptor AM baseado na técnica de "detecção de envelope":
modulated = wave.open("am.wav", "r") f = demod_am = wave.open("demod_am.wav", "w") f.setnchannels(1) f.setsampwidth(2) f.setframerate(44100) for n in range(0, modulated.getnframes()): signal = struct.unpack('h', modulated.readframes(1))[0] / 32768.0 signal = abs(signal) demod_am.writeframes(struct.pack('h', signal * 32767))
Aprecie quão simples ele é; note a ausência de funções trigonométricas. AM de radiodifusão pode ser detectado por um simples diodo, que corta fora a parte negativa da onda. O diodo ainda pode ser improvisado a partir de um cristal de galena ou uma gilete enferrujada.
Faltou conferir o resultado auditivo do detector de envelope:
Depois da filtragem final:
Há um ruído residual causado pelo detector abs(), pois ele cria picos no sinal demodulado. Num rádio AM real, esses picos cairiam numa freqüência muito alta, inaudível e fácil de remover. (Lembrar sempre que estamos usando uma portadora de freqüência relativamente baixa, 3000Hz.)
Formas de onda (domínio do tempo) da modulação AM:
O sinal modulado AM mostra um efeito de envelope mais pronunciado que AM-SC: os picos de onda seguem claramente o contorno do sinal original. Isto torna a demodulação muito fácil, pode acontecer até mesmo acidentalmente, através de uma obturação dentária ou encostando uma folha numa antena de transmissão.
A planilha que gerou as formas de onda acima pode ser abertaaqui.
Um receptor AM não é obrigado a usar a detecção de envelope. Ele pode usar um demodulador "de verdade", tal qual AM-SC. É fácil gerar a portadora no receptor, porque AM transmite a mesma junto com o sinal "útil". Tal receptor tem vantagens em relação ao detector simples: maior resistencia ao ruído e compatibilidade com sinais AM-SC/AM-SSB.
A modulação AM — AM-SC adicionado da portadora — é matematicamente equivalente a adicionar um grande "DC bias" ou valor positivo fixo ao sinal original, e então modular como AM-SC. Isto garante que a portadora seja sempre multiplicada por um valor positivo, e o sinal modulado está sempre em fase com a portadora. A fase do sinal AM não carrega nenhuma informação, e o receptor pode desprezá-la.
Já na modulação AM-SC, o conteúdo original é modulado "como está". Nos momentos em que o sinal de áudio tem polaridade negativa, a saída do transmissor tem polaridade oposta à portadora. Assim sendo, a fase do sinal AM-SC possui uma informação que não pode ser desprezada: a polaridade do sinal.
Se você tentar receber AM-SC com um detector de diodo, a fase e portanto a polaridade é perdida. O resultado será muito distorcido, embora possa fazer lembrar o áudio original. Se era voz humana, soará como o Pato Donald, porque a demodulação incorreta dobra as freqüências e adiciona harmônicas.
AM-SC tem algumas vantagens frente ao AM. Pode transmitir mais informação usando menos banda, e não despende energia enviando a portadora. Outro problema do AM é a forma que ele lida com freqüências muito baixas presentes no conteúdo original, como os graves de subwoofer de uma música. O "DC bias" tem de ser removido em algum ponto da demodulação, e o conteúdo de baixa freqüência será perdido na mesma leva. É um problema sério para transmissão de vídeo, que é mais bem servido por alguma variante de AM-SC.
Ambas as modulações AM e AM-SC "desperdiçam" banda, porque enviam duas "cópias" do mesmo sinal, abaixo e acima da portadora. Podemos eliminar uma delas, transmitindo apenas a outra. Esta modalidade é chamada AM-SSB (Suppressed sideband - banda lateral suprimida).
O espectro de modulação é obviamente diferente de AM-SC. A banda lateral abaixo de 3000Hz está praticamente extinta:
As formas de onda da modulação SSB podem ser vistas abaixo:
Na figura acima, temos dois elementos novos: uma versão 'Hilbert' do sinal original, em vermelho (90 graus adiantado) e uma segunda portadora 'Carrier Q' em amarelo, também adiantada. Você pode ignorar estes itens por ora; eles farão sentido mais adiante, quando falarmos da transformada de Hilbert.
Bem diferente de AM e AM-SC, o sinal modulado SSB não apresenta um envelope, apesar de ainda ser proporcional à amplitude do sinal original (0.5). Como o sinal original é uma senóide "pura", a onda modulada também é "pura", com freqüência muito próxima à portadora. Isto é congruente com o fato da modulação SSB ser uma translação perfeita do sinal original para outra banda, sem gerar cópias adicionais nem distorções.
O áudio a seguir ilustra como soa uma modulação AM-SSB (banda inferior removida, banda superior mantida):
Não é muito diferente de AM-SC, e de fato o demodulador AM-SC é capaz de processar o sinal AM-SSB sem qualquer modificação:
Ops, faltou a filtragem passa-baixas depois da demodulação:
Transmitindo apenas uma cópia do conteúdo original, e não tendo de transmitir a portadora, o sinal AM-SSB é econômico tanto em banda quanto em energia. Ele tem uma segunda grande vantagem sobre AM-SC. Veja o que acontece quando demodulamos um sinal AM-SSB com portadora local fora de fase:
A voz foi recuperada perfeitamente. Assim, fica demonstrado que um receptor AM-SSB não precisa se preocupar com a fase da portadora. Apenas a freqüência é importante, e esta tem de ser muito bem controlada: qualquer desvio causa uma distorção semelhante à que constatamos em AM-SC:
AM-SSB é a modulação padrão em radioamador de longa distância, TV analógica, etc. E a mesma técnica é empregada em multiplexadores FDM e incontáveis outros dispositivos que precisam enviar muitos sinais através de um único canal.
AM-SSB, assim como AM, tem um problema com freqüências muito baixas no sinal original. A TV analógica precisa delas, então emprega a modulação VSB (Vestigial Sideband - banda lateral vestigial). Em VSB, nem toda a banda lateral "excedente" é suprimida; fica o suficiente para que o conteúdo de baixa freqüência seja recebido como AM-SC, com transição para AM-SSB em freqüências mais altas.
Finalmemente, há uma questão de implementação do AM-SSB. É possível remover a banda lateral "excedente" com um filtro analógico, porém tal filtro é difícil de construir (e portanto caro). Mas podemos gerar um sinal SSB sem filtro de saída.
Uma técnica interessante, empregada por rádios com capacidade de processamento digital de sinais (DSP), é a transformada de Hilbert. Essa transformada muda a fase do áudio em 90 graus. Não é um simples atraso fixo; é uma mudança de fase sobre cada freqüência presente no áudio.
O áudio transformado parece exatamente igual ao original, porque nossos ouvidos não percebem diferenças de fase. Porém, graças às identidades trigonométricas, modular o sinal transformado com uma portadora defasada, e adicionar o resultado a um modulador AM-SC, cancela a "cópia" inferior, deixando apenas a banda superior. Obtemos assim um sinal AM-SSB perfeito sem qualquer filtragem.
A transformada de Hilbert é mais facilmente descrita e implementada no domínio da freqüência (usando FFT), mas também pode ser implementada como um filtro FIR (convolução no domínio do tempo). Tal filtro seria "não-causal": ele depende dos valores futuros do sinal para calcular uma saída no presente.
Isso parece absurdo, mas na prática se resolve colocando o filtro para trabalhar no "futuro do pretérito". O único problema é que a saída do filtro tem um certo atraso em relação à entrada — na nossa implementação, 1,13 milissegundo.
O seguinte programa Python implementa o modulador AM-SSB baseado em transformada de Hilbert, este último implementado como um filtro FIR.
#!/usr/bin/env python import wave, struct, math, numpy hlen = 500.0 hilbert_impulse = [ (1.0 / (math.pi * t / hlen)) \ for t in range(int(-hlen), 0) ] hilbert_impulse.extend([0]) hilbert_impulse.extend( [ (1.0 / (math.pi * t / hlen)) \ for t in range(1, int(hlen+1)) ] ) hilbert_impulse = [ x * 1.0 / hlen for x in hilbert_impulse ] baseband = wave.open("amssb_hilbert_orig.wav", "r") amssbh = wave.open("amssb_hilbert.wav", "w") for f in [amssbh]: f.setnchannels(1) f.setsampwidth(2) f.setframerate(44100) base = [] base.extend([ struct.unpack('h', baseband.readframes(1))[0] / 32768.0 \ for n in range(0, baseband.getnframes()) ]) base.extend([ 0 for n in range(0, int(hlen)) ]) base_hilbert = numpy.convolve(base[:], hilbert_impulse) for n in range(0, len(base) - int(hlen)): carrier_cos = math.cos(3000.0 * (n / 44100.0) * math.pi * 2) carrier_sin = -math.sin(3000.0 * (n / 44100.0) * math.pi * 2) s1 = base[n] * carrier_cos # time-shifted signal because Hilbert transform is noncausal s2 = base_hilbert[n + int(hlen)] * carrier_sin signal_amssbh = s1 + s2 amssbh.writeframes(struct.pack('h', signal_amssbh * 32767))
A análise de espectro mostra que, com esta técnica, a banda inferior foi removida muito melhor do que com filtragem:
Produzir um sinal AM-SSB como esse, com duas portadoras defasadas em 90 graus, sugere que AM-SSB é na verdade uma forma especial de QAM analógico (QAM - Quadrature Amplitude Mmodulation ou Modulação por Amplitude e Quadratura). A modulação QAM permite transmitir dois sinais ao mesmo tempo, e de fato nós estamos enviando dois sinais via modulador AM-SSB Hilbert: o áudio original e o áudio transformado.
Ambos os sinais são interdependentes e equivalentes em conteúdo de informação. Então nós estamos, num certo sentido, enviando duas cópias da mesma coisa — muito embora a intenção seja a remoção de uma banda lateral, e não criar redundância. O ângulo da fase QAM não é fixo; ele gira o tempo todo, e medir a velocidade dessa rotação seria uma forma alternativa de recuperar o áudio original.
Encarar AM-SSB como se fosse QAM também explica porque o demodulador AM-SSB consegue detectar o áudio original com uma portadora fora de fase. Uma vez que o mesmo áudio está sendo enviado em duplicata, modulado por duas portadoras ortogonais, o receptor sempre consegue demodular ou uma ou outra cópia — ou, mais tipicamente, uma mistura das duas.
(*) Um uso supreendente de AM-SC é na transmissão de FM stéreo. O segundo canal de áudio é codificado dentro do próprio canal de áudio, com uma portadora de 38KHz. O problema do sincronismo da portadora é resolvido enviando um sinal-piloto de 19kHz.