É um prazer aceitar sugestões no R ou no Matlab, mas o código que apresento abaixo é apenas para o R.
O arquivo de áudio anexado abaixo é um pequeno trecho de conversa entre duas pessoas. Meu objetivo é distorcer o discurso deles para que o conteúdo emocional se torne irreconhecível. A dificuldade é que preciso de um espaço paramétrico para essa distorção, digamos de 1 a 5, onde 1 é 'emoção altamente reconhecível' e 5 é 'emoção não reconhecível'. Existem três maneiras que pensei em usar para conseguir isso com R.
Faça o download da onda de áudio 'feliz' aqui .
Faça o download da onda de áudio 'irritada' aqui .
A primeira abordagem foi diminuir a inteligibilidade geral com a introdução de ruído. Esta solução é apresentada abaixo (obrigado a @ carl-witthoft por suas sugestões). Isso diminuirá a inteligibilidade e o conteúdo emocional do discurso, mas é uma abordagem muito "suja" - é difícil acertar na obtenção do espaço paramétrico, porque o único aspecto que você pode controlar é uma amplitude (volume) de ruído.
require(seewave)
require(tuneR)
require(signal)
h <- readWave("happy.wav")
h <- cutw(h.norm,f=44100,from=0,to=2)#cut down to 2 sec
n <- noisew(d=2,f=44100)#create 2-second white noise
h.n <- h + n #combine audio wave with noise
oscillo(h.n,f=44100)#visualize wave with noise(black)
par(new=T)
oscillo(h,f=44100,colwave=2)#visualize original wave(red)
A segunda abordagem seria ajustar de alguma forma o ruído, distorcer a fala apenas nas faixas de frequência específicas. Eu pensei que poderia fazê-lo extraindo o envelope de amplitude da onda de áudio original, gerando ruído a partir deste envelope e depois reaplicando o ruído à onda de áudio. O código abaixo mostra como fazer isso. Ele faz algo diferente do ruído em si, faz com que o som seja quebrado, mas remonta ao mesmo ponto - que eu só sou capaz de alterar a amplitude do ruído aqui.
n.env <- setenv(n, h,f=44100)#set envelope of noise 'n'
h.n.env <- h + n.env #combine audio wave with 'envelope noise'
par(mfrow=c(1,2))
spectro(h,f=44100,flim=c(0,10),scale=F)#spectrogram of normal wave (left)
spectro(h.n.env,f=44100,flim=c(0,10),scale=F,flab="")#spectrogram of wave with 'envelope noise' (right)
A abordagem final pode ser a chave para resolver isso, mas é bastante complicada. Encontrei esse método em um relatório publicado na Science por Shannon et al. (1996) . Eles usaram um padrão bastante complicado de redução espectral, para conseguir algo que provavelmente parece bastante robótico. Mas, ao mesmo tempo, pela descrição, presumo que eles possam ter encontrado a solução que poderia responder ao meu problema. As informações importantes estão no segundo parágrafo no texto e na nota número 7 em Referências e notas- todo o método é descrito lá. Minhas tentativas de replicá-lo até agora não tiveram êxito, mas abaixo está o código que consegui encontrar, juntamente com minha interpretação de como o procedimento deve ser realizado. Acho que quase todos os quebra-cabeças existem, mas ainda não consigo entender o cenário todo.
###signal was passed through preemphasis filter to whiten the spectrum
#low-pass below 1200Hz, -6 dB per octave
h.f <- ffilter(h,to=1200)#low-pass filter up to 1200 Hz (but -6dB?)
###then signal was split into frequency bands (third-order elliptical IIR filters)
#adjacent filters overlapped at the point at which the output from each filter
#was 15dB down from the level in the pass-band
#I have just a bunch of options I've found in 'signal'
ellip()#generate an Elliptic or Cauer filter
decimate()#downsample a signal by a factor, using an FIR or IIR filter
FilterOfOrder()#IIR filter specifications, including order, frequency cutoff, type...
cutspec()#This function can be used to cut a specific part of a frequency spectrum
###amplitude envelope was extracted from each band by half-wave rectification
#and low-pass filtering
###low-pass filters (elliptical IIR filters) with cut-off frequencies of:
#16, 50, 160 and 500 Hz (-6 dB per octave) were used to extract the envelope
###envelope signal was then used to modulate white noise, which was then
#spectrally limited by the same bandpass filter used for the original signal
Então, como o resultado deve soar? Deve haver algo entre rouquidão, uma rachadura barulhenta, mas não tanto robótica. Seria bom que o diálogo permanecesse até certo ponto inteligível. Eu sei - é tudo um pouco subjetivo, mas não se preocupe com isso - sugestões malucas e interpretações frouxas são muito bem-vindas.
Referências:
- Shannon, RV, Zeng, FG, Kamath, V., Wygonski, J., e Ekelid, M. (1995). Reconhecimento de fala com pistas principalmente temporais. Science , 270 (5234), 303. Download de http://www.cogsci.msu.edu/DSS/2007-2008/Shannon/temporal_cues.pdf
noisy <- audio + k*white_noise
por uma variedade de valores de k faz o que você quer? Tendo em mente, é claro, que "inteligível" é altamente subjetivo. Ah, e você provavelmente deseja uma dúzia dewhite_noise
amostras diferentes para evitar efeitos coincidentes devido à correlação falsa entreaudio
e um úniconoise
arquivo de valor aleatório .Respostas:
Eu li sua pergunta original e não tinha muita certeza do que você estava falando, mas agora é muito mais claro. O problema que você tem é que o cérebro é extremamente bom em captar fala e emoção, mesmo quando o ruído de fundo é muito alto, ou seja, suas tentativas existentes só tiveram sucesso limitado.
Eu acho que a chave para conseguir o que você quer é entender os mecanismos que transmitem o conteúdo emocional, pois eles são principalmente separados daqueles que transmitem a inteligibilidade. Eu tenho alguma experiência com isso (na verdade, minha dissertação de mestrado foi sobre um assunto semelhante), então tentarei oferecer algumas idéias.
Considere suas duas amostras como exemplos de discurso muito emocional, depois considere o que seria um exemplo "sem emoção". O melhor que consigo pensar agora é a voz do tipo "Stephen Hawking", gerada por computador. Portanto, se eu entendi direito, o que você quer fazer é entender as diferenças entre elas e descobrir como distorcer suas amostras para se tornar gradualmente como uma voz sem emoção gerada por computador.
Eu diria que os dois principais mecanismos para obter o que você deseja são através da distorção de altura e tempo, pois grande parte do conteúdo emocional está contida na entonação e ritmo do discurso. Portanto, uma sugestão de algumas coisas que podem valer a pena tentar:
Um efeito do tipo distorção de tom que dobra o tom e reduz a entonação. Isso pode ser feito da mesma maneira que o Antares Autotune funciona, onde você gradualmente inclina o tom em direção a um valor constante, cada vez mais, até que fique totalmente monótono.
Um efeito de extensão de tempo que altera a duração de algumas partes do discurso - talvez os fonemas com voz constante que quebrariam o ritmo do discurso.
Agora, se você decidiu abordar um desses métodos, serei honesto - eles não são tão simples de implementar no DSP e não serão apenas algumas linhas de código. Você precisará fazer algum trabalho para entender o processamento do sinal. Se você conhece alguém com Pro-Tools / Logic / Cubase e uma cópia do Antares Autotune, provavelmente vale a pena tentar ver se isso terá o efeito desejado antes de tentar codificar algo semelhante.
Espero que isso lhe dê algumas idéias e ajude um pouco. Se você precisar que eu explique mais alguma coisa que eu disse, me avise.
fonte
Eu sugiro que você adquira um software de produção musical e brinque com ele para obter o efeito desejado. Só então você deve se preocupar em resolver isso programaticamente. (Se o seu software de música puder ser chamado em uma linha de comando, você poderá chamá-lo em R ou MATLAB).
Uma outra possibilidade que ainda não foi discutida é eliminar completamente a emoção usando o software de fala para texto para criar uma string, depois o software de texto para fala para transformar essa string em voz de robô. Consulte /programming/491578/how-do-i-convert-speech-to-text e /programming/637616/open-source-text-to-speech-library .
Para que isso funcione de maneira confiável, você provavelmente precisará treinar o primeiro software a reconhecer o alto-falante.
fonte