É 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 de white_noise
amostras diferentes para evitar efeitos coincidentes devido à correlação falsa entre audio
e um único noise
arquivo de valor aleatório .