From: liangzhenying <867174124@qq.com> Date: Wed, 21 Aug 2024 01:53:34 +0000 (+0800) Subject: 泰凌微协议调试 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=1d017c07e346044be00917eee3f1d367499d6414;p=mirrors%2FMouseSdk-TLW.git 泰凌微协议调试 --- diff --git a/Document/adpcm.c b/Document/adpcm.c new file mode 100644 index 0000000..45fd010 --- /dev/null +++ b/Document/adpcm.c @@ -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> 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 index 0000000..0cb25a9 --- /dev/null +++ b/Document/adpcm.h @@ -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_ */ diff --git a/MouseSdk/AiMouseSdk/AiMouseSdk.xcodeproj/project.pbxproj b/MouseSdk/AiMouseSdk/AiMouseSdk.xcodeproj/project.pbxproj index 28d9cae..1d05792 100644 --- a/MouseSdk/AiMouseSdk/AiMouseSdk.xcodeproj/project.pbxproj +++ b/MouseSdk/AiMouseSdk/AiMouseSdk.xcodeproj/project.pbxproj @@ -181,6 +181,10 @@ 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 */; }; @@ -363,6 +367,10 @@ 184A711E2BDD11C70025A332 /* AiTrippleModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiTrippleModel.m; sourceTree = ""; }; 184A71222BDE2DA60025A332 /* AiSecretModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiSecretModel.h; sourceTree = ""; }; 184A71232BDE2DA60025A332 /* AiSecretModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiSecretModel.m; sourceTree = ""; }; + 187595B12C743F9300E88FFC /* ADPCMConverter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ADPCMConverter.h; sourceTree = ""; }; + 187595B22C743F9300E88FFC /* ADPCMConverter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ADPCMConverter.m; sourceTree = ""; }; + 187595B52C74423000E88FFC /* adpcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adpcm.c; sourceTree = ""; }; + 187595B62C74423000E88FFC /* adpcm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = adpcm.h; sourceTree = ""; }; 189C15842C05726600676A80 /* AiConnectManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiConnectManager.h; sourceTree = ""; }; 189C15852C05726600676A80 /* AiConnectManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiConnectManager.m; sourceTree = ""; }; 18AD83272BFB22DE009BDE3B /* AiSender.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiSender.h; sourceTree = ""; }; @@ -429,6 +437,8 @@ 184A71232BDE2DA60025A332 /* AiSecretModel.m */, 180E7AB72BD7BD7D008558E8 /* AiAudioConverter.h */, 180E7B4B2BD7BD80008558E8 /* AiAudioConverter.m */, + 187595B12C743F9300E88FFC /* ADPCMConverter.h */, + 187595B22C743F9300E88FFC /* ADPCMConverter.m */, 180E7B502BD7BD82008558E8 /* AiAudioDecoder.h */, 180E7AB52BD7BD7D008558E8 /* AiAudioDecoder.m */, 180E7B4C2BD7BD81008558E8 /* AiAudioManager.h */, @@ -439,6 +449,8 @@ 180E7B4A2BD7BD80008558E8 /* AiMouseTools.m */, 180E7B532BD7BD82008558E8 /* AiMouseTools2.h */, 180E7B4F2BD7BD81008558E8 /* AiMouseTools2.m */, + 187595B52C74423000E88FFC /* adpcm.c */, + 187595B62C74423000E88FFC /* adpcm.h */, 180E7AB82BD7BD7D008558E8 /* AiRecordManager.h */, 180E7B4E2BD7BD81008558E8 /* AiRecordManager.m */, ); @@ -719,6 +731,7 @@ 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 */, @@ -842,6 +855,7 @@ 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; @@ -904,6 +918,7 @@ 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 */, @@ -920,6 +935,7 @@ 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 index 0000000..0558f1e --- /dev/null +++ b/MouseSdk/AiMouseSdk/AiMouseSdk/ADPCMConverter.h @@ -0,0 +1,18 @@ +// +// AiAdpcm2pcm.h +// AiMouseSdk +// +// Created by incar on 2024/8/20. +// + +#import + +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 index 0000000..42e25f3 --- /dev/null +++ b/MouseSdk/AiMouseSdk/AiMouseSdk/ADPCMConverter.m @@ -0,0 +1,92 @@ + +#import "ADPCMConverter.h" +#import + + + +@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 diff --git a/MouseSdk/AiMouseSdk/AiMouseSdk/AiAudioManager.m b/MouseSdk/AiMouseSdk/AiMouseSdk/AiAudioManager.m index 42bc138..9580d61 100644 --- a/MouseSdk/AiMouseSdk/AiMouseSdk/AiAudioManager.m +++ b/MouseSdk/AiMouseSdk/AiMouseSdk/AiAudioManager.m @@ -6,109 +6,46 @@ // #import "AiAudioManager.h" -#import "AiMouseTools.h" -#import "AiAudioDecoder.h" #import -#import +#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 diff --git a/MouseSdk/AiMouseSdk/AiMouseSdk/AiMouseSdk.h b/MouseSdk/AiMouseSdk/AiMouseSdk/AiMouseSdk.h index 8c47e9a..0c3884c 100644 --- a/MouseSdk/AiMouseSdk/AiMouseSdk/AiMouseSdk.h +++ b/MouseSdk/AiMouseSdk/AiMouseSdk/AiMouseSdk.h @@ -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: 执行结果回调 diff --git a/MouseSdk/AiMouseSdk/AiMouseSdk/AiMouseSdk.m b/MouseSdk/AiMouseSdk/AiMouseSdk/AiMouseSdk.m index c64978f..535a3c0 100644 --- a/MouseSdk/AiMouseSdk/AiMouseSdk/AiMouseSdk.m +++ b/MouseSdk/AiMouseSdk/AiMouseSdk/AiMouseSdk.m @@ -224,10 +224,21 @@ [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 index 0000000..45fd010 --- /dev/null +++ b/MouseSdk/AiMouseSdk/AiMouseSdk/adpcm.c @@ -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> 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 index 0000000..0cb25a9 --- /dev/null +++ b/MouseSdk/AiMouseSdk/AiMouseSdk/adpcm.h @@ -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_ */ diff --git a/MouseSdk/MouseSdk/BleManager.m b/MouseSdk/MouseSdk/BleManager.m index 6896c6a..1ebbbe9 100644 --- a/MouseSdk/MouseSdk/BleManager.m +++ b/MouseSdk/MouseSdk/BleManager.m @@ -143,7 +143,6 @@ /// 设备信息数据回调,需要将此数据通过设备信息特征转发给蓝牙设备 /// - Parameter data: 数据 -(void)aiMouseSendDeviceInfoData:(NSData *)data{ -// [self showLog:[NSString stringWithFormat:@"[send] %@",data]]; [self.connectPeripheral writeValue:data forCharacteristic:self.deviceInfoCha type:CBCharacteristicWriteWithResponse]; } diff --git a/MouseSdk/MouseSdk/HidManager.m b/MouseSdk/MouseSdk/HidManager.m index b10ae0a..b0667ac 100644 --- a/MouseSdk/MouseSdk/HidManager.m +++ b/MouseSdk/MouseSdk/HidManager.m @@ -15,6 +15,10 @@ const long vendorID = 0x10D6; //产品id const long productID = 0xB008; +//供应商id +//const long vendorID = 0x6675; +//const long productID = 0x8601; + @interface HidManager () @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; diff --git a/MouseSdk/MouseSdk/ViewController.m b/MouseSdk/MouseSdk/ViewController.m index d13f542..c66290d 100644 --- a/MouseSdk/MouseSdk/ViewController.m +++ b/MouseSdk/MouseSdk/ViewController.m @@ -150,7 +150,7 @@ }]; } - (void)setDPI:(NSMenuItem*)sender { - [[DeviceManger shared] setDPI:1 completation:^(BOOL isSuccess, NSError * _Nonnull error) { + [[DeviceManger shared] setDPI:2 completation:^(BOOL isSuccess, NSError * _Nonnull error) { }]; }