// // AudioChatViewController.m // BuguLive // // Created by Kylin on 2024/12/2. // Copyright © 2024 xfg. All rights reserved. // #import "AudioChatViewController.h" #import "TMSmallRoomView.h" #import "AudioChatTool.h" typedef void(^IsNormalChatBlock)(BOOL isNormal); @interface AudioChatViewController () @property (nonatomic,strong) UILabel * timesLabel; @property (nonatomic,strong) TRTCCloud * trtcCloud; @property (nonatomic,strong) UILabel * tipLabel; //通话中View @property (nonatomic,strong) UIView * chatBotoomView; @property (nonatomic,strong) UIButton * receiveButton; @property (nonatomic,strong) UIButton * receiveCloseButton; @property (nonatomic,assign) int timesCount; //接听中View @property (nonatomic,strong) UIView * receiveBottomView; @property (nonatomic,strong) UIButton * maikefengButton; @property (nonatomic,strong) UILabel * maikefengLabel; @property (nonatomic,strong) UIButton * closeButton; @property (nonatomic,strong) UILabel * closeLabel; @property (nonatomic,strong) UIButton * yangshengqiButton; @property (nonatomic,strong) UILabel * yangshengqiLabel; @property(nonatomic,strong)AVAudioPlayer *player;//播放 //用户记录分钟数,用户扣费判断 @property (nonatomic,assign) int lastMin; @property (nonatomic,copy) IsNormalChatBlock isNormalChatBlock; @end @implementation AudioChatViewController static dispatch_once_t onceToken; static AudioChatViewController *_voiceRoomVC; + (instancetype)shareVoiceRoomVC{ dispatch_once(&onceToken, ^{ _voiceRoomVC = [[AudioChatViewController alloc] init]; }); return _voiceRoomVC; } /**销毁房间*/ + (void)destoryShareRootVC { /**更新打开房间的状态*/ AppDelegate.sharedAppDelegate.isInAudioVideoChatVc = NO; // app.showRoomVc = NO; // app.IsInVoiceRoom = NO; NSLog(@"房间销毁了。。。。。。。。。。。1"); /**离开房间*/ [AudioChatViewController.shareVoiceRoomVC.navigationController dismissViewControllerAnimated:YES completion:^{}]; [AudioChatViewController.shareVoiceRoomVC.trtcCloud exitRoom]; [TRTCCloud destroySharedInstance]; onceToken = 0; _voiceRoomVC = nil; //小屏的时候,也要直接销毁掉 if (AppDelegate.sharedAppDelegate.hasSmallAudioVideoView) { [[TMSmallRoomView sharedInstance] dismiss]; } NSLog(@"房间销毁了。。。。。。。。。。。2"); } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.navigationController.navigationBar.hidden = YES; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; self.navigationController.navigationBar.hidden = NO; } - (void)viewDidLoad { [super viewDidLoad]; AppDelegate.sharedAppDelegate.isInAudioVideoChatVc = YES; self.lastMin = -1; //基础UI [self initChatBaseUI]; // 音量监听 [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(volumeChanged:) name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil]; [[NSNotificationCenter defaultCenter] postNotificationName:@"MSG_VIDEO_LINE_CALL" object:nil]; } - (void)initChatBaseUI { UIImageView * bgImgV = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)]; bgImgV.image = [UIImage imageNamed:@"audioChatbgicon"]; [self.view addSubview:bgImgV]; UIButton * backVerticalBtn = [[UIButton alloc]initWithFrame:CGRectMake(15,StatusBarHeight, 44, 44)]; [backVerticalBtn setImage:[UIImage imageNamed:@"audioChatSmallIcon"] forState:UIControlStateNormal]; [backVerticalBtn addTarget:self action:@selector(backBtnClick) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:backVerticalBtn]; _timesLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 0, SCREEN_WIDTH - 120, 30)]; self.timesLabel.centerY = backVerticalBtn.centerY; self.timesLabel.textAlignment = NSTextAlignmentCenter; self.timesLabel.textColor = UIColor.whiteColor; self.timesLabel.font = [UIFont boldSystemFontOfSize:16]; self.timesLabel.text = @"00:00"; self.timesLabel.hidden = YES; [self.view addSubview:self.timesLabel]; UIImageView * headerImgV = [[UIImageView alloc] initWithFrame:CGRectMake((SCREEN_WIDTH - 90)/2, NavigationHeight + 133, 90, 90)]; headerImgV.layer.cornerRadius = 10; headerImgV.layer.masksToBounds = YES; [headerImgV sd_setImageWithURL:[NSURL URLWithString:self.mChatFriend.mHead_image] placeholderImage:kDefaultPreloadHeadImg]; [self.view addSubview:headerImgV]; UILabel * nicknameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, headerImgV.bottom + 10, SCREEN_WIDTH, 30)]; nicknameLabel.textAlignment = NSTextAlignmentCenter; nicknameLabel.textColor = UIColor.whiteColor; nicknameLabel.font = [UIFont boldSystemFontOfSize:21]; nicknameLabel.text = self.mChatFriend.mNick_name; [self.view addSubview:nicknameLabel]; #pragma mark - 接听中UI _receiveBottomView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT - SafeAreaBottomHeight - 20 - 70, SCREEN_WIDTH, 70)]; // self.receiveBottomView.layer.borderColor = UIColor.redColor.CGColor; // self.receiveBottomView.layer.borderWidth = 1; self.receiveBottomView.hidden = YES; [self.view addSubview:self.receiveBottomView]; _receiveCloseButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.receiveCloseButton.frame = CGRectMake(25, 0, 70, 70); [self.receiveCloseButton setBackgroundImage:[UIImage imageNamed:@"audioclosebtnbg"] forState:UIControlStateNormal]; [self.receiveCloseButton setBackgroundImage:[UIImage imageNamed:@"audioclosebtnbg"] forState:UIControlStateSelected]; [self.receiveBottomView addSubview:self.receiveCloseButton]; [self.receiveCloseButton addTarget:self action:@selector(receiveCloseButtonClick) forControlEvents:UIControlEventTouchUpInside]; _receiveButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.receiveButton.frame = CGRectMake(SCREEN_WIDTH - 25 - 70, 0, 70, 70); [self.receiveButton setBackgroundImage:[UIImage imageNamed:@"audioreceivebtnbg"] forState:UIControlStateNormal]; [self.receiveButton setBackgroundImage:[UIImage imageNamed:@"audioreceivebtnbg"] forState:UIControlStateSelected]; [self.receiveBottomView addSubview:self.receiveButton]; [self.receiveButton addTarget:self action:@selector(receiveButtonClick) forControlEvents:UIControlEventTouchUpInside]; #pragma mark - 通话中UI _chatBotoomView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT - SafeAreaBottomHeight - 40 - 70 - 20, SCREEN_WIDTH, 70+40)]; // self.chatBotoomView.layer.borderColor = UIColor.redColor.CGColor; // self.chatBotoomView.layer.borderWidth = 1; self.chatBotoomView.hidden = YES; [self.view addSubview:self.chatBotoomView]; _tipLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.chatBotoomView.top - 60, SCREEN_WIDTH, 30)]; self.tipLabel.textAlignment = NSTextAlignmentCenter; self.tipLabel.textColor = UIColor.whiteColor; self.tipLabel.font = [UIFont systemFontOfSize:16]; self.tipLabel.text = ASLocalizedString(@"邀请你语音通话"); self.tipLabel.textColor = [UIColor colorWithHex:0x999999]; self.tipLabel.hidden = YES; [self.view addSubview:self.tipLabel]; _maikefengButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.maikefengButton.frame = CGRectMake((SCREEN_WIDTH - 70*3)/4, 0, 70, 70); [self.maikefengButton setBackgroundImage:[UIImage imageNamed:@"maikefengopen"] forState:UIControlStateNormal]; [self.maikefengButton setBackgroundImage:[UIImage imageNamed:@"maikefengclose"] forState:UIControlStateSelected]; [self.chatBotoomView addSubview:self.maikefengButton]; [self.maikefengButton addTarget:self action:@selector(maikeFengButtonClick) forControlEvents:UIControlEventTouchUpInside]; _maikefengLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.maikefengButton.bottom + 10, SCREEN_WIDTH/3, 20)]; self.maikefengLabel.centerX = self.maikefengButton.centerX; self.maikefengLabel.textAlignment = NSTextAlignmentCenter; self.maikefengLabel.font = [UIFont systemFontOfSize:16]; self.maikefengLabel.textColor = [UIColor colorWithHex:0x999999]; self.maikefengLabel.text = ASLocalizedString(@"麦克风已开启"); [self.chatBotoomView addSubview:self.maikefengLabel]; _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.closeButton.frame = CGRectMake((SCREEN_WIDTH - 70*3)/4*2+70, self.maikefengButton.top, 70, 70); [self.closeButton setBackgroundImage:[UIImage imageNamed:@"audioclosebtnbg"] forState:UIControlStateNormal]; [self.closeButton setBackgroundImage:[UIImage imageNamed:@"audioclosebtnbg"] forState:UIControlStateSelected]; [self.chatBotoomView addSubview:self.closeButton]; [self.closeButton addTarget:self action:@selector(closeButtonClick) forControlEvents:UIControlEventTouchUpInside]; _closeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.maikefengButton.bottom + 10, SCREEN_WIDTH/3, 20)]; self.closeLabel.centerX = self.closeButton.centerX; self.closeLabel.textAlignment = NSTextAlignmentCenter; self.closeLabel.font = [UIFont systemFontOfSize:16]; self.closeLabel.textColor = [UIColor colorWithHex:0x999999]; self.closeLabel.text = ASLocalizedString(@"挂断"); [self.chatBotoomView addSubview:self.closeLabel]; _yangshengqiButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.yangshengqiButton.frame = CGRectMake((SCREEN_WIDTH - 70*3)/4*3+70*2, self.maikefengButton.top, 70, 70); [self.yangshengqiButton setBackgroundImage:[UIImage imageNamed:@"yangshengqiclose"] forState:UIControlStateNormal]; [self.yangshengqiButton setBackgroundImage:[UIImage imageNamed:@"yangshengqiopen"] forState:UIControlStateSelected]; [self.chatBotoomView addSubview:self.yangshengqiButton]; [self.yangshengqiButton addTarget:self action:@selector(yangshengqiButtonClick) forControlEvents:UIControlEventTouchUpInside]; _yangshengqiLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.maikefengButton.bottom + 10, SCREEN_WIDTH/3, 20)]; self.yangshengqiLabel.centerX = self.yangshengqiButton.centerX; self.yangshengqiLabel.textAlignment = NSTextAlignmentCenter; self.yangshengqiLabel.font = [UIFont systemFontOfSize:16]; self.yangshengqiLabel.textColor = [UIColor colorWithHex:0x999999]; self.yangshengqiLabel.text = ASLocalizedString(@"扬声器已关"); [self.chatBotoomView addSubview:self.yangshengqiLabel]; } #pragma mark - 接听点击事件 //是否接听,接听 - (void)receiveButtonClick { WeakSelf self.isNormalChatBlock = ^(BOOL isNormal) { if (isNormal) { [weakSelf receiveChatSendMsg]; return; } [AudioChatViewController destoryShareRootVC]; }; [self askChatIsNormal]; } - (void)receiveChatSendMsg { WeakSelf SIMMsgObj *obj = [self.mChatFriend sendCustomCallAudioTextMsg:@"接听者,接听语音通话" callAudioType:AudioChatType_receive isCall:self.isZhuDongCall block:^(SResBase *resb, SIMMsgObj *newObj) { if (!resb.msuccess) { [SVProgressHUD showErrorWithStatus:resb.mmsg]; } else { //发送成功了,修改UI [weakSelf joinChannel:[NSString stringWithFormat:@"%d",self.mChatFriend.mUser_id]]; weakSelf.tipLabel.hidden = YES; weakSelf.chatBotoomView.hidden = NO; weakSelf.receiveBottomView.hidden = YES; [weakSelf reloadDataWithType:(AudioChatType_receive)]; [weakSelf.player stop]; } }]; } //是否接听,挂断通话 - (void)receiveCloseButtonClick { WeakSelf SIMMsgObj *obj = [self.mChatFriend sendCustomCallAudioTextMsg:@"接听者,挂断语音通话" callAudioType:AudioChatType_beidongClose isCall:self.isZhuDongCall block:^(SResBase *resb, SIMMsgObj *newObj) { if (!resb.msuccess) { [SVProgressHUD showErrorWithStatus:resb.mmsg]; } else { //发送成功了,直接挂断销毁视图 if (self.timesCount > 0) { if ([AudioChatTool.shareInstance.delegate respondsToSelector:@selector(sendTimes:)]){ [AudioChatTool.shareInstance.delegate sendTimes:[NSString stringWithFormat:@"%@%@",ASLocalizedString(@"语音通话时间:"), self.timesLabel.text]]; } // [self.mChatFriend sendTextMsg:[NSString stringWithFormat:@"%@%@",ASLocalizedString(@"语音通话时间:"), self.timesLabel.text] block:^(SResBase *resb, SIMMsgObj *thatmsg) { // // }]; } [AudioChatViewController destoryShareRootVC]; } }]; } #pragma mark - 通话中点击事件 - (void)maikeFengButtonClick { self.maikefengButton.selected = !self.maikefengButton.isSelected; if (self.maikefengButton.isSelected) { self.maikefengLabel.text = ASLocalizedString(@"麦克风已关闭"); } else { self.maikefengLabel.text = ASLocalizedString(@"麦克风已开启"); } [self setIsMute:self.maikefengButton.isSelected]; } - (void)closeButtonClick { WeakSelf SIMMsgObj *obj = [self.mChatFriend sendCustomCallAudioTextMsg:@"发起者挂断语音通话" callAudioType:AudioChatType_zhudongClose isCall:self.isZhuDongCall block:^(SResBase *resb, SIMMsgObj *newObj) { if (!resb.msuccess) { [SVProgressHUD showErrorWithStatus:resb.mmsg]; } else { if (self.timesCount > 0) { if ([AudioChatTool.shareInstance.delegate respondsToSelector:@selector(sendTimes:)]){ [AudioChatTool.shareInstance.delegate sendTimes:[NSString stringWithFormat:@"%@%@",ASLocalizedString(@"语音通话时间:"), self.timesLabel.text]]; } } //发送成功了,直接挂断销毁视图 [AudioChatViewController destoryShareRootVC]; } }]; } - (void)yangshengqiButtonClick { self.yangshengqiButton.selected = !self.yangshengqiButton.isSelected; if (self.yangshengqiButton.isSelected) { self.yangshengqiLabel.text = ASLocalizedString(@"扬声器已开"); } else { self.yangshengqiLabel.text = ASLocalizedString(@"扬声器已关"); } [self openYangshengqi:self.yangshengqiButton.isSelected]; } - (void)backBtnClick { WeakSelf [[self getPresentingViewController] dismissViewControllerAnimated:YES completion:^{ [weakSelf dissmissWithSmallRoom]; }]; } - (UIViewController *)getPresentingViewController { NSLog(@"%s ---- %@",__FUNCTION__,self.presentingViewController); return self.presentingViewController ? self.presentingViewController : self; } #pragma mark /**最小化房间*/ - (void)dissmissWithSmallRoom { __block AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate]; app.hasSmallAudioVideoView = YES; // app.IsInVoiceRoom = YES; TMSmallRoomView * smallRoomView = [TMSmallRoomView sharedInstance]; [smallRoomView show]; @weakify(self) [smallRoomView setEnterClickBlock:^{ @strongify(self) app.isInAudioVideoChatVc = YES; app.hasSmallAudioVideoView = NO; // app.IsInVoiceRoom = YES; UIWindow *window = [UIApplication sharedApplication].keyWindow; UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:[AudioChatViewController shareVoiceRoomVC]]; nav.modalPresentationStyle = UIModalPresentationOverFullScreen; nav.modalTransitionStyle = UIModalTransitionStyleCoverVertical; [window.rootViewController presentViewController:nav animated:YES completion:^{}]; }]; } #pragma mark - ******************* 通话中,数据交互,通过消息来判断逻辑进程 ******************* - (void)reloadDataWithType:(AudioChatType)chatType { //1、请求语音通话,A给B发 B收到请求也要走这里判断,改变UI if (chatType == AudioChatType_call) { //发起者 if (self.isZhuDongCall) { self.receiveBottomView.hidden = YES; self.chatBotoomView.hidden = NO; self.tipLabel.hidden = NO; self.tipLabel.text = ASLocalizedString(@"等待对方接受邀请..."); self.closeLabel.text = ASLocalizedString(@"取消"); [self joinChannel:[IMAPlatform sharedInstance].host.userId]; return; } //接收者 self.receiveBottomView.hidden = NO; self.chatBotoomView.hidden = YES; self.tipLabel.hidden = NO; self.tipLabel.text = ASLocalizedString(@"邀请你语音通话"); [self playRecordWithName:@"phone_ringing" type:@"mp3" playCount:-1]; return; } //2、接收者接听通话(B给A发) if (chatType == AudioChatType_receive) { self.receiveBottomView.hidden = YES; self.chatBotoomView.hidden = NO; self.tipLabel.hidden = YES; self.closeLabel.text = ASLocalizedString(@"挂断"); //开始计时,执行计费逻辑 self.timesCount = 0; [self updateTimesLabelText]; self.timesLabel.hidden = NO; return; } // /** 3、挂断通话,发起者主动挂断,A给B发 */ if (chatType == AudioChatType_zhudongClose) { [self playRecordWithName:@"close" type:@"wav" playCount:0]; [AudioChatViewController destoryShareRootVC]; return; } /** 4、挂断电话,接收者挂断,B给A发 */ if (chatType == AudioChatType_beidongClose) { //接收者挂断电话,直接结束通话 [self playRecordWithName:@"close" type:@"wav" playCount:0]; [AudioChatViewController destoryShareRootVC]; return; } /** 5、挂断电话,接收者忙线中,语音中或者在直播间中,B给A发 */ if (chatType == AudioChatType_isBusy) { [self playRecordWithName:@"close" type:@"wav" playCount:0]; [[BGHUDHelper sharedInstance] tipMessage:ASLocalizedString(@"对方忙")]; //刚开始就挂断,太快了,给SDK一点反应时间,晚点再销毁,不然trtc销毁不掉 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [AudioChatViewController destoryShareRootVC]; }); return; } /** 6、主动询问A是否在房间等着B通话,B给A发 */ if (chatType == AudioChatType_askIsNormal) { if (self.isZhuDongCall == NO) { return; } //告诉A自己正常,正常进行通话 WeakSelf SIMMsgObj *obj = [self.mChatFriend sendCustomCallAudioTextMsg:@"发起者挂断语音通话" callAudioType:AudioChatType_notificationChatNormal isCall:self.isZhuDongCall block:^(SResBase *resb, SIMMsgObj *newObj) { if (!resb.msuccess) { [SVProgressHUD showErrorWithStatus:resb.mmsg]; } }]; return; } } - (void)updateTimesLabelText { if (AppDelegate.sharedAppDelegate.isInAudioVideoChatVc == NO) { return; } self.timesCount ++; int hour = self.timesCount/60/60; NSString * hoursStr = @"00"; if (hour > 9) { hoursStr = [NSString stringWithFormat:@"%d",hour]; } else { hoursStr = [NSString stringWithFormat:@"0%d",hour]; } int min = self.timesCount/60%60; if (self.isZhuDongCall && min > self.lastMin) { [self requestPay]; } self.lastMin = min; NSString * minStr = @"00"; if (min > 9) { minStr = [NSString stringWithFormat:@"%d",min]; } else { minStr = [NSString stringWithFormat:@"0%d",min]; } int seconds = self.timesCount%60; NSString * secondsStr = @"00"; if (seconds > 9) { secondsStr = [NSString stringWithFormat:@"%d",seconds]; } else { secondsStr = [NSString stringWithFormat:@"0%d",seconds]; } if (hour > 0) { self.timesLabel.text = [NSString stringWithFormat:@"%@:%@:%@",hoursStr,minStr,secondsStr]; } else { self.timesLabel.text = [NSString stringWithFormat:@"%@:%@",minStr,secondsStr]; } //小屏的话更新时间 if (AppDelegate.sharedAppDelegate.hasSmallAudioVideoView) { [TMSmallRoomView sharedInstance].timeLabel.text = self.timesLabel.text; } dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self updateTimesLabelText]; }); } #pragma mark - 私聊付费,发起者调用 语音跟视频聊天为1分钟调用一次调用成功继续进行聊天,返回失败则直接断开,发起者进行调用 - (void)requestPay { NSMutableDictionary *parmDict = [[NSMutableDictionary alloc] init]; [parmDict setObject:@"user" forKey:@"ctl"]; [parmDict setObject:@"chat_charging" forKey:@"act"]; [parmDict setObject:[NSString stringWithFormat:@"%d",self.mChatFriend.mUser_id] forKey:@"other_user_id"]; [parmDict setObject:@"voice_price" forKey:@"expend_type"]; [parmDict setObject:@"1" forKey:@"i_type"]; [parmDict setObject:[BogoNetwork shareInstance].token forKey:@"token"]; WeakSelf [[NetHttpsManager manager]POSTWithParameters:parmDict SuccessBlock:^(NSDictionary *responseJson) { if ([[responseJson valueForKeyPath:@"status"]integerValue] == 1) { NSLog(@" = = = = = = = =%@",responseJson); } else if ([[responseJson valueForKeyPath:@"status"]integerValue] == 0) { //没钱或者权限不足,挂断 [weakSelf closeButtonClick]; } } FailureBlock:^(NSError *error) { NSLog(@" = = = = = = = == %@",error); }]; } #pragma mark - ******************* 腾讯TRTC 代理方法 ******************* - (void)joinChannel:(NSString *)room_id { self.trtcCloud = [TRTCCloud sharedInstance]; [[TRTCCloud sharedInstance] addDelegate: self]; // 主播: TRTCRoleAnchor // 观众: TRTCRoleAudience [self.trtcCloud switchRole:TRTCRoleAnchor]; TRTCParams *params = [[TRTCParams alloc] init]; // 以字符串房间号为例 params.roomId = room_id.intValue; params.userId = [IMAPlatform sharedInstance].host.userId; // 从业务后台获取到的 UserSig params.userSig = [IMALoginParam loadFromLocal].userSig; // 替换成您的 SDKAppID params.sdkAppId = TXSDKAppID; // 根据需要指定场景,以语聊房为例 [self.trtcCloud enterRoom:params appScene:TRTCAppSceneAudioCall]; // TRTCAudioVolumeEvaluateParams * audioVolumeEvaluateParams = [[TRTCAudioVolumeEvaluateParams alloc] init]; // //【推荐取值】推荐值:300,单位为毫秒。 // audioVolumeEvaluateParams.interval = 300; // /// 【字段含义】是否开启本地人声检测。 // /// 【请您注意】在 startLocalAudio 之前调用才可以生效。 // audioVolumeEvaluateParams.enableVadDetection = YES; // /// 【字段含义】是否开启本地人声频率计算 // audioVolumeEvaluateParams.enablePitchCalculation = YES; // /// 【字段含义】是否开启声音频谱计算。 // audioVolumeEvaluateParams.enableSpectrumCalculation = YES; // [self.trtcCloud enableAudioVolumeEvaluation:YES withParams:audioVolumeEvaluateParams]; [self.trtcCloud startLocalAudio:TRTCAudioQualitySpeech]; } #pragma mark - 静音,默认开启 - (void)setIsMute:(BOOL)isMute { if (isMute) { [self.trtcCloud muteLocalAudio:YES]; return; } [self.trtcCloud muteLocalAudio:NO]; } #pragma mark - 开启扬声器,默认关闭 - (void)openYangshengqi:(BOOL)open { if (open) { ///使用扬声器播放(即“免提”),扬声器位于手机底部,声音偏大,适合外放音乐。 [self.trtcCloud setAudioRoute:TRTCAudioModeSpeakerphone]; return; } ///使用听筒播放,听筒位于手机顶部,声音偏小,适合需要保护隐私的通话场景。 [self.trtcCloud setAudioRoute:TRTCAudioModeEarpiece]; } // 离开房间事件回调 - (void)onExitRoom:(NSInteger)reason { if (reason == 0) { NSLog(@"主动调用 exitRoom 退出房间"); } else if (reason == 1) { NSLog(@"被服务器踢出当前房间"); } else if (reason == 2) { NSLog(@"当前房间整个被解散"); } } - (void) onEnterRoom:(NSInteger ) result { NSLog(@"onEnterRoom"); if(result > 0) { //接受者进房间后,主动问一下呼叫者是否是正常状态 if (self.isZhuDongCall == NO) { WeakSelf self.isNormalChatBlock = ^(BOOL isNormal) { if (isNormal == NO) { [weakSelf closeButtonClick]; } }; [self askChatIsNormal]; } } else { // [BGHUDHelper alert:[NSString stringWithFormat:@"进入直播间直播-%ld",result]]; } } - (void)askChatIsNormal { WeakSelf SIMMsgObj *obj = [self.mChatFriend sendCustomCallAudioTextMsg:@"接听者,忙线中" callAudioType:AudioChatType_askIsNormal isCall:self.isZhuDongCall block:^(SResBase *resb, SIMMsgObj *newObj) { if (!resb.msuccess) { [SVProgressHUD showErrorWithStatus:resb.mmsg]; } else { //1秒后,如果呼叫者没有回复说自己正常,那就退出房间 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if (weakSelf.callIsNormal && weakSelf.isNormalChatBlock) { weakSelf.isNormalChatBlock(weakSelf.callIsNormal); } else { [weakSelf judjeAskChatIsNormalBackCount:0]; } }); } }]; } - (void)judjeAskChatIsNormalBackCount:(int)count { count ++; if (count > 10) { if (self.isNormalChatBlock) { self.isNormalChatBlock(self.callIsNormal); } return; } if (self.callIsNormal) { if (self.isNormalChatBlock) { self.isNormalChatBlock(self.callIsNormal); } return; } dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self judjeAskChatIsNormalBackCount:count]; }); } - (void)onRemoteUserLeaveRoom:(NSString *)userId reason:(NSInteger)reason { //有人异常退出,可能不是正常退出的,自己也退出,不聊了 //,直接挂断销毁视图 [AudioChatViewController destoryShareRootVC]; NSLog(@"%@", [NSString stringWithFormat:@"用户离开%@",userId]); } //功能描述:音量大小的反馈回调 - (void)onUserVoiceVolume:(NSArray *)userVolumes totalVolume:(NSInteger)totalVolume { /*bug:当a用户在麦上正在说话时,切换到无网状态,此时虽然还显示在麦上(im还没下线), 但观众席听不到声音,光圈还在闪烁 原因: 这时观众席speakers 里面找不到a,就不会进入for循环,就不会更新a的声音为0 解决: 1先找到 麦上的用户 2去判断有无声音 */ // NSMutableArray *wheat_type_list = [NSMutableArray arrayWithArray:self.voiceRoomVC.roomModel.wheat_type_list]; // // for (int i = 0; i < wheat_type_list.count; i ++) { // // Wheat_Type_List *info = wheat_type_list[i]; // // if (info.even_wheat.user_id) { // // BOOL online = NO; // //// for (AgoraRtcAudioVolumeInfo *speaker in speakers) { // for (TRTCVolumeInfo * volumeInfo in userVolumes) { // // NSString *uid = @""; // if (volumeInfo.userId.intValue == 0) { // uid = [IMAPlatform sharedInstance].host.userId; // online = YES; // }else if (info.even_wheat.user_id == volumeInfo.userId.intValue){ // uid = [NSString stringWithFormat:@"%@",volumeInfo.userId]; // online = YES; // } // if (online) { // info.totalVolume = volumeInfo.volume; // // [self.users updateUser:uid volume:speaker.volume]; // } // } // // wheat_type_list[i] = info; // // // if (!online) { // // [self.users updateUser:info.user_id volume:0]; // // } // } // } // self.voiceRoomVC.roomModel.wheat_type_list = wheat_type_list; // [self.voiceRoomVC setRoomModel:self.voiceRoomVC.roomModel]; // [self.uiController.micView setUsers:self.users]; } #pragma mark - ******************* 腾讯TRTC 代理方法 end ******************* #pragma mark 解决不能调为最小音量问题 - (void)volumeChanged:(NSNotification *)noti { NSDictionary *tmpDict = noti.userInfo; if (tmpDict && [tmpDict isKindOfClass:[NSDictionary class]]) { // if ([[tmpDict toString:@"AVSystemController_AudioVolumeChangeReasonNotificationParameter"] isEqualToString:@"ExplicitVolumeChange"] && !_isMuted) if ([[tmpDict toString:@"AVSystemController_AudioVolumeChangeReasonNotificationParameter"] isEqualToString:@"ExplicitVolumeChange"]) { float volume = [[tmpDict objectForKey:@"AVSystemController_AudioVolumeNotificationParameter"] floatValue]; if (volume <= 0.062500) { // [_publishController.txLivePublisher setMute:YES]; } else { // [_publishController.txLivePublisher setMute:NO]; } } } } #pragma mark - ************** 播放声音 ************ /**播放录音*/ -(void)playRecordWithName:(NSString *)musicName type:(NSString *)musicType playCount:(int)count { NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:musicName ofType:musicType]; NSURL *audioFileURL = [NSURL fileURLWithPath:audioFilePath]; AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *sessionError; //AVAudioSessionCategoryPlayAndRecord,这个确保了既能录音也能播放 [session setCategory:AVAudioSessionCategoryPlayback error:&sessionError]; if (session == nil) { NSLog(@"Error creating sessing:%@", [sessionError description]); } else { [session setActive:YES error:nil]; } NSError *playError; self.player = [[AVAudioPlayer alloc]initWithContentsOfURL:audioFileURL error:&playError]; self.player.numberOfLoops = count; // self.player.volume = 20; //当播放录音为空, 打印错误信息 if (self.player == nil) { NSLog(@"Error crenting player: %@", [playError description]); } self.player.delegate = self; if ([self.player isPlaying]) { [self.player pause]; } else { [self.player play]; } } - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { // self.player = nil; NSLog(@"播放完成"); // [self playRecord]; } @end