Maneira mais simples de detectar onde os envelopes de áudio começam e param

43

Abaixo está um sinal que representa a gravação de alguém falando. Eu gostaria de criar uma série de sinais de áudio menores com base nisso. A idéia é detectar quando o som 'importante' começa e termina e usa-os como marcadores para criar um novo trecho de áudio. Em outras palavras, eu gostaria de usar o silêncio como indicadores de quando um 'pedaço' de áudio foi iniciado ou parado e criar novos buffers de áudio com base nisso.

Por exemplo, se uma pessoa se registra dizendo

Hi [some silence] My name is Bob [some silence] How are you?

então eu gostaria de fazer três clipes de áudio com isso. Um que diz Hi, um que diz My name is Bobe outro que diz How are you?.

Minha idéia inicial é percorrer o buffer de áudio constantemente verificando onde existem áreas de baixa amplitude. Talvez eu possa fazer isso coletando as dez primeiras amostras, calculando a média dos valores e, se o resultado for baixo, rotule-o como silencioso. Eu continuaria com o buffer verificando as próximas dez amostras. Incrementando desta maneira, eu pude detectar onde os envelopes começam e param.

Se alguém tiver algum conselho sobre uma maneira boa, mas simples de fazer isso, seria ótimo. Para meus propósitos, a solução pode ser bastante rudimentar.

Não sou profissional no DSP, mas entendo alguns conceitos básicos. Além disso, eu faria isso programaticamente, para que fosse melhor falar sobre algoritmos e amostras digitais.

Obrigado por toda a ajuda!

insira a descrição da imagem aqui


EDIT 1

Ótimas respostas até agora! Só queria esclarecer que isso não está no áudio ao vivo e eu mesmo escreverei os algoritmos em C ou Objective-C, para que quaisquer soluções que usem bibliotecas não sejam realmente uma opção.

Eric Brotto
fonte
11
Parece que você está tentando terminar usando períodos de silêncio como pontos de interrupção. Por que não usar o limiar de energia para determinar o "silêncio" e ter um tempo limite para determinar se é longo o suficiente para constituir uma interrupção?
21612 Jim Clay
@ JimClay Sim, é exatamente isso que estou tentando fazer. Eu nunca ouvi falar de limiar de energia, mas parece algo que eu poderia usar. É complicado? Você poderia expandir um pouco isso?
Eric Brotto
@EricBrotto Talvez você deva nos contar um pouco sobre quais recursos você tem em suas bibliotecas. Isso nos permitirá massagear a metodologia real para você melhor.
Spacey
essa abordagem para detecção de silêncio é melhor - qual deve ser o nível de retenção diferente de 0,05 x = wavread ('s1.wav'); i = 1; enquanto abs (x (i)) <0,05% Detecção de silêncio i = i + 1; final x (1: i) = []; x (6000: 10000) = 0;
Zeee

Respostas:

26

Esse é o problema clássico da detecção de fala . A primeira coisa a fazer seria pesquisar no Google o conceito. É amplamente utilizado em comunicação digital e tem havido muita pesquisa sobre o assunto e existem bons trabalhos por aí.

Geralmente, quanto mais ruído de fundo você tiver para lidar, mais elaborado deve ser o método de detecção de fala. Se você estiver usando gravações feitas em uma sala silenciosa, poderá fazê-lo com muita facilidade (mais tarde). Se você tem todo o tipo de barulho enquanto alguém está falando (caminhões passando, latidos de cães, esmagamento de pratos, alienígenas atacando), você terá que usar algo muito mais inteligente.

Olhando para a forma de onda que você anexou, seu ruído é mínimo, então sugiro o seguinte:

  1. Extrair envelope de sinal
  2. Escolha um bom limite
  3. Detectar lugares onde a magnitude do envelope excede o limite

O que tudo isso significa? Um envelope de um sinal é uma curva que descreve sua magnitude ao longo do tempo, independentemente de como seu conteúdo de frequência o faça oscilar (veja a imagem abaixo).

insira a descrição da imagem aqui

{1,45,6,2,43,2}{1,45,6,2,43,2} pode ser encontrado experimentalmente e pode depender de várias coisas, como a taxa de amostragem.

