Como distinguir a voz do ronco?

22

Antecedentes: estou trabalhando em um aplicativo para iPhone (mencionado em várias outras postagens ) que "ouve" roncar / respirar enquanto alguém está dormindo e determina se há sinais de apneia do sono (como uma pré-tela para "laboratório do sono" teste). O aplicativo emprega principalmente "diferença espectral" para detectar roncos / respirações e funciona muito bem (correlação de 0,85 a 0,90) quando testado em gravações do laboratório do sono (que na verdade são bastante barulhentas).

Problema: A maioria dos ruídos do "quarto" (ventiladores, etc.) posso filtrar através de várias técnicas e, freqüentemente, detectai de forma confiável a respiração nos níveis S / N, onde o ouvido humano não pode detectá-la. O problema é o ruído da voz. Não é incomum ter uma televisão ou rádio funcionando em segundo plano (ou simplesmente ter alguém falando à distância), e o ritmo da voz se aproxima da respiração / ronco. Na verdade, eu fiz uma gravação do falecido autor / contador de histórias Bill Holm através do aplicativo e era essencialmente indistinguível de roncar no ritmo, variabilidade de nível e várias outras medidas. (Embora eu possa dizer que aparentemente ele não teve apneia do sono, pelo menos não enquanto estava acordado.)

Portanto, este é um longo plano (e provavelmente uma série de regras do fórum), mas estou procurando algumas idéias sobre como distinguir a voz. Não precisamos filtrar os roncos de alguma forma (achei que seria legal), mas precisamos apenas de uma maneira de rejeitar o som "muito barulhento" que é excessivamente poluído com a voz.

Alguma ideia?

Arquivos publicados: coloquei alguns arquivos no dropbox.com:

O primeiro é uma peça de rock bastante aleatória (eu acho), e o segundo é uma gravação do falecido Bill Holm. Ambos (que eu uso como minhas amostras de "ruído" são diferenciados de ronco) foram misturados com ruído para ofuscar o sinal. (Isso torna a tarefa de identificá-los significativamente mais difícil.) O terceiro arquivo consiste em dez minutos de uma gravação sua, na qual o primeiro terço é principalmente a respiração, o terço do meio é misto de respiração / ronco e o terço final é o ronco bastante constante. (Você tosse por um bônus.)

Todos os três arquivos foram renomeados de ".wav" para "_wav.dat", pois muitos navegadores dificultam o download de arquivos wav. Apenas renomeie-os novamente para ".wav" após o download.

Atualização: Eu pensei que a entropia estava "fazendo o truque" para mim, mas acabou sendo principalmente peculiaridades dos casos de teste que eu estava usando, além de um algoritmo que não foi muito bem projetado. No caso geral, a entropia está fazendo muito pouco por mim.

Posteriormente, tentei uma técnica na qual calculei a FFT (usando várias funções diferentes da janela) da magnitude geral do sinal (tentei potência, fluxo espectral e várias outras medidas) amostradas cerca de 8 vezes por segundo (tomando as estatísticas do ciclo principal da FFT) (a cada 1024/8000 segundos). Com 1024 amostras, isso abrange um intervalo de tempo de cerca de dois minutos. Eu esperava poder ver padrões nisso devido ao ritmo lento do ronco / respiração versus voz / música (e que também poderia ser uma maneira melhor de resolver o problema da " variabilidade "), mas enquanto houver dicas de um padrão aqui e ali, não há nada em que realmente possa me agarrar.

( Informações adicionais: em alguns casos, a FFT de magnitude do sinal produz um padrão muito distinto, com um pico forte em cerca de 0.2Hz e harmônicos na escada. Mas o padrão não é tão distinto na maioria das vezes, e a voz e a música podem gerar menos distintas pode haver alguma maneira de calcular um valor de correlação para uma figura de mérito, mas parece que isso exigiria o ajuste de curva para um polinômio de quarta ordem, e fazer isso uma vez por segundo no telefone parece impraticável.)

Também tentei fazer o mesmo FFT de amplitude média para as 5 "bandas" individuais em que dividi o espectro. As bandas são 4000-2000, 2000-1000, 1000-500 e 500-0. O padrão para as 4 primeiras bandas era geralmente semelhante ao padrão geral (embora não houvesse uma banda real "destacada" e muitas vezes um sinal extremamente pequeno nas bandas de frequência mais alta), mas a banda 500-0 geralmente era apenas aleatória.

Recompensa: eu vou dar a recompensa a Nathan, mesmo que ele não tenha oferecido nada de novo, já que essa foi a sugestão mais produtiva até hoje. Ainda tenho alguns pontos que gostaria de premiar com outra pessoa, se eles tivessem boas idéias.

