Этот пример показывает, как получить и обработать live многоканальное аудио. Он также представляет простой алгоритм для оценки направления прибытия (DOA) источника звука с использованием нескольких пар микрофонов в линейном массиве.
Если доступен многоканальный входной аудиоинтерфейс, измените этот скрипт, чтобы задать sourceChoice
на 'live'
. В этом режиме пример использует live audio входные сигналы. Пример предполагает, что все входы (два или более) управляются микрофонами, расположенными на линейном массиве. Если массив микрофонов или многоканальная аудиокарта не доступны, установите sourceChoice
на 'recorded'
. В этом режиме в примере используются предварительно записанные аудио выборки, полученные с помощью линейного массива. Для sourceChoice = 'live'
, следующий код использует audioDeviceReader
получить 4 канала аудиосигнала через Microsoft Kinect™ для Windows ®. Чтобы использовать другую настройку микрофонного массива, убедитесь, что установленный драйвер аудио устройства является одним из обычных типов, поддерживаемых MATLAB, и установите Device
свойство audioDeviceReader
соответственно. Можно запросить допустимое Device
назначения для вашего компьютера вызовом getAudioDevices
функция объекта от audioDeviceReader
. Обратите внимание, что даже при использовании Microsoft Kinect имя устройства может различаться на разных компьютерах и может не совпадать с именем, используемым в этом примере. Используйте заполнение клавишей Tab, чтобы получить правильное имя на вашем компьютере.
sourceChoice = 'recorded';
Установите длительность live обработки. Установите, сколько выборок на канал для получения и обработки каждой итерации.
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; 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);
Создайте образец вспомогательного объекта построения графика 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: read 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)