Você pode ver na imagem que não há muito ruído presente, seu envelope de sinal sempre estará acima de um certo limiar (nível de intensidade sonora) e você pode considerar essas regiões como regiões detectadas pela fala .

Phonon
fonte
3
Na verdade, eu tinha implementado isso como um dos plug-ins no good'ol winamp. O que você está descrevendo é bom, mas não suficiente. Geralmente, há sons sonoros (vogais) e sons sonoros (consoantes). Se houvesse apenas som sonoro, o que você está descrevendo funcionará - mas o som sonoro é de energia muito baixa e não é totalmente distinguível do ruído geral. E condições sem ruído também são muito raras, mesmo em estúdios.
Dipan Mehta 22/02/12
como conseguir isso em python?
Krazzy R
26

O que você realmente deseja fazer é essencialmente chamado de detecção de atividade de voz ou detecção de fala.

Basicamente, qualquer sinal de fala pura (que não contém música) tem três partes.

  1. O som sonoro - que é basicamente causado pelas vogais
  2. O som não sonoro - que contém consoantes.

A característica do som humano é tal que, embora muita energia seja usada no som sonoro, a informação real está contida nas consoantes. Além disso, o som sonoro é geralmente a frequência mais baixa, enquanto os sons sonoros são as frequências mais altas. [Para ser preciso, todo som sonoro é ressonado mais ou menos com uma frequência constante para uma determinada pessoa que é o seu tom].

Agora, como qualquer sistema, há ruído. O som sonoro é geralmente bastante poderoso o suficiente para ser visível. Quando você aplica uma filtragem de frequência mais baixa, é possível coletar boa magnitude dos sons sonoros, no entanto, o som sonoro (com todas as informações ricas) se perde.

Chegando à pergunta de como resolvê-lo:

O truque está no fato de que o som não-sonoro ainda vem de uma fonte ressonante; e inerentemente restrito a uma certa frequência. Onde como, o barulho é bastante uniforme. Portanto, uma medida simples que distingue os três é "poder local" ou, alternativamente, mas equivalente é assumir a correlação automática em janelas.

Se você pegar por vez, digamos 100 amostras - e se correlacionar automaticamente, se contiver apenas ruído, os resultados serão praticamente zero (esta é a propriedade do ruído branco), onde, quanto ao sinal de fala, essa magnitude será observável porque o sinal ainda tem melhor estrutura. Isso funcionou para mim no passado.

O VAD tem sido uma área de pesquisa ativa - porque quase todas as comunicações por telefone celular desejam detectar partes que não são da fala e removê-las da codificação. Mas se eles removessem a fala sem voz, isso tornaria a telefonia inútil.

O padrão G.729 calcula o VAD com base em recursos como: frequências espectrais de linha, energia de banda completa, energia de banda baixa (<1 kHz) e taxa de cruzamento zero.

O padrão GSM funciona da seguinte maneira: a opção 1 calcula o SNR em nove bandas e aplica um limite a esses valores. A opção 2 calcula parâmetros diferentes: potência do canal, métricas de voz e potência de ruído. Em seguida, limita as métricas de voz usando um limite que varia de acordo com o SNR estimado. (da wikipedia)

Para técnicas mais avançadas, estou listando algumas referências sobre esse assunto.

  1. Referência mais citada : Jongseo Sohn; Nam Soo Kim; Wonyong Sung; "Uma detecção de atividade de voz baseada em modelo estatístico" Signal Processing Letters, IEEE, janeiro de 1999, volume: 6 Edição: 1 pp: 1-3

  2. Mais relevantes para você: Mark Marzinzik e Birger Kollmeier "Detecção de pausa na fala para estimativa de espectro de ruído, rastreando a dinâmica dos envelopes de potência" 10, NO. 2, fevereiro de 2002, p.109

  3. Ramírez, J .; JM Górriz, JC Segura (2007). "Detecção de atividade de voz. Fundamentos e robustez do sistema de reconhecimento de fala". Em M. Grimm e K. Kroschel. Reconhecimento e compreensão robustos da fala. pp. 1–22. ISBN 978-3-902613-08-0.

  4. Introdutório: Jonathan Kola, Carol Espy-Wilson e Tarun Pruthi "Detecção de atividade de voz"

