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

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

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

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

sourceChoice = 'recorded';

Установите длительность живой обработки. Установите сколько выборок на канал получать и обрабатывать каждую итерацию.

endTime = 20;
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'    
        % This audio file 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(length(micPositions),2). В этом случае эти 3 пары с самыми большими расстояниями межмикрофона выбраны. Чем больше расстояние межмикрофона, тем более чувствительный оценка DOA. Каждый столбец следующей матрицы описывает выбор пары микрофона в массиве. Все значения должны быть целыми числами между 1 и length(micPositions).

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

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

Создайте экземпляр помощника, строящего объект DOADisplay. Это отображает предполагаемый DOA, живой стрелой на полярном графике.

DOAPointer = DOADisplay();

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

Используйте объект помощника перестроить входные выборки согласно тому, как пары микрофона выбраны.

bufferLength = 64;
preprocessor = PairArrayPreprocessor( ...
    'MicPositions',micPositions, ...
    'MicPairs',micPairs, ...
    'BufferLength',bufferLength);
micSeparations = getPairSeparations(preprocessor);

Основной алгоритмический базовый блок этого примера является перекрестным коррелятором. Это используется в сочетании с интерполятором, чтобы гарантировать более прекрасное разрешение DOA. В этом простом случае достаточно использовать те же два объекта через различные доступные пары. В общем случае однако различные каналы, возможно, должны независимо сохранить свои внутренние состояния и следовательно быть обработаны отдельными объектами.

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 = xcorr( ...
                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)