12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709 |
- //
- // KSAccompanyWebViewController.m
- // KulexiuForTeacher
- //
- // Created by Kyle on 2022/3/20.
- //
- #import "KSAccompanyWebViewController.h"
- #import "RecordCheckManager.h"
- #import "KSAQRecordManager.h"
- #import "KSWebSocketManager.h"
- #import "KSVideoRecordManager.h"
- #import "KSWebNavView.h"
- #import "KSAudioSessionManager.h"
- #import "KSCloudBeatView.h"
- #import "MidiPlayerEngine.h"
- #import "AccompanyLoadingView.h"
- #import "KSPremissionAlert.h"
- #define KSMidiSongFileKey (@"KSDownloadMidiSong")
- #import "KulexiuForStudent-swift.h"
- #import "kSNewPlayer.h"
- #import "KSMediaEditor.h"
- #import "KSMediaMergeView.h"
- @interface KSAccompanyWebViewController ()<KSAQRecordManagerDelegate,KSAudioSessionManagerDelegate,PlayerEngineDelegate,TunerDelegate,kSNewPlayerManagerDelegate>
- @property (nonatomic, strong) KSAudioSessionManager *audioSessionManager;
- @property (nonatomic, assign) MetronomeType beatType;
- @property (nonatomic, strong) MidiPlayerEngine *playerEngine; // player
- @property (nonatomic, assign) BOOL initEngineSuccess; // 加载引擎是否成功
- @property (nonatomic, assign) float songOriginalSpeed;
- @property (nonatomic, assign) float currentSpeed; // 当前播放的速度
- @property (nonatomic, assign) BOOL isPlaying; // 是否正在播放的状态
- @property (nonatomic, strong) NSString *currentSongId; // song id
- @property (nonatomic, strong) NSDictionary *configEngineParm; // 初始化mid播放引擎的参数
- @property (nonatomic, strong) NSMutableDictionary *metronomeParm; // 节拍器播放的参数
- // 是否发送了musicXML信息
- @property (nonatomic, assign) BOOL hasSendStartMessage;
- @property (nonatomic, strong) KSAQRecordManager *AQManager;
- @property (nonatomic, strong) KSWebSocketManager *socketManager;
- @property (nonatomic, strong) NSMutableDictionary *evaluatParm;
- // 录制的message
- @property (nonatomic, strong) NSMutableDictionary *recordParm;
- // 评测开始时发送recordStart消息的标识
- @property (nonatomic, assign) BOOL isCompareStart;
- // 校音开始时发送 checkStart消息标识
- @property (nonatomic, assign) BOOL isSoundCheckStart;
- // 自定义UI控件容器
- @property (nonatomic, strong) UIView *viewContainer;
- @property (nonatomic, strong) KSVideoRecordManager *videoRecordManager;
- @property (nonatomic, strong) NSDictionary *endRecordParm;
- @property (nonatomic, assign) BOOL isCameraOpen;
- @property (nonatomic, strong) AccompanyLoadingView *loadingView;
- @property (nonatomic, assign) BOOL isTunerRuning;
- @property (nonatomic, strong) Tuner *tuner;
- // 延迟校准开始时发送 AdjustStart消息标识
- @property (nonatomic, assign) BOOL isDelayCheckStart;
- // 检测延迟播放器
- @property (nonatomic, strong) kSNewPlayer *dingPlayer;
- @property (nonatomic, strong) kSNewPlayer *dongPlayer;
- // 音频播放器
- @property (nonatomic, strong) kSNewPlayer *musicPlayer;
- // 录音开始时间
- @property (nonatomic, assign) NSTimeInterval recordStartTime;
- // 播放开始时间
- @property (nonatomic, assign) NSTimeInterval playerStartTime;
- // 播放延迟
- @property (nonatomic, assign) NSInteger offsetTime;
- @property (nonatomic, assign) BOOL dingPlayerReady;
- @property (nonatomic, assign) BOOL dongPlayerReady;
- @property (nonatomic, assign) BOOL musicPlayerReady;
- @property (nonatomic, strong) NSDictionary *playerParm;
- @property (nonatomic, strong) NSMutableArray *delayArray;
- @property (nonatomic, assign) NSInteger checkIndex;
- @property (nonatomic, assign) NSInteger firstFrequence;
- @property (nonatomic, assign) NSInteger secondFrequence;
- @property (nonatomic, strong) NSURL *bgAudioUrl;
- @property (nonatomic, strong) NSURL *recordUrl;
- @property (nonatomic, strong) NSString *accompanyUrl;
- @end
- @implementation KSAccompanyWebViewController
- - (void)handerAudioInterruption {
- if (_playerEngine) {
- [self stopPlayAction];
- }
- }
- - (void)resumeAudioSession {
- // 恢复
- if (_playerEngine) {
- [self.playerEngine resumeAUGraph];
- }
- }
- // 打断处理
- - (void)audioInterruption {
- if (_videoRecordManager) {
- [self.videoRecordManager resetSession];
- }
- [self handerAudioInterruption];
- }
- - (void)ignorRecordVideo {
- if (_videoRecordManager) {
- self.videoRecordManager.skipSaveRecord = YES;
- }
- }
- - (void)stopSession {
- if (_videoRecordManager) {
- [self.videoRecordManager stopSession];
- }
- }
- - (void)resetPlayerConfig {
- [self freeMp3Player]; // 若之前有播放器,剔除
- self.firstFrequence = 800;
- self.secondFrequence = 800;
- self.dingPlayerReady = NO;
- self.dongPlayerReady = NO;
- self.musicPlayerReady = NO;
- self.recordStartTime = 0;
- self.playerStartTime = 0;
- self.offsetTime = 0;
- }
- - (void)initMp3Player:(NSString *)musicUrl checkUrl:(NSString *)checkUrl {
- [self resetPlayerConfig];
- self.accompanyUrl = musicUrl;
- [self.musicPlayer preparePlaySongWithUrl:musicUrl];
- [self.dingPlayer preparePlaySongWithUrl:checkUrl];
- [self.dongPlayer preparePlaySongWithUrl:checkUrl];
-
- [self prepareMusic];
- }
- - (void)prepareMusic {
-
- self.dingPlayer.isMute = YES;
- [self.dingPlayer startPlay];
- self.dongPlayer.isMute = YES;
- [self.dongPlayer startPlay];
- self.musicPlayer.isMute = YES;
- [self.musicPlayer startPlay];
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- [self.musicPlayer puasePlay];
- self.musicPlayer.isMute = NO;
- [self.dingPlayer puasePlay];
- self.dingPlayer.isMute = NO;
- [self.dongPlayer puasePlay];
- self.dongPlayer.isMute = NO;
- [self configPlayerDelegate];
- });
- }
- - (void)freeMp3Player {
- if (_dingPlayer) {
- [self.dingPlayer freePlayer];
- }
- if (_dongPlayer) {
- [self.dongPlayer freePlayer];
- }
- if (_musicPlayer) {
- [self.musicPlayer freePlayer];
- }
- }
- - (void)stopMp3Player {
- if (_dingPlayer) {
- [self.dingPlayer puasePlay];
- }
- if (_dongPlayer) {
- [self.dongPlayer puasePlay];
- }
- if (_musicPlayer) {
- [self.musicPlayer puasePlay];
- }
- }
- - (void)viewDidLoad {
- [super viewDidLoad];
- // Do any additional setup after loading the view.
- [self configAudioSession];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnterBackground) name:@"appEnterBackground" object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnterForeground) name:@"appEnterForeground" object:nil];
- }
- - (void)checkMessage:(id)message {
- NSDictionary *result = [message mj_JSONObject];
- NSString *type = [[result ks_dictionaryValueForKey:@"header"] ks_stringValueForKey:@"type"];
- NSString *commond = [[result ks_dictionaryValueForKey:@"header"] ks_stringValueForKey:@"commond"];
- if ([type isEqualToString:@"DELAY_CHECK"] && [commond isEqualToString:@"recordEnd"]) {
- NSDictionary *body = [result ks_dictionaryValueForKey:@"body"];
- NSTimeInterval micDelay = [body ks_doubleValueForKey:@"firstNoteDelayDuration"] - self.offsetTime;
- [self.delayArray addObject:[NSNumber numberWithDouble:micDelay]];
- }
- }
- - (void)connectSocketService {
-
- MJWeakSelf;
- self.socketManager.didReceiveMessage = ^(id _Nonnull message) {
- dispatch_async(dispatch_get_main_queue(), ^{
- [weakSelf checkMessage:message];
- // api
- NSMutableDictionary *sendMessage = [NSMutableDictionary dictionary];
- [sendMessage setValue:@"sendResult" forKey:@"api"];
- [sendMessage setValue:message forKey:@"content"];
- // 服务返回数据传给H5
- [weakSelf postMessage:sendMessage];
- });
- };
- self.socketManager.connectionStatus = ^(BOOL isSuccess) {
- dispatch_async(dispatch_get_main_queue(), ^{
-
- if (!isSuccess) {
- // NSLog(@"-----连接失败");
- if (weakSelf.hasSendStartMessage) {
- if (weakSelf.AQManager.isRunning) {
- NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
- @"content" : @{@"reson":@"服务异常,请重试"}
- };
- [weakSelf postMessage:postParm];
- [weakSelf stopRecordService];
- weakSelf.isCompareStart = NO;
- weakSelf.isSoundCheckStart = NO;
- weakSelf.isDelayCheckStart = NO;
- }
- }
- else if (weakSelf.evaluatParm) {
- NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:weakSelf.evaluatParm];
- NSDictionary *valueDic = [weakSelf.evaluatParm ks_dictionaryValueForKey:@"content"];
- [valueDic setValue:@"服务异常,请重试" forKey:@"reson"];
- [sendParm setValue:valueDic forKey:@"content"];
- [weakSelf postMessage:sendParm];
- weakSelf.hasSendStartMessage = YES;
- weakSelf.isCompareStart = NO;
- weakSelf.isSoundCheckStart = NO;
- weakSelf.isDelayCheckStart = NO;
- }
- else { // 其他断开
- if (weakSelf.AQManager.isRunning) {
- NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
- @"content" : @{@"reson":@"服务异常,请重试"}
- };
- [weakSelf postMessage:postParm];
- [weakSelf stopRecordService];
- weakSelf.isCompareStart = NO;
- weakSelf.isSoundCheckStart = NO;
- weakSelf.isDelayCheckStart = NO;
- }
- }
- }
- else {
- // NSLog(@"-----连接成功");
- if (weakSelf.hasSendStartMessage == NO && weakSelf.evaluatParm) {
- NSDictionary *content = [weakSelf.evaluatParm ks_dictionaryValueForKey:@"content"];
- NSString *sendData = [weakSelf configDataCommond:@"musicXml" body:content type:@"SOUND_COMPARE"];
- [weakSelf sendDataToSocketService:sendData];
- [weakSelf postMessage:weakSelf.evaluatParm];
- weakSelf.hasSendStartMessage = YES;
- }
- }
- });
- };
- [self.socketManager SRWebSocketOpen];
- }
- - (void)appEnterBackground {
- NSDictionary *parm = @{@"api":@"suspendPlay"};
- [self postMessage:parm];
- [self handerAudioInterruption];
- }
- - (void)appEnterForeground {
- if (self.isCameraOpen) {
- if ([self.videoRecordManager getSessionStatusisActive] == NO) {
- [self.videoRecordManager configSessiondisplayInView:self.viewContainer];
- }
- }
- }
- - (void)initWebView {
- [self.scrollView removeFromSuperview];
-
- [self.view addSubview:self.viewContainer];
- [self.viewContainer mas_makeConstraints:^(MASConstraintMaker *make) {
- make.left.right.top.bottom.mas_equalTo(self.view);
- }];
-
- if (self.myWebView == nil) {
-
- WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
- config.selectionGranularity = WKSelectionGranularityDynamic;
- config.allowsInlineMediaPlayback = YES;
- config.mediaTypesRequiringUserActionForPlayback = NO;
-
- config.processPool = [KSBaseWKWebViewController singleWkProcessPool];
- config.websiteDataStore = [WKWebsiteDataStore defaultDataStore];
- [self configUserAgent:config];
-
- //自定义的WKScriptMessageHandler 是为了解决内存不释放的问题
- WeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self];
- //这个类主要用来做native与JavaScript的交互管理
- WKUserContentController * wkUController = [[WKUserContentController alloc] init];
- [wkUController addScriptMessageHandler:weakScriptMessageDelegate name:@"COLEXIU"];
- config.userContentController = wkUController;
-
- WKPreferences *preferences = [WKPreferences new];
- // 是否支出javaScript
- preferences.javaScriptEnabled = YES;
- //不通过用户交互,是否可以打开窗口
- preferences.javaScriptCanOpenWindowsAutomatically = YES;
- config.preferences = preferences;
- self.myWebView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
- self.myWebView.opaque = NO;
- self.myWebView.UIDelegate = self;
- self.myWebView.navigationDelegate = self;
- self.myWebView.scrollView.bounces = NO;
- self.myWebView.backgroundColor = [UIColor clearColor];
- self.myWebView.scrollView.backgroundColor = [UIColor clearColor];
- // 加载进度条和title
- [self.myWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
- [self.view addSubview:self.myWebView];
- [self.myWebView mas_makeConstraints:^(MASConstraintMaker *make) {
- make.left.right.mas_equalTo(self.view);
- make.top.mas_equalTo(self.view.mas_top);
- make.bottom.mas_equalTo(self.view.mas_bottom);
- }];
- self.myWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
-
- [self setupProgress];
-
- [self loadRequest];
- }
- else {
- [self.myWebView reload];
- }
- }
- - (void)configUserAgent:(WKWebViewConfiguration *)config {
- NSString *oldUserAgent = config.applicationNameForUserAgent;
- NSString *newAgent = [NSString stringWithFormat:@"%@ %@ %@",oldUserAgent,@"ORCHESTRAAPPI",@"ORCHESTRASTUDENT"];
- config.applicationNameForUserAgent = newAgent;
- }
- - (void)configRecordManager {
- self.AQManager = [[KSAQRecordManager alloc] init];
- self.AQManager.delegate = self;
- }
- - (void)viewWillAppear:(BOOL)animated {
- [super viewWillAppear:animated];
- [self connectSocketService];
- if (self.isCameraOpen) {
- [self.videoRecordManager configSessiondisplayInView:self.viewContainer];
- }
- }
- - (void)viewWillDisappear:(BOOL)animated {
- [super viewWillDisappear:animated];
-
- if (_socketManager) {
- [self.socketManager SRWebSocketClose];
- _socketManager = nil;
- }
- // 停止播放和录制
- [self stopSession];
- [self stopPlayAction];
- [self stopRecordService];
- [self stopTuner];
-
- BOOL isBack = [self isViewPopDismiss];
- if (isBack) { // 页面销毁才删除
- if (_AQManager) {
- [_AQManager freeAudioQueue];
- _AQManager = nil;
- }
- // 如果退出评测页面 清除 playerEngine
- if (self.playerEngine) {
- [self.playerEngine cleanup];
- self.playerEngine = nil;
- }
- // 返回不保存视频
- [self ignorRecordVideo];
- [self freeMp3Player];
- }
- }
- - (void)sendDataToSocketService:(id)data {
- if (_socketManager) {
- [self.socketManager sendData:data];
- }
- }
- #pragma mark --- WKScriptMessageHandler
- - (void)userContentController:(WKUserContentController *)userContentController
- didReceiveScriptMessage:(WKScriptMessage *)message {
- if ([message.name isEqualToString:@"COLEXIU"]) {
- NSDictionary *parm = [self convertJsonStringToNSDictionary:message.body];
- NSLog(@"---- receive parm %@", [parm mj_JSONString]);
- // 回到主线程
- dispatch_async(dispatch_get_main_queue(), ^{
- if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"createMusicPlayer"]) {
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- NSString *musicUrl = [content ks_stringValueForKey:@"musicSrc"];
- NSString *checkUrl = [content ks_stringValueForKey:@"tuneSrc"];
- self.playerParm = parm;
- [self initMp3Player:musicUrl checkUrl:checkUrl];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"startEvaluating"]) { // 开始评测
- [self configRecordManager];
- self.hasSendStartMessage = NO;
- PREMISSIONTYPE isOk = [RecordCheckManager checkPermissionShowAlert:NO showInView:nil];
- if (isOk == PREMISSIONTYPE_YES) {
- self.evaluatParm = [NSMutableDictionary dictionaryWithDictionary:parm];
- // 如果socket 连上了
- if (self.socketManager.socketReadyState == SR_OPEN) {
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- NSString *sendData = [self configDataCommond:@"musicXml" body:content type:@"SOUND_COMPARE"];
- [self sendDataToSocketService:sendData];
- [self postMessage:parm];
- self.hasSendStartMessage = YES;
- }
- else {
- [self connectSocketService];
- }
- }
- else {
- NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
- @"content" : @{@"reson":@"没有麦克风权限"}
- };
- [self postMessage:postParm];
- }
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"endEvaluating"]) {// 停止评测
- self.evaluatParm = nil;
- [self stopRecordService];
- [self postMessage:parm];
- [self sendEndMessage];
- [self stopMp3Player]; // 停止播放
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cancelEvaluating"]) { // 取消评测
- self.evaluatParm = nil;
- [self stopRecordService];
- [self postMessage:parm];
- // [self sendEndMessage];
- [self stopMp3Player]; // 停止播放
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"startRecording"]) { // 开始录制
- if (self.videoRecordManager) {
- [self.videoRecordManager clearVideoFile];
- }
- [self postMessage:parm];
- self.isCompareStart = YES;
- [self startRecordService];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"endRecording"]) { // 停止录音
- self.recordParm = nil;
- [self stopRecordService];
- [self postMessage:parm];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"pauseRecording"]) {
- [self puaseRecordService];
- [self postMessage:parm];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"resumeRecording"]) {
- [self resumeRecordService];
- [self postMessage:parm];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"isWiredHeadsetOn"]) {
- [self configAudioDeviceType:parm];
- }
- // 发送消息给socket service
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"proxyMessage"]) {
- [self sendMessageToSocket:parm];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"proxyServiceMessage"]) {
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- NSString *sendData = [content mj_JSONString];
- NSLog(@"proxyServiceMessage ------- %@",sendData);
- [self sendDataToSocketService:sendData];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"openCamera"]) { // 开启摄像头
- PREMISSIONTYPE canOpenCamera = [RecordCheckManager checkCameraPremissionAvaiable:NO showInView:nil];
- PREMISSIONTYPE albumEnable = [RecordCheckManager checkPhotoLibraryPremissionAvaiable:NO showInView:nil];
- if (canOpenCamera == PREMISSIONTYPE_YES) {
- self.isCameraOpen = YES;
- [self.videoRecordManager setIgnoreAudio:YES];
- [self.videoRecordManager configSessiondisplayInView:self.viewContainer];
- [self postMessage:parm];
- }
- if (albumEnable == PREMISSIONTYPE_NO) {
- [self showAlertWithMessage:@"请开启相册访问权限" type:CHECKDEVICETYPE_CAMREA];
- }
-
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"closeCamera"]) { // 关闭摄像头
- self.isCameraOpen = NO;
- if (self->_videoRecordManager) {
- [self.videoRecordManager removeDisplay];
- }
- [self postMessage:parm];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"startCapture"]) { // 开始录制
- // 需要合成音频
- [self.videoRecordManager setIgnoreAudio:YES];
- [RecordCheckManager checkPhotoLibraryPremissionAvaiable:YES showInView:self.view];
- self.videoRecordManager.audioUrl = self.AQManager.audioUrl;
- [self.videoRecordManager startRecord];
- [self postMessage:parm];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"endCapture"]) { // 结束录制
- if (self->_videoRecordManager) {
- self.endRecordParm = parm;
- [self.videoRecordManager stopRecord];
- }
- else {
- [self postMessage:parm];
- }
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"setCaptureMode"]) {
- NSString *modeString = [[parm ks_dictionaryValueForKey:@"content"] ks_stringValueForKey:@"mode"];
- BOOL isIgnoreAudio = [modeString isEqualToString:@"evaluating"];
- [self postMessage:parm];
- [self.videoRecordManager setIgnoreAudio:isIgnoreAudio];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"startSoundCheck"]) { // 开始校音
- [self configRecordManager];
- [self postMessage:parm];
- self.isCompareStart = NO;
- self.isSoundCheckStart = YES;
- self.isDelayCheckStart = NO;
- [self startRecordService];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"endSoundCheck"]) {
- // 结束校音
- self.isSoundCheckStart = NO;
- [self stopRecordService];
- [self postMessage:parm];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"videoUpdate"]) { // 上传
- NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:parm];
- NSMutableDictionary *contentParm = [NSMutableDictionary dictionaryWithDictionary:[sendParm ks_dictionaryValueForKey:@"content"]];
- if (self.videoRecordManager) {
-
- MJWeakSelf;
- [self.videoRecordManager saveVideoCallback:^(BOOL isSuccess, NSString * _Nullable message) {
- if (isSuccess) {
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"已保存到相册"];
- [weakSelf uploadVideoWithParm:contentParm sendParm:sendParm];
- }
- }];
- }
- }
- #pragma mark -------- 云教练原生播放对接
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudDetail"]) { // 初始化方法
- /**
- api: 'cloudDetail',
- content: {
- midi: '',
- denominator: 4,
- numerator: 4,
- // xml整体原始速度
- originalSpeed: 90,
- // 间隔(ms)
- interval: 50
- }
- */
-
- [self configAudioSession];
- // 重置track num array
- self.configEngineParm = [parm copy];
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- NSString *midiUrl = [content ks_stringValueForKey:@"midi"];
- NSInteger denominator = [content ks_integerValueForKey:@"denominator"];
- NSInteger numerator = [content ks_integerValueForKey:@"numerator"];
- NSString *beatString = [NSString stringWithFormat:@"%zd/%zd", numerator,denominator];
- self.beatType = [self getBeatTypeFromString:beatString];
-
- float originalSpeed = [content ks_floatValueForKey:@"originalSpeed"];
- self.songOriginalSpeed = originalSpeed;
- self.currentSpeed = originalSpeed;
- NSInteger reportInterval = [content ks_integerValueForKey:@"interval"];
- // 下载midi文件
- BOOL hasSaveSong = [self checkSongHasSaveWithSongUrl:midiUrl];
- NSString *fileName = [midiUrl getUrlFileName];
- NSString *filePath = [self getFilePathWithName:fileName];
- if (hasSaveSong) {
- [self configPlayerEngineWithSong:filePath reportTime:reportInterval];
- }
- else {
- MJWeakSelf;
- [self downloadMidiFile:midiUrl success:^{
- [weakSelf configPlayerEngineWithSong:filePath reportTime:reportInterval];
- } faliure:^{
-
- }];
- }
-
- }
-
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudGetMediaStatus"]) { // 获取播放状态
- /**
- api: 'cloudGetMediaStatus',
- content: {
- status: 'init' | 'play' | 'suspend'
- }
- */
- NSString *engineStatus = @"init";
- if (self.initEngineSuccess) {
- if (self.isPlaying) {
- engineStatus = @"play";
- }
- else {
- engineStatus = @"suspend";
- }
- }
- NSMutableDictionary *valueDic = [NSMutableDictionary dictionaryWithDictionary:[parm ks_dictionaryValueForKey:@"content"]];
- [valueDic setValue:engineStatus forKey:@"status"];
- NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:parm];
- [sendParm setValue:valueDic forKey:@"content"];
- [self postMessage:sendParm];
- }
- // 播放、暂停、进度、播放结束、跳转指定位置
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudPlay"]) { // 播放
- /**
- api: 'cloudPlay',
- content: {
- // 当前曲目id
- songID: 0,
- // xml整体原始速度
- originalSpeed: 90,
- // 当前选择速度
- speed: 90,
- // 开始时间(ms)
- startTime: 0
- // 播放频率
- hertz:440
- }
- */
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- self.currentSongId = [content ks_stringValueForKey:@"songID"];
- float speed = [content ks_floatValueForKey:@"speed"];
- float originalSpeed = [content ks_floatValueForKey:@"originalSpeed"];
- double rate = speed / originalSpeed;
- self.currentSpeed = speed;
- float hertz = [content ks_floatValueForKey:@"hertz"];
- // 播放的hertz
- [self.playerEngine adjustPitchByHZ:hertz];
-
- [self.playerEngine setMusicPlayerSpeed:rate];
- Float64 startTime = [content ks_doubleValueForKey:@"startTime"];
- NSLog(@"------%@", [content ks_stringValueForKey:@"startTime"]);
- [self.playerEngine setProgressTime:(startTime/1000)];
- // 播放
- [self playAction];
- [self postMessage:parm];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudSuspend"]) { // 暂停
- /**
- api: 'cloudSuspend',
- content: {
- // 当前曲目id
- songID: 0,
- }
- */
- [self stopPlayAction];
- [self postMessage:parm];
-
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudSetCurrentTime"]) { // // 跳转指定位置
- /**
- api: 'cloudSetCurrentTime',
- content: {
- // 当前曲目id
- songID: 0,
- // 指定位置时间(ms)
- currentTime: 0
- }
- */
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- Float64 currentTime = [content ks_doubleValueForKey:@"currentTime"];
- if (self.playerEngine) {
- [self.playerEngine setProgressTime:(currentTime/1000)];
- }
- [self postMessage:parm];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudChangeSpeed"]) { // 调速 范围(45-270整数)
- /**
- api: 'cloudChangeSpeed',
- content: {
- // 当前曲目id
- songID: 0,
- // 调整速度
- speed: 90
- // xml整体原始速度
- originalSpeed: 90,
- }
- */
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- float speed = [content ks_floatValueForKey:@"speed"];
- float originalSpeed = [content ks_floatValueForKey:@"originalSpeed"];
- double rate = speed / originalSpeed;
- self.currentSpeed = speed;
- [self.playerEngine setMusicPlayerSpeed:rate];
- // 回报信息
- [self postMessage:parm];
- }
- // 设置每个轨道音量
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudVolume"]) {
- /**
- api: 'cloudVolume',
- content: {
- parts: [
- {
- name: '',
- volume: 90,//0-100
- }
- ]
- }
- */
- NSLog(@"-cloudVolume -----%@",parm);
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- int instrumentId = [content ks_intValueForKey:@"activeMidiId"];
- float volume = [content ks_floatValueForKey:@"activeMidiVolume"];
- if (instrumentId < 0) {
- [self postMessage:parm];
- [self.playerEngine getAllTrackVolume];
- return;
- }
- [self.playerEngine volumeTrackVolumeWithInstrumentId:instrumentId volume:volume/100];
- [self postMessage:parm];
- [self.playerEngine getAllTrackVolume];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudMetronome"]) { // 节拍器播放
- self.metronomeParm = [NSMutableDictionary dictionaryWithDictionary:parm];
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- NSInteger repeatCount = [content ks_integerValueForKey:@"repeat"];
- NSInteger denominator = [content ks_integerValueForKey:@"denominator"];
- NSInteger numerator = [content ks_integerValueForKey:@"numerator"];
- NSInteger supplement = [content ks_integerValueForKey:@"supplement"];
- NSString *beatString = [NSString stringWithFormat:@"%zd/%zd", numerator,denominator];
- self.beatType = [self getBeatTypeFromString:beatString];
- [self showBeatViewRepeatCount:repeatCount supplement:supplement];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudDestroy"]) { // 销毁播放器
- self.initEngineSuccess = NO;
- // 重置track num array
- self.isPlaying = NO;
- if (self.playerEngine) {
- [self.playerEngine cleanup];
- self.playerEngine = nil;
- }
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudLoading"]) { // loading
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- BOOL showLoading = [content ks_boolValueForKey:@"show"];
- if (showLoading) {
- [self showCustomLoading];
- }
- else {
- [self removeCustomLoadingView];
- }
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudAccompanyMessage"]) { // 获取伴奏
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- NSString *accompanyUrl = [content ks_stringValueForKey:@"accompanyUrl"];
- if (![NSString isEmptyString:accompanyUrl]) {
- NSString *fileName = [accompanyUrl getUrlFileName];
- NSString *filePath = [self getAccompanyFilePathWithName:fileName];
- NSURL *fileUrl = [[NSURL alloc] initFileURLWithPath:filePath];
- self.accompanyUrl = accompanyUrl;
- if ([self checkSongHasSaveAccompanyWithSongUrl:accompanyUrl]) {
- [self configVideoRecord:fileUrl];
- }
- else {
- MJWeakSelf;
- [self downloadUrl:accompanyUrl success:^{
- [weakSelf configVideoRecord:fileUrl];
- } faliure:^{
-
- }];
-
- }
- }
- else {
- // [LOADING_MANAGER MBShowAUTOHidingInWindow:@"当前曲目无mp3伴奏"];
- [self configVideoRecord:nil];
- }
- }
-
- // 跟音
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudToggleFollow"]) {
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- NSString *status = [content ks_stringValueForKey:@"state"];
- if ([status isEqualToString:@"start"]) { // 开始
- [self startTuner];
- }
- else if ([status isEqualToString:@"end"]) { // 结束
- [self stopTuner];
- }
- }
- // 延迟检测
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"startTune"]) { // 延迟测试开始
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- NSInteger count = [content ks_integerValueForKey:@"count"];
- if (count == 0) {
- [self.delayArray removeAllObjects];
- self.checkIndex = 0;
- }
- self.checkIndex += 1;
- [self configRecordManager];
- [self postMessage:parm];
- self.isCompareStart = NO;
- self.isSoundCheckStart = NO;
- self.isDelayCheckStart = YES;
- [self startRecordService];
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"endTune"]) { // 延迟测试结束
-
- self.isDelayCheckStart = NO;
- [self stopRecordService];
- [self postMessage:parm];
- [self stopMp3Player];
- [self sendAdjustEndMessage]; // 发送结束消息
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"finishTune"]) { // 延迟测试结束
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
-
- NSInteger errorCount = 0;
- NSInteger totalDelay = 0;
- for (NSInteger index = 0 ; index < self.delayArray.count; index++) {
- NSInteger micDelay = [self.delayArray[index] integerValue];
- if (micDelay > 10 && micDelay < 100) {
- totalDelay += micDelay;
- }
- else {
- errorCount++;
- }
- }
- NSMutableDictionary *contentParm = [NSMutableDictionary dictionaryWithDictionary:content];
- if (errorCount > 1) { // 错误次数过多
- [contentParm setValue:@(NO) forKey:@"result"];
- }
- else {
- [contentParm setValue:@(YES) forKey:@"result"];
- NSInteger averageDelay = totalDelay / (self.delayArray.count - errorCount);
- UserDefaultSet([NSNumber numberWithDouble:averageDelay], @"micDelay");
- }
- NSMutableDictionary *sendParm = [NSMutableDictionary dictionary];
- [sendParm setValue:@"finishTune" forKey:@"api"];
- [sendParm setValue:contentParm forKey:@"content"];
- [self postMessage:sendParm];
- [self.delayArray removeAllObjects];
- self.checkIndex = 0;
- }
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"getDeviceDelay"]) {
- NSInteger micDelay = [UserDefaultObjectForKey(@"micDelay") integerValue];
- NSMutableDictionary *content = [NSMutableDictionary dictionaryWithDictionary:[parm ks_dictionaryValueForKey:@"content"]];
- [content setValue:[NSNumber numberWithInteger:micDelay] forKey:@"value"];
- NSMutableDictionary *sendParm = [NSMutableDictionary dictionary];
- [sendParm setValue:@"getDeviceDelay" forKey:@"api"];
- [sendParm setValue:content forKey:@"content"];
- [self postMessage:sendParm];
- }
- // 音视频合成
- else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"openAdjustRecording"]) {
- KSMediaMergeView *mergeView = [[KSMediaMergeView alloc] init];
- if (self.bgAudioUrl == nil) {
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"当前曲目无mp3伴奏"];
- }
- else {
- if (self.AQManager && self.AQManager.audioUrl) {
- self.recordUrl = self.AQManager.audioUrl;
- [self.view addSubview:mergeView];
- [mergeView mas_makeConstraints:^(MASConstraintMaker *make) {
- make.left.right.top.bottom.mas_equalTo(self.view);
- }];
- NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
- mergeView.recordId = [content ks_stringValueForKey:@"recordId"];
- mergeView.songName = [content ks_stringValueForKey:@"title"];
- mergeView.coverImage = [content ks_stringValueForKey:@"coverImg"];
- MJWeakSelf;
- [mergeView configWithVideoUrl:self.videoRecordManager.videoFileURL bgAudioUrl:self.bgAudioUrl remoteBgUrl:self.accompanyUrl recordUrl:self.recordUrl offsetTime:self.offsetTime mergeCallback:^{
- [weakSelf musicPublishCallBack:content];
- }];
- }
- else {
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"麦克风被占用"];
- }
- }
- }
- else {
- [super handleScriptMessageSource:parm];
- }
-
- });
- }
- }
- - (void)musicPublishCallBack:(NSDictionary *)content {
- NSMutableDictionary *parm = [NSMutableDictionary dictionary];
- [parm setValue:@"hideComplexButton" forKey:@"api"];
- [parm setValue:@{} forKey:@"content"];
- [self postMessage:parm];
- }
- - (void)uploadVideoWithParm:(NSMutableDictionary *)contentParm sendParm:(NSMutableDictionary *)sendParm {
- MJWeakSelf;
- [self.videoRecordManager uploadRecordVideoSuccess:^(NSString * _Nonnull videoUrl) {
- [contentParm setValue:@"success" forKey:@"type"];
- [contentParm setValue:videoUrl forKey:@"filePath"];
- [contentParm setValue:@"上传成功" forKey:@"message"];
- [sendParm setValue:contentParm forKey:@"content"];
-
- [weakSelf postMessage:sendParm];
- } failure:^(NSString * _Nonnull desc) {
- [contentParm setValue:@"error" forKey:@"type"];
- [contentParm setValue:desc forKey:@"message"];
- [sendParm setValue:contentParm forKey:@"content"];
- [weakSelf postMessage:sendParm];
- }];
- }
- - (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {
- [KSPremissionAlert shareInstanceDisplayImage:deviceType message:message showInView:self.view cancel:^{
-
- } confirm:^{
- [self openSettingView];
- }];
-
- }
- - (void)openSettingView {
- [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
- }
- - (void)downloadUrl:(NSString *)url success:(void(^)(void))success faliure:(void(^)(void))faliure {
-
- [KSNetworkingManager downloadFileRequestWithFileUrl:url progress:^(int64_t bytesRead, int64_t totalBytes) {
-
- } success:^(NSURL * _Nonnull fileUrl) {
-
- if ([self saveAccompanyFileWithUrl:fileUrl accompanyUrl:url]) {
- if (success) {
- success();
- }
- }
- } faliure:^(NSError * _Nonnull error) {
- if (faliure) {
- faliure();
- }
- }];
- }
- - (void)configVideoRecord:(NSURL *)path {
- self.videoRecordManager.bgAudioUrl = path;
- self.bgAudioUrl = path;
- }
- - (void)showBeatViewRepeatCount:(NSInteger)repeatCount supplement:(NSInteger)supplement {
- KSCloudBeatView *beatView = [KSCloudBeatView shareInstanceWithBeatType:self.beatType speed:self.currentSpeed repeatCount:repeatCount supplement:supplement];
- MJWeakSelf;
- [beatView startPlayWithEndCallback:^(BOOL isCancle) {
- if (isCancle) { // 取消
- [weakSelf sendEndMetronomeMessage:YES];
- }
- else { // 播放完成
- [weakSelf sendEndMetronomeMessage:NO];
- }
- }];
- [self.view addSubview:beatView];
- }
- - (void)sendEndMetronomeMessage:(BOOL)isCancel {
- NSString *status = isCancel ? @"cancel" : @"finish";
- NSMutableDictionary *valueDic = [NSMutableDictionary dictionaryWithDictionary:[self.metronomeParm ks_dictionaryValueForKey:@"content"]];
- [valueDic setValue:status forKey:@"status"];
- NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:self.metronomeParm];
- [sendParm setValue:valueDic forKey:@"content"];
- [self postMessage:sendParm];
- }
- - (void)downloadMidiFile:(NSString *)midiUrl success:(void(^)(void))success faliure:(void(^)(void))faliure {
-
- [KSNetworkingManager downloadFileRequestWithFileUrl:midiUrl progress:^(int64_t bytesRead, int64_t totalBytes) {
-
- } success:^(NSURL * _Nonnull fileUrl) {
-
- if ([self saveMidiFileWithUrl:fileUrl midiUrl:midiUrl]) {
- success();
- }
- } faliure:^(NSError * _Nonnull error) {
- faliure();
- }];
- }
- - (BOOL)saveMidiFileWithUrl:(NSURL *)fileUrl midiUrl:(NSString *)midiUrl {
- NSData *sourceData = [NSData dataWithContentsOfURL:fileUrl];
- NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
- NSString *filePath= [cachePath stringByAppendingPathComponent:@"MidiSong"];
- // 先创建子目录
- NSFileManager *fileManager = [NSFileManager defaultManager];
- if (![fileManager fileExistsAtPath:filePath]) {
- [fileManager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
- }else{
- NSLog(@"已创建文件夹");
- }
- NSString *fileName = [midiUrl getUrlFileName];
- NSString *tempPath = [filePath stringByAppendingPathComponent:fileName];
- BOOL success = [sourceData writeToFile:tempPath atomically:NO];
- return success;
- }
- - (NSString *)getFilePathWithName:(NSString *)fileName {
- NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
- NSString *filePath= [cachePath stringByAppendingPathComponent:@"MidiSong"];
- return [filePath stringByAppendingPathComponent:fileName];;
- }
- - (BOOL)checkSongHasSaveWithSongUrl:(NSString *)songUrl {
- BOOL hasSaveFile = NO;
- NSString *fileName = [songUrl getUrlFileName];
- NSString *filePath = [self getFilePathWithName:fileName];
-
- NSFileManager *fileManager = [NSFileManager defaultManager];
- if ([fileManager fileExistsAtPath:filePath]) {
- hasSaveFile = YES;
- }
- return hasSaveFile;
- }
- - (void)sendMessageToSocket:(NSDictionary *)parm {
- NSString *messageHeader = @"proxyMessage";
- NSString *sendMessage = [self configDataCommond:messageHeader body:[parm ks_dictionaryValueForKey:@"content"]];
- [self sendDataToSocketService:sendMessage];
- }
- - (void)configAudioDeviceType:(NSDictionary *)parm {
- AUDIODEVICE_TYPE type = [KSAQRecordManager queryAudioOutputDeviceType];
- NSString *valueStr = @"";
- BOOL checkIsWired = NO;
- switch (type) {
- case AUDIODEVICE_TYPE_HEADPHONE:
- {
- valueStr = @"有线耳机";
- checkIsWired = YES;
- }
- break;
- case AUDIODEVICE_TYPE_BLUETOOTH:
- {
- valueStr = @"蓝牙耳机";
- checkIsWired = YES;
- }
- break;
- case AUDIODEVICE_TYPE_NONE:
- {
- valueStr = @"";
- checkIsWired = NO;
- }
- break;
- default:
- break;
- }
- NSMutableDictionary *valueDic = [NSMutableDictionary dictionaryWithDictionary:[parm ks_dictionaryValueForKey:@"content"]];
- [valueDic setValue:valueStr forKey:@"type"];
- [valueDic setValue:[NSNumber numberWithBool:checkIsWired] forKey:@"checkIsWired"];
- NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:parm];
- [sendParm setValue:valueDic forKey:@"content"];
- [self postMessage:sendParm];
- }
- - (void)startRecordService {
- if (self.AQManager.isRunning) {
- [self.AQManager stopRecord];
- }
- [self.AQManager startRecord];
- }
- - (void)stopRecordService {
- if (self.AQManager.isRunning) {
- [self.AQManager stopRecord];
- }
- }
- - (void)puaseRecordService {
- if (self.AQManager.isRunning) {
- [self.AQManager pauserRecord];
- }
- }
- - (void)resumeRecordService {
- [self.AQManager resumeRecord];
- }
- - (void)sendEndMessage {
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- // 上传停止的信息 发送给服务端
- NSString *endMessage = @"recordEnd";
- NSString *endData = [self configDataCommond:endMessage body:nil type:@"SOUND_COMPARE"];
- [self sendDataToSocketService:endData];
- self.isCompareStart = NO;
- NSLog(@"---- send end message");
- });
- }
- - (void)sendAdjustEndMessage {
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- // 上传停止的信息 发送给服务端
- NSString *endMessage = @"recordEnd";
- NSString *endData = [self configDataCommond:endMessage body:nil type:@"DELAY_CHECK"];
- [self sendDataToSocketService:endData];
- self.isDelayCheckStart = NO;
- NSLog(@"---- send adjust end message");
- });
- }
- - (void)sendOffsetTimeToService {
- // 上传停止的信息 发送给服务端
- NSString *offsetMessage = @"audioPlayStart";
- NSTimeInterval micDelay = [UserDefault(@"micDelay") doubleValue];
- NSDictionary *dic = @{@"offsetTime" : [NSNumber numberWithInteger:self.offsetTime], @"micDelay": [NSNumber numberWithInteger:micDelay]};
- NSString *endData = [self configDataCommond:offsetMessage body:dic type:@"SOUND_COMPARE"];
- NSLog(@"------ %@", endData);
- [self sendDataToSocketService:endData];
- self.isCompareStart = NO;
- }
- #pragma mark-------- KSAQRecordManagerDelegate
- - (void)recordInterruption {
- NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
- @"content" : @{@"reson":@"录制错误,请重试"}
- };
- [self postMessage:postParm];
- }
- - (void)audioRouteChange:(AUDIODEVICE_TYPE)type {
- NSString *valueStr = @"";
- BOOL checkIsWired = NO;
- switch (type) {
- case AUDIODEVICE_TYPE_HEADPHONE:
- {
- valueStr = @"有线耳机";
- checkIsWired = YES;
- }
- break;
- case AUDIODEVICE_TYPE_BLUETOOTH:
- {
- valueStr = @"蓝牙耳机";
- checkIsWired = YES;
- }
- break;
- case AUDIODEVICE_TYPE_NONE:
- {
- valueStr = @"";
- checkIsWired = NO;
- }
- break;
- default:
- break;
- }
-
- NSDictionary *postParm = @{@"api" : @"listenerWiredStatus",
- @"content" : @{@"type":valueStr,
- @"checkIsWired":[NSNumber numberWithBool:checkIsWired]
- }
- };
- [self postMessage:postParm];
- }
- #pragma mark ------- 评测app播放
- /*
- - (void)recordDidStart:(NSTimeInterval)time { // ms
- self.recordStartTime = time;
- if (self.isDelayCheckStart) {
- NSLog(@"---- delay - record did start %f", time);
- // 播放音频
- // 播放校音音频
- dispatch_main_sync_safe(^{
- if (self.checkIndex % 2 == 0) {
- [self.dongPlayer startPlay];
- }
- else {
- [self.dingPlayer startPlay];
- }
- });
- }
- else if (self.isCompareStart) {
- NSLog(@"---- compare - record did start %f", time);
- // 播放伴奏
- dispatch_main_sync_safe(^{
- [self.musicPlayer startPlay];
- });
- }
- }
- */
- - (void)audioRecord:(KSAQRecordManager *)audioRecord didRecordAudioData:(void *)data length:(UInt32)length {
-
- if (self.socketManager.socketReadyState != SR_OPEN) {
- return;
- }
- NSData *pushData = [[NSData alloc] initWithBytes:data length:length];
- if (self.isCompareStart) { // 发送评测开始消息
- dispatch_async(dispatch_get_main_queue(), ^{
- NSDate *date = [NSDate date];
- NSTimeInterval inteveral = [date timeIntervalSince1970];
- double beginTime = inteveral - audioRecord.sampleTime;
- NSDictionary *parm = @{
- @"api" : @"recordStartTime",
- @"content" : @{@"inteveral" : [NSNumber numberWithDouble:beginTime]}
- };
- [self postMessage:parm];
- });
-
- NSLog(@"--------- send start message");
- _isCompareStart = NO;
- NSString *startMessage = @"recordStart";
- NSString *startString = [self configDataCommond:startMessage body:nil type:@"SOUND_COMPARE"];
- [self sendDataToSocketService:startString];
- }
- else if (self.isSoundCheckStart) { // 校音开始
-
- NSLog(@"--------- send check start message");
- _isSoundCheckStart = NO;
- NSString *checkStartMessage = @"start";
- NSString *startString = [self configDataCommond:checkStartMessage body:nil type:@"PITCH_DETECTION"];
- [self sendDataToSocketService:startString];
- }
- else if (self.isDelayCheckStart) {
- NSLog(@"--------- send delay check start message");
- _isDelayCheckStart = NO;
- NSString *checkStartMessage = @"recordStart";
- NSInteger frequence = 0.0f;
- if (self.checkIndex % 2 == 0) {
- frequence = self.secondFrequence;
- }
- else {
- frequence = self.firstFrequence;
- }
- NSDictionary *parm = @{@"HZ" : @(frequence)};
- NSString *startString = [self configDataCommond:checkStartMessage body:parm type:@"DELAY_CHECK"];
- [self sendDataToSocketService:startString];
- }
- // NSLog(@"--------- send audio data length %d", length);
- [self sendDataToSocketService:pushData];
- }
- - (NSString *)configDataCommond:(NSString *)commond body:(id)bodyMessage type:(NSString *)dataType {
- NSMutableDictionary *parm = [NSMutableDictionary dictionary];
- if (bodyMessage) {
- [parm setValue:bodyMessage forKey:@"body"];
- }
- NSMutableDictionary *headerParm = [NSMutableDictionary dictionary];
- if ([NSString isEmptyString:commond]) {
- [headerParm setValue:@"" forKey:@"commond"];
- }
- else {
- [headerParm setValue:commond forKey:@"commond"];
- }
- if (![NSString isEmptyString:dataType]) {
- [headerParm setValue:dataType forKey:@"type"];
- }
- [headerParm setValue:@(200) forKey:@"status"];
- [parm setValue:headerParm forKey:@"header"];
- return [parm mj_JSONString];
- }
- - (NSString *)configDataCommond:(NSString *)commond body:(id)bodyMessage {
- NSMutableDictionary *parm = [NSMutableDictionary dictionary];
- if (bodyMessage) {
- [parm setValue:bodyMessage forKey:@"body"];
- }
- if ([NSString isEmptyString:commond]) {
- [parm setValue:@{@"commond":@""} forKey:@"header"];
- }
- else {
- [parm setValue:@{@"commond":commond} forKey:@"header"];
- }
- return [parm mj_JSONString];
- }
- - (KSWebSocketManager *)socketManager {
- if (!_socketManager) {
- _socketManager = [[KSWebSocketManager alloc] init];
- }
- return _socketManager;
- }
- #pragma mark --- lazying
- - (UIView *)viewContainer {
- if (!_viewContainer) {
- _viewContainer = [[UIView alloc] init];
- }
- return _viewContainer;
- }
- - (KSVideoRecordManager *)videoRecordManager {
- if (!_videoRecordManager) {
- MJWeakSelf;
- _videoRecordManager = [[KSVideoRecordManager alloc] initSessionRecordCallback:^(BOOL isSuccess, NSString * _Nullable message) {
- if (isSuccess) {
- [weakSelf showSuccessMessage:message];
- }
- else {
- if (![NSString isEmptyString:message]) {
- [LOADING_MANAGER MBShowAUTOHidingInWindow:message];
- }
-
- }
- }];
- }
- return _videoRecordManager;
- }
- - (void)showSuccessMessage:(NSString *)message {
- if (![NSString isEmptyString:message]) {
- [LOADING_MANAGER MBShowAUTOHidingInWindow:message];
- }
- // 成功
- if (self.endRecordParm) {
- [self postMessage:self.endRecordParm];
- self.endRecordParm = nil;
- }
- }
- - (MetronomeType)getBeatTypeFromString:(NSString *)typeString {
- if ([typeString isEqualToString:@"1/4"]) {
- return MetronomeType1V4;
- }
- else if ([typeString isEqualToString:@"2/4"]) {
- return MetronomeType2V4;
- }
- else if ([typeString isEqualToString:@"3/4"]) {
- return MetronomeType3V4;
- }
- else if ([typeString isEqualToString:@"4/4"]) {
- return MetronomeType4V4;
- }
- else if ([typeString isEqualToString:@"3/8"]) {
- return MetronomeType3V8;
- }
- else if ([typeString isEqualToString:@"6/8"]) {
- return MetronomeType6V8;
- }
- else {
- return MetronomeType4V4;
- }
- }
- #pragma mark ------- midi 播放相关
- - (void)configPlayerEngineWithSong:(NSString *)songPath reportTime:(NSInteger)reportTime {
- self.initEngineSuccess = NO;
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- self.playerEngine = [[MidiPlayerEngine alloc] init];
- self.playerEngine.reportTime = reportTime;
- self.playerEngine.delegate = self;
- [self.playerEngine configSoundFilePath:[[NSBundle mainBundle]
- pathForResource:@"synthgms" ofType:@"sf2"]];
- [self.playerEngine loadMIDIFileWithString:songPath];
- });
- }
- - (void)configAudioSession {
- self.audioSessionManager = [[KSAudioSessionManager alloc] init];
- self.audioSessionManager.delegate = self;
- [self.audioSessionManager configAudioSession:AUDIOCONFIG_PLAYANDRECORD];
- }
- #pragma mark ---- PlayerEngineDelegate
- /** 进度更新
- api: 'cloudTimeUpdae',
- content: {
- // 当前曲目id
- songID: 0,
- // 当前位置时间(ms)
- currentTime: 0
- }
- */
- /** 播放结束事件
- api: 'cloudplayed',
- content: {
- // 当前曲目id
- songID: 0,
- }
- */
- - (void)ProgressUpdated:(float)progress currentTime:(MusicTimeStamp)currentTime {
- if (self.isPlaying == NO) {
- return;
- }
- // 回调
- NSMutableDictionary *sendParm = [NSMutableDictionary dictionary];
- [sendParm setValue:@"cloudTimeUpdae" forKey:@"api"];
- NSMutableDictionary *content = [NSMutableDictionary dictionary];
- [content setValue:self.currentSongId forKey:@"songID"];
- [content setValue:@(currentTime*1000) forKey:@"currentTime"];
- [sendParm setValue:content forKey:@"content"];
- [self postMessage:sendParm];
- }
- - (void)playEnd {
- [self stopPlayAction];
- NSMutableDictionary *sendParm = [NSMutableDictionary dictionary];
- [sendParm setValue:@"cloudplayed" forKey:@"api"];
- NSMutableDictionary *content = [NSMutableDictionary dictionary];
- [content setValue:self.currentSongId forKey:@"songID"];
- [sendParm setValue:content forKey:@"content"];
- [self postMessage:sendParm];
- }
- - (void)initPlayerEngineSuccess:(float)totalTime {
- self.initEngineSuccess = YES;
- if (self.configEngineParm) {
- NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:self.configEngineParm];
- NSMutableDictionary *content = [NSMutableDictionary dictionaryWithDictionary:[sendParm ks_dictionaryValueForKey:@"content"]];
- [content setValue:@(totalTime*1000) forKey:@"midiDuration"];
- [sendParm setValue:content forKey:@"content"];
- [self postMessage:sendParm];
- self.configEngineParm = nil;
- }
- }
- // 总时长
- - (void)GetMusicTotalTime:(float)time {
-
- }
- #pragma mark ----- 播放控制
- - (void)playAction {
- if (self.playerEngine) {
- self.isPlaying = YES;
- [self.playerEngine playMIDIFile];
- }
- }
- - (void)stopPlayAction {
- if (self.playerEngine) {
- self.isPlaying = NO;
- if ([self.playerEngine isPlayingFile]) {
- [self.playerEngine stopPlayingMIDIFile];
- }
- }
- }
- #pragma mark ----- 小酷AI loading
- - (AccompanyLoadingView *)loadingView {
- if (!_loadingView) {
- _loadingView = [AccompanyLoadingView shareInstance];
- MJWeakSelf;
- [_loadingView loadingCallback:^{
- [weakSelf backAction];
- }];
- }
- return _loadingView;
- }
- - (void)showCustomLoading {
- if ([self.view.subviews containsObject:self.loadingView]) {
- return;
- }
- [self.view addSubview:self.loadingView];
- [self.loadingView mas_makeConstraints:^(MASConstraintMaker *make) {
- make.left.top.right.bottom.mas_equalTo(self.view);
- }];
- [self.view bringSubviewToFront:self.loadingView];
- [self.loadingView showLoading];
- }
- - (void)removeCustomLoadingView {
- [self.loadingView stopLoading];
- }
- #pragma mark ----- 跟音模块
- - (void)startTuner {
- if (self.isTunerRuning == NO) {
- self.isTunerRuning = YES;
- [self.tuner start];
- }
- }
- - (void)stopTuner {
- if (self.isTunerRuning) {
- self.isTunerRuning = NO;
- [self.tuner stop];
- }
- }
- - (Tuner *)tuner {
- if (!_tuner) {
- _tuner = [[Tuner alloc] initWithThreshold:0 smoothing:0.25];
- _tuner.delegate = self;
- }
- return _tuner;
- }
- - (void)tunerDidUpdate:(Tuner *)tuner output:(TunerOutput *)output {
- if (output.amplitude < 0.01) {
-
- }
- else {
- // 回调频率
- NSDictionary *parm = @{
- @"api" : @"cloudFollowTime",
- @"content" : @{@"frequency" : [NSNumber numberWithDouble:output.frequency]}
- };
- [self postMessage:parm];
- }
- NSLog(@"-------- %@%zd --- distance :%f frequence : %f" , output.pitch, output.octave, output.distance, output.frequency);
-
- }
- #pragma mark ---- 保存伴奏
- - (BOOL)saveAccompanyFileWithUrl:(NSURL *)fileUrl accompanyUrl:(NSString *)accompanyUrl {
- NSData *sourceData = [NSData dataWithContentsOfURL:fileUrl];
- NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
- NSString *filePath= [cachePath stringByAppendingPathComponent:@"AccompanySong"];
- // 先创建子目录
- NSFileManager *fileManager = [NSFileManager defaultManager];
- if (![fileManager fileExistsAtPath:filePath]) {
- [fileManager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
- }else{
- NSLog(@"已创建文件夹");
- }
- NSString *fileName = [accompanyUrl getUrlFileName];
- NSString *tempPath = [filePath stringByAppendingPathComponent:fileName];
- BOOL success = [sourceData writeToFile:tempPath atomically:NO];
- return success;
- }
- - (NSString *)getAccompanyFilePathWithName:(NSString *)fileName {
- NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
- NSString *filePath= [cachePath stringByAppendingPathComponent:@"AccompanySong"];
- return [filePath stringByAppendingPathComponent:fileName];;
- }
- - (BOOL)checkSongHasSaveAccompanyWithSongUrl:(NSString *)songUrl {
- BOOL hasSaveFile = NO;
- NSString *fileName = [songUrl getUrlFileName];
- NSString *filePath = [self getAccompanyFilePathWithName:fileName];
-
- NSFileManager *fileManager = [NSFileManager defaultManager];
- if ([fileManager fileExistsAtPath:filePath]) {
- hasSaveFile = YES;
- }
- return hasSaveFile;
- }
- #pragma mark ---- player
- - (void)configPlayerDelegate {
- self.dingPlayer.delegate = self;
- self.dongPlayer.delegate = self;
- self.musicPlayer.delegate = self;
- }
- - (kSNewPlayer *)dingPlayer {
- if (!_dingPlayer) {
- _dingPlayer = [[kSNewPlayer alloc] init];
- }
- return _dingPlayer;
- }
- - (kSNewPlayer *)dongPlayer {
- if (!_dongPlayer) {
- _dongPlayer = [[kSNewPlayer alloc] init];
- }
- return _dongPlayer;
- }
- - (kSNewPlayer *)musicPlayer {
- if (!_musicPlayer) {
- _musicPlayer = [[kSNewPlayer alloc] init];
- }
- return _musicPlayer;
- }
- #pragma mark ---- new player delegate
- - (void)getSongCurrentTime:(NSInteger)currentTime andTotalTime:(NSInteger)totalTime andProgress:(CGFloat)progress currentInterval:(NSTimeInterval)currentInterval playTime:(NSTimeInterval)playTime inPlayer:(kSNewPlayer *)player {
-
- if (player == self.dingPlayer || player == self.dongPlayer) {
- if (playTime >= 300 && playTime < 310 && self.recordStartTime > 0) {
- NSLog(@" --- check player start play time %f", currentInterval*1000 - playTime);
- self.playerStartTime = currentInterval*1000 - playTime;
- self.offsetTime = self.playerStartTime - self.recordStartTime;
- NSLog(@"--------- check player offset time -- %zd", self.offsetTime);
- }
- }
-
- if (playTime >= 300 && playTime < 310 && player == self.musicPlayer) {
- if (self.recordStartTime > 0) {
- NSLog(@" --- music player start play time %f", currentInterval*1000 - playTime);
- self.playerStartTime = currentInterval*1000 - playTime;
- self.offsetTime = self.playerStartTime - self.recordStartTime;
- NSLog(@"--------- music play offset time -- %zd", self.offsetTime);
- [self sendOffsetTimeToService];
- }
- NSLog(@"------- record start time %f", self.recordStartTime);
- }
-
- // 回调进度
- if (player == self.musicPlayer) {
- // NSLog(@"------ music play progress - %f", progress);
- // 回调进度
- NSDictionary *parm = @{
- @"api" : @"playProgress",
- @"content" : @{@"currentTime" : [NSNumber numberWithInteger:currentTime],
- @"totalDuration" : [NSNumber numberWithInteger:totalTime],
- }
- };
- // NSLog(@" -----music play progress %@---- ", parm);
- [self postMessage:parm];
- }
- }
- - (void)sendPlayerReadyMsg {
- if (self.playerParm) {
- [self postMessage:self.playerParm];
- }
- }
- - (void)preparePlay:(kSNewPlayer *)player {
- if (player == self.musicPlayer) {
- self.musicPlayerReady = YES;
- }
- else if (player == self.dingPlayer) {
- self.dingPlayerReady = YES;
-
- }
- else if (player == self.dongPlayer) {
- self.dongPlayerReady = YES;
- }
- // 如果都准备好
- if (self.musicPlayerReady && self.dingPlayerReady && self.dongPlayerReady) {
- [self sendPlayerReadyMsg];
- }
- }
- - (NSMutableArray *)delayArray {
- if (!_delayArray) {
- _delayArray = [NSMutableArray array];
- }
- return _delayArray;
- }
- /*
- #pragma mark - Navigation
-
- // In a storyboard-based application, you will often want to do a little preparation before navigation
- - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
- // Get the new view controller using [segue destinationViewController].
- // Pass the selected object to the new view controller.
- }
- */
- @end
|