Dipan Mehta
fonte
como conseguir isso em python?
Krazzy R
9

Eu recomendaria totalmente Jim Clay em sua abordagem, mas variaria ligeiramente o sabor usando o envelope:

Sabemos que a fala ocorre principalmente em torno de 1-2kHz. É provável que a amostragem de dados seja de 44kHz (isso depende do seu dispositivo de gravação). Então, o que eu faria primeiro é uma média móvel do sinal quadrado em tempo real em 10 pontos, para ter um envelope da potência do sinal. Isso induzirá um atraso na detecção, então você deseja manter isso baixo.

Então, eu adicionaria uma fase de calibração no seu sistema: peça ao usuário que permaneça em silêncio, pressione um botão e registre o ruído de fundo por, digamos, 10 segundos. Pegue a amplitude média ou mediana do envelope, multiplique por 2 para ter uma segurança, e isso daria o limite de que Jim está falando automaticamente.

Se não for uma gravação em tempo real, você pode achar útil usar a média móvel de fase 0 para diminuir o aborrecimento causado pelo atraso. Diga-nos se funciona para você como está.

Jean-Yves
fonte
9

Eric,

Se você está realmente buscando algo rápido e sujo, a primeira coisa que você precisa obter é o envelope, e eu faria isso simplesmente (no MATLAB):

 envelope = abs(hilbert(yourSignal));

Nesse ponto, eu simplesmente limiaria, e a 'voz existe' se você estiver acima de um determinado limite.

Esta é uma solução muito simples, mas pode funcionar para você.

Spacey
fonte
11
+1. Talvez você possa elaborar o método por trás dessa linha de código? Tenho certeza de que o OP não está familiarizado com a extração de envelope por meio da Hilbert Transform.
Phonon
@Mohammad Thanks! Mas, por favor, veja minha EDIT 1. Definitivamente, eu gostaria de trabalhar rápido e sujo, mas também preciso fazer os algoritmos :)
Eric Brotto
@ EricBrotto Ah, ok, posso dizer como implementar um transformador hilbert, mas suponho que você tenha a capacidade de executar uma FFT nas suas bibliotecas C / Obj-C? Se não for isso vai ser um problema ... :-)
Spacey
como conseguir isso em python?
Krazzy R
Tipo senhor / senhora, você poderia me indicar um recurso sobre como esse hilbert foi implementado em Python?
Krazzy R
6

Suponho que você esteja lidando com sinais reais e não complexos - se não for esse o caso, avise-me e posso alterar a resposta.

A potência é definida como o quadrado do sinal (ou seja, as amostras de sinal multiplicadas por elas mesmas). Você pode comparar o poder a algum limite para determinar se há fala presente ou não. Você provavelmente precisaria fazer algumas medições em suas gravações para encontrar empiricamente um bom limite.

Se suas gravações estiverem "limpas" (ou seja, sem muito ruído), eu provavelmente seria o mais simples possível comparando a potência instantânea (ou seja, uma única amostra) com o limite. Isso significa que você nem precisa quadrá-lo se não quiser, apenas precisa do valor absoluto e o compara com a raiz quadrada do limite de energia, que pode ser pré-computado. Quando você detecta a fala, agarre-a e uma certa quantidade de gravação antes dela, para garantir que você receba toda a fala (talvez 1/10 de segundo?). Continue até encontrar um período prolongado de nenhuma amostra que exceda o limite. Novamente, a duração do período precisaria ser determinada empiricamente.

Enxague e repita.

Jim Clay
fonte
4

Eu escrevi uma classe de detector de atividades em Java. Faz parte da minha coleção de código aberto Java DSP . Você pode usar o programa de teste WavSplitter.java para verificar com um arquivo WAV como entrada.

Christian d'Heureuse
fonte
Tenha em mente o OP diz especificamente que ele precisa para escrever os algoritmos-se em C.
Sam Maloney
É muito fácil de converter esses algoritmos de Java para C.
Christian d'Heureuse
Senhor, como conseguir isso em python?
Krazzy R