Calibración ultrasónica de altavoces y emisión de señales calibradas

10

Estoy tratando de calibrar un altavoz ultrasónico con el objetivo de emitir señales predecibles, pero lamentablemente sigo teniendo problemas, probablemente debido a mi falta de DSP-fu.

Un poco de historia

Quiero poder reproducir sonidos lo más cerca posible de una grabación calibrada que tengo. Hasta donde entiendo la teoría, necesito encontrar la función de transferencia de altavoces y desconvolver las señales que quiero emitir con ella. Algo como esto (en el dominio de la frecuencia):

X -> H -> XH

Donde Xestá la señal emitida Hes la función de transferencia de los altavoces y XHson los Xtiempos H. Una división ( ./) ahora debería darme H.

Ahora, para emitir una señal calibrada, debe dividirse entre H:

X/H -> H -> X

Que se ha hecho

  • Altavoz colocado y un micrófono calibrado a 1 m de distancia sobre trípodes.
  • Grabado 30+ barridos lineales 150KHz-20KHz, 20ms de largo, y grabado a 500 KS / s.
  • Señales alineadas y promediadas con el script Matlab / Octave a continuación, debajo del script se puede ver la señal resultante.
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);

Señales alineadas y promediadas

  • Fourier se transformó Xe XHhizo los cálculos mencionados anteriormente, el resultado parece plausible. A continuación se muestra una gráfica normalizada de H(púrpura) y X/H(verde).

    Gráfico de frecuencia de H y X / H

La trama se ha truncado a las frecuencias relevantes.

Por favor, avíseme si voy por el camino equivocado.

Mi pregunta

Después de calcular X/Hque necesito transformarlo nuevamente en el dominio del tiempo, asumí que esto sería simple ifft(X./H)y wavwrite, pero todos mis intentos hasta ahora no han logrado obtener una respuesta plausible. Un vector de frecuencias Hf, Hy Xse puede encontrar aquí en formato binario mat7.

Quizás estoy cansado y hay una solución simple aquí, pero por el momento no puedo verla. Cualquier ayuda / consejo es muy apreciada.

Thor
fuente
1
Este hilo - dsp.stackexchange.com/questions/953/… - y este - dsp.stackexchange.com/questions/2705/… - puede serle útil.
Jim Clay
Sí, encontré mi error, gracias Jim. Solo estaba considerando la magnitud de las señales, lo que resulta en una señal de tiempo de fase cero. Parece que ahora tengo el resultado correcto y lo agregaré como respuesta.
Thor

Respuestas:

3

Encontré la respuesta después de mirar las referencias que Jim Clay mencionó en los comentarios, gracias Jim.

Cometí el error de solo considerar la magnitud que da como resultado una señal de fase cero y no se puede usar de manera sensata para la emisión, al menos no en esta configuración.

El código que finalmente terminé usando se puede ver a continuación.

El script se adhiere a la convención de nomenclatura de mantener las señales del dominio del tiempo en minúsculas y las señales del dominio de frecuencia en mayú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

Los espectrogramas de x conv hy x deconv hse pueden ver a continuación:

espectrograma de x conv h espectrograma de x deconv h

Esto me parece plausible, aunque hay algo de ruido en la señal deconvolucionada.

La siguiente prueba será ver si emitir x_deconv_yproduce algo parecido xa las frecuencias que el altavoz no puede emitir.

Actualización con resultados de prueba

Rediseñamos las medidas descritas anteriormente usando un barrido descendente logarítmico. Estos resultados parecen sugerir que el método funciona.

La prueba de verificación consistió en emitir X / Hy esperar Xvolver, es decir, igual energía en todas las frecuencias. Como la peor frecuencia de salida es aproximadamente 20 dB más débil que la mejor, se espera que el nivel de salida más alto sea mucho más bajo.

La señal que se emitió:

Series temporales de señal emitida

La serie temporal y el espectrograma de la señal grabada se ven así:

Series temporales de señal emitida Series temporales de señal emitida

Thor
fuente
¿Algún avance en esto? ¿Cómo emitiste la señal?
Lance
@Busk: Gracias por el interés. Todavía no he tenido la oportunidad de probarlo ya que el equipo se está utilizando en otros lugares. Publicaré los resultados cuando termine la prueba.
Thor
@Busk: ahora lo hemos probado y parece funcionar :-).
Thor