Files
youle_app_ios_v2/.gitignore
T
joywayer 5b38456c66 3.B:vendor opencore-amr + AMRCodec Swift wrapper,打通 AMR↔WAV 编解码
为支撑 H5 的 prepareaudio / mediaTypeAudio 录音上传 + 远端语音播放
(docs/H5-Native-Contract.md §3.1 [4][5] + §3.2 [9])接入 AMR-NB
编解码能力。AMR-NB 是跨端(iOS / Android / 旧版本客户端)契约硬约束,
不可换 AAC / Opus。

## 接入路径

直接 vendor daoqi msext 现成的 fat .a(已上线多年),不打 xcframework /
不重编源码:
- Vendor/OpenCoreAMR/v0.1.x/libopencore-amrnb.a:daoqi 同款 5-slice fat
  库(含 2026-06-20 lipo -segalign 8 修过的对齐版本)
- Vendor/OpenCoreAMR/v0.1.x/{interf_dec,interf_enc}.h:amrnb 公开头
- Vendor/OpenCoreAMR/README.md:来源、版本、修复历史、为何不打 xcframework
- ylgamehall/Source/Audio/AMRFileCodec/{amrFileCodec.h,amrFileCodec.mm}:
  daoqi 同款 wrapper(文件级 WAV↔AMR 处理)
- ylgamehall/Source/Audio/AMRCodec.swift:Swift 薄 wrapper(wavToAmr /
  amrToWav 两个纯函数 + AMRCodec.Error)

理由见 Vendor/OpenCoreAMR/README.md「为何不打 xcframework / 不重编源码」
一节,本质是 opencore-amr 整个 iOS 生态没有"现代主流"分发形态,社区无
官方 SPM / xcframework 维护,强行打反而引入新风险。

## 关键技术点:extern "C" 修复 ObjC++ name mangling

amrFileCodec.h 在原项目里没有 extern "C" 包裹函数声明,daoqi 能跑是
因为调用方 VoiceConverter.mm 也是 ObjC++,双方按相同 C++ name mangling
链接能对上。

新外壳从 Swift 通过 bridging-header 调用,Swift 按 C 函数解析,期望符号
_EncodeWAVEFileToAMRFile / _DecodeWAVEFileToWAVEFile(C 链接);但
.mm 编译时默认 C++ name mangling,符号变成 __Z25Encode...,导致链接器
报 Undefined symbol。

修复:在 amrFileCodec.h 的函数声明外加 #ifdef __cplusplus / extern "C"
包裹。这是标准 C/C++ 头文件兼容写法,对 daoqi 老路径无影响(ObjC++
调用方仍能链接 C-linkage 函数)。

## .gitignore:白名单 Vendor 下的 .a

发现历史遗留问题:原 .gitignore *.a 通配规则把 libWeChatSDK.a 也排除
了,意味着别人 clone 此仓库后链接失败。本次顺带修复:

  !Vendor/**/*.a

让 Vendor 下的 .a 显式纳入跟踪。本提交同时把 libWeChatSDK.a(历史
缺失)+ libopencore-amrnb.a(本次新增)一并加入 git 跟踪。

## 工程改动

pbxproj 改动由用户在 Xcode UI 完成(4 项 Build Settings:Add .a 到
Frameworks group / Header Search Paths +2 / Library Search Paths +1;
EXCLUDED_ARCHS arm64-simulator 因真机调试场景暂未配,需要时再加)。

## 验证

BuildProject 通过,0 错误,符号链接正确。XcodeRefreshCodeIssuesInFile
对 AMRCodec.swift 0 诊断。
2026-06-24 01:20:30 +08:00

103 lines
1.9 KiB
Plaintext

# ===== macOS =====
.DS_Store
._*
.Spotlight-V100
.Trashes
# ===== Xcode =====
# 构建产物
build/
DerivedData/
*.o
*.lo
*.la
*.al
.libs
*.so
*.so.[0-9]*
*.la
*.a
# Vendor 下的 .a 是项目依赖(如 libWeChatSDK.a / libopencore-amrnb.a),必须跟踪
# —— 否则其他人 clone 后链接失败。覆盖上面 *.a 的通配规则。
!Vendor/**/*.a
*.pyc
*.swp
*~.nib
# 用户级数据(每个开发者本地不同,不能共享)
xcuserdata/
*.xcuserstate
*.xcuserdatad
*.xcscmblueprint
*.xccheckout
# 项目文件内的用户专属配置
*.moved-aside
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
# Playgrounds
timeline.xctimeline
playground.xcworkspace
# ===== Swift Package Manager =====
# 本地 SPM 缓存(每台机器各自重建)
.build/
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.swiftpm/xcode/xcuserdata/
.swiftpm/configuration/
# Package.resolved 需要提交,确保多人 / CI 用同一版本
# 故意不忽略 Package.resolved
# ===== CocoaPods =====
# Pods/ 不提交(CI / 新人 pod install 重建);Podfile.lock 必须提交
Pods/
# 故意不忽略 Podfile.lock
# ===== Carthage(如使用)=====
Carthage/Build/
Carthage/Checkouts
# ===== fastlane =====
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
# ===== 代码覆盖率 / Profile =====
*.gcda
*.gcno
*.profraw
*.profdata
# ===== AppCode / JetBrains =====
.idea/
# ===== 签名 / 证书(绝不入库)=====
*.mobileprovision
*.provisionprofile
*.cer
*.p12
*.pem
*.key
# ===== 本地敏感配置 =====
.env
.env.*
secrets.xcconfig
Secrets/
# ===== 备份 / 临时 =====
*.orig
*.bak
*.tmp
*~
# ===== docs/res 大型素材 / SDK 下载副本 =====
# docs/res 是项目维护者的私人素材池(CLAUDE.md 约定),整体 git 跟踪但
# 排除特别大的 SDK 下载副本(已经走 SPM / Vendor 接入,不需要副本):
docs/res/AMap_iOS_Loc_ALL/
docs/res/objc-sdk-8.9.2/