赞
踩
FP-AUD-SMARTMIC1是一个STM32Cube功能包。该软件包实现了一个完整的应用程序,目标是MEMS麦克风阵列的高级处理,包括数字MEMS麦克风采集、波束成形、源定位和回声消除。处理后的音频被发送到USB主机和连接到相关扩展板的扬声器。该功能包基于STM32Cube软件技术,可轻松在不同的STM32微控制器之间进行移植。
此示例实现支持两种系统:STM32 NUCLEO-F446RE开发板,配备X-NUCLEO-CA01M1或X-NUCLEO-CA02M2扩展板和STEVAL-MIC001V1、STEVAL-MIC002V1、STEVAL-MIC003V1或STEVAL-MIC 005V1数字麦克风评估板或BlueCoin
该软件也可以在GitHub上获得,用户可以通过“问题”和“拉取请求”选项卡发出错误信号并提出新想法。
所有功能
STM32Cube的软件扩展:
AcousticBF实时波束形成
AcousticEC实时声学回声消除
AcousticSL实时声源定位
完整的应用程序,包括单个示例应用程序中的所有声学功能软件图形用户界面,可从主机PC轻松控制参数和算法当连接到X-NUCLEO-CA01M1和X-NUCLEO-CA02M2扩展板时,NUCLEO-F446RE开发板上可用的示例实现
本文针对该功能包中的声源定位算法进行探索研究,相关算法文件的可以从Github中下载
文件夹路径fp-aud-smartmic1-main\Middlewares\ST\STM32_AcousticSL_Library
重点文件内容
- /*
- 此文件包含声学声源定位库定义。
- */
- #ifndef __ACOUSTIC_SL_H
- #define __ACOUSTIC_SL_H
-
- #include "stdint.h"
-
- /*算法类型定义*/
- #define ACOUSTIC_SL_ALGORITHM_XCORR ((uint32_t)0x00000001)
- #define ACOUSTIC_SL_ALGORITHM_GCCP ((uint32_t)0x00000002)
- #define ACOUSTIC_SL_ALGORITHM_BMPH ((uint32_t)0x00000004)
-
- /*错误类型*/
- #define ACOUSTIC_SL_ALGORITHM_ERROR ((uint32_t)0x00000001)
- #define ACOUSTIC_SL_PTR_CHANNELS_ERROR ((uint32_t)0x00000002)
- #define ACOUSTIC_SL_CHANNEL_NUMBER_ERROR ((uint32_t)0x00000004)
- #define ACOUSTIC_SL_SAMPLING_FREQ_ERROR ((uint32_t)0x00000008)
- #define ACOUSTIC_SL_RESOLUTION_ERROR ((uint32_t)0x00000010)
- #define ACOUSTIC_SL_THRESHOLD_ERROR ((uint32_t)0x00000020)
- #define ACOUSTIC_SL_DISTANCE_ERROR ((uint32_t)0x00000040)
- #define ACOUSTIC_SL_NUM_OF_SAMPLES_ERROR ((uint32_t)0x00000080)
- #define ACOUSTIC_SL_PROCESSING_ERROR ((uint32_t)0x00000100)
-
- #ifndef ACOUSTIC_LOCK_ERROR
- #define ACOUSTIC_LOCK_ERROR ((uint32_t)0x10000000)
- #endif
-
- /**/
- #define ACOUSTIC_SL_NO_AUDIO_DETECTED -100
-
- /*输出参数结构体*/
- typedef struct
- {
- /*算法类型选择,即上述定义的XCORR,GCCP和BMPH*/
- uint32_t algorithm;
-
- /*设置采样频率*/
- uint32_t sampling_frequency;
-
- /*设置通道数,2通道进行180°定位,4通道进行360°定位*/
- uint32_t channel_number;
-
- /*麦克风通道选择*/
- uint8_t ptr_M1_channels;
- uint8_t ptr_M2_channels;
- uint8_t ptr_M3_channels;
- uint8_t ptr_M4_channels;
-
- /*麦克风1,2之间的距离(mm),默认150*/
- uint16_t M12_distance;
- /*麦克风3,4之间的距离(mm),默认150*/
- uint16_t M34_distance;
-
- /*内部存储空间大小设置,采用AcousticSL_getMemorySize()函数*/
- uint32_t internal_memory_size;
-
- /*指向用户分配的内存*/
- uint32_t * pInternalMemory;
-
- /*指向单次处理的样本数*/
- int16_t samples_to_process;
-
- } AcousticSL_Handler_t;
-
- typedef struct
- {
- /*指定语音响度阈值,低于阈值算法不起作用,阈值范围从0到1000,默认值为24*/
- uint16_t threshold;
-
- /*算法的角度分辨率,默认值为4.如果使用XCORR,则忽略*/
- uint32_t resolution;
-
- } AcousticSL_Config_t;
-
-
- /*内存分配函数*/
- uint32_t AcousticSL_getMemorySize(AcousticSL_Handler_t * pHandler);
-
- /*初始化函数*/
- uint32_t AcousticSL_Init(AcousticSL_Handler_t * pHandler);
-
- /*数据输入函数*/
- uint32_t AcousticSL_Data_Input(void *pM1, void *pM2, void *pM3, void *pM4, AcousticSL_Handler_t * pHandler);
-
- /*音频处理函数*/
- uint32_t AcousticSL_Process(int32_t * Estimated_Angle, AcousticSL_Handler_t * pHandler);
-
- /*设置阈值与分辨率的值*/
- uint32_t AcousticSL_setConfig(AcousticSL_Handler_t * pHandler, AcousticSL_Config_t * pConfig);
-
- /*获取参数*/
- uint32_t AcousticSL_getConfig(AcousticSL_Handler_t * pHandler, AcousticSL_Config_t * pConfig);
-
- /*获取版本信息*/
- uint32_t AcousticSL_GetLibVersion(char *version);
-
- #endif
该功能可以选择三种不同的声源定位算法,分别是XCORR(时域互相关),GCCP(频域变换广义互相关),BMPH(The block-matching pursuit with hangover)
XCORR算法应用在时域,需要的资源较少,分辨率低,对麦克风放置距离有要求
GCCP算法应用在频域,需要的资源脚多,分辨率高,对麦克风放置距离无要求
BMPH算法应用在频域,需要的资源适中,对麦克风放置距离无要求,需要执行一个遗传的步骤,增强稳定性
双通道麦克风放置示意图
四通道麦克风放置示意图
对于XCORR算法分辨率取决于采样频率与麦克风之间的距离,如下式所示(floor下取整)
以双通道放置为例,麦克风间距10cm,采样频率100kHz,声速343.1m/s,可以计算得到角度分辨率为3°。如需要更高精度,则需要提高麦克风间距与采样频率。
- #include "libSoundSourceLoc.c"
-
- /*初始化函数*/
- uint32_t AcousticSL_Init(AcousticSL_Handler_t * pHandler)
- {
- return libSoundSourceLoc_Init(pHandler);
- }
-
- /*数据输入函数*/
- uint32_t AcousticSL_Data_Input(void *pM1, void *pM2, void *pM3, void *pM4, AcousticSL_Handler_t * pHandler)
- {
- return libSoundSourceLoc_Data_Input((int16_t *)pM1, (int16_t *)pM2, (int16_t *)pM3, (int16_t *)pM4, pHandler);
- }
-
- /*音频分析函数*/
- uint32_t AcousticSL_Process(int32_t * Estimated_Angle, AcousticSL_Handler_t * pHandler)
- {
- return libSoundSourceLoc_Process(Estimated_Angle, pHandler);
- }
-
- /*参数设置函数*/
- uint32_t AcousticSL_setConfig(AcousticSL_Handler_t * pHandler, AcousticSL_Config_t * pConfig)
- {
- return libSoundSourceLoc_setConfig(pHandler, pConfig);
- }
-
- /*获取参数函数*/
- uint32_t AcousticSL_getConfig(AcousticSL_Handler_t * pHandler, AcousticSL_Config_t * pConfig)
- {
- return libSoundSourceLoc_getConfig(pHandler, pConfig);
- }
-
- /*内存配置函数*/
- uint32_t AcousticSL_getMemorySize(AcousticSL_Handler_t * pHandler)
- {
- return libSoundSourceLoc_getMemorySize(pHandler);
- }
-
- /*获取版本信息*/
- uint32_t AcousticSL_GetLibVersion(char *version)
- {
- return libSoundSourceLoc_GetLibVersion(version);
- }
可以看到在AcousticSL.c文件中的所有函数都是调用libSoundSourceLoc.c中的函数,之后我们仔细阅读该函数中的库
- #ifndef __LIB_SOUNDSOURCELOC_H
- #define __LIB_SOUNDSOURCELOC_H
-
- #include "acoustic_sl.h"
- #include "arm_math.h"
- #include "math.h"
-
- struct _libSoundSourceLoc_Handler_Internal;
-
- typedef struct {
- float32_t (*SourceLocFunction)(struct _libSoundSourceLoc_Handler_Internal *SLocInternal, int32_t * out_angles);
- uint32_t (*CheckEventFunction)(struct _libSoundSourceLoc_Handler_Internal *SLocInternal);
- }libSoundSourceLoc_Handler_Callbacks;
-
- typedef struct _libSoundSourceLoc_Handler_Internal{
-
- /*采样频率*/
- uint32_t sampling_frequency;
-
- /*算法类型*/
- uint32_t Type;
-
- /**/
- uint32_t Buffer_State;
-
- /*采样数目*/
- uint32_t Sample_Number_To_Process;
-
- /*采样数目(每毫秒)*/
- uint16_t Sample_Number_Each_ms;
-
- /*输入数据数目*/
- uint16_t Input_Counter;
-
- /**/
- uint16_t EVENT_THRESHOLD;
-
- /*麦克风配置*/
- uint16_t Mic_Number;
- uint8_t ptr_M1_channels;
- uint8_t ptr_M2_channels;
- uint8_t ptr_M3_channels;
- uint8_t ptr_M4_channels;
-
- /*麦克风之间的距离和TAUD*/
- float32_t M12_distance;
- float32_t M34_distance;
- int32_t M12_TAUD;
- int32_t M34_TAUD;
-
- libSoundSourceLoc_Handler_Callbacks Callbacks;
-
- /*音频分析数据*/
- int32_t Estimated_Angle_12;
- int32_t Estimated_Angle_34;
- uint32_t resolution;
-
- void * M1_Data;
- void * M2_Data;
- void * M3_Data;
- void * M4_Data;
-
- arm_rfft_fast_instance_f32 * SFast;
-
- float32_t * FFT_Out;
- float32_t * PowerSpectrum;
- float32_t * Phase;
- float32_t * sumArray;
- int32_t * SourceLocFilterArray;
- int32_t * SourceLocFilterArray1;
- float32_t * window;
-
- //dz
- uint32_t Sample_Number_To_Store;
- uint8_t * remap_mic; // 4
- uint16_t num_of_freq;
- uint16_t num_of_angles;
- uint16_t freq_range_min;
- uint16_t freq_range_max;
-
- float32_t * mics_distance; // AUDIO_CHANNELS
- float32_t * mics_angle; // AUDIO_CHANNELS
- float32_t * theta; // NUM_ANGLES
- float32_t phi;//
- uint16_t mics_write_offset; //starting point in every mic \in {0,16,32,...} \subseteq [0 MIC_LEN)
- uint16_t mics_read_offset; //starting point in every mic \in 0,MIC_LEN
- int16_t * score_theta;// RESOLUTION
- uint8_t reactivity;
- uint8_t stability;
- uint8_t array_type;// CIRCULAR_ARRAY
- uint8_t local_stabilizer;
- float32_t * mic_tmp;//[DFT_LEN]
- float32_t * ptr_freq_energies;// ptr
- float32_t * s;//[2*AUDIO_CHANNELS*NUMOF_FREQ]
- int16_t * frequencies_under_analysis; // NUM OF FREQ
- int16_t * sources; // 2* OUTPUT SOURCES
- float32_t * steering_tau;
-
- } libSoundSourceLoc_Handler_Internal;
-
-
- #define FFT_POINTS 512
-
- #define LIB_VERSION ((uint32_t)0x00030000)
-
- #define FILTER_MIN 10
- #define FILTER_STEP_MAIN 10
- #define FILTER_MAX_MAIN 50
- #define FILTER_STEP_SEC 8
- #define FILTER_MAX_SEC 20
-
- #define FACTOR_INDEX_2_HZ (uint16_t)(SLocInternal->sampling_frequency/SLocInternal->Sample_Number_To_Process)
-
- #define MIN_RESOLUTION 4U
- #define MAX_NUM_OF_ANGLES (360U/MIN_RESOLUTION)
- #define MAX_NUM_OF_FREQUENCIES 16U
- #define MAX_AUDIO_CHANNELS 8U
- #define MAX_THRESHOLD 1000U
- #define NUM_OUTPUT_SOURCES 4U
- #define CIRCULAR_ARRAY 1U
- #define LINEAR_ARRAY 2U
-
- #ifndef SOUND_SPEED
- #define SOUND_SPEED (float32_t)343.1f
- #endif
-
- #ifndef UNUSED
- #define UNUSED(X) (void)X /* To avoid gcc/g++ warnings */
- #endif
-
- #include "doa_via_block_sparsity.c"
-
- #define Abs(x) ( (((float32_t)x) < 0.0f) ? (-((float32_t)x)) : ((float32_t)x))
- #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
- #define SaturaL(N, L) (((N)<(L))?(L):(N))
- #define SaturaH(N, H) (((N)>(H))?(H):(N))
-
- static uint32_t CheckEvent(libSoundSourceLoc_Handler_Internal * SLocInternal);
- static float32_t XCORR_GetAngle(libSoundSourceLoc_Handler_Internal * SLocInternal, int32_t * out_angles);
- static float32_t GCC_GetAngle(libSoundSourceLoc_Handler_Internal * SLocInternal, int32_t * out_angles);
- static int32_t get_max_pos(libSoundSourceLoc_Handler_Internal * SLocInternal,int32_t length,int32_t step);
- static void FilterAngle(int32_t *SourceAngle, int32_t* LedStatus, uint16_t max_value, uint16_t A, uint16_t SatA, uint16_t B, uint16_t SatB);
-
- /*版本信息*/
- static uint32_t libSoundSourceLoc_GetLibVersion(char *version)
- {
- char str1[35] = "ST AcousticSL v3.0.0";
-
- (void)strcpy(version, str1);
- return strlen(str1);
- }
-
- /*数据输入*/
- static uint32_t libSoundSourceLoc_Data_Input(void *pM1, void *pM2, void *pM3, void *pM4, AcousticSL_Handler_t * pHandler)
- {
- libSoundSourceLoc_Handler_Internal * SLocInternal = (libSoundSourceLoc_Handler_Internal *)(pHandler->pInternalMemory);
-
- uint8_t ret = 0;
- uint32_t i;
- /*如果XCORR和BMPH算法,输入数据格式为int16;如果GCCP算法,输入数据格式为float32*/
- /*兼容双通道麦克风与四通道麦克风*/
- if((SLocInternal->Type == ACOUSTIC_SL_ALGORITHM_XCORR) || (SLocInternal->Type == ACOUSTIC_SL_ALGORITHM_BMPH) )
- {
- for (i = 0; i < SLocInternal->Sample_Number_Each_ms; i ++)
- {
- ((int16_t *)(SLocInternal->M1_Data))[SLocInternal->Input_Counter] = ((int16_t *)(pM1))[i*SLocInternal->ptr_M1_channels];
- ((int16_t *)(SLocInternal->M2_Data))[SLocInternal->Input_Counter] = ((int16_t *)(pM2))[i*SLocInternal->ptr_M2_channels];
- if (SLocInternal->Mic_Number == 4U)
- {
- ((int16_t *)(SLocInternal->M3_Data))[SLocInternal->Input_Counter] = ((int16_t *)(pM3))[i*SLocInternal->ptr_M3_channels];
- ((int16_t *)(SLocInternal->M4_Data))[SLocInternal->Input_Counter] = ((int16_t *)(pM4))[i*SLocInternal->ptr_M4_channels];
- }
- SLocInternal->Input_Counter ++;
- }
- }
- else if(SLocInternal->Type == ACOUSTIC_SL_ALGORITHM_GCCP )
- {
- for (i = 0; i < SLocInternal->Sample_Number_Each_ms; i ++)
- {
- ((float32_t *)(SLocInternal->M1_Data))[SLocInternal->Input_Counter] = (float32_t)((int16_t *)(pM1))[i*SLocInternal->ptr_M1_channels];//todo interleaving
- ((float32_t *)(SLocInternal->M2_Data))[SLocInternal->Input_Counter] = (float32_t)((int16_t *)(pM2))[i*SLocInternal->ptr_M2_channels];
- if (SLocInternal->Mic_Number == 4U)
- {
- ((float32_t *)(SLocInternal->M3_Data))[SLocInternal->Input_Counter] = (float32_t)((int16_t *)(pM3))[i*SLocInternal->ptr_M3_channels];
- ((float32_t *)(SLocInternal->M4_Data))[SLocInternal->Input_Counter] = (float32_t)((int16_t *)(pM4))[i*SLocInternal->ptr_M4_channels];
- }
- SLocInternal->Input_Counter ++;
- }
- }
- else
- {
- /* no other use cases are handled */
- }
-
- /*如果算法是BMPH,需要设置mics_read_offset参数,对于双通道为0,四通道为Sample_Number_To_Store*/
- if(SLocInternal->Type == ACOUSTIC_SL_ALGORITHM_BMPH)
- {
- if(SLocInternal->Input_Counter == SLocInternal->Sample_Number_To_Store)
- {
- ret = 1;
- SLocInternal->Buffer_State = 1;
- SLocInternal->mics_read_offset= 0;
- }
- if(SLocInternal->Input_Counter == (SLocInternal->Sample_Number_To_Store * 2U))
- {
- ret = 1;
- SLocInternal->Buffer_State = 2;
- SLocInternal->Input_Counter = 0;
- SLocInternal->mics_read_offset = (uint16_t)SLocInternal->Sample_Number_To_Store;
- }
- }
- else
- {
- if(SLocInternal->Input_Counter == SLocInternal->Sample_Number_To_Store)
- {
- ret = 1;
- SLocInternal->Buffer_State = 1;
- }
- if(SLocInternal->Input_Counter == (SLocInternal->Sample_Number_To_Store * 2U))
- {
- ret = 1;
- SLocInternal->Buffer_State = 2;
- SLocInternal->Input_Counter = 0;
- }
- }
-
- return ret;
- }
-
- /*音频处理函数*/
- static uint32_t libSoundSourceLoc_Process(int32_t * Estimated_Angle, AcousticSL_Handler_t * pHandler)
- {
- libSoundSourceLoc_Handler_Internal * SLocInternal = (libSoundSourceLoc_Handler_Internal *)(pHandler->pInternalMemory);
-
- /*计算寄存变量*/
- int32_t Estimated_temp_360[2];
-
- /*Buffer_State不为0,即完成数据输入*/
- if(SLocInternal->Buffer_State!=0U)
- {
- /*如果BMPH算法,或者调用Check函数返回1,则采用定位函数。否则寄存变量1变为-1*/
- if((SLocInternal->Type==ACOUSTIC_SL_ALGORITHM_BMPH) || (SLocInternal->Callbacks.CheckEventFunction(SLocInternal)==1))
- {
- SLocInternal->Callbacks.SourceLocFunction(SLocInternal,Estimated_temp_360);
- }
- else
- {
- Estimated_temp_360[0]=-1;
- }
- }
-
- /*如果BMPH算法,调用定位函数之后,如果寄存变量1为-500,则会重新赋值-100*/
- if (SLocInternal->Type == ACOUSTIC_SL_ALGORITHM_BMPH)
- {
- if (Estimated_temp_360[0]==-500)
- {
- Estimated_temp_360[0]=-100;
- }
- }
- /*如果不是BMPH算法,但是四通道输入*/
- else if(SLocInternal->Mic_Number==4U)
- {
- STEP
- /*角度计算前需要进行滤波处理,滤波器参数设计(360,STEPM,MAXM,STEPS,MAXS)*/
- FilterAngle((int32_t *)&Estimated_temp_360[0], SLocInternal->SourceLocFilterArray, 360 , FILTER_STEP_MAIN , FILTER_MAX_MAIN, FILTER_STEP_SEC ,FILTER_MAX_SEC);
-
- /*如果寄存变量1为-1,寄存变量1重新赋值-100*/
- if(Estimated_temp_360[0]==-1)
- {
- Estimated_temp_360[0]=-100;
- }
- }
- /*如果不是BMPH算法,且双通道输入*/
- else
- {
- /*角度计算前需要进行滤波处理,滤波器固定参数(180,10,50,8,20)*/
- FilterAngle((int32_t *)&Estimated_temp_360[0], SLocInternal->SourceLocFilterArray, 180 , 10 , 50, 8 ,20);
-
- /*如果寄存变量1为-1,寄存变量1重新赋值-100,否则寄存变量1值减90*/
- if(Estimated_temp_360[0]==-1)
- {
- Estimated_temp_360[0]=-100;
- }
- else
- {
- Estimated_temp_360[0]-=90;
- }
- }
-
- /*计算角度参数1为寄存变量1*/
- Estimated_Angle[0] = Estimated_temp_360[0];
- return 0;
- }
- static float32_t XCORR_GetAngle(libSoundSourceLoc_Handler_Internal * SLocInternal, int32_t * out_angles)
- {
- /*tau时延*/
- int32_t tau, k;
- float32_t delta_t24 = 0.0f;
- float32_t delta_t13 = 0.0f;
- float32_t test = 0.0f;
- uint32_t correlation, MAX13, MAX24;
- if(SLocInternal->Mic_Number >= 2U)
- {
- MAX13=0x80000000U; //-inf
- /*遍历所有离散时域信号延迟*/
- for(tau=-SLocInternal->M12_TAUD;tau<=SLocInternal->M12_TAUD;tau++)
- {
- correlation=0;
- /*互相关计算*/
- for(k=SLocInternal->M12_TAUD; k<((int32_t)SLocInternal->Sample_Number_To_Process-SLocInternal->M12_TAUD);k++)
- {
- correlation = correlation + (((uint32_t)((int16_t *)(SLocInternal->M2_Data))[((SLocInternal->Buffer_State-1U)*SLocInternal->Sample_Number_To_Process)+(uint32_t)k] * (uint32_t)((int16_t *)(SLocInternal->M1_Data))[((SLocInternal->Buffer_State-1U)*SLocInternal->Sample_Number_To_Process)+(uint32_t)k+(uint32_t)tau])/256U);
- }
- /*寻找互相关计算的最大值与对应的时延值*/
- if (correlation > MAX13)
- {
- MAX13 = correlation;
- delta_t13=(float32_t)tau;
- }
- }
- }
- /*针对四通道,格外计算M34之间的互相关*/
- if(SLocInternal->Mic_Number == 4U)
- {
- MAX24=0x80000000U; //-inf
- for(tau=-SLocInternal->M34_TAUD;tau<=SLocInternal->M34_TAUD;tau++)
- {
- correlation=0;
- for(k=SLocInternal->M34_TAUD; k<((int32_t)SLocInternal->Sample_Number_To_Process-SLocInternal->M34_TAUD); k++)
- {
- correlation = correlation + (((uint32_t)((int16_t *)(SLocInternal->M4_Data))[((SLocInternal->Buffer_State-1U)*SLocInternal->Sample_Number_To_Process)+(uint32_t)k] * (uint32_t)((int16_t *)(SLocInternal->M3_Data))[((SLocInternal->Buffer_State-1U)*SLocInternal->Sample_Number_To_Process)+(uint32_t)k+(uint32_t)tau])/256U);
- }
- if (correlation > MAX24)
- {
- MAX24 = correlation;
- delta_t24=(float32_t)tau;
- }
- }
- }
- /*通过计算得到的互相关最大时的时延和最大时延进行角度计算*/
- SLocInternal->Buffer_State=0;
- if(SLocInternal->Mic_Number == 2U)
- {
- test = (delta_t13+(float32_t)SLocInternal->M12_TAUD )* (180.0f/((float32_t)SLocInternal->M12_TAUD*2.0f));
- }
- else if(SLocInternal->Mic_Number == 4U)
- {
- test=(float32_t)atan2(delta_t13, delta_t24);
- test= test * (360.0f / (3.14f*2.0f) );
- if(test<0.0f)
- {
- test+=360.0f; /* in [0 360] -> TODO: Optimize the whole angle computation from the maximum phase index*/
- }
- }
- else
- {
- /* no other use cases are handled */
- }
-
- out_angles[0]=(int32_t)test;
- return test;
- }
使用XCORR算法,以双通道输入为例,基于采集到的麦克风数据,通过增加不同的时延,调整两个序列时间差进行互相关的计算,当补充时延到两个麦克风采集到的信号相同时互相关计算值最大。即可通过补充的时延值判断声源的角度。
SLocInternal->M12_TAUD = (int32_t)SLocInternal->M12_distance * ((int32_t)SLocInternal->sampling_frequency/(int32_t)SOUND_SPEED);
SLocInternal->M34_TAUD =(int16_t)floor((float64_t)SLocInternal->M34_distance * ((float64_t)SLocInternal->sampling_frequency/(float64_t)SOUND_SPEED));
- static float32_t GCC_GetAngle(libSoundSourceLoc_Handler_Internal * SLocInternal, int32_t * out_angles)
- {
- uint32_t j;
- float32_t fi = 0.0f;;
- uint32_t buffer_offset = (SLocInternal->Buffer_State-1U)*SLocInternal->Sample_Number_To_Process;
- float32_t * M1_Data = (float32_t *)SLocInternal->M1_Data;
- float32_t * M2_Data = (float32_t *)SLocInternal->M2_Data;
- float32_t * M3_Data = (float32_t *)SLocInternal->M3_Data;
- float32_t * M4_Data = (float32_t *)SLocInternal->M4_Data;
- float32_t * Power_Spectrum = (float32_t *)SLocInternal->PowerSpectrum;
- float32_t * FFT_Out = (float32_t *)SLocInternal->FFT_Out;
- float32_t * hanning = (float32_t *)SLocInternal->window;
- float32_t tempMag = 1e-7f;
- /*WINDOWING*/
- /*处理用的窗函数*/
- for(j=0;j<SLocInternal->Sample_Number_To_Process;j++)
- {
- if(SLocInternal->Mic_Number >= 2U)
- {
- M1_Data[buffer_offset + j] *= hanning[j];
- M2_Data[buffer_offset + j] *= hanning[j];
- }
- if(SLocInternal->Mic_Number == 4U)
- {
- M3_Data[buffer_offset + j] *= hanning[j];
- M4_Data[buffer_offset + j] *= hanning[j];
- }
- }
- /*FFTs*/
- /*进行傅里叶变换,得到频域数据*/
- if(SLocInternal->Mic_Number >= 2U)
- {
- /*M1 FFT*/
- arm_rfft_fast_f32(SLocInternal->SFast,&M1_Data[buffer_offset],(float32_t *)FFT_Out,0);
- for (j=0;j<SLocInternal->Sample_Number_To_Process;j++)
- {
- M1_Data[buffer_offset + j]=((float32_t *)FFT_Out)[j];
- }
- /*M2 FFT*/
- arm_rfft_fast_f32(SLocInternal->SFast,&M2_Data[buffer_offset],(float32_t *)FFT_Out,0);
- for (j=0;j<SLocInternal->Sample_Number_To_Process;j++)
- {
- M2_Data[buffer_offset + j]=((float32_t *)FFT_Out)[j];
- }
- }
- if(SLocInternal->Mic_Number == 4U)
- {
- /*M3 FFT*/
- arm_rfft_fast_f32(SLocInternal->SFast,&M3_Data[buffer_offset],(float32_t *)FFT_Out,0);
- for (j=0;j<SLocInternal->Sample_Number_To_Process;j++)
- {
- M3_Data[buffer_offset + j]=((float32_t *)FFT_Out)[j];
- }
- /*M4 FFT*/
- arm_rfft_fast_f32(SLocInternal->SFast,&M4_Data[buffer_offset],(float32_t *)FFT_Out,0);
- for (j=0;j<SLocInternal->Sample_Number_To_Process;j++)
- {
- M4_Data[buffer_offset + j]=((float32_t *)FFT_Out)[j];
- }
- }
-
- /*FILTERING*/
- if(SLocInternal->Mic_Number >= 2U)
- {
- M1_Data[buffer_offset]=0.0f;
- M2_Data[buffer_offset]=0.0f;
-
- M1_Data[buffer_offset+1U]=0.0f;
- M2_Data[buffer_offset+1U]=0.0f;
- }
- if(SLocInternal->Mic_Number == 4U)
- {
- M3_Data[buffer_offset]=0.0f;
- M4_Data[buffer_offset]=0.0f;
-
- M3_Data[buffer_offset+1U]=0.0f;
- M4_Data[buffer_offset+1U]=0.0f;
- }
-
- if(SLocInternal->Mic_Number >= 2U)
- {
- /*POWER SPECTRUM*/
- for(j=0; j<(SLocInternal->Sample_Number_To_Process/8U); j++)
- {
- Power_Spectrum[(j*2U)] = (M2_Data[buffer_offset+(j*2U)] * M1_Data[buffer_offset+(j*2U)]) + (M2_Data[buffer_offset+(j*2U)+1U] * M1_Data[buffer_offset+(j*2U)+1U]);
- Power_Spectrum[(j*2U)+1U] = (-((M2_Data[buffer_offset+(j*2U)])*(M1_Data[buffer_offset+(j*2U)+1U]))) + (M2_Data[buffer_offset+(j*2U)+1U] * M1_Data[buffer_offset+(j*2U)]);
-
- float32_t arg_sqrtf = (Power_Spectrum[(j*2U)]*Power_Spectrum[(j*2U)]) + (Power_Spectrum[(j*2U)+1U]*Power_Spectrum[(j*2U)+1U]);
- if (arg_sqrtf >= 0.0f)
- {
- tempMag=sqrtf(arg_sqrtf);
- if(tempMag<(1e-7f))
- {
- tempMag=(1e-7f);
- }
- }
- Power_Spectrum[(j*2U)]=(Power_Spectrum[(j*2U)])/tempMag;
- Power_Spectrum[(j*2U)+1U]=(Power_Spectrum[(j*2U)+1U])/tempMag;
- }
-
- int32_t angle;
- float32_t anglesNum=(180.0f/(float32_t)SLocInternal->resolution);
-
- for(angle=0;angle<(int32_t)anglesNum;angle++)
- {
- float32_t idftSum=0.0f;
- int32_t bin;
- float32_t theta;
- float32_t cosineTerm;
- float32_t sineTerm;
- float32_t theta_term= -2.0f*PI*(float32_t)SLocInternal->sampling_frequency*SLocInternal->M12_distance*(float32_t)arm_cos_f32(PI - ((PI*(float32_t)angle)/(anglesNum-1.0f)))/((float32_t)SLocInternal->Sample_Number_To_Process*SOUND_SPEED);
- for(bin=0; bin<((int32_t)SLocInternal->Sample_Number_To_Process/8); bin++)
- {
- theta = theta_term*(float32_t)bin;
- cosineTerm=arm_cos_f32(theta);
- sineTerm=arm_sin_f32(theta);
- idftSum+=(Power_Spectrum[2*bin]*cosineTerm)-(Power_Spectrum[(2*bin)+1]*sineTerm);
- }
- SLocInternal->Phase[angle]=idftSum;
- }
-
- SLocInternal->Estimated_Angle_12=get_max_pos(SLocInternal,(int32_t)anglesNum,(((int32_t)anglesNum/40)+1));
- SLocInternal->Estimated_Angle_12= 180-(int32_t)floor((180.0/((float64_t)anglesNum*2.0))+((float64_t)SLocInternal->Estimated_Angle_12*(float64_t)(SLocInternal->resolution)));
- }
- if(SLocInternal->Mic_Number == 4U)
- {
- /*POWER SPECTRUM*/
- for(j=0; j<(SLocInternal->Sample_Number_To_Process/8U); j++)
- {
- Power_Spectrum[(j*2U)] = (M4_Data[buffer_offset+(j*2U)] * M3_Data[buffer_offset+(j*2U)]) + (M4_Data[buffer_offset+(j*2U)+1U] * M3_Data[buffer_offset+(j*2U)+1U]);
- Power_Spectrum[(j*2U)+1U] = (-((M4_Data[buffer_offset+(j*2U)])*(M3_Data[buffer_offset+(j*2U)+1U]))) + (M4_Data[buffer_offset+(j*2U)+1U] * M3_Data[buffer_offset+(j*2U)]);
-
- float32_t arg_sqrtf = (Power_Spectrum[(j*2U)]*Power_Spectrum[(j*2U)]) + (Power_Spectrum[(j*2U)+1U]*Power_Spectrum[(j*2U)+1U]);
- if (arg_sqrtf >= 0.0f)
- {
- tempMag=sqrtf(arg_sqrtf);
- if(tempMag<(1e-7f))
- {
- tempMag=(1e-7f);
- }
- }
- Power_Spectrum[(j*2U)]=(Power_Spectrum[(j*2U)])/tempMag;
- Power_Spectrum[(j*2U)+1U]=(Power_Spectrum[(j*2U)+1U])/tempMag;
- }
-
- int32_t angle;
- float32_t anglesNum=(180.0f/(float32_t)SLocInternal->resolution);
-
- for(angle=0;angle<(int32_t)anglesNum;angle++)
- {
- float32_t idftSum=0.0f;
- int32_t bin;
- float32_t theta;
- float32_t cosineTerm;
- float32_t sineTerm;
- float32_t theta_term= -2.0f*PI*(float32_t)SLocInternal->sampling_frequency*SLocInternal->M34_distance*(float32_t)arm_cos_f32(PI - ((PI*(float32_t)angle)/(anglesNum-1.0f)))/((float32_t)SLocInternal->Sample_Number_To_Process*SOUND_SPEED);
- for(bin=0; bin<((int32_t)SLocInternal->Sample_Number_To_Process/8); bin++)
- {
- theta = theta_term*(float32_t)bin;
- cosineTerm=arm_cos_f32(theta);
- sineTerm=arm_sin_f32(theta);
- idftSum+=(Power_Spectrum[2*bin]*cosineTerm)-(Power_Spectrum[(2*bin)+1]*sineTerm);
- }
- SLocInternal->Phase[angle]=idftSum;
- }
-
- SLocInternal->Estimated_Angle_34=get_max_pos(SLocInternal,(int32_t)anglesNum,(((int32_t)anglesNum/40)+1));
- SLocInternal->Estimated_Angle_34= 180-(int32_t)floor((180.0/((float64_t)anglesNum*2.0))+((float64_t)SLocInternal->Estimated_Angle_34*(float64_t)(SLocInternal->resolution)));
- }
- float32_t angle_out_f = 0.0f;
-
- if(SLocInternal->Mic_Number == 2U)
- {
- angle_out_f=(float32_t)SLocInternal->Estimated_Angle_12;
- }
- else if (SLocInternal->Mic_Number == 4U)
- {
- if((SLocInternal->Estimated_Angle_12 + SLocInternal->Estimated_Angle_34) < (90 - ((int32_t)SLocInternal->resolution * 2)))
- {
- out_angles[0]=-1;
- out_angles[1]=-1;
- return -1.0f;
- }
- else
- {
- float32_t angle1_f = arm_cos_f32((((float32_t)SLocInternal->Estimated_Angle_12)/180.0f)*3.14f);
- float32_t angle2_f = arm_cos_f32((((float32_t)SLocInternal->Estimated_Angle_34)/180.0f)*3.14f);
- float32_t cos_fi = 0.0f;
- float32_t arg_cos_fi = 1.0f - (angle1_f*angle1_f) - (angle2_f*angle2_f);
-
- if (arg_cos_fi >= 0.0f)
- {
- cos_fi = sqrtf(arg_cos_fi);
- }
- angle_out_f = atan2f((angle1_f),(angle2_f));
- angle_out_f= angle_out_f * (360.0f / (3.14f*2.0f));
- if(angle_out_f < 0.0f)
- {
- angle_out_f+=360.0f; /* in [0 360] -> TODO: Optimize the whole angle computation from the maximum phase index*/
- }
-
- if ((cos_fi <= 1.0f) && (cos_fi >= -1.0f))
- {
- fi = acosf(cos_fi)*180.0f/3.14f;
- }
- }
- }
-
- SLocInternal->Buffer_State=0;
- out_angles[0]=(int32_t)angle_out_f;
-
- if(isnan(fi)!= 0U)
- {
- out_angles[1]=(int32_t)fi;
- }
- else
- {
- out_angles[1]=-1;
- }
-
- return angle_out_f;
- }
(更新中)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。