Calibração por alto-falante ultrassônico e emissão de sinais calibrados

10

Estou tentando calibrar um alto-falante ultrassônico com o objetivo de emitir sinais previsíveis, mas infelizmente continuo tendo problemas, provavelmente devido à minha falta de DSP-fu.

Um pouco de fundo

Quero poder reproduzir sons o mais próximo possível de uma gravação calibrada que possuo. Tanto quanto eu entendo a teoria, preciso encontrar a função de transferência de alto-falantes e desconvolver os sinais que quero emitir com ela. Algo assim (no domínio da frequência):

X -> H -> XH

Onde Xestá o sinal emitido Hé a função de transferência dos alto-falantes e XHé Xvezes H. Uma divisão ( ./) agora deve me dar H.

Agora, para emitir um sinal calibrado, ele deve ser dividido por H:

X/H -> H -> X

O que foi feito

  • Alto-falante colocado e um microfone calibrado com 1 m de distância nos tripés.
  • Gravou mais de 30 varreduras lineares de 150 KHz a 20 KHz, 20 ms de comprimento e gravou a 500 KS / s.
  • Sinais alinhados e calculados com o script Matlab / Octave abaixo, abaixo do script, o sinal resultante pode ser visto.
files = dir('Mandag*');

rng = [1.5e6, 1.52e6];

[X, fs] = wavread(files(1).name, rng);
X = X(:,1);

for i=2:length(files)
    [Y, fs] = wavread(files(i).name, rng);
    sig = Y(:,1);
    [x, off] = max(xcorr(X', sig'));
    off = length(X) - off;
    if(off < 0)
        sig = [zeros(1, -off), sig(1:end+off)'];
    elseif (off > 0)
        sig = [sig(off:end)', zeros(1, off-1)];
    end
    X = X + sig';
end
X = X/length(files);

Sinais alinhados e médios

  • Fourier transformou Xe XHfez os cálculos mencionados acima, o resultado parece plausível. Abaixo está um gráfico normalizado de H(roxo) e X/H(verde).

    Gráfico de frequência de H e X / H

O gráfico foi truncado para as frequências relevantes.

Por favor, deixe-me saber se estou fazendo isso da maneira errada.

Minha pergunta

Depois de calcular X/Hque preciso transformá-lo de volta ao domínio do tempo, presumi que isso seria simples ifft(X./H)e wavwrite, mas todas as minhas tentativas até agora não conseguiram obter nenhuma resposta plausível. Um vector de frequência Hf, He Xpode ser encontrada aqui em formato mat7-binário.

Talvez eu esteja apenas cansado e haja uma solução simples aqui, mas no momento não consigo vê-lo. Qualquer ajuda / conselho é muito apreciada.

Thor
fonte
11
Esse encadeamento - dsp.stackexchange.com/questions/953/… - e este - dsp.stackexchange.com/questions/2705/… - pode ser útil para você.
22612 Jim Clay
Sim, encontrei o meu erro, obrigado Jim. Eu estava apenas considerando a magnitude dos sinais, o que resulta em um sinal de tempo em fase zero. Parece que eu tenho o resultado certo agora e vou adicioná-lo como resposta.
Thor

Respostas:

3

Encontrei a resposta depois de examinar as referências mencionadas por Jim Clay nos comentários, obrigado Jim.

Cometi o erro de considerar apenas a magnitude que resulta em sinal de fase zero e não pode ser sensatamente usado para emissão, pelo menos não nesta configuração.

O código que finalmente acabei usando pode ser visto abaixo.

O script segue a convenção de nomenclatura de manter os sinais do domínio do tempo em minúsculas e os sinais do domínio de frequência em maiúsculas.

% Align and sum all files called Mandag*
files = dir('Mandag*');

% Where in the recordings the signal is
rng = [1.5e6, 1.52e6];

% Initialize the xh vector
[xh, fs] = wavread(files(1).name, rng);
xh = xh(:,1);

for i=2:length(files)
    y = wavread(files(i).name, rng);
    y = y(:,1);
    % Determine offset between xh and y
    [~, off] = max(xcorr(xh', y'));
    off = length(xh) - off;
    % Shift signal appropriately
    if(off < 0)
        y = [zeros(1, -off), y(1:end+off)'];
    elseif (off > 0)
        y = [y(off:end)', zeros(1, off-1)];
    end
    xh = xh + y';
end

% Average
xh = xh/length(files);

% Location of the 20ms signal
xh = xh(2306:12306-1);

% Normalize
xh = xh / max(xh);

% Apply a moving average filter on xh to reduce noise. Window size of 4 was
% experimentally determined to give the best results
n = 4;
B = zeros(n, 1);
for i=1:n
  B(i) = 1/n;
end
xh = filter(B, 1, xh);
xh = xh / max(xh);

x = wavread('sweep.wav');
x = x(1:2:end);            % Sweep generated @ 1MHz, decimate
                           % to have same length as xh

% Transform x into frequency domain and determine H
X = fft(x);
H = fft(xh) ./ X;

% Vector indices to choose only frequencies of interest
starti =  20e3 / 50;
endi   = 100e3 / 50;
rng    = starti:endi;
irng   = (length(x) - endi) : (length(x) - starti);

% Zero out unwanted frequencies
X = [zeros(1,      starti - 1   ), X( rng)', zeros(1, length(X)/2 - endi) ...
     zeros(1, length(X)/2 - endi), X(irng)', zeros(1,      starti - 1   )]';

% Deconvolve x with h
X_deconv_H = X ./ H;

% Transform X/H to time domain and normalise
x_deconv_h = real(ifft(X_deconv_H));
x_deconv_h = x_deconv_h / max(x_deconv_h);

% Save the deconvolved sweep
wavwrite(x_deconv_h, fs, 'deconvolved_sweep.wav');

% Generate  spectrograms of xh and x_deconv_h
winsize = 512;
overlap = round(.99 * winsize);
figure(1)
specgram(xh, winsize, fs, hann(winsize), overlap)
colorbar
figure(2)
specgram(x_deconv_h, winsize, fs, hann(winsize), overlap)
colorbar

Os espectrogramas de x conv he x deconv hpodem ser vistos abaixo:

espectrograma de x conv h espectrograma de x deconv h

Isso me parece plausível, embora exista algum ruído no sinal não envolvido.

O próximo teste será ver se a emissão x_deconv_ydá algo semelhante à xrestrição daquelas frequências que o falante não pode emitir.

Atualizar com os resultados do teste

Nós refazemos as medidas descritas acima usando uma varredura logarítmica para baixo. Esses resultados parecem sugerir que o método funciona.

O teste de verificação consistiu em emitir X / He esperar Xvoltar, ou seja, energia igual em todas as frequências. Como a pior frequência de saída é cerca de 20dB mais fraca que a melhor, espera-se que o nível de saída mais alto seja muito menor.

O sinal que foi emitido:

Séries temporais do sinal emitido

A série temporal e o espectrograma do sinal gravado são assim:

Séries temporais do sinal emitido Séries temporais do sinal emitido

Thor
fonte
alguma atualização disso? Como você emitiu o sinal?
Lance
@ Busk: Obrigado pelo interesse. Ainda não tive a chance de testá-lo, pois o equipamento está sendo usado em outro lugar. Vou postar os resultados quando tiver feito o teste.
Thor
@ Busk: agora testamos e parece funcionar :-).
Thor