Calibration ultrasonique des haut-parleurs et émission de signaux calibrés

10

J'essaie de calibrer un haut-parleur à ultrasons dans le but d'émettre des signaux prévisibles, mais hélas, je continue de rencontrer des problèmes, probablement en raison de mon manque de DSP-fu.

Un peu de fond

Je veux pouvoir lire des sons aussi près que possible d'un enregistrement calibré que j'ai. Pour autant que je comprends la théorie, je dois trouver la fonction de transfert des haut-parleurs et déconvolver les signaux que je veux émettre avec. Quelque chose comme ça (dans le domaine fréquentiel):

X -> H -> XH

Xest le signal émis Hest la fonction de transfert des haut-parleurs et XHest le Xtemps H. Une division ( ./) devrait maintenant me donner H.

Maintenant, afin d'émettre un signal calibré, il doit être divisé par H:

X/H -> H -> X

Ce qui a été fait

  • Haut-parleur placé et un microphone calibré à 1 m de distance sur les trépieds.
  • Enregistré plus de 30 balayages linéaires 150KHz-20KHz, 20ms de long, et enregistré à 500 KS / s.
  • Signaux alignés et moyennés avec le script Matlab / Octave ci-dessous, sous le script, le signal résultant peut être vu.
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);

Signaux alignés et moyennés

  • Fourier s'est transformé Xet XHet a fait les calculs mentionnés ci-dessus, le résultat semble plausible. Vous trouverez ci-dessous un tracé normalisé de H(violet) et X/H(vert).

    Diagramme de fréquence de H et X / H

Le tracé a été tronqué aux fréquences pertinentes.

S'il vous plaît, faites-moi savoir si je m'y trompe.

Ma question

Après avoir calculé que X/Hje devais le reconvertir dans le domaine temporel, j'ai supposé que ce serait simple ifft(X./H)et wavwrite, mais toutes mes tentatives jusqu'à présent n'ont pas réussi à obtenir une réponse plausible. Un vecteur de fréquence Hf, Het Xpeut être trouvé ici en format mat7 binaire.

Peut-être que je suis juste fatigué et qu'il y a une solution simple ici, mais pour le moment je ne la vois pas. Toute aide / conseil est très apprécié.

Thor
la source
1
Ce fil - dsp.stackexchange.com/questions/953/… - et celui- ci - dsp.stackexchange.com/questions/2705/… - pourraient vous être utiles.
Jim Clay
Oui, j'ai trouvé mon erreur merci Jim. Je ne considérais que l'amplitude des signaux, ce qui donne un signal temporel à phase nulle. On dirait que j'ai le bon résultat maintenant et je vais ajouter cela comme réponse.
Thor

Réponses:

3

J'ai trouvé la réponse après avoir regardé les références que Jim Clay a mentionnées dans les commentaires, merci Jim.

J'ai fait l'erreur de ne considérer que l'amplitude qui se traduit par un signal déphasé et ne peut pas être utilisé de manière raisonnable pour l'émission, du moins pas dans cette configuration.

Le code que j'ai finalement utilisé peut être vu ci-dessous.

Le script respecte la convention de dénomination consistant à conserver les signaux du domaine temporel en minuscules et les signaux du domaine fréquentiel en majuscules.

% 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

Les spectrogrammes de x conv het x deconv hpeuvent être vus ci-dessous:

spectrogramme de x conv h spectrogramme de x deconv h

Ceux-ci me semblent plausibles bien qu'il y ait du bruit dans le signal déconvolué.

Le prochain test consistera à voir si l'émission x_deconv_ydonne quelque chose de semblable xsauf les fréquences que le haut-parleur ne peut pas émettre.

Mise à jour avec les résultats des tests

Nous avons refait les mesures décrites ci-dessus en utilisant un balayage descendant logarithmique. Ces résultats semblent suggérer que la méthode fonctionne.

Le test de vérification consistait à émettre X / Het à espérer récupérer X, c'est-à-dire une énergie égale à toutes les fréquences. Comme la pire fréquence de sortie est environ 20 dB plus faible que la meilleure, le niveau de sortie le plus élevé devrait être beaucoup plus faible.

Le signal émis:

Série temporelle du signal émis

La série chronologique et le spectrogramme du signal enregistré ressemblent à ceci:

Série temporelle du signal émis Série temporelle du signal émis

Thor
la source
Une mise à jour pour ceci? Comment avez-vous émis le signal?
Lance
@Busk: Merci pour l'intérêt. Je n'ai pas encore eu l'occasion de le tester car l'équipement est utilisé ailleurs. Je publierai les résultats une fois le test terminé.
Thor
@Busk: nous l'avons maintenant testé et il semble fonctionner :-).
Thor