Живое направление оценки прибытия с линейным массивом микрофона

Этот пример показывает, как получить и обработать живое многоканальное аудио. Это также представляет простой алгоритм для оценки Направления прибытия (DOA) источника звука с помощью нескольких пар микрофона в линейной матрице.

Выберите и сконфигурируйте источник аудиосэмплов

Если многоканальный входной аудиоинтерфейс доступен, то измените этот скрипт, чтобы установить sourceChoice 'жить'. В этом режиме пример будет использовать живые входные аудиосигналы - это также примет, что все входные параметры (два или больше) управляются микрофонами, расположенными на линейной матрице. Если никакой массив микрофона или многоканальная звуковая карта не доступны, то установленный sourceChoice к 'записанному'. В этом режиме пример будет использовать записанные заранее аудиосэмплы, полученные с линейной матрицей. Для sourceChoice = 'живой', следующий код использует audioDeviceReader, чтобы получить 4 живых звуковых канала через Microsoft Kinect™ для Windows®. Чтобы использовать другую настройку массива микрофона, гарантируйте, что установленный драйвер аудиоустройства является одним из обычных типов, поддержанных MATLAB, и установил свойство Device audioDeviceReader соответственно. Можно запросить допустимые присвоения Device для компьютера путем вызова метода getAudioDevices объекта audioDeviceReader. Обратите внимание на то, что даже когда с помощью Microsoft Kinect, имя устройства может отличаться через машины и не может совпадать с той, используемой в этом примере. Используйте заполнение клавишей Tab, чтобы получить правильное имя на вашей машине.

% sourceChoice = {'recorded'|'live'}
sourceChoice = 'recorded';

% Set for how long the live processing should last
endTime = 20;
% And how many samples per channel should be acquired and processed at each
% iteration
audioFrameLength = 3200;

switch sourceChoice
    case 'live'
        fs = 16000;
        audioInput = audioDeviceReader(...
            'Device', 'Microphone Array (Microsoft Kinect USB Audio)',...
            'SampleRate', fs, ...
            'NumChannels', 4,...
            'OutputDataType','double',...
            'SamplesPerFrame', audioFrameLength);
    case 'recorded'
        % The following audio files holds a 20-second recording of 4 raw
        % audio channels acquired with a Microsoft Kinect(TM) for
        % Windows(R) in the presence of a noisy source moving in front of
        % the array roughly from -40 to about +40 degrees and then back
        % to the initial position.
        audioFileName = 'AudioArray-16-16-4channels-20secs.wav';
        audioInput = dsp.AudioFileReader(...
            'OutputDataType','double',...
            'Filename', audioFileName,...
            'PlayCount', inf, ...
            'SamplesPerFrame', audioFrameLength);
        fs = audioInput.SampleRate;
end

Задайте геометрию массивов

Следующие значения идентифицируют аппроксимированные линейные координаты 4 встроенных микрофонов Microsoft Kinect™ относительно положения камеры RGB (не используемый в этом примере). Для 3D использования координат [[x1; y1; z1], [x2; y2; z2]..., [xN; yN; цинк]]

micPositions = [-0.088, 0.042, 0.078, 0.11];

Сформируйте пары микрофона

Алгоритм, используемый в этом примере, работает с парами микрофонов независимо. Это затем комбинирует отдельные оценки DOA, чтобы предоставить одному живому DOA вывод. Чем больше доступных пар, тем более устойчивый (все же в вычислительном отношении дорогой) оценка DOA. Максимальное количество доступных пар может быть вычислено через nchoosek (длина (micPositions), 2). В этом случае эти 3 пары с самыми большими расстояниями межмикрофона выбраны. Чем больше расстояние межмикрофона, тем более чувствительный оценка DOA. Каждый столбец следующей матрицы описывает выбор пары микрофона в массиве. Все значения должны быть целыми числами между 1 и длина (micPositions).

micPairs = [1 4; 1 3; 1 2];
numPairs = size(micPairs, 1);

