骨传导替换opus解码库
authorliangzhenying <867174124@qq.com>
Tue, 6 Jan 2026 01:59:29 +0000 (09:59 +0800)
committerliangzhenying <867174124@qq.com>
Tue, 6 Jan 2026 01:59:29 +0000 (09:59 +0800)
38 files changed:
ShenYin/DeepChordsSdk/DCCallRecord.swift
ShenYin/DeepChordsSdk/DCLogger.swift
ShenYin/DeepChordsSdk/DeepChordsAiSdk.swift
ShenYin/ShenYin.xcodeproj/project.pbxproj
ShenYin/ShenYin/Sdk/DcSdk/DcStereo.swift
ShenYin/ShenYin/Sdk/DcSdk/OpusTools.swift [new file with mode: 0644]
ShenYin/ShenYin/Sdk/DcSdk/opus/OpusTool.h
ShenYin/ShenYin/Sdk/DcSdk/opus/OpusTool.m
ShenYin/framework/JLAudioUnitKit.xcframework/Info.plist [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLAudioUnitKit.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLAudioUnitPlayer.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusDecoder.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusEncodeConfig.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusEncoder.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusFormat.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusToOgg.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLPcmToWav.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLPcmToWtg.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLSpeexDecoder.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Info.plist [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/JLAudioUnitKit [new file with mode: 0755]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Modules/module.modulemap [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/readme.txt [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLAudioUnitKit.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLAudioUnitPlayer.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusDecoder.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusEncodeConfig.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusEncoder.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusFormat.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusToOgg.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLPcmToWav.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLPcmToWtg.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLSpeexDecoder.h [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Info.plist [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/JLAudioUnitKit [new file with mode: 0755]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Modules/module.modulemap [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/_CodeSignature/CodeResources [new file with mode: 0644]
ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/readme.txt [new file with mode: 0644]

index b293dd0..3b482a3 100644 (file)
@@ -27,7 +27,7 @@ public class DCCallRecord {
     /// 状态码回调
     public var codeCallback:((Int)->Void)?
     /// 录音文件回调
-    public var filePathCallBack:((String?)->Void)?
+    public var filePathCallBack:((String)->Void)?
     /// opus回调
     public var opusCallBack:((Data)->Void)?
     
@@ -38,7 +38,7 @@ public class DCCallRecord {
     var asrOtherText = ""
     
     init() {
-        setupRecord()
+//        setupRecord()
     }
     
     func setupRecord(){
@@ -57,7 +57,7 @@ public class DCCallRecord {
         } recognizeText: { [weak self]  model in
             guard let self = self else {return}
             guard let model = model else {return}
-            DCLogger.debug(model.channel,"asr =",model.definiteIndex,model.textResult)
+//            DCLogger.debug(model.channel,"asr =",model.definiteIndex,model.textResult)
             if let text = model.textResult,!text.isEmpty{
                 
                 if model.channel == 1 {
@@ -99,7 +99,7 @@ public class DCCallRecord {
             self?.codeCallback?(code.rawValue)
         } finished: {[weak self]  filePath in
             DCLogger.debug("文件录音保存路径 \(filePath ?? "")")
-            self?.filePathCallBack?(filePath)
+            self?.filePathCallBack?(filePath ?? "")
         }
         
         //通话录音声道数。1:单声道 ;2:⽴体声;默认单声道
index c605936..6319ca8 100644 (file)
@@ -45,17 +45,16 @@ public class DCLogger {
 
 extension DCLogger {
     public static func debug(_ logs: Any..., line: Int = #line, separator: String = " ", terminator: String = "\n") {
-        objc_sync_enter(DCLogger.shared)
+        
         if DCLogger.isDebug {
+            objc_sync_enter(DCLogger.shared)
             print(DCLogger.shared.dateString, terminator: " [DeepChordsSdk-\(String(format: "%03d", line))]: ")
             print(logs, separator: separator, terminator: terminator)
             let logString = DCLogger.shared.dateString + " [DeepChordsSdk-\(String(format: "%03d", line))]: " + logs.map({ "\($0)" }).joined(separator: separator) + terminator
             Self.logs.append(logString)
             DCLogger.shared.saveLog(log: logString)
+            objc_sync_exit(DCLogger.shared)
         }
-        objc_sync_exit(DCLogger.shared)
-        
-        
     }
     
     private func saveLog(log:String){
index 9aa91fc..7f50d91 100644 (file)
@@ -14,7 +14,7 @@ public class DeepChordsAiSdk{
     }
     public var isDebug:Bool = false{
         didSet{
-            StarburstConfig.shared().isDebug = false
+            StarburstConfig.shared().isDebug = isDebug
             DCLogger.isDebug = isDebug
         }
     }
@@ -54,7 +54,7 @@ public class DeepChordsAiSdk{
             DCBleManager.shared.sendToStarburst(data)
         }
         StarburstSdk.shared().bleRecordStateCallback = {[weak self] state in
-            
+            DCLogger.debug("录音状态改变",state)
         }
     }
     
index debd2f1..860ce97 100644 (file)
@@ -9,6 +9,8 @@
 /* Begin PBXBuildFile section */
                3F469CB12F0B539600121DBD /* DeepChordsSdk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D54E0EF2F0A61E600A80EE7 /* DeepChordsSdk.framework */; };
                3F8F58292EBCA2B800FFC00B /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3F8F58282EBCA2B800FFC00B /* PrivacyInfo.xcprivacy */; };
+               3FD1A2952F0BCACB00A62733 /* JLAudioUnitKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3FD1A2912F0BC9D800A62733 /* JLAudioUnitKit.xcframework */; };
+               3FD1A2962F0BCACB00A62733 /* JLAudioUnitKit.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3FD1A2912F0BC9D800A62733 /* JLAudioUnitKit.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
                644D1BB5EDD3EA1D77C57786 /* Pods_DeepChordsSdk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 248D8B53B5A178ACA5867275 /* Pods_DeepChordsSdk.framework */; };
                F2E449CAD5874BE652A69B50 /* Pods_ShenYin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3862D5561144E20721225B96 /* Pods_ShenYin.framework */; };
 /* End PBXBuildFile section */
@@ -40,6 +42,7 @@
                        dstPath = "";
                        dstSubfolderSpec = 10;
                        files = (
+                               3FD1A2962F0BCACB00A62733 /* JLAudioUnitKit.xcframework in Embed Frameworks */,
                        );
                        name = "Embed Frameworks";
                        runOnlyForDeploymentPostprocessing = 0;
@@ -53,6 +56,7 @@
                3F7602EA2EFA891200588C18 /* DeepChordsSdk.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DeepChordsSdk.framework; sourceTree = BUILT_PRODUCTS_DIR; };
                3F887B9C2E38D8DC00C98658 /* ShenYin.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShenYin.app; sourceTree = BUILT_PRODUCTS_DIR; };
                3F8F58282EBCA2B800FFC00B /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
+               3FD1A2912F0BC9D800A62733 /* JLAudioUnitKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = JLAudioUnitKit.xcframework; path = framework/JLAudioUnitKit.xcframework; sourceTree = "<group>"; };
                5A92F7DC2CB6E6E69D2AB23E /* Pods-DeepChordsSdk.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DeepChordsSdk.debug.xcconfig"; path = "Target Support Files/Pods-DeepChordsSdk/Pods-DeepChordsSdk.debug.xcconfig"; sourceTree = "<group>"; };
                5F5DE5910965D53C2B3405B0 /* Pods-ShenYin.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShenYin.debug.xcconfig"; path = "Target Support Files/Pods-ShenYin/Pods-ShenYin.debug.xcconfig"; sourceTree = "<group>"; };
                CB933A7969ADF81D59503790 /* Pods-LingQi.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LingQi.debug.xcconfig"; path = "Target Support Files/Pods-LingQi/Pods-LingQi.debug.xcconfig"; sourceTree = "<group>"; };
                        files = (
                                3F469CB12F0B539600121DBD /* DeepChordsSdk.framework in Frameworks */,
                                F2E449CAD5874BE652A69B50 /* Pods_ShenYin.framework in Frameworks */,
+                               3FD1A2952F0BCACB00A62733 /* JLAudioUnitKit.xcframework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                676B86A4BA2639E8694D56B4 /* Frameworks */ = {
                        isa = PBXGroup;
                        children = (
+                               3FD1A2912F0BC9D800A62733 /* JLAudioUnitKit.xcframework */,
                                3F7602EA2EFA891200588C18 /* DeepChordsSdk.framework */,
                                3862D5561144E20721225B96 /* Pods_ShenYin.framework */,
                                248D8B53B5A178ACA5867275 /* Pods_DeepChordsSdk.framework */,
index 8c64dee..5b40844 100644 (file)
@@ -10,6 +10,7 @@ import DeepChordsSdk
 
 class DcStereo:NSObject{
     static let shared = DcStereo()
+    var fileData = Data()
     
     var recordFinish:((String)->Void)?
     var stereoNeedReloadData:((String,Int)->Void)?
@@ -41,7 +42,8 @@ class DcStereo:NSObject{
             codeCallback?(code)
         }
         DCCallRecord.shared.opusCallBack = { data in
-            OpusManager.shared().write(data)
+//            OpusManager.shared().write(data)
+            OpusTools.shared.inputData(data)
         }
         DCCallRecord.shared.filePathCallBack = { [weak self] path in
             guard let self = self else{return}
@@ -49,28 +51,41 @@ class DcStereo:NSObject{
 //            if selfText.isEmpty && otherText.isEmpty {
 //                return
 //            }
-            guard let path = path,path.isNotEmpty else{
-                return
-            }
-            let path1 = OpusTool.opusFile(toWAVFile: path)
+//            guard let path = path,path.isNotEmpty else{
+//                return
+//            }
+            
+//            YLToos.saveToFile(data: fileData, path: DCFolder.cacheDirectory() + "/11123.pcm")
+//            Logger.debug("文件路径pcm ==",DCFolder.cacheDirectory() + "/11123.pcm")
+//            let path1 = OpusTool.opusStereoFile(toWAVFile: path)
+            let path1 = OpusTools.pcmTowav(fileData) ?? ""
             guard let wavPath = DCFolder.recordFileResave(srcPath: path1) else{return}
             Logger.debug("文件路径wav ==",wavPath)
             recordFinish?(wavPath)
+            fileData = Data()
+            
         }
         
-        //设置解码参数
-        OpusManager.shared().setupSampleRate(16000, frameRate: 80)
-        //opus转成pcm,发送给sdk
-        OpusManager.shared().pcmDataCallback = { data in
+//        //设置解码参数
+//        OpusManager.shared().setupSampleRate(16000, frameRate: 80)
+//        //opus转成pcm,发送给sdk
+//        OpusManager.shared().pcmDataCallback = { data in
+//            self.data.append(data)
+//            DCCallRecord.shared.inputPcm(data: data)
+//        }
+        
+        OpusTools.shared.output = { data in
+            self.fileData.append(data)
             DCCallRecord.shared.inputPcm(data: data)
         }
     }
     func setRecordLanage(_ language:CCAiLanguage){
-        DCBleRecord.shared.fromLanguage = language.value
+        DCCallRecord.shared.fromLanguage = language.value
     }
     func recordStart(){
         selfText = ""
         otherText = ""
+        fileData = Data()
         setupSdk()
         if !CCCall.shared.isInCall {
             callRecordNotOnCall?()
@@ -80,6 +95,6 @@ class DcStereo:NSObject{
         DCCallRecord.shared.start()
     }
     func recordStop(){
-        DCBleRecord.shared.stop()
+        DCCallRecord.shared.stop()
     }
 }
diff --git a/ShenYin/ShenYin/Sdk/DcSdk/OpusTools.swift b/ShenYin/ShenYin/Sdk/DcSdk/OpusTools.swift
new file mode 100644 (file)
index 0000000..164fcce
--- /dev/null
@@ -0,0 +1,52 @@
+//
+//  OpusTools.swift
+//  JLAudioUnitKitDemo
+//
+//  Created by liangshi on 2026/1/5.
+//
+import JLAudioUnitKit
+
+class OpusTools:NSObject, JLOpusDecoderDelegate {
+    static let shared = OpusTools()
+    private var opusDecoder:JLOpusDecoder!
+    private var format = JLOpusFormat.defaultFormats()
+    
+    var output:((Data)->Void)?
+    
+    override init(){
+        super.init()
+        format.sampleRate = 16000
+        format.hasDataHeader = false
+        format.channels = 2
+        format.dataSize = 80
+        self.opusDecoder = JLOpusDecoder(decoder: format, delegate: self)
+        
+//        opusDecoder.resetOpusFramet(format)
+    }
+    
+    func inputData(_ data:Data){
+        self.opusDecoder.opusDecoderInputData(data)
+        
+    }
+    
+    func opusDecoder(_ decoder: JLOpusDecoder, data: Data?, error: (any Error)?) {
+        if let data = data{
+            output?(data)
+        }
+    }
+    
+}
+
+
+extension OpusTools{
+    static func pcmTowav(_ data:Data)->String?{
+        do{
+            let path = DCFolder.cacheDirectory() + "/\(Date().timeIntervalSince1970).wav"
+            try JLPcmToWav.convertPCMData(data, toWAVFile: path, sampleRate: 16000, numChannels: 2, bitsPerSample: 16)
+            return path
+        }
+        catch{
+            return nil
+        }
+    }
+}
index 00e35a0..ed7688d 100644 (file)
@@ -11,6 +11,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface OpusTool : NSObject
 + (NSString*)opusFileToWAVFile:(NSString*)path;
+
++ (NSString*)opusStereoFileToWAVFile:(NSString*)path;
 @end
 
 NS_ASSUME_NONNULL_END
index df19485..1409883 100644 (file)
     return nil;
 }
 
++ (NSString*)opusStereoFileToWAVFile:(NSString*)path {
+    NSString *dataFilePath = [path stringByDeletingLastPathComponent];
+    // 获取当前时间
+    NSDate *currentDate = [NSDate date];
+    // 创建日期格式化器
+    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+    [dateFormatter setDateFormat:@"yyyyMMddHHmmssSSS"]; // 设置时间格式
+    // 将当前时间格式化为字符串
+    NSString *timestamp = [dateFormatter stringFromDate:currentDate];
+    // 生成文件名
+    NSString *fileName = [NSString stringWithFormat:@"%@_%@.%@", @"output", timestamp, @"pcm"];
+    NSString *filePath = [dataFilePath stringByAppendingPathComponent:fileName];
+    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
+        [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
+        //NSLog(@"remove file : %@", filePath);
+    }
+    NSString *txt = @"";
+    [txt writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
+    [OpusUnit opusSetSampleRate:16000 frameRate:80 Channels:2 isHeader:NO];
+    // 调用解码方法,输入 Opus文件路径 与 PCM文件路径
+    int result = [OpusUnit opusDecodeOPUS:path PCM:filePath];
+    if (result == 0) {
+        // 删除opus文件
+        [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
+        // 解码成功
+        NSURL *url = [[NSURL alloc] initFileURLWithPath:filePath];
+        NSData *pcmData = [[NSData alloc] initWithContentsOfURL:url];
+        // 生成文件名
+        NSString *wavFileName = [NSString stringWithFormat:@"%@_%@.%@", @"output", timestamp, @"wav"];
+        NSURL *output = [[NSURL alloc] initFileURLWithPath: [dataFilePath stringByAppendingPathComponent:wavFileName]];
+        [self writePCMToWAV:pcmData sampleRate:16000 numChannels:2 bitsPerSample:16 outputURL:output];
+        // 删除pcm文件
+        [[NSFileManager defaultManager] removeItemAtURL:url error:nil];
+        
+        return output.path;
+    }
+    return nil;
+}
+
 + (void)writePCMToWAV:(NSData *)pcmData
            sampleRate:(UInt32)sampleRate
           numChannels:(UInt16)numChannels
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/Info.plist b/ShenYin/framework/JLAudioUnitKit.xcframework/Info.plist
new file mode 100644 (file)
index 0000000..c989e87
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>AvailableLibraries</key>
+       <array>
+               <dict>
+                       <key>BinaryPath</key>
+                       <string>JLAudioUnitKit.framework/JLAudioUnitKit</string>
+                       <key>LibraryIdentifier</key>
+                       <string>ios-arm64</string>
+                       <key>LibraryPath</key>
+                       <string>JLAudioUnitKit.framework</string>
+                       <key>SupportedArchitectures</key>
+                       <array>
+                               <string>arm64</string>
+                       </array>
+                       <key>SupportedPlatform</key>
+                       <string>ios</string>
+               </dict>
+               <dict>
+                       <key>BinaryPath</key>
+                       <string>JLAudioUnitKit.framework/JLAudioUnitKit</string>
+                       <key>LibraryIdentifier</key>
+                       <string>ios-x86_64-simulator</string>
+                       <key>LibraryPath</key>
+                       <string>JLAudioUnitKit.framework</string>
+                       <key>SupportedArchitectures</key>
+                       <array>
+                               <string>x86_64</string>
+                       </array>
+                       <key>SupportedPlatform</key>
+                       <string>ios</string>
+                       <key>SupportedPlatformVariant</key>
+                       <string>simulator</string>
+               </dict>
+       </array>
+       <key>CFBundlePackageType</key>
+       <string>XFWK</string>
+       <key>XCFrameworkFormatVersion</key>
+       <string>1.0</string>
+</dict>
+</plist>
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLAudioUnitKit.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLAudioUnitKit.h
new file mode 100644 (file)
index 0000000..e6b3af6
--- /dev/null
@@ -0,0 +1,26 @@
+//
+//  JLAudioUnitKit.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2024/11/14.
+//
+
+#import <Foundation/Foundation.h>
+
+//! Project version number for JLAudioUnitKit.
+FOUNDATION_EXPORT double JLAudioUnitKitVersionNumber;
+
+//! Project version string for JLAudioUnitKit.
+FOUNDATION_EXPORT const unsigned char JLAudioUnitKitVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import <JLAudioUnitKit/PublicHeader.h>
+
+#import <JLAudioUnitKit/JLSpeexDecoder.h>
+#import <JLAudioUnitKit/JLOpusDecoder.h>
+#import <JLAudioUnitKit/JLOpusEncoder.h>
+#import <JLAudioUnitKit/JLOpusFormat.h>
+#import <JLAudioUnitKit/JLOpusEncodeConfig.h>
+#import <JLAudioUnitKit/JLPcmToWtg.h>
+#import <JLAudioUnitKit/JLPcmToWav.h>
+#import <JLAudioUnitKit/JLAudioUnitPlayer.h>
+#import <JLAudioUnitKit/JLOpusToOgg.h>
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLAudioUnitPlayer.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLAudioUnitPlayer.h
new file mode 100644 (file)
index 0000000..7da831c
--- /dev/null
@@ -0,0 +1,58 @@
+//
+//  JLAudioUnitPlayer.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2025/4/16.
+//  Copyright © 2025 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <AudioToolbox/AudioToolbox.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef NS_ENUM(NSInteger, JLAudioUnitPlayerType) {
+    JLAudioUnitPlayerTypeFile,   // 支持 MP3/WAV/AAC 等文件格式(AVAudioPlayer)
+    JLAudioUnitPlayerTypePCM      // 支持 PCM 流式播放(Audio Queue)
+};
+
+@class JLAudioUnitPlayer;
+
+@protocol JLAudioPlayerDelegate <NSObject>
+@optional
+// 播放进度更新(秒)
+- (void)audioPlayer:(JLAudioUnitPlayer *)player didUpdateProgress:(NSTimeInterval)currentTime duration:(NSTimeInterval)duration;
+// 播放完成
+- (void)audioPlayerDidFinishPlaying:(JLAudioUnitPlayer *)player;
+// 播放错误
+- (void)audioPlayer:(JLAudioUnitPlayer *)player didFailWithError:(NSError *)error;
+@end
+
+@interface JLAudioUnitPlayer : NSObject
+
+@property (nonatomic, weak) id<JLAudioPlayerDelegate> delegate;
+@property (nonatomic, readonly) NSTimeInterval duration;  // 总时长(文件模式下有效)
+@property (nonatomic, readonly) NSTimeInterval currentTime;
+@property (nonatomic, readonly) BOOL isPlaying;
+
+#pragma mark - 初始化方法
+
+/// 文件播放初始化(MP3/WAV/AAC)
+- (instancetype)initWithAudioFile:(NSString *)filePath;
+
+/// PCM 流播放初始化(需指定格式)
+- (instancetype)initWithPCMFormat:(AudioStreamBasicDescription)format;
+
+#pragma mark - 播放控制
+- (void)play;
+- (void)pause;
+- (void)stop;
+- (void)seekToTime:(NSTimeInterval)time; // 仅文件模式有效
+
+#pragma mark - PCM 流式输入(仅 PCM 模式有效)
+- (void)appendPCMData:(NSData *)pcmData;
+- (void)endPCMStream; // 结束 PCM 流输入
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusDecoder.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusDecoder.h
new file mode 100644 (file)
index 0000000..711e2e9
--- /dev/null
@@ -0,0 +1,66 @@
+//
+//  JLOpusDecoder.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2024/11/14.
+//  Copyright © 2024 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <JLAudioUnitKit/JLOpusFormat.h>
+
+NS_ASSUME_NONNULL_BEGIN
+@class JLOpusDecoder;
+
+/// Opus 解码代理
+@protocol JLOpusDecoderDelegate <NSObject>
+
+/// Opus 数据解码
+/// - Parameters:
+///   - decoder: 解码器
+///   - data: pcm 数据
+///   - error: 错误信息
+-(void)opusDecoder:(JLOpusDecoder *)decoder Data:(NSData* _Nullable)data error:(NSError* _Nullable)error;
+
+@end
+
+typedef void(^JLOpusDecoderConvertBlock)(NSString *_Nullable pcmPath,NSError *_Nullable error);
+
+/// Opus 解码
+@interface JLOpusDecoder : NSObject
+
+/// 数据格式参数
+@property (nonatomic, strong) JLOpusFormat *opusFormat;
+
+/// 代理委托
+@property(nonatomic, weak) id<JLOpusDecoderDelegate> delegate;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+/// 初始化
+/// - Parameters:
+///   - format: 解码格式
+///   - delegate: 代理
+- (instancetype)initDecoder:(JLOpusFormat *)format delegate:(id<JLOpusDecoderDelegate>)delegate;
+
+/// 重置解码格式
+/// - Parameter format: 解码格式
+-(void)resetOpusFramet:(JLOpusFormat *)format;
+
+/// 输入 Opus 数据
+/// - Parameter data: Opus 数据
+-(void)opusDecoderInputData:(NSData *)data;
+
+/// 解码文件
+/// - Parameters:
+///   - input: opus 文件
+///   - outPut: 输出路径
+///   - result: 结果回调
+-(void)opusDecodeFile:(NSString *)input outPut:(NSString *_Nullable)outPut Resoult:(JLOpusDecoderConvertBlock _Nullable)result;
+
+/// 释放
+-(void)opusOnRelease;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusEncodeConfig.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusEncodeConfig.h
new file mode 100644 (file)
index 0000000..037284e
--- /dev/null
@@ -0,0 +1,83 @@
+//
+//  JLOpusEncodeConfig.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2025/8/27.
+//  Copyright © 2025 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef NS_ENUM(NSInteger, JLOpusEncoderBandwidth) {
+    ///(4kHz bandpass)
+    JLOpusEncoderBandwidthNarrowband = 1101,   // 对应 OPUS_BANDWIDTH_NARROWBAND
+    /// (6kHz bandpass)
+    JLOpusEncoderBandwidthMediumband = 1102,   // 对应 OPUS_BANDWIDTH_MEDIUMBAND
+    /// (8kHz bandpass)
+    JLOpusEncoderBandwidthWideband   = 1103,     // 对应 OPUS_BANDWIDTH_WIDEBAND
+    /// (12kHz bandpass)
+    JLOpusEncoderBandwidthSuperwideband = 1104,// 对应 OPUS_BANDWIDTH_SUPERWIDEBAND
+    /// (20kHz bandpass)
+    JLOpusEncoderBandwidthFullband   = 1105      // 对应 OPUS_BANDWIDTH_FULLBAND
+};
+
+@interface JLOpusEncodeConfig : NSObject
+
+/// 采样率
+@property (nonatomic, assign) int sampleRate;
+
+/// 单/双声道
+@property (nonatomic, assign) int channels;
+
+/// 帧长度 20ms 默认值
+@property (nonatomic, assign) int frameDuration;
+
+/// 帧长度
+@property (nonatomic, assign) int frameSize;
+
+/// BitRate
+@property (nonatomic, assign) int bitRate;
+
+/// 可变比特率开关,默认 NO(使用 CBR)
+@property (nonatomic, assign) BOOL useVBR;
+
+/// VBR 限制模式,默认 NO
+@property (nonatomic, assign) BOOL constrainedVBR;
+
+/// 编码复杂度 0~10,默认 5
+@property (nonatomic, assign) int complexity;
+
+/// 强制输出声道数 -1: 自适应, 1: 单声道, 2: 双声道, 默认 -1
+@property (nonatomic, assign) int forceChannels;
+
+/// 是否启用 DTX(静音段不发送数据),默认 NO
+@property (nonatomic, assign) BOOL useDTX;
+
+/// 网络丢包百分比,默认 0
+@property (nonatomic, assign) int packetLossPercent;
+
+/// 最大带宽限制(OPUS_BANDWIDTH_*),默认 FULLBAND
+@property (nonatomic, assign) int bandwidth;
+
+/// PCM 输入有效位深,默认 16
+@property (nonatomic, assign) int lsbDepth;
+
+/// 专家模式下帧时长(ms),默认与 frameDuration 一致
+@property (nonatomic, assign) int expertFrameDuration;
+
+/// 是否启用数据头
+/// 默认是启用的
+@property (nonatomic, assign) BOOL hasDataHeader;
+
+/// 创建默认编码配置
++ (instancetype)defaultConfig;
+
+/// 获取默认配置
+/// 杰理的无头配置
++ (instancetype)defaultJL;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusEncoder.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusEncoder.h
new file mode 100644 (file)
index 0000000..fbe5af7
--- /dev/null
@@ -0,0 +1,62 @@
+//
+//  JLOpusEncoder.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2024/11/14.
+//  Copyright © 2024 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <JLAudioUnitKit/JLOpusEncodeConfig.h>
+
+NS_ASSUME_NONNULL_BEGIN
+@class JLOpusEncoder;
+
+/// Opus 编码代理
+@protocol JLOpusEncoderDelegate <NSObject>
+
+/// PCM 数据编码
+/// - Parameters:
+///   - encoder: 解码器
+///   - data: opus 数据
+///   - error: 错误信息
+-(void)opusEncoder:(JLOpusEncoder *)encoder Data:(NSData* _Nullable)data error:(NSError* _Nullable)error;
+
+@end
+
+typedef void(^JLOpusEncoderConvertBlock)(NSString *_Nullable pcmPath,NSError *_Nullable error);
+
+/// Opus 编码
+@interface JLOpusEncoder : NSObject
+
+/// 音频格式
+@property (nonatomic, strong) JLOpusEncodeConfig *opusFormat;
+
+/// 代理
+@property (nonatomic, weak) id<JLOpusEncoderDelegate> delegate;
+
+-(instancetype)init NS_UNAVAILABLE;
+
+/// 初始化
+/// - Parameters:
+///   - config: 音频格式
+///   - delegate: 代理
+-(instancetype)initFormat:(JLOpusEncodeConfig *)format delegate:(id<JLOpusEncoderDelegate>)delegate;
+
+/// PCM 数据
+/// - Parameter data: PCM 数据
+-(void)opusEncodeData:(NSData *)data;
+
+/// PCM 文件转换成 Opus 文件
+/// - Parameters:
+///   - pcmPath: PCM 文件存放路径
+///   - outPut: 文件输出路径
+///   - result: 结果回调
+-(void)opusEncodeFile:(NSString *)pcmPath outPut:(NSString *_Nullable)outPut Resoult:(JLOpusEncoderConvertBlock _Nullable)result;
+
+/// 释放
+-(void)opusOnRelease;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusFormat.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusFormat.h
new file mode 100644 (file)
index 0000000..0165487
--- /dev/null
@@ -0,0 +1,59 @@
+//
+//  JLOpusOptions.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2024/11/14.
+//  Copyright © 2024 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+#define OPUS_JL_MAX_FRAME_SIZE 48000 * 2
+#define OPUS_JL_MAX_PACKET_SIZE 1500
+
+
+@interface JLOpusFormat : NSObject
+
+/// 采样率
+@property (nonatomic, assign) int sampleRate;
+
+/// 单/双声道
+@property (nonatomic, assign) int channels;
+
+/// 帧长度 20ms 默认值
+@property (nonatomic, assign) int frameDuration;
+
+/// BitRate
+@property (nonatomic, assign) int bitRate;
+
+/// 数据帧大小
+@property (nonatomic, assign, readonly) int frameSize;
+
+/// 数据大小
+@property (nonatomic, assign) int dataSize;
+
+/// 是否包含数据头部
+@property (nonatomic, assign) BOOL hasDataHeader;
+
+/// 是否开启slik语音优化
+@property (nonatomic, assign) BOOL usVoipSlik;
+
+
+-(instancetype)init NS_UNAVAILABLE;
+
+/// 默认配置
+/// sampleRate: 16000
+/// channels: 1
+/// frameDuration: 20
+/// dataSize: 40
+/// frameSize: 320
+/// hasDataHeader: YES
+/// bitRate: 16000
+/// usVoipSlik: false
++(JLOpusFormat*)defaultFormats;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusToOgg.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLOpusToOgg.h
new file mode 100644 (file)
index 0000000..27b919b
--- /dev/null
@@ -0,0 +1,67 @@
+//
+//  JLOpusToOgg.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2025/5/16.
+//  Copyright © 2025 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void(^JLOpusToOggConvertBlock)(NSData *_Nullable oggData, BOOL isLast, NSError *_Nullable error);
+
+/// 将Opus数据转换为Ogg数据
+@interface JLOpusToOgg : NSObject
+
+/// 转码内容的回调
+@property(nonatomic,strong)JLOpusToOggConvertBlock _Nullable convertBlock;
+
+/// 帧长
+/// - Parameter frameLen: 帧长
+/// 默认值 40
+- (instancetype)initWithFrameLength:(uint32_t)frameLen;
+
+/// 开始流
+-(void)startStream;
+
+/// 添加Opus数据
+/// - Parameter opusData: 符合杰理的无头裸 opus 数据
+- (void)appendOpusData:(NSData *)opusData;
+
+/// 关闭流
+- (void)closeStream;
+
+
+/// 将Opus数据转换为Ogg数据
+/// opus 必须为 16000
+/// opus 必须是 单声道
+/// - Parameters:
+///   - opusData: 符合杰理的无头裸 opus 数据
+///   - frameLen: 帧长 公版默认帧长是 40
+///   - duration: 转换后的时长
+///   - error: 错误
++ (NSData *_Nullable)convertOpusDataToOgg:(NSData *)opusData
+                                 frameLen:(uint32_t)frameLen
+                                 duration:(double *)duration
+                                    error:(NSError *__autoreleasing _Nullable *)error ;
+
+/// 将Opus文件转换为Ogg文件
+/// 符合杰理的无头裸 opus 文件
+/// opus 必须为 16000
+/// opus 必须是 单声道
+/// - Parameters:
+///   - opusFilePath: opus文件路径
+///   - oggFilePath: ogg文件路径
+///   - frameLen: 帧长 公版默认帧长是 40
+///   - duration: 转换后的时长
++(void)convertOpusFileToOgg:(NSString *)opusFilePath
+                oggFilePath:(NSString *)oggFilePath
+                   frameLen:(uint32_t)frameLen
+                   duration:(double *)duration;
+
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLPcmToWav.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLPcmToWav.h
new file mode 100644 (file)
index 0000000..b32ecef
--- /dev/null
@@ -0,0 +1,55 @@
+//
+//  JLPcmToWav.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2025/4/15.
+//  Copyright © 2025 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// PCM 转 WAV
+@interface JLPcmToWav : NSObject
+
+#pragma mark - 流式编码接口
+
+/// 初始化流式编码器
+/// @param outputPath 输出文件路径
+/// @param sampleRate 采样率(如 16000)
+/// @param numChannels 声道数(1 或 2)
+/// @param bitsPerSample 位深(16)
+- (instancetype)initWithOutputPath:(NSString *)outputPath
+                       sampleRate:(uint32_t)sampleRate
+                     numChannels:(uint16_t)numChannels
+                  bitsPerSample:(uint16_t)bitsPerSample;
+
+/// 追加 PCM 数据(需确保数据格式与初始化参数一致)
+/// @param pcmData PCM 数据块
+/// @param error 错误信息
+- (BOOL)appendPCMData:(NSData *)pcmData error:(NSError **)error;
+
+/// 完成编码并关闭文件(必须调用以更新 WAV 头)
+/// @param error 错误信息
+- (BOOL)finishWithError:(NSError **)error;
+
+#pragma mark - 一次性编码接口(便捷方法)
+
+/// 将 PCM 数据一次性转为 WAV 文件
+/// @param pcmData PCM 数据块
+/// @param outputPath 输出文件路径
+/// @param sampleRate 采样率(如 16000)
+/// @param numChannels 声道数(1 或 2)
+/// @param bitsPerSample 位深(16)
+/// @param error 错误信息
++ (BOOL)convertPCMData:(NSData *)pcmData
+            toWAVFile:(NSString *)outputPath
+           sampleRate:(uint32_t)sampleRate
+         numChannels:(uint16_t)numChannels
+      bitsPerSample:(uint16_t)bitsPerSample
+              error:(NSError **)error;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLPcmToWtg.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLPcmToWtg.h
new file mode 100644 (file)
index 0000000..231b3e8
--- /dev/null
@@ -0,0 +1,51 @@
+//
+//  JLPcmToWtg.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2025/1/21.
+//  Copyright © 2025 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface JLPcm2WtgModel : NSObject <NSCopying>
+
+/// 音频文件
+@property (nonatomic, copy) NSString *pcmPath;
+
+/// 输出文件
+@property (nonatomic, copy) NSString *wtgPath;
+
+@end
+
+
+/// JLPcmToWtgProtocol
+@protocol JLPcmToWtgDelegate <NSObject>
+
+/// 音频转码完成
+/// - Parameter model: 音频转码模型
+- (void)convertPcmToWtgDone:(JLPcm2WtgModel *)model;
+
+@end
+
+/// 音频转码
+/// PCM 转 WTG
+@interface JLPcmToWtg : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
+
+/// 音频转码初始化
+/// - Parameter delegate: 音频转码代理
+- (instancetype)initWithDelegate:(id<JLPcmToWtgDelegate>)delegate;
+
+/// 音频转码
+/// 当前接口模型只限制 PCM 文件格式为:8k 16bit
+/// 输入的pcm文件(16bit,小端,8k采样率),wtg_filename:输出的wtg文件
+/// - Parameter model: 音频转码模型
+-(void)convertPcmToWtg:(JLPcm2WtgModel *)model;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLSpeexDecoder.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Headers/JLSpeexDecoder.h
new file mode 100644 (file)
index 0000000..ad223d0
--- /dev/null
@@ -0,0 +1,54 @@
+//
+//  JLSpeexUnit.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2024/11/14.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+@class JLSpeexDecoder;
+
+@protocol JLSpeexDelegate <NSObject>
+
+/// Speex 数据解码
+/// - Parameters:
+///   - decoder: 解码器
+///   - data: PCM 数据
+///   - error: 错误信息
+- (void)speexDecoder:(JLSpeexDecoder *)decoder Data:(NSData* _Nullable)data error:(NSError* _Nullable)error;
+
+@end
+
+typedef void(^JLSpeexConvertBlock)(NSString *_Nullable pcmPath,NSError *_Nullable error);
+
+/// Speex 数据解码
+@interface JLSpeexDecoder : NSObject
+
+-(instancetype)init NS_UNAVAILABLE;
+
+/// 初始化
+/// - Parameter delegate: 委托
+-(instancetype)initWithDelegate:(id<JLSpeexDelegate>)delegate;
+
+/// 委托
+@property (nonatomic, weak) id<JLSpeexDelegate> delegate;
+
+/// 输入 Speex 数据
+/// - Parameter data: Speex 数据
+-(void)speexInputData:(NSData*)data;
+
+/// 将 Speex 转换为 PCM
+/// - Parameters:
+///   - filePath: Speex 路径
+///   - opPath: 输出路径
+///   - result: 结果回调
+-(void)speexConvertToPcm:(NSString *)filePath outPutFilePath:(NSString * _Nullable)opPath Result:(JLSpeexConvertBlock)result;
+
+/// 释放对象
+-(void)speexOnRelease;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Info.plist b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Info.plist
new file mode 100644 (file)
index 0000000..8464456
Binary files /dev/null and b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Info.plist differ
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/JLAudioUnitKit b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/JLAudioUnitKit
new file mode 100755 (executable)
index 0000000..10234ec
Binary files /dev/null and b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/JLAudioUnitKit differ
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Modules/module.modulemap b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/Modules/module.modulemap
new file mode 100644 (file)
index 0000000..5e1ae1d
--- /dev/null
@@ -0,0 +1,6 @@
+framework module JLAudioUnitKit {
+  umbrella header "JLAudioUnitKit.h"
+  export *
+
+  module * { export * }
+}
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/readme.txt b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-arm64/JLAudioUnitKit.framework/readme.txt
new file mode 100644 (file)
index 0000000..6789fe6
--- /dev/null
@@ -0,0 +1,52 @@
+DESCRIPTION\r
+-----------\r
+This package includes the files needed to build the fixed point implementation\r
+of the ITU-T G.729 Appendix IV.\r
+\r
+DIFFERENCES WITH G.729B\r
+-----------------------\r
+The ANSI-C source code simulating the bit-exact, fixed point simulation \r
+software of enhanced VAD is integrated into the G.729B source code. \r
+The modification to the G.729B source code updated files of coder.c, \r
+cod_ld8k.c, bits.c, dec_sid.c, dtx.c, qsidgain.c, qsidlsf.c, tab_dtx.c, \r
+tab_dtx.h, ld8k.h, deleted vad.c/h and integrated the enhanced VAD functions\r
+into the G.729B project. The modification also replaced the original basic \r
+operators used in the original G.729B source code by the basic operators of \r
+ITU-T Software Tool Library STL2005.\r
+\r
+COMPILATION\r
+-----------\r
+For UNIX systems the following makefiles are provided\r
+\r
+   coder.mak\r
+   decoder.mak\r
+\r
+Edit the makefiles coder.mak and decoder.mak to set the proper options\r
+for your system.\r
+The command to compile and link all code on a UNIX system is\r
+\r
+   make -f coder.mak\r
+   make -f decoder.mak\r
+\r
+For other platforms, the *.mak files can be used to work out the\r
+compilation procedures.\r
+\r
+USAGE\r
+-----\r
+The command line instruction for the encoder is as follows:\r
+   coder inputfile bitstreamfile dtx_option mode x \r
+where:\r
+   inputfile    : 8 kHz sampled data file containing 16 bit linear PCM signal \r
+   bitstreamfile: binary file containing bitstream \r
+   dtx_option   : = 1 : DTX enabled   0 : DTX disabled\r
+   mode X       : Run encoder with enhanced VAD in operating point X, \r
+                  X=0 or 1 or 2 representing balanced or quality-preferred \r
+                  or bandwidth saving operating point, respectively  \r
+\r
+The command line for the decoder is as follows:\r
+   decoder bitstreamfile outputfile\r
+where:\r
+   bitstreamfile: binary file containing bitstream\r
+   outputfile   : 8 kHz sampled data file containing 16 bit linear PCM signal\r
+\r
+\r
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLAudioUnitKit.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLAudioUnitKit.h
new file mode 100644 (file)
index 0000000..e6b3af6
--- /dev/null
@@ -0,0 +1,26 @@
+//
+//  JLAudioUnitKit.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2024/11/14.
+//
+
+#import <Foundation/Foundation.h>
+
+//! Project version number for JLAudioUnitKit.
+FOUNDATION_EXPORT double JLAudioUnitKitVersionNumber;
+
+//! Project version string for JLAudioUnitKit.
+FOUNDATION_EXPORT const unsigned char JLAudioUnitKitVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import <JLAudioUnitKit/PublicHeader.h>
+
+#import <JLAudioUnitKit/JLSpeexDecoder.h>
+#import <JLAudioUnitKit/JLOpusDecoder.h>
+#import <JLAudioUnitKit/JLOpusEncoder.h>
+#import <JLAudioUnitKit/JLOpusFormat.h>
+#import <JLAudioUnitKit/JLOpusEncodeConfig.h>
+#import <JLAudioUnitKit/JLPcmToWtg.h>
+#import <JLAudioUnitKit/JLPcmToWav.h>
+#import <JLAudioUnitKit/JLAudioUnitPlayer.h>
+#import <JLAudioUnitKit/JLOpusToOgg.h>
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLAudioUnitPlayer.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLAudioUnitPlayer.h
new file mode 100644 (file)
index 0000000..7da831c
--- /dev/null
@@ -0,0 +1,58 @@
+//
+//  JLAudioUnitPlayer.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2025/4/16.
+//  Copyright © 2025 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <AudioToolbox/AudioToolbox.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef NS_ENUM(NSInteger, JLAudioUnitPlayerType) {
+    JLAudioUnitPlayerTypeFile,   // 支持 MP3/WAV/AAC 等文件格式(AVAudioPlayer)
+    JLAudioUnitPlayerTypePCM      // 支持 PCM 流式播放(Audio Queue)
+};
+
+@class JLAudioUnitPlayer;
+
+@protocol JLAudioPlayerDelegate <NSObject>
+@optional
+// 播放进度更新(秒)
+- (void)audioPlayer:(JLAudioUnitPlayer *)player didUpdateProgress:(NSTimeInterval)currentTime duration:(NSTimeInterval)duration;
+// 播放完成
+- (void)audioPlayerDidFinishPlaying:(JLAudioUnitPlayer *)player;
+// 播放错误
+- (void)audioPlayer:(JLAudioUnitPlayer *)player didFailWithError:(NSError *)error;
+@end
+
+@interface JLAudioUnitPlayer : NSObject
+
+@property (nonatomic, weak) id<JLAudioPlayerDelegate> delegate;
+@property (nonatomic, readonly) NSTimeInterval duration;  // 总时长(文件模式下有效)
+@property (nonatomic, readonly) NSTimeInterval currentTime;
+@property (nonatomic, readonly) BOOL isPlaying;
+
+#pragma mark - 初始化方法
+
+/// 文件播放初始化(MP3/WAV/AAC)
+- (instancetype)initWithAudioFile:(NSString *)filePath;
+
+/// PCM 流播放初始化(需指定格式)
+- (instancetype)initWithPCMFormat:(AudioStreamBasicDescription)format;
+
+#pragma mark - 播放控制
+- (void)play;
+- (void)pause;
+- (void)stop;
+- (void)seekToTime:(NSTimeInterval)time; // 仅文件模式有效
+
+#pragma mark - PCM 流式输入(仅 PCM 模式有效)
+- (void)appendPCMData:(NSData *)pcmData;
+- (void)endPCMStream; // 结束 PCM 流输入
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusDecoder.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusDecoder.h
new file mode 100644 (file)
index 0000000..711e2e9
--- /dev/null
@@ -0,0 +1,66 @@
+//
+//  JLOpusDecoder.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2024/11/14.
+//  Copyright © 2024 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <JLAudioUnitKit/JLOpusFormat.h>
+
+NS_ASSUME_NONNULL_BEGIN
+@class JLOpusDecoder;
+
+/// Opus 解码代理
+@protocol JLOpusDecoderDelegate <NSObject>
+
+/// Opus 数据解码
+/// - Parameters:
+///   - decoder: 解码器
+///   - data: pcm 数据
+///   - error: 错误信息
+-(void)opusDecoder:(JLOpusDecoder *)decoder Data:(NSData* _Nullable)data error:(NSError* _Nullable)error;
+
+@end
+
+typedef void(^JLOpusDecoderConvertBlock)(NSString *_Nullable pcmPath,NSError *_Nullable error);
+
+/// Opus 解码
+@interface JLOpusDecoder : NSObject
+
+/// 数据格式参数
+@property (nonatomic, strong) JLOpusFormat *opusFormat;
+
+/// 代理委托
+@property(nonatomic, weak) id<JLOpusDecoderDelegate> delegate;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+/// 初始化
+/// - Parameters:
+///   - format: 解码格式
+///   - delegate: 代理
+- (instancetype)initDecoder:(JLOpusFormat *)format delegate:(id<JLOpusDecoderDelegate>)delegate;
+
+/// 重置解码格式
+/// - Parameter format: 解码格式
+-(void)resetOpusFramet:(JLOpusFormat *)format;
+
+/// 输入 Opus 数据
+/// - Parameter data: Opus 数据
+-(void)opusDecoderInputData:(NSData *)data;
+
+/// 解码文件
+/// - Parameters:
+///   - input: opus 文件
+///   - outPut: 输出路径
+///   - result: 结果回调
+-(void)opusDecodeFile:(NSString *)input outPut:(NSString *_Nullable)outPut Resoult:(JLOpusDecoderConvertBlock _Nullable)result;
+
+/// 释放
+-(void)opusOnRelease;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusEncodeConfig.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusEncodeConfig.h
new file mode 100644 (file)
index 0000000..037284e
--- /dev/null
@@ -0,0 +1,83 @@
+//
+//  JLOpusEncodeConfig.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2025/8/27.
+//  Copyright © 2025 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef NS_ENUM(NSInteger, JLOpusEncoderBandwidth) {
+    ///(4kHz bandpass)
+    JLOpusEncoderBandwidthNarrowband = 1101,   // 对应 OPUS_BANDWIDTH_NARROWBAND
+    /// (6kHz bandpass)
+    JLOpusEncoderBandwidthMediumband = 1102,   // 对应 OPUS_BANDWIDTH_MEDIUMBAND
+    /// (8kHz bandpass)
+    JLOpusEncoderBandwidthWideband   = 1103,     // 对应 OPUS_BANDWIDTH_WIDEBAND
+    /// (12kHz bandpass)
+    JLOpusEncoderBandwidthSuperwideband = 1104,// 对应 OPUS_BANDWIDTH_SUPERWIDEBAND
+    /// (20kHz bandpass)
+    JLOpusEncoderBandwidthFullband   = 1105      // 对应 OPUS_BANDWIDTH_FULLBAND
+};
+
+@interface JLOpusEncodeConfig : NSObject
+
+/// 采样率
+@property (nonatomic, assign) int sampleRate;
+
+/// 单/双声道
+@property (nonatomic, assign) int channels;
+
+/// 帧长度 20ms 默认值
+@property (nonatomic, assign) int frameDuration;
+
+/// 帧长度
+@property (nonatomic, assign) int frameSize;
+
+/// BitRate
+@property (nonatomic, assign) int bitRate;
+
+/// 可变比特率开关,默认 NO(使用 CBR)
+@property (nonatomic, assign) BOOL useVBR;
+
+/// VBR 限制模式,默认 NO
+@property (nonatomic, assign) BOOL constrainedVBR;
+
+/// 编码复杂度 0~10,默认 5
+@property (nonatomic, assign) int complexity;
+
+/// 强制输出声道数 -1: 自适应, 1: 单声道, 2: 双声道, 默认 -1
+@property (nonatomic, assign) int forceChannels;
+
+/// 是否启用 DTX(静音段不发送数据),默认 NO
+@property (nonatomic, assign) BOOL useDTX;
+
+/// 网络丢包百分比,默认 0
+@property (nonatomic, assign) int packetLossPercent;
+
+/// 最大带宽限制(OPUS_BANDWIDTH_*),默认 FULLBAND
+@property (nonatomic, assign) int bandwidth;
+
+/// PCM 输入有效位深,默认 16
+@property (nonatomic, assign) int lsbDepth;
+
+/// 专家模式下帧时长(ms),默认与 frameDuration 一致
+@property (nonatomic, assign) int expertFrameDuration;
+
+/// 是否启用数据头
+/// 默认是启用的
+@property (nonatomic, assign) BOOL hasDataHeader;
+
+/// 创建默认编码配置
++ (instancetype)defaultConfig;
+
+/// 获取默认配置
+/// 杰理的无头配置
++ (instancetype)defaultJL;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusEncoder.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusEncoder.h
new file mode 100644 (file)
index 0000000..fbe5af7
--- /dev/null
@@ -0,0 +1,62 @@
+//
+//  JLOpusEncoder.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2024/11/14.
+//  Copyright © 2024 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <JLAudioUnitKit/JLOpusEncodeConfig.h>
+
+NS_ASSUME_NONNULL_BEGIN
+@class JLOpusEncoder;
+
+/// Opus 编码代理
+@protocol JLOpusEncoderDelegate <NSObject>
+
+/// PCM 数据编码
+/// - Parameters:
+///   - encoder: 解码器
+///   - data: opus 数据
+///   - error: 错误信息
+-(void)opusEncoder:(JLOpusEncoder *)encoder Data:(NSData* _Nullable)data error:(NSError* _Nullable)error;
+
+@end
+
+typedef void(^JLOpusEncoderConvertBlock)(NSString *_Nullable pcmPath,NSError *_Nullable error);
+
+/// Opus 编码
+@interface JLOpusEncoder : NSObject
+
+/// 音频格式
+@property (nonatomic, strong) JLOpusEncodeConfig *opusFormat;
+
+/// 代理
+@property (nonatomic, weak) id<JLOpusEncoderDelegate> delegate;
+
+-(instancetype)init NS_UNAVAILABLE;
+
+/// 初始化
+/// - Parameters:
+///   - config: 音频格式
+///   - delegate: 代理
+-(instancetype)initFormat:(JLOpusEncodeConfig *)format delegate:(id<JLOpusEncoderDelegate>)delegate;
+
+/// PCM 数据
+/// - Parameter data: PCM 数据
+-(void)opusEncodeData:(NSData *)data;
+
+/// PCM 文件转换成 Opus 文件
+/// - Parameters:
+///   - pcmPath: PCM 文件存放路径
+///   - outPut: 文件输出路径
+///   - result: 结果回调
+-(void)opusEncodeFile:(NSString *)pcmPath outPut:(NSString *_Nullable)outPut Resoult:(JLOpusEncoderConvertBlock _Nullable)result;
+
+/// 释放
+-(void)opusOnRelease;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusFormat.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusFormat.h
new file mode 100644 (file)
index 0000000..0165487
--- /dev/null
@@ -0,0 +1,59 @@
+//
+//  JLOpusOptions.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2024/11/14.
+//  Copyright © 2024 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+#define OPUS_JL_MAX_FRAME_SIZE 48000 * 2
+#define OPUS_JL_MAX_PACKET_SIZE 1500
+
+
+@interface JLOpusFormat : NSObject
+
+/// 采样率
+@property (nonatomic, assign) int sampleRate;
+
+/// 单/双声道
+@property (nonatomic, assign) int channels;
+
+/// 帧长度 20ms 默认值
+@property (nonatomic, assign) int frameDuration;
+
+/// BitRate
+@property (nonatomic, assign) int bitRate;
+
+/// 数据帧大小
+@property (nonatomic, assign, readonly) int frameSize;
+
+/// 数据大小
+@property (nonatomic, assign) int dataSize;
+
+/// 是否包含数据头部
+@property (nonatomic, assign) BOOL hasDataHeader;
+
+/// 是否开启slik语音优化
+@property (nonatomic, assign) BOOL usVoipSlik;
+
+
+-(instancetype)init NS_UNAVAILABLE;
+
+/// 默认配置
+/// sampleRate: 16000
+/// channels: 1
+/// frameDuration: 20
+/// dataSize: 40
+/// frameSize: 320
+/// hasDataHeader: YES
+/// bitRate: 16000
+/// usVoipSlik: false
++(JLOpusFormat*)defaultFormats;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusToOgg.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLOpusToOgg.h
new file mode 100644 (file)
index 0000000..27b919b
--- /dev/null
@@ -0,0 +1,67 @@
+//
+//  JLOpusToOgg.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2025/5/16.
+//  Copyright © 2025 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void(^JLOpusToOggConvertBlock)(NSData *_Nullable oggData, BOOL isLast, NSError *_Nullable error);
+
+/// 将Opus数据转换为Ogg数据
+@interface JLOpusToOgg : NSObject
+
+/// 转码内容的回调
+@property(nonatomic,strong)JLOpusToOggConvertBlock _Nullable convertBlock;
+
+/// 帧长
+/// - Parameter frameLen: 帧长
+/// 默认值 40
+- (instancetype)initWithFrameLength:(uint32_t)frameLen;
+
+/// 开始流
+-(void)startStream;
+
+/// 添加Opus数据
+/// - Parameter opusData: 符合杰理的无头裸 opus 数据
+- (void)appendOpusData:(NSData *)opusData;
+
+/// 关闭流
+- (void)closeStream;
+
+
+/// 将Opus数据转换为Ogg数据
+/// opus 必须为 16000
+/// opus 必须是 单声道
+/// - Parameters:
+///   - opusData: 符合杰理的无头裸 opus 数据
+///   - frameLen: 帧长 公版默认帧长是 40
+///   - duration: 转换后的时长
+///   - error: 错误
++ (NSData *_Nullable)convertOpusDataToOgg:(NSData *)opusData
+                                 frameLen:(uint32_t)frameLen
+                                 duration:(double *)duration
+                                    error:(NSError *__autoreleasing _Nullable *)error ;
+
+/// 将Opus文件转换为Ogg文件
+/// 符合杰理的无头裸 opus 文件
+/// opus 必须为 16000
+/// opus 必须是 单声道
+/// - Parameters:
+///   - opusFilePath: opus文件路径
+///   - oggFilePath: ogg文件路径
+///   - frameLen: 帧长 公版默认帧长是 40
+///   - duration: 转换后的时长
++(void)convertOpusFileToOgg:(NSString *)opusFilePath
+                oggFilePath:(NSString *)oggFilePath
+                   frameLen:(uint32_t)frameLen
+                   duration:(double *)duration;
+
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLPcmToWav.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLPcmToWav.h
new file mode 100644 (file)
index 0000000..b32ecef
--- /dev/null
@@ -0,0 +1,55 @@
+//
+//  JLPcmToWav.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2025/4/15.
+//  Copyright © 2025 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// PCM 转 WAV
+@interface JLPcmToWav : NSObject
+
+#pragma mark - 流式编码接口
+
+/// 初始化流式编码器
+/// @param outputPath 输出文件路径
+/// @param sampleRate 采样率(如 16000)
+/// @param numChannels 声道数(1 或 2)
+/// @param bitsPerSample 位深(16)
+- (instancetype)initWithOutputPath:(NSString *)outputPath
+                       sampleRate:(uint32_t)sampleRate
+                     numChannels:(uint16_t)numChannels
+                  bitsPerSample:(uint16_t)bitsPerSample;
+
+/// 追加 PCM 数据(需确保数据格式与初始化参数一致)
+/// @param pcmData PCM 数据块
+/// @param error 错误信息
+- (BOOL)appendPCMData:(NSData *)pcmData error:(NSError **)error;
+
+/// 完成编码并关闭文件(必须调用以更新 WAV 头)
+/// @param error 错误信息
+- (BOOL)finishWithError:(NSError **)error;
+
+#pragma mark - 一次性编码接口(便捷方法)
+
+/// 将 PCM 数据一次性转为 WAV 文件
+/// @param pcmData PCM 数据块
+/// @param outputPath 输出文件路径
+/// @param sampleRate 采样率(如 16000)
+/// @param numChannels 声道数(1 或 2)
+/// @param bitsPerSample 位深(16)
+/// @param error 错误信息
++ (BOOL)convertPCMData:(NSData *)pcmData
+            toWAVFile:(NSString *)outputPath
+           sampleRate:(uint32_t)sampleRate
+         numChannels:(uint16_t)numChannels
+      bitsPerSample:(uint16_t)bitsPerSample
+              error:(NSError **)error;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLPcmToWtg.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLPcmToWtg.h
new file mode 100644 (file)
index 0000000..231b3e8
--- /dev/null
@@ -0,0 +1,51 @@
+//
+//  JLPcmToWtg.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2025/1/21.
+//  Copyright © 2025 ZhuHai JieLi Technology Co.,Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface JLPcm2WtgModel : NSObject <NSCopying>
+
+/// 音频文件
+@property (nonatomic, copy) NSString *pcmPath;
+
+/// 输出文件
+@property (nonatomic, copy) NSString *wtgPath;
+
+@end
+
+
+/// JLPcmToWtgProtocol
+@protocol JLPcmToWtgDelegate <NSObject>
+
+/// 音频转码完成
+/// - Parameter model: 音频转码模型
+- (void)convertPcmToWtgDone:(JLPcm2WtgModel *)model;
+
+@end
+
+/// 音频转码
+/// PCM 转 WTG
+@interface JLPcmToWtg : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
+
+/// 音频转码初始化
+/// - Parameter delegate: 音频转码代理
+- (instancetype)initWithDelegate:(id<JLPcmToWtgDelegate>)delegate;
+
+/// 音频转码
+/// 当前接口模型只限制 PCM 文件格式为:8k 16bit
+/// 输入的pcm文件(16bit,小端,8k采样率),wtg_filename:输出的wtg文件
+/// - Parameter model: 音频转码模型
+-(void)convertPcmToWtg:(JLPcm2WtgModel *)model;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLSpeexDecoder.h b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Headers/JLSpeexDecoder.h
new file mode 100644 (file)
index 0000000..ad223d0
--- /dev/null
@@ -0,0 +1,54 @@
+//
+//  JLSpeexUnit.h
+//  JLAudioUnitKit
+//
+//  Created by EzioChan on 2024/11/14.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+@class JLSpeexDecoder;
+
+@protocol JLSpeexDelegate <NSObject>
+
+/// Speex 数据解码
+/// - Parameters:
+///   - decoder: 解码器
+///   - data: PCM 数据
+///   - error: 错误信息
+- (void)speexDecoder:(JLSpeexDecoder *)decoder Data:(NSData* _Nullable)data error:(NSError* _Nullable)error;
+
+@end
+
+typedef void(^JLSpeexConvertBlock)(NSString *_Nullable pcmPath,NSError *_Nullable error);
+
+/// Speex 数据解码
+@interface JLSpeexDecoder : NSObject
+
+-(instancetype)init NS_UNAVAILABLE;
+
+/// 初始化
+/// - Parameter delegate: 委托
+-(instancetype)initWithDelegate:(id<JLSpeexDelegate>)delegate;
+
+/// 委托
+@property (nonatomic, weak) id<JLSpeexDelegate> delegate;
+
+/// 输入 Speex 数据
+/// - Parameter data: Speex 数据
+-(void)speexInputData:(NSData*)data;
+
+/// 将 Speex 转换为 PCM
+/// - Parameters:
+///   - filePath: Speex 路径
+///   - opPath: 输出路径
+///   - result: 结果回调
+-(void)speexConvertToPcm:(NSString *)filePath outPutFilePath:(NSString * _Nullable)opPath Result:(JLSpeexConvertBlock)result;
+
+/// 释放对象
+-(void)speexOnRelease;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Info.plist b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Info.plist
new file mode 100644 (file)
index 0000000..6d387d3
Binary files /dev/null and b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Info.plist differ
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/JLAudioUnitKit b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/JLAudioUnitKit
new file mode 100755 (executable)
index 0000000..61fc959
Binary files /dev/null and b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/JLAudioUnitKit differ
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Modules/module.modulemap b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/Modules/module.modulemap
new file mode 100644 (file)
index 0000000..5e1ae1d
--- /dev/null
@@ -0,0 +1,6 @@
+framework module JLAudioUnitKit {
+  umbrella header "JLAudioUnitKit.h"
+  export *
+
+  module * { export * }
+}
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/_CodeSignature/CodeResources b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/_CodeSignature/CodeResources
new file mode 100644 (file)
index 0000000..be9f00c
--- /dev/null
@@ -0,0 +1,234 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>files</key>
+       <dict>
+               <key>Headers/JLAudioUnitKit.h</key>
+               <data>
+               hE2nr+4q2/NdSgBaayJc7ZoOXb0=
+               </data>
+               <key>Headers/JLAudioUnitPlayer.h</key>
+               <data>
+               QPMLV/XA8hjk39d+vT+S57t0fDU=
+               </data>
+               <key>Headers/JLOpusDecoder.h</key>
+               <data>
+               K1bYcaJ67prImNlGuldy8csTRHc=
+               </data>
+               <key>Headers/JLOpusEncodeConfig.h</key>
+               <data>
+               NArAew5QxnSJGsD0tRzQ2V7bHrY=
+               </data>
+               <key>Headers/JLOpusEncoder.h</key>
+               <data>
+               BkgtVe9kCM4Fkc9oH1tC3BNh5Kw=
+               </data>
+               <key>Headers/JLOpusFormat.h</key>
+               <data>
+               Du1x3VNk87NstmspRk7ElijuZrk=
+               </data>
+               <key>Headers/JLOpusToOgg.h</key>
+               <data>
+               fSJT6LcyylJHTHX1wsN3JHG2FxU=
+               </data>
+               <key>Headers/JLPcmToWav.h</key>
+               <data>
+               /BbZmqmWpWVBusXqjnzbjaBNCNg=
+               </data>
+               <key>Headers/JLPcmToWtg.h</key>
+               <data>
+               zoOdOFpIulND0F1OrfIXR1H0kh0=
+               </data>
+               <key>Headers/JLSpeexDecoder.h</key>
+               <data>
+               5ecBKtD3BDGccLiKpTs0fS0CSgs=
+               </data>
+               <key>Info.plist</key>
+               <data>
+               Q2Tz1ljDQKvKxkn8afbgb/2RVnU=
+               </data>
+               <key>Modules/module.modulemap</key>
+               <data>
+               2vYf0m+hGTOTapX6sliv/F1E1VI=
+               </data>
+               <key>readme.txt</key>
+               <data>
+               wijZX0Dr2OlODWS6XYbpeKabb7g=
+               </data>
+       </dict>
+       <key>files2</key>
+       <dict>
+               <key>Headers/JLAudioUnitKit.h</key>
+               <dict>
+                       <key>hash2</key>
+                       <data>
+                       J5pq6Ed3fR+cQ7CGPXDoPl7BZzix7Cjf5yJZFRRvxqs=
+                       </data>
+               </dict>
+               <key>Headers/JLAudioUnitPlayer.h</key>
+               <dict>
+                       <key>hash2</key>
+                       <data>
+                       qBz0OA82HUH4kBtO8xiUw7Q4ohtiIvCSYfCqax5xjJY=
+                       </data>
+               </dict>
+               <key>Headers/JLOpusDecoder.h</key>
+               <dict>
+                       <key>hash2</key>
+                       <data>
+                       cnAj6Nt6vgRLoEH6QY3Q+gYpjcxGPN1OLLZbCgdLymI=
+                       </data>
+               </dict>
+               <key>Headers/JLOpusEncodeConfig.h</key>
+               <dict>
+                       <key>hash2</key>
+                       <data>
+                       qrPpsrXaNCvyxf0/gUZtvveL+ywsfgBUrMPFibjneOo=
+                       </data>
+               </dict>
+               <key>Headers/JLOpusEncoder.h</key>
+               <dict>
+                       <key>hash2</key>
+                       <data>
+                       PK+jl5IacMxuDEKkBwsjwpnGYxj/6Th3ICW4YQ7aRPA=
+                       </data>
+               </dict>
+               <key>Headers/JLOpusFormat.h</key>
+               <dict>
+                       <key>hash2</key>
+                       <data>
+                       Nm6vM9/EbFzyIWbsysu6EOO2S+vZVeplcop4NvoJaMA=
+                       </data>
+               </dict>
+               <key>Headers/JLOpusToOgg.h</key>
+               <dict>
+                       <key>hash2</key>
+                       <data>
+                       dNSvJJnED/6E1p7TYZ4zBzUnLDVsZ8NovuNYjge6T/w=
+                       </data>
+               </dict>
+               <key>Headers/JLPcmToWav.h</key>
+               <dict>
+                       <key>hash2</key>
+                       <data>
+                       l/SEQhSFh7ctq/pBV+Z7X+Z0/gz30eCw3s31otjMPho=
+                       </data>
+               </dict>
+               <key>Headers/JLPcmToWtg.h</key>
+               <dict>
+                       <key>hash2</key>
+                       <data>
+                       MwtbX3Sa0nytA+m11x+1rDvP4WvJnZLljshuT5B3WD0=
+                       </data>
+               </dict>
+               <key>Headers/JLSpeexDecoder.h</key>
+               <dict>
+                       <key>hash2</key>
+                       <data>
+                       pV0X3xn07Ps7wE+0EfL9Yu/08tp8Ug8s14iDigRU46o=
+                       </data>
+               </dict>
+               <key>Modules/module.modulemap</key>
+               <dict>
+                       <key>hash2</key>
+                       <data>
+                       akFCUM59aSAaRM/ADWQ138YT9GD3oAjcaTvTUo24Ml8=
+                       </data>
+               </dict>
+               <key>readme.txt</key>
+               <dict>
+                       <key>hash2</key>
+                       <data>
+                       +2GG9ORrf2yJnBe2joKWtyBZL9p2sCH8EXqK1GIgW0E=
+                       </data>
+               </dict>
+       </dict>
+       <key>rules</key>
+       <dict>
+               <key>^.*</key>
+               <true/>
+               <key>^.*\.lproj/</key>
+               <dict>
+                       <key>optional</key>
+                       <true/>
+                       <key>weight</key>
+                       <real>1000</real>
+               </dict>
+               <key>^.*\.lproj/locversion.plist$</key>
+               <dict>
+                       <key>omit</key>
+                       <true/>
+                       <key>weight</key>
+                       <real>1100</real>
+               </dict>
+               <key>^Base\.lproj/</key>
+               <dict>
+                       <key>weight</key>
+                       <real>1010</real>
+               </dict>
+               <key>^version.plist$</key>
+               <true/>
+       </dict>
+       <key>rules2</key>
+       <dict>
+               <key>.*\.dSYM($|/)</key>
+               <dict>
+                       <key>weight</key>
+                       <real>11</real>
+               </dict>
+               <key>^(.*/)?\.DS_Store$</key>
+               <dict>
+                       <key>omit</key>
+                       <true/>
+                       <key>weight</key>
+                       <real>2000</real>
+               </dict>
+               <key>^.*</key>
+               <true/>
+               <key>^.*\.lproj/</key>
+               <dict>
+                       <key>optional</key>
+                       <true/>
+                       <key>weight</key>
+                       <real>1000</real>
+               </dict>
+               <key>^.*\.lproj/locversion.plist$</key>
+               <dict>
+                       <key>omit</key>
+                       <true/>
+                       <key>weight</key>
+                       <real>1100</real>
+               </dict>
+               <key>^Base\.lproj/</key>
+               <dict>
+                       <key>weight</key>
+                       <real>1010</real>
+               </dict>
+               <key>^Info\.plist$</key>
+               <dict>
+                       <key>omit</key>
+                       <true/>
+                       <key>weight</key>
+                       <real>20</real>
+               </dict>
+               <key>^PkgInfo$</key>
+               <dict>
+                       <key>omit</key>
+                       <true/>
+                       <key>weight</key>
+                       <real>20</real>
+               </dict>
+               <key>^embedded\.provisionprofile$</key>
+               <dict>
+                       <key>weight</key>
+                       <real>20</real>
+               </dict>
+               <key>^version\.plist$</key>
+               <dict>
+                       <key>weight</key>
+                       <real>20</real>
+               </dict>
+       </dict>
+</dict>
+</plist>
diff --git a/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/readme.txt b/ShenYin/framework/JLAudioUnitKit.xcframework/ios-x86_64-simulator/JLAudioUnitKit.framework/readme.txt
new file mode 100644 (file)
index 0000000..6789fe6
--- /dev/null
@@ -0,0 +1,52 @@
+DESCRIPTION\r
+-----------\r
+This package includes the files needed to build the fixed point implementation\r
+of the ITU-T G.729 Appendix IV.\r
+\r
+DIFFERENCES WITH G.729B\r
+-----------------------\r
+The ANSI-C source code simulating the bit-exact, fixed point simulation \r
+software of enhanced VAD is integrated into the G.729B source code. \r
+The modification to the G.729B source code updated files of coder.c, \r
+cod_ld8k.c, bits.c, dec_sid.c, dtx.c, qsidgain.c, qsidlsf.c, tab_dtx.c, \r
+tab_dtx.h, ld8k.h, deleted vad.c/h and integrated the enhanced VAD functions\r
+into the G.729B project. The modification also replaced the original basic \r
+operators used in the original G.729B source code by the basic operators of \r
+ITU-T Software Tool Library STL2005.\r
+\r
+COMPILATION\r
+-----------\r
+For UNIX systems the following makefiles are provided\r
+\r
+   coder.mak\r
+   decoder.mak\r
+\r
+Edit the makefiles coder.mak and decoder.mak to set the proper options\r
+for your system.\r
+The command to compile and link all code on a UNIX system is\r
+\r
+   make -f coder.mak\r
+   make -f decoder.mak\r
+\r
+For other platforms, the *.mak files can be used to work out the\r
+compilation procedures.\r
+\r
+USAGE\r
+-----\r
+The command line instruction for the encoder is as follows:\r
+   coder inputfile bitstreamfile dtx_option mode x \r
+where:\r
+   inputfile    : 8 kHz sampled data file containing 16 bit linear PCM signal \r
+   bitstreamfile: binary file containing bitstream \r
+   dtx_option   : = 1 : DTX enabled   0 : DTX disabled\r
+   mode X       : Run encoder with enhanced VAD in operating point X, \r
+                  X=0 or 1 or 2 representing balanced or quality-preferred \r
+                  or bandwidth saving operating point, respectively  \r
+\r
+The command line for the decoder is as follows:\r
+   decoder bitstreamfile outputfile\r
+where:\r
+   bitstreamfile: binary file containing bitstream\r
+   outputfile   : 8 kHz sampled data file containing 16 bit linear PCM signal\r
+\r
+\r