exponenta event banner

Оценка направления поступления в реальном времени с помощью линейного микрофонного массива

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

Выбор и настройка источника аудиозаписей

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

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 встроенных микрофонов Kinect™ Microsoft относительно положения камеры RGB (в данном примере не используется). Для 3D координат используйте [[x1; y1; z1], [x2; y2; z2],..., [xN; yN; zN]]

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. В этом простом случае достаточно использовать одни и те же два объекта в различных доступных парах. В целом, однако, различные каналы могут нуждаться в независимом сохранении своих внутренних состояний и, следовательно, в обработке отдельными объектами.

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);

Получение и обработка сигналов в контуре

Для каждой итерации следующего цикла while: читать 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)