Инициализируйте визуализацию DOA

% Create an instance of the helper plotting object DOADisplay. This will
% display the estimated DOA live with an arrow in a polar plot.
DOAPointer = DOADisplay();

Создайте и сконфигурируйте алгоритмические стандартные блоки

Аудио длины Кадра

bufferLength = 64;

% Use a helper object to rearrange the input samples according the how the
% microphone pairs are selected
preprocessor = PairArrayPreprocessor(...
    'MicPositions', micPositions,...
    'MicPairs', micPairs,...
    'BufferLength', bufferLength);
micSeparations = getPairSeparations(preprocessor);

% The main algorithmic builing block of this example is a cross-correlator.
% That is used in conjunction with an interpolator to ensure a finer DOA
% resolution. In this simple case it is sufficient to use the same two
% objects across the different pairs available. In general, however,
% different channels may need to independently save their internal states
% and hence to be handled by separate objects.
XCorrelator = dsp.Crosscorrelator(...
    'Method', 'Frequency Domain');
interpFactor = 8;
b = interpFactor * fir1((2*interpFactor*8-1),1/interpFactor);
groupDelay = median(grpdelay(b));
interpolator = dsp.FIRInterpolator(...
    'InterpolationFactor',interpFactor,...
    'Numerator',b);

Получите и сигналы процесса в цикле

Для каждой итерации следующего цикла с условием продолжения: считайте audioFrameLength выборки для каждого звукового канала, обработайте данные, чтобы оценить значение DOA и отобразить результат на сделанной на заказ основанной на стрелке полярной визуализации.

tic
for idx = 1:(endTime*fs/audioFrameLength)
    cycleStart = toc;
    % Read a multichannel frame from the audio source
    % The returned array is of size AudioFrameLength x size(micPositions,2)
    multichannelAudioFrame = audioInput();

    % Rearrange the acquired sample in 4-D array of size
    % bufferLength x numBuffers x 2 x numPairs where 2 is the number of
    % channels per microphone pair
    bufferedFrame = preprocessor(multichannelAudioFrame);

    % First estimate the DOA for each pair, independently

    % Initialize arrays used across available pairs
    numBuffers = size(bufferedFrame, 2);
    delays = zeros(1,numPairs);
    anglesInRadians = zeros(1,numPairs);
    xcDense = zeros((2*bufferLength-1)*interpFactor, numPairs);

    % Loop through available pairs
    for kPair = 1:numPairs
        % Estimate inter-microphone delay for each 2-channel buffer
        delayVector = zeros(numBuffers, 1);
        for kBuffer = 1:numBuffers
            % Cross-correlate pair channels to get a coarse
            % crosscorrelation
            xcCoarse = XCorrelator( ...
                bufferedFrame(:,kBuffer,1,kPair), ...
                bufferedFrame(:,kBuffer,2,kPair));

            % Interpolate to increase spatial resolution
            xcDense = interpolator(flipud(xcCoarse));

            % Extract position of maximum, equal to delay in sample time
            % units, including the group delay of the interpolation filter
            [~,idxloc] = max(xcDense);
            delayVector(kBuffer) = ...
                (idxloc - groupDelay)/interpFactor - bufferLength;
        end

        % Combine DOA estimation across pairs by selecting the median value
        delays(kPair) = median(delayVector);

        % Convert delay into angle using the microsoft pair spatial
        % separations provided
        anglesInRadians(kPair) = HelperDelayToAngle(delays(kPair), fs, ...
            micSeparations(kPair));
    end

    % Combine DOA estimation across pairs by keeping only the median value
    DOAInRadians = median(anglesInRadians);

    % Arrow display
    DOAPointer(DOAInRadians)

    % Delay cycle execution artificially if using recorded data
    if(strcmp(sourceChoice,'recorded'))
        pause(audioFrameLength/fs - toc + cycleStart)
    end
end

release(audioInput)