泰凌微协议调试
authorliangzhenying <867174124@qq.com>
Wed, 21 Aug 2024 01:53:34 +0000 (09:53 +0800)
committerliangzhenying <867174124@qq.com>
Wed, 21 Aug 2024 01:53:34 +0000 (09:53 +0800)
13 files changed:
Document/adpcm.c [new file with mode: 0644]
Document/adpcm.h [new file with mode: 0644]
MouseSdk/AiMouseSdk/AiMouseSdk.xcodeproj/project.pbxproj
MouseSdk/AiMouseSdk/AiMouseSdk/ADPCMConverter.h [new file with mode: 0644]
MouseSdk/AiMouseSdk/AiMouseSdk/ADPCMConverter.m [new file with mode: 0644]
MouseSdk/AiMouseSdk/AiMouseSdk/AiAudioManager.m
MouseSdk/AiMouseSdk/AiMouseSdk/AiMouseSdk.h
MouseSdk/AiMouseSdk/AiMouseSdk/AiMouseSdk.m
MouseSdk/AiMouseSdk/AiMouseSdk/adpcm.c [new file with mode: 0644]
MouseSdk/AiMouseSdk/AiMouseSdk/adpcm.h [new file with mode: 0644]
MouseSdk/MouseSdk/BleManager.m
MouseSdk/MouseSdk/HidManager.m
MouseSdk/MouseSdk/ViewController.m