Daniel R Hicks
fonte
2
Você pode postar alguns espectrogramas representativos? (Deixe os dados falarem.) Como você está computando a "diferença espectral"?
Emre
A "diferença espectral" é algumas vezes referida como "fluxo espectral" e alguns outros termos. Basicamente, é a soma dos quadrados das diferenças individuais nas sucessivas FFTs do som.
Daniel R Hicks
2
Venha para pensar sobre isso, os clipes de áudio seriam ainda melhores. Obrigado pelo esclarecimento.
Emre
Estou tentando descobrir qual seria a melhor apresentação. Não tenho software sofisticado para fazer espectros (além dos meus FFTs reais) para amostras curtas - o Audacity requer uma amostra muito longa para capturar o espectro de um som individual. E existem alguns problemas de privacidade médica com a publicação de sons reais do paciente.
Daniel R Hicks
1
@DanielRHicks Spectrograms with TV + ressonar e apenas ressonar ou algo assim realmente ajudaria bastante.
Spacey

Respostas:

10

fundo

De acordo com os documentos abaixo, o ronco é caracterizado por um pico em cerca de 130Hz e está totalmente concentrado abaixo de 12kHz:

Vamos ver se podemos aproveitar isso.

Exemplo MATLAB

Temos um registro ruim de uma criança roncando ; um arquivo WAV mono de 10 minutos e 8 bits. A taxa de amostragem é de 8KHz, o que significa que a largura de banda do sinal de áudio é de 4KHz. O nível é muito baixo, então eu o companderei primeiro.

[snd,fs]=wavread('recordedFile20120408010300_first_ten_minutes');
cmp=compand(snd,255,1);
wavwrite(cmp,'companded'); % used for listening purposes
[s,f,t,p]=spectrogram(snd,hann(8192));
surf(linspace(0,600,length(t)),f/pi,10*log10(p),'edgecolor','none'); 
axis tight; view(0,90);

Espectrograma completo

O eixo y é normalizado para a largura de banda, 4KHz, para que o entalhe que você vê em 0,1 corresponda a uma frequência de 400Hz. Há um pico correspondente a uma tosse a ~ 186s; ignore isso. Podemos ver vagamente os entalhes durante cada ronco. Não apenas isso, mas eles parecem concentrados abaixo de 0,2 x 4KHz = 800Hz. Vamos olhar mais de perto.

idx_max_freq=round(0.2*length(f));
surf(linspace(0,600,length(t)),fs*f(1:,idx_max_freq:)/(2*pi),10*log10(p(1:idx_max_freq,:)),'edgecolor','none');
axis tight; view(0,90);

Zoom do espectrograma para 0-800Hz.

Desta vez, o eixo da frequência foi rotulado em Hertz. Agora os entalhes estão bem claros. Podemos até ver as conotações do ruído da linha de energia começando em 60Hz (180Hz, 300Hz, 420Hz). Agora vem a essência do algoritmo: vamos classificar o sinal com base na energia nesta sub-banda, com o ruído da linha removido.

freq_list=round([1:57 63:177 183:297 303:417 423:800]*idx_max_freq/800);
y=10*log10(sum(p(freq_list,:)));
plot(linspace(0,600,length(y)),y-median(y))
stem(linspace(0,600,length(y)),y-median(y)>.5*std(y))

Se queremos ser extravagantes, podemos descartar picos grandes demais:

stem(linspace(0,600,length(y)),(y-median(y)>.5*std(y)).*(y-median(y)<5*std(y)))

Gráfico da energia na sub-banda entalhada 0-800Hz

O resultado final

O baixo SNR, manifestado na dificuldade em discernir o sinal no primeiro gráfico, significa que temos margem de manobra de apenas meio desvio padrão (cujo valor foi 4,1). As hastes marcam os roncos.

Emre
fonte
Sim, meu algoritmo atual cancela zumbidos e outros ruídos harmônicos (o ruído do ventilador tende a ser de cerca de 110Hz) zerando os baldes de FFT que estão em um nível mais ou menos constante. Não estou claro o que você quer dizer quando diz "vamos classificar o sinal com base na energia desta sub-banda" - a que sub-banda você está se referindo?
Daniel R Hicks
Ah, entendo, você está falando abaixo de 800 Hz - eu perdi essa parte.
Daniel R Hicks
Se você olhar para o gráfico superior, verá que há bastante informação perto do topo e outra banda logo abaixo do meio. E essas bandas têm muito menos ruído competitivo. Meu esquema atual divide o espectro e tenta avaliar o SNR de cada fatia e, em seguida, avalia-os de acordo.
Daniel R Hicks
Você pode concatenar vários recursos, como a energia em sub-bandas selecionadas, o nivelamento espectral etc. para criar um vetor de recurso experimental. Em seguida, execute o PCA para descobrir quais são as mais importantes, conforme explicado no último artigo.
Emre 25/05
É basicamente o que estou fazendo, sem o rigor do PCA.
Daniel R Hicks
9

Apenas jogando isso aqui para cobrir todas as possibilidades, você pode usar a entropia, não sei qual é o nível de entropia do ronco x da fala, mas se for diferente o suficiente, pode funcionar. http://www.ee.columbia.edu/~dpwe/papers/ShenHL98-endpoint.pdf

