66// Copyright © 2020 agora. All rights reserved.
77//
88
9- #ifdef MEDIAPLAYER
109#import " AgoraRtcChannelPublishHelper.h"
1110#import < AgoraRtcKit/IAgoraRtcEngine.h>
1211#import < AgoraRtcKit/IAgoraMediaEngine.h>
13- #import " AudioFrameObserver.h"
12+ #import " AudioCircularBuffer.h"
13+ #import " scoped_ptr.h"
1414#import < mutex>
1515using namespace AgoraRTC ;
16+ static NSObject *threadLockPush = [[NSObject alloc ] init ];
17+ static NSObject *threadLockPlay = [[NSObject alloc ] init ];
1618
19+ class AgoraAudioFrameObserver :public agora ::media::IAudioFrameObserver
20+ {
21+ private:
22+ int16_t * record_buf_tmp_ = nullptr ;
23+ char * record_audio_mix_ = nullptr ;
24+ int16_t * record_send_buf_ = nullptr ;
25+
26+ int16_t * play_buf_tmp_ = nullptr ;
27+ char * play_audio_mix_ = nullptr ;
28+ int16_t * play_send_buf_ = nullptr ;
29+ scoped_ptr<AudioCircularBuffer<char >> record_audio_buf_;
30+ scoped_ptr<AudioCircularBuffer<char >> play_audio_buf_;
31+ public:
32+ std::atomic<float > publishSignalValue_{1 .0f };
33+ std::atomic<float > playOutSignalValue_{1 .0f };
34+ std::atomic<bool > isOnlyAudioPlay_{false };
35+ AgoraAudioFrameObserver (){
36+ record_audio_buf_.reset (new AudioCircularBuffer<char >(true ,2048 ));
37+ play_audio_buf_.reset (new AudioCircularBuffer<char >(true ,2048 ));
38+ }
39+ ~AgoraAudioFrameObserver ()
40+ {
41+ if (record_buf_tmp_) {
42+ free (record_buf_tmp_);
43+ }
44+ if (record_audio_mix_){
45+ free (record_audio_mix_);
46+ }
47+ if (record_send_buf_){
48+ free (record_send_buf_);
49+ }
50+
51+ if (play_buf_tmp_) {
52+ free (play_buf_tmp_);
53+ }
54+ if (play_audio_mix_){
55+ free (play_audio_mix_);
56+ }
57+ if (play_send_buf_) {
58+ free (play_send_buf_);
59+ }
60+ }
61+ void resetAudioBuffer (){
62+
63+ record_audio_buf_.reset (new AudioCircularBuffer<char >(2048 ,true ));
64+ play_audio_buf_.reset (new AudioCircularBuffer<char >(2048 ,true ));
65+ }
66+ void setPublishSignalVolume (int volume){
67+ @synchronized (threadLockPush) {
68+ publishSignalValue_ = volume/100 .0f ;
69+ }
70+ }
71+ void enableOnlyAudioPlay (bool isEnable){
72+ isOnlyAudioPlay_ = isEnable;
73+ }
74+ void setPlayoutSignalVolume (int volume){
75+ @synchronized (threadLockPlay) {
76+ playOutSignalValue_ = volume/100 .0f ;
77+ }
78+ }
79+ void pushData (char *data,int length){
80+ {
81+ if (!isOnlyAudioPlay_) {
82+ record_audio_buf_->Push (data, length);
83+ }
84+ }
85+ {
86+ play_audio_buf_->Push (data, length);
87+ }
88+
89+ }
90+ virtual bool onRecordAudioFrame (AudioFrame& audioFrame){
91+ @synchronized (threadLockPush) {
92+ int bytes = audioFrame.samples * audioFrame.channels * audioFrame.bytesPerSample ;
93+ int ret = record_audio_buf_->mAvailSamples - bytes;
94+ if ( ret < 0 ) {
95+ return false ;
96+ }
97+ // 计算重采样钱的数据大小 重采样的采样率 * SDK回调时间 * 声道数 * 字节数
98+ if (!record_buf_tmp_) {
99+ record_buf_tmp_ = (int16_t *)malloc (bytes);
100+ }
101+ if (!record_audio_mix_){
102+ record_audio_mix_ = (char *)malloc (bytes);
103+ }
104+ if (!record_send_buf_){
105+ record_send_buf_ = (int16_t *)malloc (bytes);
106+ }
107+ record_audio_buf_->Pop (record_audio_mix_, bytes);
108+ int16_t * p16 = (int16_t *) record_audio_mix_;
109+ memcpy (record_buf_tmp_, audioFrame.buffer , bytes);
110+ for (int i = 0 ; i < bytes / 2 ; ++i) {
111+ record_buf_tmp_[i] += (p16[i] * publishSignalValue_);
112+ // audio overflow
113+ if (record_buf_tmp_[i] > 32767 ) {
114+ record_send_buf_[i] = 32767 ;
115+ }
116+ else if (record_buf_tmp_[i] < -32768 ) {
117+ record_send_buf_[i] = -32768 ;
118+ }
119+ else {
120+ record_send_buf_[i] = record_buf_tmp_[i];
121+ }
122+ }
123+ memcpy (audioFrame.buffer , record_send_buf_,bytes);
124+ }
125+ return true ;
126+ }
127+ /* *
128+ * Occurs when the playback audio frame is received.
129+ * @param audioframe The reference to the audio frame: AudioFrame.
130+ * @return
131+ * - true: The playback audio frame is valid and is encoded and sent.
132+ * - false: The playback audio frame is invalid and is not encoded or sent.
133+ */
134+ virtual bool onPlaybackAudioFrame (AudioFrame& audioFrame){
135+ @synchronized (threadLockPlay) {
136+
137+ int bytes = audioFrame.samples * audioFrame.channels * audioFrame.bytesPerSample ;
138+ int ret = play_audio_buf_->mAvailSamples - bytes;
139+ if (ret < 0 ) {
140+ return false ;
141+ }
142+ // 计算重采样钱的数据大小 重采样的采样率 * SDK回调时间 * 声道数 * 字节数
143+ if (!play_buf_tmp_){
144+ play_buf_tmp_ = (int16_t *)malloc (bytes);
145+ }
146+ if (!play_audio_mix_){
147+ play_audio_mix_ = (char *)malloc (bytes);
148+ }
149+ if (!play_send_buf_){
150+ play_send_buf_ = (int16_t *)malloc (bytes);
151+ }
152+ play_audio_buf_->Pop (play_audio_mix_, bytes);
153+ int16_t * p16 = (int16_t *) play_audio_mix_;
154+ memcpy (play_buf_tmp_, audioFrame.buffer , bytes);
155+ for (int i = 0 ; i < bytes / 2 ; ++i) {
156+ play_buf_tmp_[i] += (p16[i] * playOutSignalValue_);
157+ // audio overflow
158+ if (play_buf_tmp_[i] > 32767 ) {
159+ play_send_buf_[i] = 32767 ;
160+ }
161+ else if (play_buf_tmp_[i] < -32768 ) {
162+ play_send_buf_[i] = -32768 ;
163+ }
164+ else {
165+ play_send_buf_[i] = play_buf_tmp_[i];
166+ }
167+ }
168+ memcpy (audioFrame.buffer , play_buf_tmp_,bytes);
169+ }
170+ return true ;
171+ }
172+ /* *
173+ * Occurs when the mixed audio data is received.
174+ * @param audioframe The reference to the audio frame: AudioFrame.
175+ * @return
176+ * - true: The mixed audio data is valid and is encoded and sent.
177+ * - false: The mixed audio data is invalid and is not encoded or sent.
178+ */
179+ virtual bool onMixedAudioFrame (AudioFrame& audioFrame){
180+ return false ;
181+ }
182+ /* *
183+ * Occurs when the playback audio frame before mixing is received.
184+ * @param audioframe The reference to the audio frame: AudioFrame.
185+ * @return
186+ * - true: The playback audio frame before mixing is valid and is encoded and sent.
187+ * - false: The playback audio frame before mixing is invalid and is not encoded or sent.
188+ */
189+ virtual bool onPlaybackAudioFrameBeforeMixing (unsigned int uid, AudioFrame& audioFrame){
190+ return false ;
191+ }
192+ };
17193@interface AgoraRtcChannelPublishHelper ()<AgoraMediaPlayerDelegate,AgoraVideoSourceProtocol>
18194{
19195 std::unique_ptr<AgoraAudioFrameObserver> audioFrameObserver;
@@ -39,7 +215,7 @@ + (instancetype)shareInstance{
39215}
40216// 连接 MediaPlayer 到主版本 RTC SDK
41217- (void )attachPlayerToRtc : (AgoraMediaPlayer *)playerKit RtcEngine : (AgoraRtcEngineKit *)rtcEngine enableVideoSource : (bool )enable {
42- audioFrameObserver. reset ( new AgoraAudioFrameObserver);
218+ audioFrameObserver = std::make_unique< AgoraAudioFrameObserver>( );
43219 isPublishVideo = false ;
44220 audioFrameObserver->setPublishSignalVolume (0 );
45221 self.isDispatchMainQueue = false ;
@@ -48,7 +224,7 @@ - (void)attachPlayerToRtc:(AgoraMediaPlayer *)playerKit RtcEngine:(AgoraRtcEngin
48224 [rtcEngine setVideoSource: self ];
49225 }
50226 [rtcEngine setParameters: @" {\" che.audio.keep.audiosession\" :true}" ];
51- [rtcEngine setAudioProfile: AgoraAudioProfileMusicStandardStereo scenario: AgoraAudioScenarioGameStreaming ];
227+ [rtcEngine setAudioProfile: AgoraAudioProfileMusicStandardStereo scenario: AgoraAudioScenarioChatRoomEntertainment ];
52228 [rtcEngine setRecordingAudioFrameParametersWithSampleRate: 48000 channel: 2 mode: AgoraAudioRawFrameOperationModeReadWrite samplesPerCall: 960 ];
53229 [rtcEngine setPlaybackAudioFrameParametersWithSampleRate: 48000 channel: 2 mode: AgoraAudioRawFrameOperationModeReadWrite samplesPerCall: 960 ];
54230
@@ -70,6 +246,13 @@ - (void)unpublishAudio{
70246 }
71247
72248}
249+ - (void )enableOnlyLocalAudioPlay : (bool )isEnable
250+
251+ {
252+ @synchronized (self) {
253+ audioFrameObserver->enableOnlyAudioPlay (isEnable);
254+ }
255+ }
73256// 启动/停止推送视频流到频道
74257- (void )publishVideo {
75258 @synchronized (self) {
@@ -99,15 +282,15 @@ - (void)detachPlayerFromRtc{
99282 @synchronized (self) {
100283 isPublishVideo=false ;
101284 audioFrameObserver->setPublishSignalVolume (0 );
102- _playerKit.delegate = NULL ;
103- [_rtcEngineKit setVideoSource: NULL ];
104285 [self unregisterRtcEngine: _rtcEngineKit];
105-
286+ [_rtcEngineKit setVideoSource: NULL ];
287+ _playerKit.delegate = NULL ;
288+
106289 }
107290}
108291- (void )resetAudioBuf {
109292 @synchronized (self) {
110- audioFrameObserver->resetAudioBuf ();
293+ audioFrameObserver->resetAudioBuffer ();
111294 }
112295}
113296- (void )AgoraMediaPlayer : (AgoraMediaPlayer *_Nonnull)playerKit
@@ -178,19 +361,10 @@ - (void)shouldStop {
178361
179362}
180363
181- - (AgoraVideoCaptureType)captureType {
182- return AgoraVideoCaptureTypeUnknown;
183- }
184-
185-
186- - (AgoraVideoContentHint)contentHint {
187- return AgoraVideoContentHintDetails;
188- }
189-
190-
191364// / Description of state of Mediaplayer's state
192365// / @param playerKit AgoraMediaPlayer
193366// / @param state AgoraMediaPlayerState
367+ // / @param reason AgoraMediaPlayerStateReason
194368// / @param error AgoraMediaPlayerError
195369- (void )AgoraMediaPlayer : (AgoraMediaPlayer *_Nonnull)playerKit
196370 didChangedToState : (AgoraMediaPlayerState)state
@@ -272,4 +446,4 @@ - (void)executeBlock:(void (^)())block {
272446
273447@end
274448
275- # endif
449+
0 commit comments