diff --git a/Document/adpcm.c b/Document/adpcm.c
new file mode 100644 (file)
index 0000000..45fd010
--- /dev/null
@@ -0,0 +1,148 @@
+/********************************************************************************************************
+ * @file       adpcm.c
+ *
+ * @brief      This is the source file for BLE SDK
+ *
+ * @author     BLE GROUP
+ * @date       06,2020
+ *
+ * @par     Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
+ *          All rights reserved.
+ *
+ *          Redistribution and use in source and binary forms, with or without
+ *          modification, are permitted provided that the following conditions are met:
+ *
+ *              1. Redistributions of source code must retain the above copyright
+ *              notice, this list of conditions and the following disclaimer.
+ *
+ *              2. Unless for usage inside a TELINK integrated circuit, redistributions
+ *              in binary form must reproduce the above copyright notice, this list of
+ *              conditions and the following disclaimer in the documentation and/or other
+ *              materials provided with the distribution.
+ *
+ *              3. Neither the name of TELINK, nor the names of its contributors may be
+ *              used to endorse or promote products derived from this software without
+ *              specific prior written permission.
+ *
+ *              4. This software, with or without modification, must only be used with a
+ *              TELINK integrated circuit. All other usages are subject to written permission
+ *              from TELINK and different commercial license may apply.
+ *
+ *              5. Licensee shall be solely responsible for any claim to the extent arising out of or
+ *              relating to such deletion(s), modification(s) or alteration(s).
+ *
+ *          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ *          ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *          WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *          DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
+ *          DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *          (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *          LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *          ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *          (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *******************************************************************************************************/
+
+#include       "adpcm.h"
+
+static const signed char idxtbl[] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8};
+static const unsigned short steptbl[] = {
+ 7,  8,  9,  10,  11,  12,  13,  14,  16,  17,
+ 19,  21,  23,  25,  28,  31,  34,  37,  41,  45,
+ 50,  55,  60,  66,  73,  80,  88,  97,  107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+    15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767   };
+
+#define         NUM_OF_ORIG_SAMPLE                             2
+
+void adpcm_to_pcm (signed short *ps, signed short *pd, int len)
+{
+       int i;
+       //byte2,byte1: predict;  byte3: predict_idx; byte4:adpcm data len
+       int predict = ps[0];
+       int predict_idx = ps[1] & 0xff;
+//     int adpcm_len = (ps[1]>>8) & 0xff;
+       unsigned char *pcode = (unsigned char *) (ps + NUM_OF_ORIG_SAMPLE);
+       unsigned char code;
+       code = *pcode ++;
+
+       //byte5- byte128: 124 byte(62 sample) adpcm data
+       for (i=0; i<len; i++) {
+
+               if (1) {
+                       int step = steptbl[predict_idx];
+
+                       int diffq = step >> 3;
+
+                       if (code & 4) {
+                               diffq = diffq + step;
+                       }
+                       step = step >> 1;
+                       if (code & 2) {
+                               diffq = diffq + step;
+                       }
+                       step = step >> 1;
+                       if (code & 1) {
+                               diffq = diffq + step;
+                       }
+
+                       if (code & 8) {
+                               predict = predict - diffq;
+                       }
+                       else {
+                               predict = predict + diffq;
+                       }
+
+                       if (predict > 32767) {
+                               predict = 32767;
+                       }
+                       else if (predict < -32768) {
+                               predict = -32768;
+                       }
+
+                       predict_idx = predict_idx + idxtbl[code & 15];
+
+                       if(predict_idx < 0) {
+                               predict_idx = 0;
+                       }
+                       else if(predict_idx > 88) {
+                               predict_idx = 88;
+                       }
+
+                       if (i&1) {
+                               code = *pcode ++;
+                       }
+                       else {
+                               code = code >> 4;
+                       }
+               }
+
+               if (0 && i < NUM_OF_ORIG_SAMPLE) {
+                       *pd++ = ps[i];
+               }
+               else {
+                       *pd++ = predict;
+               }
+       }
+}
+
+//例子
+#if 0
+#define MIC_ADPCM_FRAME_SIZE           128                                             //一包 adpcm 的数据长度 128 byte
+#define MIC_SHORT_DEC_SIZE                     248
+#define DEC_BUFFER_SIZE                (MIC_SHORT_DEC_SIZE<<2)
+
+unsigned char          abuf_dec_wptr;                                                  // 0~3 , 4个缓冲 ,循环使用                               
+unsigned char          abuf_mic[MIC_ADPCM_FRAME_SIZE * 4];             //压缩的语音数据adpcm缓冲区 ,4个缓冲 ,每个缓冲区 128 byte , 循环使用
+signed short           abuf_dec[DEC_BUFFER_SIZE];                              //解压后存放的数据,注意数组类型是 16 bit,4个缓冲,循环使用
+
+//abuf_mic 源 ,  abuf_dec 目的 , 每次解压 128 byte adpcm 
+adpcm_to_pcm ((signed short *)(abuf_mic + (abuf_dec_wptr & 3) * MIC_ADPCM_FRAME_SIZE), abuf_dec + (abuf_dec_wptr & 3) * MIC_SHORT_DEC_SIZE, MIC_SHORT_DEC_SIZE );
+
+#endif
+
diff --git a/Document/adpcm.h b/Document/adpcm.h
new file mode 100644 (file)
index 0000000..0cb25a9
--- /dev/null
@@ -0,0 +1,51 @@
+/********************************************************************************************************
+ * @file       adpcm.h
+ *
+ * @brief      This is the header file for BLE SDK
+ *
+ * @author     BLE GROUP
+ * @date       06,2020
+ *
+ * @par     Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
+ *          All rights reserved.
+ *
+ *          Redistribution and use in source and binary forms, with or without
+ *          modification, are permitted provided that the following conditions are met:
+ *
+ *              1. Redistributions of source code must retain the above copyright
+ *              notice, this list of conditions and the following disclaimer.
+ *
+ *              2. Unless for usage inside a TELINK integrated circuit, redistributions
+ *              in binary form must reproduce the above copyright notice, this list of
+ *              conditions and the following disclaimer in the documentation and/or other
+ *              materials provided with the distribution.
+ *
+ *              3. Neither the name of TELINK, nor the names of its contributors may be
+ *              used to endorse or promote products derived from this software without
+ *              specific prior written permission.
+ *
+ *              4. This software, with or without modification, must only be used with a
+ *              TELINK integrated circuit. All other usages are subject to written permission
+ *              from TELINK and different commercial license may apply.
+ *
+ *              5. Licensee shall be solely responsible for any claim to the extent arising out of or
+ *              relating to such deletion(s), modification(s) or alteration(s).
+ *
+ *          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ *          ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *          WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *          DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
+ *          DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *          (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *          LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *          ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *          (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *******************************************************************************************************/
+#ifndef ADPCM_H_
+#define ADPCM_H_
+
+void adpcm_to_pcm(signed short *ps, signed short *pd, int len);
+
+#endif /* ADPCM_H_ */
index 28d9cae..1d05792 100644 (file)
                184A71202BDD11C70025A332 /* AiTrippleModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 184A711E2BDD11C70025A332 /* AiTrippleModel.m */; };
                184A71242BDE2DA60025A332 /* AiSecretModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 184A71222BDE2DA60025A332 /* AiSecretModel.h */; };
                184A71252BDE2DA60025A332 /* AiSecretModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 184A71232BDE2DA60025A332 /* AiSecretModel.m */; };
