目录1.概述1.1 AVAS简介1.2 AVAS出现的原因2.实现方案2.1 方案简介2.2 技术要求2.3方案架构3. 关键代码实现3.1 Avas_core文件3.1.1数据结构3.1.2 计算频率3.2 audio_engine代码3.2.1 引擎关键结构3.2.2 产生波形3.2.3 初始化引擎3.2.4 播放线程3.3 主函数调用1.概述1.1 AVAS简介AVASAcoustic Vehicle Alerting System声学车辆警报系统是一种用于电动汽车和混合动力汽车的声音警报系统。由于这些车辆在低速行驶时几乎没有发动机噪音可能对行人特别是视障人士构成安全隐患AVAS的作用就是在车辆低速行驶时发出可识别的声音。1.2 AVAS出现的原因行人安全: 在低速行驶时电动汽车几乎无声行人难以察觉盲人辅助: 视力障碍者依赖听觉判断车辆位置和速度法规要求: 多国已立法要求电动汽车安装AVAS系统事故预防: 降低因车辆无声造成的交通事故对于AVAS有相应的国标最新的是GBT 371532018 电动汽车低速提示音》, 从2024年慢慢开始变成强制性要求。2.实现方案2.1 方案简介本文实现一个AVAS简单算法算法对应相应的demo可以在linux系统下运行基于Linux的ALSA接口。完全符合国标: 严格遵循GBT 371532018标准两种音色: 提供未来科技、正弦波音色智能调节: 声音随车速智能变化自动验证: 内置国标合规性检查可视化分析: 完整的频谱和波形分析工具2.2 技术要求1适用范围标准适用于最高车速大于20 km/h的电动汽车要求在车速不大于20 km/h时发出提示音。2 速度范围激活速度: 车速 ≤ 20 km/h系统响应: 车速变化时声音特性应相应变化3 声压级要求| 测量位置 | 最小声压级 | 最大声压级 || 车辆前方2m处 | 56 dB(A) | 75 dB(A) || 车辆侧方2m处 | 56 dB(A) | 75 dB(A) |4 频率要求总体频率范围: 160 Hz ~ 5000 Hz主要频率成分: 至少包含2个1/3倍频程频率分布: 应包含多个频率成分避免单一纯音5 声音特性要求可识别性: 声音应易于识别为车辆声音方向性: 行人应能判断车辆方向和运动趋势连续性: 车辆行驶时应连续发声变化性: 声音特性应随车速变化2.3方案架构AVAS架构如下图1 AVAS系统架构这里AVAS系统比较简单包括AVAS控制器 AvasController音频生成器AvasCore以及音频调度引擎AudioEngine。AvasController是总控根据输入信号生成音频后通过音频接口发声。以下为类图和序列图图2 类图图3序列图代码文件结构如下图4 代码结构avas_core是核心算法类audio_engine产生波形并调用linux alsa接口完成播放3. 关键代码实现3.1 Avas_core文件3.1.1数据结构/* 常量定义 */ #define AVAS_MAX_SPEED_KMH 20.0f /* AVAS触发的最大车速 (km/h) */ #define AVAS_MIN_FREQ_HZ 315.0f /* 最小频率 (Hz) */ #define AVAS_MAX_FREQ_HZ 5000.0f /* 最大频率 (Hz) */ #define AVAS_MIN_DB 56.0f /* 最小声压级 (dB) */ #define AVAS_MAX_DB 75.0f /* 最大声压级 (dB) */ /** * brief AVAS状态结构体 */ typedef struct { float speed_kmh; /* 当前车速 (km/h) */ float frequency_hz; /* 当前提示音频率 (Hz) */ float volume_db; /* 当前音量 (dB) */ bool is_active; /* AVAS系统是否激活 */ } avas_state_t;3.1.2 计算频率/** * brief 计算提示音频率随车速线性增加 * param speed_kmh 车速 (km/h) * return 频率 (Hz) */ static float calculate_frequency(float speed_kmh) { if (speed_kmh 0.0f) { return AVAS_MIN_FREQ_HZ; } /* 频率随车速线性增加: 0 km/h - 315 Hz, 20 km/h - 2000 Hz */ float freq AVAS_MIN_FREQ_HZ (speed_kmh / AVAS_MAX_SPEED_KMH) * (2000.0f - AVAS_MIN_FREQ_HZ); /* 限制在标准范围内 */ if (freq AVAS_MIN_FREQ_HZ) freq AVAS_MIN_FREQ_HZ; if (freq AVAS_MAX_FREQ_HZ) freq AVAS_MAX_FREQ_HZ; return freq; }3.1.3 计算音量** * brief 计算音量随车速变化 * param speed_kmh 车速 (km/h) * return 音量 (dB) */ static float calculate_volume(float speed_kmh) { /* 音量随速度略微增加: 0 km/h - 60 dB, 20 km/h - 70 dB */ float volume 60.0f (speed_kmh / AVAS_MAX_SPEED_KMH) * 10.0f; /* 限制在标准范围内 */ if (volume AVAS_MIN_DB) volume AVAS_MIN_DB; if (volume AVAS_MAX_DB) volume AVAS_MAX_DB; return volume; }3.1.4 更新状态/** * brief 更新AVAS系统状态 */ bool avas_update(avas_state_t *state, float speed_kmh) { if (state NULL) return false; /* 确保速度非负 */ if (speed_kmh 0.0f) speed_kmh 0.0f; state-speed_kmh speed_kmh; /* GB/T 37153-2018: 车速 20 km/h 时激活AVAS */ if (speed_kmh AVAS_MAX_SPEED_KMH) { state-is_active true; state-frequency_hz calculate_frequency(speed_kmh); state-volume_db calculate_volume(speed_kmh); } else { state-is_active false; state-frequency_hz 0.0f; state-volume_db 0.0f; } return state-is_active; }3.2 audio_engine代码3.2.1 引擎关键结构/* 音效风格 */ typedef enum { SOUND_STYLE_SINE 0, /* 正弦波平滑科技感 */ SOUND_STYLE_FUTURISTIC 1 /* 未来感带谐波 */ } sound_style_t; /** * brief 音频引擎状态 */ typedef struct { void *alsa_handle; /* ALSA设备句柄 */ sound_style_t style; /* 当前音效风格 */ float current_freq; /* 当前频率 */ float current_volume; /* 当前音量 */ bool is_playing; /* 是否正在播放 */ uint32_t sample_rate; /* 采样率 */ double phase; /* 波形相位 */ } audio_engine_t;3.2.2 产生波形/** * brief 生成正弦波音效 */ static void generate_sine_wave(int16_t *buffer, int frames, audio_engine_t *engine) { float amplitude db_to_amplitude(engine-current_volume); float freq engine-current_freq; for (int i 0; i frames; i) { float sample amplitude * sinf(2.0f * M_PI * engine-phase); buffer[i] (int16_t)(sample * 32767.0f); engine-phase freq / SAMPLE_RATE; if (engine-phase 1.0) engine-phase - 1.0; } }/** * brief 生成未来感音效基础频率谐波 */ static void generate_futuristic_sound(int16_t *buffer, int frames, audio_engine_t *engine) { float amplitude db_to_amplitude(engine-current_volume); float freq engine-current_freq; for (int i 0; i frames; i) { /* 基础频率 */ float sample 0.6f * sinf(2.0f * M_PI * engine-phase); /* 添加三次谐波增加科技感 */ sample 0.25f * sinf(2.0f * M_PI * engine-phase * 3.0f); /* 添加五次谐波增加丰富度 */ sample 0.15f * sinf(2.0f * M_PI * engine-phase * 5.0f); buffer[i] (int16_t)(sample * amplitude * 32767.0f); engine-phase freq / SAMPLE_RATE; if (engine-phase 1.0) engine-phase - 1.0; } }3.2.3 初始化引擎/** * brief 初始化音频引擎 */ int audio_engine_init(audio_engine_t *engine, sound_style_t style) { if (engine NULL) return -1; memset(engine, 0, sizeof(audio_engine_t)); engine-style style; engine-sample_rate SAMPLE_RATE; engine-phase 0.0; /* 打开ALSA设备 */ snd_pcm_t *pcm_handle; int err snd_pcm_open(pcm_handle, default, SND_PCM_STREAM_PLAYBACK, 0); if (err 0) { return -1; } /* 配置ALSA参数 */ snd_pcm_hw_params_t *params; snd_pcm_hw_params_alloca(params); snd_pcm_hw_params_any(pcm_handle, params); snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(pcm_handle, params, CHANNELS); snd_pcm_hw_params_set_rate_near(pcm_handle, params, engine-sample_rate, 0); err snd_pcm_hw_params(pcm_handle, params); if (err 0) { snd_pcm_close(pcm_handle); return -1; } snd_pcm_prepare(pcm_handle); /* 启动播放线程 */ g_audio_data.pcm_handle pcm_handle; g_audio_data.engine engine; g_audio_data.running true; if (pthread_create(g_audio_data.thread, NULL, audio_playback_thread, g_audio_data) ! 0) { snd_pcm_close(pcm_handle); return -1; } engine-alsa_handle pcm_handle; return 0; }3.2.4 播放线程/** * brief 音频播放线程 */ static void *audio_playback_thread(void *arg) { audio_thread_data_t *data (audio_thread_data_t *)arg; int16_t buffer[BUFFER_FRAMES]; while (data-running) { if (data-engine-is_playing) { /* 根据风格生成音频 */ if (data-engine-style SOUND_STYLE_SINE) { generate_sine_wave(buffer, BUFFER_FRAMES, style="margin-left:0px; margin-right:0px">3.3 主函数调用int main() { ...... /* 初始化AVAS系统 */ avas_init(avas_state); avas_update(avas_state, current_speed); /* 初始化音频引擎 */ if (audio_engine_init(audio, current_style) ! 0) { ...... } /* 主循环 */ while (running) { /* 显示状态 */ display_status(avas_state, current_style); /* 检查按键 */ int key get_key(); if (key ! -1) { ...... } /* 限制速度范围 */ if (current_speed 0.0f) current_speed 0.0f; if (current_speed 30.0f) current_speed 30.0f; /* 更新AVAS状态 */ avas_update(avas_state, current_speed); } /* 根据AVAS状态控制音频 */ if (avas_state.is_active) { audio_engine_update(audio, avas_state.frequency_hz, avas_state.volume_db); if (!audio.is_playing) { audio_engine_play(audio, avas_state.frequency_hz, avas_state.volume_db); } } else { audio_engine_stop(audio); } ...... } /* 清理资源 */ audio_engine_destroy(audio); clear_screen(); printf(\n COLOR_GREEN 感谢使用AVAS演示系统\n COLOR_RESET); return 0; }