You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32替换字符switch case实现按名称调用播放大量WAV文件方案咨询

方案1:直接传入文件名调用(最灵活,符合你要的playWAV(filename)需求)

直接修改playWAV函数的参数类型,不需要维护映射关系,新增WAV文件只要丢进SD卡对应目录即可直接调用:

// 函数第一个参数改为const char*类型,传入不带后缀的文件名
void playWAV (const char* effectName, int bg1248_general_volume)
{
  Serial.println("Entered playWAV");
  // 拼接完整SD卡路径
  char filePath[64];
  snprintf(filePath, sizeof(filePath), "/wav/%s.wav", effectName);
  file = new AudioFileSourceSD(filePath);
  // 新增文件存在判断,避免传错文件名导致程序崩溃
  if (!file->isOpen()) {
    Serial.printf("文件不存在:%s\n", filePath);
    delete file;
    return;
  }

  float volumeGain = ((float)bg1248_general_volume / 100.0) * 39.0;
  Serial.print("volumeGain:");
  Serial.println(volumeGain);
  id3 = new AudioFileSourceID3(file);
  out = new AudioOutputI2S(0, 0); // Output to builtInDAC
  out->SetPinout(12, 0, 2);
  out->SetOutputModeMono(true);
  out->SetGain(volumeGain);
  wav = new AudioGeneratorWAV();
  wav->begin(id3, out);
}

调用方式完全符合你的预期,原来的playWAV('a', 100)直接改成:

playWAV("alarm", 100);

后续新增WAV文件不需要修改函数内部代码,只要把xxx.wav放入SD卡的/wav目录,直接调用playWAV("xxx", 音量)即可。

方案2:枚举+映射数组(更严谨,避免写错文件名)

如果担心拼写字符串出错,可以用枚举做统一管理,编译期就能检查参数合法性:

  1. 先全局定义音频枚举和对应文件名映射:
// 定义所有音频效果的枚举,新增文件只要在这里加项即可,支持上千个都没问题
enum AudioEffect {
  EFFECT_ALARM,
  EFFECT_ALARM_HIGH,
  EFFECT_ALARM_LOW,
  EFFECT_ERROR,
  EFFECT_ERROR1,
  EFFECT_NO_READ,
  // 在这里新增71个新的音频枚举项即可
  EFFECT_MAX // 用来做边界校验
};

// 枚举和文件名的映射表,顺序要和上面的枚举完全对应
const char* g_effectFileMap[] = {
  "alarm",
  "alarmhigh",
  "alarmlow",
  "error",
  "error1",
  "noread",
  // 对应上面枚举的顺序补充文件名即可
};
  1. 修改playWAV函数:
void playWAV (AudioEffect effect, int bg1248_general_volume)
{
  Serial.println("Entered playWAV");
  // 先做参数合法校验
  if (effect < 0 || effect >= EFFECT_MAX) {
    Serial.println("无效的音频效果参数");
    return;
  }
  // 拼接路径
  char filePath[64];
  snprintf(filePath, sizeof(filePath), "/wav/%s.wav", g_effectFileMap[effect]);
  file = new AudioFileSourceSD(filePath);
  if (!file->isOpen()) {
    Serial.printf("文件不存在:%s\n", filePath);
    delete file;
    return;
  }

  // 后面的音量设置、播放逻辑和原来完全一致
  float volumeGain = ((float)bg1248_general_volume / 100.0) * 39.0;
  Serial.print("volumeGain:");
  Serial.println(volumeGain);
  id3 = new AudioFileSourceID3(file);
  out = new AudioOutputI2S(0, 0);
  out->SetPinout(12, 0, 2);
  out->SetOutputModeMono(true);
  out->SetGain(volumeGain);
  wav = new AudioGeneratorWAV();
  wav->begin(id3, out);
}

调用示例:

playWAV(EFFECT_ALARM, 100);

你之前用enum报case重复的错误,大概率是枚举项定义了重复的数值,按上面的方式顺序定义枚举、不手动赋值的话,编译器会自动从0开始递增赋值,不会出现重复问题。

额外注意事项

你当前代码里new出来的AudioFileSourceSD、AudioFileSourceID3、AudioOutputI2S、AudioGeneratorWAV对象,要记得在播放完成后手动delete释放内存,ESP32的堆内存很小,长期不释放会出现内存泄漏导致程序崩溃。

内容的提问来源于stack exchange,提问作者Krystal Shaw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 14:24:00