+               187595B32C743F9300E88FFC /* ADPCMConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 187595B12C743F9300E88FFC /* ADPCMConverter.h */; };
+               187595B42C743F9300E88FFC /* ADPCMConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 187595B22C743F9300E88FFC /* ADPCMConverter.m */; };
+               187595B72C74423000E88FFC /* adpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 187595B52C74423000E88FFC /* adpcm.c */; };
+               187595B82C74423000E88FFC /* adpcm.h in Headers */ = {isa = PBXBuildFile; fileRef = 187595B62C74423000E88FFC /* adpcm.h */; };
                189C15862C05726600676A80 /* AiConnectManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 189C15842C05726600676A80 /* AiConnectManager.h */; };
                189C15872C05726600676A80 /* AiConnectManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 189C15852C05726600676A80 /* AiConnectManager.m */; };
                18AD83292BFB22DE009BDE3B /* AiSender.h in Headers */ = {isa = PBXBuildFile; fileRef = 18AD83272BFB22DE009BDE3B /* AiSender.h */; };
                184A711E2BDD11C70025A332 /* AiTrippleModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiTrippleModel.m; sourceTree = "<group>"; };
                184A71222BDE2DA60025A332 /* AiSecretModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiSecretModel.h; sourceTree = "<group>"; };
                184A71232BDE2DA60025A332 /* AiSecretModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiSecretModel.m; sourceTree = "<group>"; };
+               187595B12C743F9300E88FFC /* ADPCMConverter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ADPCMConverter.h; sourceTree = "<group>"; };
+               187595B22C743F9300E88FFC /* ADPCMConverter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ADPCMConverter.m; sourceTree = "<group>"; };
+               187595B52C74423000E88FFC /* adpcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adpcm.c; sourceTree = "<group>"; };
+               187595B62C74423000E88FFC /* adpcm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = adpcm.h; sourceTree = "<group>"; };
                189C15842C05726600676A80 /* AiConnectManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiConnectManager.h; sourceTree = "<group>"; };
                189C15852C05726600676A80 /* AiConnectManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiConnectManager.m; sourceTree = "<group>"; };
                18AD83272BFB22DE009BDE3B /* AiSender.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiSender.h; sourceTree = "<group>"; };
                                184A71232BDE2DA60025A332 /* AiSecretModel.m */,
                                180E7AB72BD7BD7D008558E8 /* AiAudioConverter.h */,
                                180E7B4B2BD7BD80008558E8 /* AiAudioConverter.m */,
+                               187595B12C743F9300E88FFC /* ADPCMConverter.h */,
+                               187595B22C743F9300E88FFC /* ADPCMConverter.m */,
                                180E7B502BD7BD82008558E8 /* AiAudioDecoder.h */,
                                180E7AB52BD7BD7D008558E8 /* AiAudioDecoder.m */,
                                180E7B4C2BD7BD81008558E8 /* AiAudioManager.h */,
                                180E7B4A2BD7BD80008558E8 /* AiMouseTools.m */,
                                180E7B532BD7BD82008558E8 /* AiMouseTools2.h */,
                                180E7B4F2BD7BD81008558E8 /* AiMouseTools2.m */,
+                               187595B52C74423000E88FFC /* adpcm.c */,
+                               187595B62C74423000E88FFC /* adpcm.h */,
                                180E7AB82BD7BD7D008558E8 /* AiRecordManager.h */,
                                180E7B4E2BD7BD81008558E8 /* AiRecordManager.m */,
                        );
                                180E7CE02BD8FC4E008558E8 /* version.h in Headers */,
                                180E7C972BD8FC4E008558E8 /* base64.h in Headers */,
                                180E7CC02BD8FC4E008558E8 /* mastering_display_metadata.h in Headers */,
+                               187595B82C74423000E88FFC /* adpcm.h in Headers */,
                                180E7CA02BD8FC4E008558E8 /* crc.h in Headers */,
                                180E7C8A2BD8FC4E008558E8 /* hwcontext_cuda.h in Headers */,
                                180E7CA62BD8FC4E008558E8 /* hwcontext_vaapi.h in Headers */,
                                180E7CD72BD8FC4E008558E8 /* aes_ctr.h in Headers */,
                                180E7CFC2BD8FC4F008558E8 /* vorbis_parser.h in Headers */,
                                180E7CE82BD8FC4E008558E8 /* avcodec.h in Headers */,
+                               187595B32C743F9300E88FFC /* ADPCMConverter.h in Headers */,
                                180E7C962BD8FC4E008558E8 /* pixdesc.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        buildActionMask = 2147483647;
                        files = (
                                180E7BE52BD7BD84008558E8 /* AiMouseTools2.m in Sources */,
+                               187595B42C743F9300E88FFC /* ADPCMConverter.m in Sources */,
                                184A71252BDE2DA60025A332 /* AiSecretModel.m in Sources */,
                                18AD832A2BFB22DE009BDE3B /* AiSender.m in Sources */,
                                184A71202BDD11C70025A332 /* AiTrippleModel.m in Sources */,
                                189C15872C05726600676A80 /* AiConnectManager.m in Sources */,
                                180E7BDF2BD7BD84008558E8 /* AiMouseConfig.m in Sources */,
                                184A710D2BDA4C050025A332 /* AFSecurityPolicy.m in Sources */,
+                               187595B72C74423000E88FFC /* adpcm.c in Sources */,
                                180E7B552BD7BD83008558E8 /* AiAudioDecoder.m in Sources */,
                                184A71092BDA4C050025A332 /* AFURLSessionManager.m in Sources */,
                        );