Nathan Day
fonte
Eu não entendo completamente o que estou fazendo com isso (a teoria da informação faz minha cabeça explodir), mas implementei um cálculo bruto de entropia, introduzi um pouco de normalização totalmente não-teórica e parece estar funcionando. Música e voz têm uma entropia baixa (negativa), enquanto o ronco é significativamente maior. E o ruído de fundo em geral parece diminuir o valor (negativo), por isso fornece uma boa figura de mérito. Mais experimentação necessária, no entanto.
Daniel R Hicks
Uma coisa a ter cuidado é que você também precisa incluir um portão de nível simples, pois, você pode ter um ruído de fundo de nível extremamente baixo que pode corresponder ao que você está tentando deixar passar, também minha experiência parece sugerir a quantização de dígitos de ruídos de nível extremamente baixo podem aumentar a ordem de chegada do sinal, uma vez que em níveis baixos há um número reduzido de possíveis valores de amostra e a entropia sozinha não considera diferenças na amplitude.
Nathan Day
Sim, estou regularmente lutando contra o ruído e tenho uma boa maneira de medir isso separadamente. Quando o ruído excede um certo nível, eu bato. (É incrivelmente difícil, na verdade, para medir o ruído.)
Daniel R Hicks
Infelizmente, eu descobri que muito do que eu estava medindo com o meu cálculo bruto de entropia era um artefato do cálculo (devido a zeros nos dados do teste). É meio que funciona para a minha necessidade, mas não tão bem quanto eu pensava.
Daniel R Hicks
Seguimento: Substituí a FFT fixa / flutuante que estava usando por uma de ponto flutuante completo (que não produz zeros quando os níveis são baixos), e a utilidade da entropia foi mais longe nos tubos - não parecem fornecer algo particularmente útil.
Daniel R Hicks
3

Estatísticas do domínio do tempo, talvez? O ronco parece ter períodos relativamente longos de estado estacionário, enquanto a energia da fala muda bastante em curtos períodos de tempo. Isso poderia ser combinado com a análise espectral também. As vogais têm mais conteúdo de baixa frequência e consoantes mais altas. Durante a fala, o espectro pode saltar rapidamente entre esses estados, enquanto o armazenamento pode permanecer em um estado por períodos mais longos.

Hilmar
fonte
As estatísticas básicas do domínio do tempo são indistinguíveis. No entanto, é um bom ponto que eu poderia olhar para a variabilidade de curto prazo (que eu normalmente suavizo). Procurar o "salto" entre as bandas de frequência também é uma boa idéia ... Atualmente, divido em 5 bandas e rejeito bandas com S / N baixo aparente.
Daniel R Hicks
@DanielRHicks Eu vi como calcular o envelope cepstral em outro lugar, mas talvez você possa usá-lo como uma medida da sua variabilidade espectral, em vez do espectro puro, que será mais 'barulhento / irregular', enquanto o (s) cepstrum (s) me tendem a ser mais suaves . Também ouvi dizer que o cepstrum da Mel-Frequency é usado no reconhecimento de voz, e isso pode parecer útil para você.
Spacey
@DanielRHicks: Indistinguível por qual método? Eles são certamente distinguíveis para mim.
endolith 25/03
@endolith - Indistinguível pelas minhas métricas atuais - a "diferença espectral" mais o nível geral de energia. Mas eles são filtrados com passa-baixa com uma constante de tempo de cerca de 0,5 segundo. Acho que vou tentar olhar um pouco para os dados não filtrados.
Daniel R Hicks
Eu tentei capturar as estatísticas de tempo de curta duração. Algumas "dicas", mas nada definitivo.
Daniel R Hicks
1

Complexidade espectral ao longo do tempo. Suponho que a fala humana provavelmente use mais fonemas e com muito mais complexidade estatística em seu seqüenciamento do que as seqüências de ronco do fonema.

Esse provavelmente é um problema muito mais fácil do que o reconhecimento contínuo de fala, pois você não precisará reconhecer corretamente nenhum fonema ou sentença em particular corretamente, apenas o número de segmentos espectrais que soam no fonema e alguma medida estatística da complexidade de suas sequências (uma entropia ou teste de compressibilidade pode funcionar). Então veja se você pode determinar um limite confiável para essas medidas.

hotpaw2
fonte
O problema é que o ronco é surpreendentemente complexo / aleatório e carece muito de características distintas quando seu espectro é examinado.
Daniel R Hicks
Seria uma informação interessante se uma pessoa adormecida formasse tantos filtros e plosivos diferentes de forro de vogal (e dígrafos e trigramas dessa densidade em uma densidade ao longo do tempo) e inflexões de tom (etc.), enquanto dormia como quando acordado e conversando.
hotpaw2
A falta de recursos pode ser um recurso significativo. A fala tem características.
hotpaw2
Um problema é que o ronco pode variar imensamente, de uma respiração para a seguinte. Uma respiração pesada e simples é muito "branca", mas um ronco pode ter alguns picos muito fortes. É essencialmente uma onda quadrada, embora isso seja uma simplificação excessiva. E precisamos fazer a análise em tempo real em um telefone inteligente, para que a complexidade do algoritmo seja limitada.
Daniel R Hicks