diff --git a/MouseSdk/AiMouseSdk/AiMouseSdk/ADPCMConverter.h b/MouseSdk/AiMouseSdk/AiMouseSdk/ADPCMConverter.h
new file mode 100644 (file)
index 0000000..0558f1e
--- /dev/null
@@ -0,0 +1,18 @@
+//
+//  AiAdpcm2pcm.h
+//  AiMouseSdk
+//
+//  Created by incar on 2024/8/20.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ADPCMConverter : NSObject
+
+- (NSData *)convertADPCMToPCM:(NSData *)adpcmData;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/MouseSdk/AiMouseSdk/AiMouseSdk/ADPCMConverter.m b/MouseSdk/AiMouseSdk/AiMouseSdk/ADPCMConverter.m
new file mode 100644 (file)
index 0000000..42e25f3
--- /dev/null
@@ -0,0 +1,92 @@
+
+#import "ADPCMConverter.h"
+#import <Foundation/Foundation.h>
+
+
+
+@implementation ADPCMConverter
+
+static const signed char idxtbl[] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8};
+static const unsigned short steptbl[] = {
+    7,  8,  9,  10,  11,  12,  13,  14,  16,  17,
+    19,  21,  23,  25,  28,  31,  34,  37,  41,  45,
+    50,  55,  60,  66,  73,  80,  88,  97,  107, 118,
+    130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+    337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+    876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+    2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+    5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+       15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
+#define NUM_OF_ORIG_SAMPLE 2
+
+- (NSData *)convertADPCMToPCM:(NSData *)adpcmData {
+    NSMutableData *pcmData = [NSMutableData data];
+    const signed short *source = (const signed short *)[adpcmData bytes];
+    signed short *destination = (signed short *)[pcmData mutableBytes];
+    int len = (int)[adpcmData length] / sizeof(signed short);
+
+    int i;
+    // 假设 source 中的前两个元素分别是 predict 和 predict_idx
+    int predict = source[0];
+    int predict_idx = source[1] & 0xff;
+    const unsigned char *pcode = (const unsigned char *)(source + NUM_OF_ORIG_SAMPLE);
+    unsigned char code;
+    code = *pcode++;
+
+    for (i = 0; i < len; i++) {
+        if (1) {
+            int step = steptbl[predict_idx];
+
+            int diffq = step >> 3;
+
+            if (code & 4) {
+                diffq = diffq + step;
+            }
+            step = step >> 1;
+            if (code & 2) {
+                diffq = diffq + step;
+            }
+            step = step >> 1;
+            if (code & 1) {
+                diffq = diffq + step;
+            }
+
+            if (code & 8) {
+                predict = predict - diffq;
+            } else {
+                predict = predict + diffq;
+            }
+
+            if (predict > 32767) {
+                predict = 32767;
+            } else if (predict < -32768) {
+                predict = -32768;
+            }
+
+            predict_idx = predict_idx + idxtbl[code & 15];
+
+            if (predict_idx < 0) {
+                predict_idx = 0;
+            } else if (predict_idx > 88) {
+                predict_idx = 88;
+            }
+
+            if (i & 1) {
+                code = *pcode++;
+            } else {
+                code = code >> 4;
+            }
+        }
+
+        if (0 && i < NUM_OF_ORIG_SAMPLE) {
+            destination[i] = source[i];
+        } else {
+            destination[i] = predict;
+        }
+    }
+    return pcmData;
+}
+
+@end
index 42bc138..9580d61 100644 (file)
 //
 
 #import "AiAudioManager.h"
-#import "AiMouseTools.h"
-#import "AiAudioDecoder.h"
 #import <AVFoundation/AVFoundation.h>
-#import <AudioToolbox/AudioToolbox.h>
+#import "ADPCMConverter.h"
+#import "adpcm.h"
 
 @interface AiAudioManager ()
-@property (nonatomic,strong)AiAudioDecoder *audioDecoder;
 @end
 
 @implementation AiAudioManager
 
 -(instancetype)init{
     if (self = [super init]) {
-        [self setupAudioDecoder];
+
     }
     return self;
 }
 
 - (void)receiveData:(NSData *)data{
 //    [self.audioDecoder decodeSBCData:data];
-    if(self.decodeCallBack)self.decodeCallBack(data);
+    
+    
+    NSData *pcmData = [self convertADPCMDataToPCMData:data];
+    if(self.decodeCallBack)self.decodeCallBack(pcmData);
 }
+- (NSData *)convertADPCMDataToPCMData:(NSData *)adpcmData {
+    const unsigned char *adpcmBytes = (const unsigned char *)[adpcmData bytes];
+    NSUInteger adpcmLength = [adpcmData length];
 
-- (void)setupAudioDecoder{
-    self.audioDecoder = [AiAudioDecoder sharedInstance];
-    __weak typeof(self) ws = self;
-    self.audioDecoder.onRecvPCMData = ^(NSData * _Nonnull pcmData) {
-//        [ws showLog:[NSString stringWithFormat:@"转换后数据%@",[AiMouseTools dataToHexString:pcmData]]];
-        if(ws.decodeCallBack)ws.decodeCallBack(pcmData);
-    };
-    [self.audioDecoder initSBCDecodec];
-}
+    signed short *ps = (signed short *)malloc(adpcmLength);
+    memcpy(ps, adpcmBytes, adpcmLength);
 
-- (void)showLog:(NSString *)log{
-    if (self.outputLog) {
-        self.outputLog([NSString stringWithFormat:@"[audio] %@",log]);
-    }
+    signed short *pd = (signed short *)malloc(adpcmLength * 4);
+
+    adpcm_to_pcm(ps, pd, adpcmLength / sizeof(signed short)*2);
+
+    NSData *pcmData = [NSData dataWithBytes:pd length:adpcmLength * 4];
+
+    free(ps);
+    free(pd);
+
+    return pcmData;
 }
 
-//- (NSData *)convertADPCMData:(NSData *)adpcmData {
-//    // 定义输入的 ADPCM 音频格式
-//       AudioStreamBasicDescription adpcmInputFormat;
-//       memset(&adpcmInputFormat, 0, sizeof(AudioStreamBasicDescription));
-//       adpcmInputFormat.mFormatID = kAudioFormatADPCM;
-//       adpcmInputFormat.mSampleRate = 44100.0;
-//       adpcmInputFormat.mChannelsPerFrame = 1;
-//       adpcmInputFormat.mBitsPerChannel = 4;
-//       adpcmInputFormat.mBytesPerPacket = 4;
-//       adpcmInputFormat.mFramesPerPacket = 1;
-//       adpcmInputFormat.mBytesPerFrame = 4;
-//       adpcmInputFormat.mReserved = 0;
-//
-//       // 定义输出的 PCM 音频格式
-//       AudioStreamBasicDescription pcmOutputFormat;
-//       memset(&pcmOutputFormat, 0, sizeof(AudioStreamBasicDescription));
-//       pcmOutputFormat.mFormatID = kAudioFormatLinearPCM;
-//       pcmOutputFormat.mSampleRate = 44100.0;
-//       pcmOutputFormat.mChannelsPerFrame = 1;
-//       pcmOutputFormat.mBitsPerChannel = 16;
-//       pcmOutputFormat.mBytesPerPacket = 2;
-//       pcmOutputFormat.mFramesPerPacket = 1;
-//       pcmOutputFormat.mBytesPerFrame = 2;
-//       pcmOutputFormat.mReserved = 0;
-//
-//       AudioConverterRef converter;
-//       OSStatus status = AudioConverterNew(&adpcmInputFormat, &pcmOutputFormat, &converter);
-//
-//       if (status!= noErr) {
-//           NSLog(@"Failed to create audio converter. Error: %d", (int)status);
-//           return nil;
-//       }
-//
-//       NSMutableData *outputData = [NSMutableData data];
-//
-//       const UInt32 inputBufferSize = 1024;
-//       UInt8 *inputBuffer = (UInt8 *)malloc(inputBufferSize);
-//       UInt32 outputBufferSize = 2048;
-//       UInt8 *outputBuffer = (UInt8 *)malloc(outputBufferSize);
-//
-//       NSInteger offset = 0;
-//       while (offset < [adpcmData length]) {
-//           NSInteger dataToRead = MIN(inputBufferSize, [adpcmData length] - offset);
-//           [adpcmData getBytes:inputBuffer range:NSMakeRange(offset, dataToRead)];
-//
-//           UInt32 outputUsed = 0;
-//           status = AudioConverterConvertBuffer(converter, dataToRead, inputBuffer, &outputUsed, outputBuffer);
-//
-//           if (status!= noErr) {
-//               NSLog(@"Conversion error. Error: %d", (int)status);
-//               free(inputBuffer);
-//               free(outputBuffer);
-//               AudioConverterDispose(converter);
-//               return nil;
-//           }
-//
-//           [outputData appendBytes:outputBuffer length:outputUsed];
-//           offset += dataToRead;
-//       }
-//
-//       free(inputBuffer);
-//       free(outputBuffer);
-//       AudioConverterDispose(converter);
-//
-//       return outputData;
-//}
 @end
index 8c47e9a..0c3884c 100644 (file)
@@ -99,7 +99,7 @@ typedef NS_ENUM(NSInteger,AiMouseConnectType) {
 /// - Parameters:
 ///   - value: 数值(1-4)
 ///   - finished: 设置结果回调
-- (void)setDPI:(int)value completation:(void (^)(BOOL isSuccess,NSError *error))finished;
+- (void)setDPI:(uint8_t)value completation:(void (^)(BOOL isSuccess,NSError *error))finished;
 
 /// 打开录音
 /// - finished: 执行结果回调
index c64978f..535a3c0 100644 (file)
     [self sendToDevice:data];
 }
 
-- (void)setDPI:(int)value completation:(void (^)(BOOL isSuccess,NSError *error))finished{
+- (void)setDPI:(uint8_t)value completation:(void (^)(BOOL isSuccess,NSError *error))finished{
     self.setDpi  = finished;
-    NSData *data = [AiMouseTools dataWithHexString:[NSString stringWithFormat:@"0601010%d",value]];
-    [self sendToDevice:data];
+    
+    uint8_t type = 0x06;
+    uint8_t success = 0x01;
+    uint8_t len = 0x01;
+    
+    NSMutableData *mData = NSMutableData.data;
+    [mData appendBytes:&type length:1];
+    [mData appendBytes:&success length:1];
+    [mData appendBytes:&len length:1];
+    [mData appendBytes:&value length:1];
+    
+//    NSData *data = [AiMouseTools dataWithHexString:[NSString stringWithFormat:@"0601010%d",value]];
+    [self sendToDevice:mData];
 }
 - (void)getDeviceInfo:(void (^)(AiMouseDeviceInfo *deviceInfo,NSError *error))finished{
     self.getMouseInfo = finished;
diff --git a/MouseSdk/AiMouseSdk/AiMouseSdk/adpcm.c b/MouseSdk/AiMouseSdk/AiMouseSdk/adpcm.c
new file mode 100644 (file)
index 0000000..45fd010
--- /dev/null
@@ -0,0 +1,148 @@
+/********************************************************************************************************
+ * @file       adpcm.c
+ *
+ * @brief      This is the source file for BLE SDK
+ *
+ * @author     BLE GROUP
+ * @date       06,2020
+ *
+ * @par     Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
+ *          All rights reserved.
+ *
+ *          Redistribution and use in source and binary forms, with or without
+ *          modification, are permitted provided that the following conditions are met:
+ *
+ *              1. Redistributions of source code must retain the above copyright
+ *              notice, this list of conditions and the following disclaimer.
+ *
+ *              2. Unless for usage inside a TELINK integrated circuit, redistributions
+ *              in binary form must reproduce the above copyright notice, this list of
+ *              conditions and the following disclaimer in the documentation and/or other
+ *              materials provided with the distribution.
+ *
+ *              3. Neither the name of TELINK, nor the names of its contributors may be
+ *              used to endorse or promote products derived from this software without
+ *              specific prior written permission.
+ *
+ *              4. This software, with or without modification, must only be used with a
+ *              TELINK integrated circuit. All other usages are subject to written permission
+ *              from TELINK and different commercial license may apply.
+ *
+ *              5. Licensee shall be solely responsible for any claim to the extent arising out of or
+ *              relating to such deletion(s), modification(s) or alteration(s).
+ *
+ *          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ *          ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *          WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *          DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
+ *          DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *          (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *          LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *          ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *          (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *******************************************************************************************************/
+
+#include       "adpcm.h"
+
+static const signed char idxtbl[] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8};
+static const unsigned short steptbl[] = {
+ 7,  8,  9,  10,  11,  12,  13,  14,  16,  17,
+ 19,  21,  23,  25,  28,  31,  34,  37,  41,  45,
+ 50,  55,  60,  66,  73,  80,  88,  97,  107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+    15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767   };
+
+#define         NUM_OF_ORIG_SAMPLE                             2
+
+void adpcm_to_pcm (signed short *ps, signed short *pd, int len)
+{
+       int i;
+       //byte2,byte1: predict;  byte3: predict_idx; byte4:adpcm data len
+       int predict = ps[0];
+       int predict_idx = ps[1] & 0xff;
+//     int adpcm_len = (ps[1]>>8) & 0xff;
+       unsigned char *pcode = (unsigned char *) (ps + NUM_OF_ORIG_SAMPLE);
+       unsigned char code;
+       code = *pcode ++;
+
+       //byte5- byte128: 124 byte(62 sample) adpcm data
+       for (i=0; i<len; i++) {
+
+               if (1) {
+                       int step = steptbl[predict_idx];
+
+                       int diffq = step >> 3;
+
+                       if (code & 4) {
+                               diffq = diffq + step;
+                       }
+                       step = step >> 1;
+                       if (code & 2) {
+                               diffq = diffq + step;
+                       }
+                       step = step >> 1;
+                       if (code & 1) {
+                               diffq = diffq + step;
+                       }
+
+                       if (code & 8) {
+                               predict = predict - diffq;
+                       }
+                       else {
+                               predict = predict + diffq;
+                       }
+
+                       if (predict > 32767) {
+                               predict = 32767;
+                       }
+                       else if (predict < -32768) {
+                               predict = -32768;
+                       }
+
+                       predict_idx = predict_idx + idxtbl[code & 15];
+
+                       if(predict_idx < 0) {
+                               predict_idx = 0;
+                       }
+                       else if(predict_idx > 88) {
+                               predict_idx = 88;
+                       }
+
+                       if (i&1) {
+                               code = *pcode ++;
+                       }
+                       else {
+                               code = code >> 4;
+                       }
+               }
+
+               if (0 && i < NUM_OF_ORIG_SAMPLE) {
+                       *pd++ = ps[i];
+               }
+               else {
+                       *pd++ = predict;
+               }
+       }
+}
+
+//例子
+#if 0
+#define MIC_ADPCM_FRAME_SIZE           128                                             //一包 adpcm 的数据长度 128 byte
+#define MIC_SHORT_DEC_SIZE                     248
+#define DEC_BUFFER_SIZE                (MIC_SHORT_DEC_SIZE<<2)
+
+unsigned char          abuf_dec_wptr;                                                  // 0~3 , 4个缓冲 ,循环使用                               
+unsigned char          abuf_mic[MIC_ADPCM_FRAME_SIZE * 4];             //压缩的语音数据adpcm缓冲区 ,4个缓冲 ,每个缓冲区 128 byte , 循环使用
+signed short           abuf_dec[DEC_BUFFER_SIZE];                              //解压后存放的数据,注意数组类型是 16 bit,4个缓冲,循环使用
+
+//abuf_mic 源 ,  abuf_dec 目的 , 每次解压 128 byte adpcm 
+adpcm_to_pcm ((signed short *)(abuf_mic + (abuf_dec_wptr & 3) * MIC_ADPCM_FRAME_SIZE), abuf_dec + (abuf_dec_wptr & 3) * MIC_SHORT_DEC_SIZE, MIC_SHORT_DEC_SIZE );
+
+#endif
+
diff --git a/MouseSdk/AiMouseSdk/AiMouseSdk/adpcm.h b/MouseSdk/AiMouseSdk/AiMouseSdk/adpcm.h
new file mode 100644 (file)
index 0000000..0cb25a9
--- /dev/null
@@ -0,0 +1,51 @@
+/********************************************************************************************************
+ * @file       adpcm.h
+ *
+ * @brief      This is the header file for BLE SDK
+ *
+ * @author     BLE GROUP
+ * @date       06,2020
+ *
+ * @par     Copyright (c) 2020, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
+ *          All rights reserved.
+ *
+ *          Redistribution and use in source and binary forms, with or without
+ *          modification, are permitted provided that the following conditions are met:
+ *
+ *              1. Redistributions of source code must retain the above copyright
+ *              notice, this list of conditions and the following disclaimer.
+ *
+ *              2. Unless for usage inside a TELINK integrated circuit, redistributions
+ *              in binary form must reproduce the above copyright notice, this list of
+ *              conditions and the following disclaimer in the documentation and/or other
+ *              materials provided with the distribution.
+ *
+ *              3. Neither the name of TELINK, nor the names of its contributors may be
+ *              used to endorse or promote products derived from this software without
+ *              specific prior written permission.
+ *
+ *              4. This software, with or without modification, must only be used with a
+ *              TELINK integrated circuit. All other usages are subject to written permission
+ *              from TELINK and different commercial license may apply.
+ *
+ *              5. Licensee shall be solely responsible for any claim to the extent arising out of or
+ *              relating to such deletion(s), modification(s) or alteration(s).
+ *
+ *          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ *          ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *          WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *          DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
+ *          DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *          (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *          LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *          ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *          (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *******************************************************************************************************/
+#ifndef ADPCM_H_
+#define ADPCM_H_
+
+void adpcm_to_pcm(signed short *ps, signed short *pd, int len);
+
+#endif /* ADPCM_H_ */
index 6896c6a..1ebbbe9 100644 (file)
 /// 设备信息数据回调,需要将此数据通过设备信息特征转发给蓝牙设备
 /// - Parameter data: 数据
 -(void)aiMouseSendDeviceInfoData:(NSData *)data{
-//    [self showLog:[NSString stringWithFormat:@"[send] %@",data]];
     [self.connectPeripheral writeValue:data forCharacteristic:self.deviceInfoCha type:CBCharacteristicWriteWithResponse];
 }
 
index b10ae0a..b0667ac 100644 (file)
@@ -15,6 +15,10 @@ const long vendorID = 0x10D6;
 //产品id
 const long productID = 0xB008;
 
+//供应商id
+//const long vendorID = 0x6675;
+//const long productID = 0x8601;
+
 @interface HidManager ()<AiMouseDelegate>
 
 @property(nonatomic, assign) IOHIDManagerRef hidManager;///hid管理
@@ -87,7 +91,7 @@ static void hidAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOH
         //注册消息回调
         unsigned char InputBuffer[128];
         IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), hidReceiveData, NULL);
-        IOReturn ret = IOHIDDeviceOpen(inIOHIDDeviceRef, 0);
+        IOReturn ret = IOHIDDeviceOpen(inIOHIDDeviceRef, kIOHIDOptionsTypeNone);
         if (ret != kIOReturnSuccess) {
             NSLog(@"打开设备信息失败!");
         }else{
@@ -133,17 +137,18 @@ static void hidReceiveData(void* context, IOReturn result, void* sender, IOHIDRe
     NSData *data = [[NSData alloc] initWithBytes:report length:len];
     [[HidManager shared] showLog:[NSString stringWithFormat:@"[receive] 处理后 %@",data]];
     
-    uint32_t PrimaryUsagePage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsagePageKey));
-    uint32_t PrimaryUsage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsageKey));
-
-    if(PrimaryUsagePage == 1 && PrimaryUsage == 0){
-        [[AiMouse shared] sendDeviceDataToSdk:data];
-        
-    }
-    else if(PrimaryUsagePage == 65283 && PrimaryUsage == 0){
-        [[AiMouse shared] sendAiDataToSdk:data];
-    }
+//    uint32_t PrimaryUsagePage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsagePageKey));
+//    uint32_t PrimaryUsage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsageKey));
+//
+//    if(PrimaryUsagePage == 1 && PrimaryUsage == 0){
+//        [[AiMouse shared] sendDeviceDataToSdk:data];
+//        
+//    }
+//    else if(PrimaryUsagePage == 65283 && PrimaryUsage == 0){
+//        [[AiMouse shared] sendAiDataToSdk:data];
+//    }
 }
+
 #pragma mark - AiDelegate
 /// 设备信息数据回调,需要将此数据通过设备信息特征转发给蓝牙设备
 /// - Parameter data: 数据
@@ -153,20 +158,19 @@ static void hidReceiveData(void* context, IOReturn result, void* sender, IOHIDRe
 
 /// 鼠标按键指令回调
 /// - Parameter data: 数据。
-/// 前  第一次单击31(开始录音), 第二次单击32(结束录音) , 按下21(开始录音)抬起22(结束录音)
-/// 中  单击42, 按下25(开始录音)抬起26(结束录音)
-/// 后  单击43,按下27(开始录音)抬起28(结束录音)
+/// 前  单击0x06, 按下0x13(开始录音)抬起0x14(结束录音)
+/// 中  单击0x03, 按下0x11(开始录音)抬起0x12(结束录音)
+/// 后  第一次单击0x01, 第二次单击0x02(结束录音) , 按下0x09(开始录音)抬起0x10(结束录音)
 /// 其他未定义
 - (void)aiMouseSendCmdData:(NSData *)data{
     uint8 cmd;
     [data getBytes:&cmd length:1];
-    [self showLog:[NSString stringWithFormat:@"收到指令 = %X",cmd]];
     
-    if(cmd == 0x31 || cmd == 0x21 || cmd == 0x25 ||cmd == 0x27){
+    if(cmd == 0x13 || cmd == 0x11 || cmd == 0x01 ||cmd == 0x09){
         [self showLog:@"开始录音"];
         self.recordData = [[NSMutableData alloc] init];
     }
-    else if(cmd == 0x32 || cmd == 0x22 || cmd == 0x26 ||cmd == 0x28){
+    else if(cmd == 0x14 || cmd == 0x12 || cmd == 0x02 ||cmd == 0x10){
         [self showLog:@"结束录音"];
         [self finishRecored:self.recordData];
     }
@@ -190,17 +194,32 @@ static void hidReceiveData(void* context, IOReturn result, void* sender, IOHIDRe
 - (void)aiMouseConnectStateDidChange:(BOOL)connected{
     [HidManager shared].connectStateCallBack(connected);
 }
+
 #pragma mark - public
+/// 获取设备信息
+- (void)getDeviceInfo:(void (^)(AiMouseDeviceInfo * _Nonnull, NSError * _Nonnull))completation{
+    [[AiMouse shared] getDeviceInfo:completation];
+}
+/// setDPI
+- (void)setDPI:(int)value completation:(void (^)(BOOL isSuccess,NSError *error))finished{
+    [[AiMouse shared] setDPI:value completation:finished];
+}
+/// 打开录音
+- (void)openRecord:(void (^)(BOOL isSuccess,NSError *error))finished{
+    [[AiMouse shared] openRecord:finished];
+}
+/// 停止录音
+- (void)closeRecord:(void (^)(BOOL isSuccess,NSError *error))finished{
+    [[AiMouse shared] closeRecord:finished];
+}
+
+#pragma mark - other
 -(void)connectDevice{
     //设置代理
     [AiMouse shared].delegate = self;
     //切换当前连接类型
     [[AiMouse shared] switchConnect:AiMouseConnectType_hid];
 }
-/// 获取设备信息
-- (void)getDeviceInfo:(void (^)(AiMouseDeviceInfo * _Nonnull, NSError * _Nonnull))completation{
-    [[AiMouse shared] getDeviceInfo:completation];
-}
 
 /// 发送数据给设备
 -(void)sendData:(NSData *)data toDevice:(IOHIDDeviceRef)device{
@@ -216,6 +235,7 @@ static void hidReceiveData(void* context, IOReturn result, void* sender, IOHIDRe
         [self showLog:@"数据发送成功!"];
     }
 }
+
 //将录音数据保存
 - (void)finishRecored:(NSData *)data{
     NSString *doc = NSTemporaryDirectory();
@@ -233,6 +253,7 @@ static void hidReceiveData(void* context, IOReturn result, void* sender, IOHIDRe
     NSLog(@"%@",log);
 }
 
+
 /// 实际到数据长度
 static inline int get_data_len(uint8_t *buf, u_long len) {
     if (len <= 0 ) return 0;
index d13f542..c66290d 100644 (file)
     }];
 }
 - (void)setDPI:(NSMenuItem*)sender {
-    [[DeviceManger shared] setDPI:1 completation:^(BOOL isSuccess, NSError * _Nonnull error) {
+    [[DeviceManger shared] setDPI:2 completation:^(BOOL isSuccess, NSError * _Nonnull error) {
         
     }];
 }