1/* 2* Copyright (C) 2023-2024 Huawei Device Co., Ltd. 3* Licensed under the Apache License, Version 2.0 (the "License"); 4* you may not use this file except in compliance with the License. 5* You may obtain a copy of the License at 6* 7* http://www.apache.org/licenses/LICENSE-2.0 8* 9* Unless required by applicable law or agreed to in writing, software 10* distributed under the License is distributed on an "AS IS" BASIS, 11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12* See the License for the specific language governing permissions and 13* limitations under the License. 14*/ 15 16import Logger from '../../../ohosTest/ets/utils/Logger'; 17import common from '@ohos.app.ability.common'; 18import fs from '@ohos.file.fs'; 19import router from '@ohos.router'; 20import audio from '@ohos.multimedia.audio'; 21import { BusinessError } from '@ohos.base'; 22 23const CLOSE_MODE = 0; 24const OPEN_MODE = 1; 25const TRACKING_MODE = 2; 26 27@Entry 28@Component 29struct SpatialAudio { 30 private audioRenderers: audio.AudioRenderer[] = []; 31 private audioRendererOptions: audio.AudioRendererOptions[] = [ 32 { 33 streamInfo: { 34 samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, 35 channels: audio.AudioChannel.CHANNEL_2, 36 sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, 37 encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW, 38 channelLayout: audio.AudioChannelLayout.CH_LAYOUT_STEREO 39 }, 40 41 rendererInfo: { 42 usage: audio.StreamUsage.STREAM_USAGE_MUSIC, 43 rendererFlags: 0 44 } 45 }, 46 { 47 streamInfo: { 48 samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, 49 channels: audio.AudioChannel.CHANNEL_6, 50 sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, 51 encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW, 52 channelLayout: audio.AudioChannelLayout.CH_LAYOUT_5POINT1 53 }, 54 rendererInfo: { 55 usage: audio.StreamUsage.STREAM_USAGE_MOVIE, 56 rendererFlags: 0 57 } 58 } 59 ]; 60 61 private appContext?: common.Context; 62 private audioSources = ['/2p0.pcm', '/5p1.pcm']; 63 private audioSpatializationManager?: audio.AudioSpatializationManager; 64 private audioRoutingManager?: audio.AudioRoutingManager; 65 private curPos: number[] = [0, 0] 66 @State supportState: number = 1; 67 @State spatializationEnabled: boolean = false; 68 @State trackingEnabled: boolean = false; 69 @State musicState1: boolean = false; 70 @State musicState2: boolean = false; 71 @State spatialSceneMode: audio.AudioSpatializationSceneType = audio.AudioSpatializationSceneType.DEFAULT; 72 73 @Builder Press2PlayDemo1() { 74 Image($r("app.media.ic_pause_spa")) 75 .height(36) 76 .width(36) 77 .margin({ right: 16 }) 78 .id("2P0_play_btn") 79 .onClick(async () => { 80 this.musicState1 = !this.musicState1; 81 await this.playAudio(0); 82 }) 83 } 84 85 @Builder Press2PauseDemo1() { 86 Image($r("app.media.ic_play_spa")) 87 .height(36) 88 .width(36) 89 .margin({ right: 16 }) 90 .id("2P0_pause_btn") 91 .onClick(async () => { 92 this.musicState1 = !this.musicState1; 93 await this.pauseAudio(0); 94 }) 95 } 96 97 @Builder Press2PlayDemo2() { 98 Image($r("app.media.ic_pause_spa")) 99 .height(36) 100 .width(36) 101 .margin({ right: 16 }) 102 .id("5P1_play_btn") 103 .onClick(async () => { 104 this.musicState2 = !this.musicState2; 105 await this.playAudio(1); 106 }) 107 } 108 109 @Builder Press2PauseDemo2() { 110 Image($r("app.media.ic_play_spa")) 111 .height(36) 112 .width(36) 113 .margin({ right: 16 }) 114 .id("5P1_pause_btn") 115 .onClick(async () => { 116 this.musicState2 = !this.musicState2; 117 await this.pauseAudio(1); 118 }) 119 120 } 121 122 @Builder CloseModeOn() { 123 Image($r("app.media.ic_audio_close_on")) 124 .height(48) 125 .width(48) 126 .margin({ left: 8 }) 127 .id("close_mode_on") 128 } 129 130 @Builder CloseModeOff() { 131 Image($r("app.media.ic_audio_close_normal")) 132 .height(48) 133 .width(48) 134 .margin({ left: 8 }) 135 .id("close_mode_off") 136 .onClick(async () => { 137 if (this.supportState !== CLOSE_MODE && this.audioSpatializationManager) { 138 try { 139 this.audioSpatializationManager.setSpatializationEnabled(false, () => { 140 }) 141 this.audioSpatializationManager.setHeadTrackingEnabled(false, () => { 142 }) 143 } catch (err) { 144 Logger.error(`Set Spatialization or Head Tracking disabled failed, ${JSON.stringify(err)}`); 145 return; 146 } 147 } 148 }) 149 } 150 151 @Builder OpenModeDisabled() { 152 Image($r("app.media.ic_audio_open_disable")) 153 .height(48) 154 .width(48) 155 } 156 157 @Builder OpenModeOn() { 158 Image($r("app.media.ic_audio_open_on")) 159 .height(48) 160 .width(48) 161 .id("open_mode_on") 162 } 163 164 @Builder OpenModeOff() { 165 Image($r("app.media.ic_audio_open_normal")) 166 .height(48) 167 .width(48) 168 .id("open_mode_off") 169 .onClick(async () => { 170 if (this.audioSpatializationManager) { 171 try { 172 this.audioSpatializationManager.setSpatializationEnabled(true, () => { 173 }) 174 this.audioSpatializationManager.setHeadTrackingEnabled(false, () => { 175 }) 176 } catch (err) { 177 Logger.error(`Set open mode failed, ${JSON.stringify(err)}`); 178 return; 179 } 180 } 181 182 }) 183 } 184 185 @Builder TrackingModeOn() { 186 Image($r("app.media.ic_audio_track_on")) 187 .height(48) 188 .width(48) 189 .margin({ right: 8 }) 190 .id("tracking_mode_on") 191 } 192 193 @Builder TrackingModeOff() { 194 Image($r("app.media.ic_audio_track_normal")) 195 .height(48) 196 .width(48) 197 .margin({ right: 8 }) 198 .id("tracking_mode_off") 199 .onClick(async () => { 200 if (this.audioSpatializationManager) { 201 try { 202 this.audioSpatializationManager.setSpatializationEnabled(true, () => { 203 }) 204 this.audioSpatializationManager.setHeadTrackingEnabled(true, () => { 205 }) 206 } catch (err) { 207 Logger.error(`Set HeadTracking enabled failed, ${JSON.stringify(err)}`); 208 return; 209 } 210 } 211 }) 212 } 213 214 @Builder TrackingModeDisabled() { 215 Image($r("app.media.ic_audio_track_disable")) 216 .height(48) 217 .width(48) 218 .margin({ right: 8 }) 219 .fillColor("#182431") 220 } 221 222 @Builder UIForClose() { 223 this.CloseModeOn(); 224 this.OpenModeDisabled(); 225 this.TrackingModeDisabled(); 226 } 227 228 @Builder UIForOpen() { 229 if (this.spatializationEnabled === true) { 230 this.CloseModeOff(); 231 this.OpenModeOn(); 232 } else { 233 this.CloseModeOn(); 234 this.OpenModeOff(); 235 } 236 this.TrackingModeDisabled(); 237 } 238 239 @Builder UIForTracking() { 240 if (this.spatializationEnabled === true && this.trackingEnabled === true) { 241 this.CloseModeOff(); 242 this.OpenModeOff(); 243 this.TrackingModeOn(); 244 } else if (this.spatializationEnabled === true && this.trackingEnabled === false) { 245 this.CloseModeOff(); 246 this.OpenModeOn(); 247 this.TrackingModeOff(); 248 } else { 249 this.CloseModeOn(); 250 this.OpenModeOff(); 251 this.TrackingModeOff(); 252 } 253 } 254 255 @Builder OpenTextEnable() { 256 Text($r("app.string.OPEN_TEXT")) 257 .height("100%") 258 .width(64) 259 .fontSize(12) 260 .fontWeight(500) 261 .margin({ right: 68 }) 262 .fontColor("#182431") 263 .textAlign(TextAlign.Center) 264 } 265 266 @Builder OpenTextDisable() { 267 Text($r("app.string.OPEN_TEXT")) 268 .height("100%") 269 .width(64) 270 .fontSize(12) 271 .fontWeight(500) 272 .margin({ right: 68 }) 273 .fontColor(Color.Grey) 274 .textAlign(TextAlign.Center) 275 .id("open_mode_disabled") 276 } 277 278 @Builder TrackingTextEnable() { 279 Text($r("app.string.TRACKING_TEXT")) 280 .height(16) 281 .width(48) 282 .fontSize(12) 283 .fontWeight(500) 284 .fontColor("#182431") 285 .textAlign(TextAlign.Center) 286 } 287 288 @Builder TrackingTextDisable() { 289 Text($r("app.string.TRACKING_TEXT")) 290 .height(16) 291 .width(48) 292 .fontSize(12) 293 .fontWeight(500) 294 .fontColor(Color.Grey) 295 .textAlign(TextAlign.Center) 296 .id("tracking_mode_disabled") 297 } 298 299 @Builder DIYTitle() { 300 Row() { 301 Text($r('app.string.SPATIAL_AUDIO')) 302 .fontWeight(700) 303 .fontSize(20) 304 } 305 .height("100%") 306 .justifyContent(FlexAlign.Center) 307 } 308 309 @Builder ChooseSpatialSceneMode() { 310 Row() { 311 Row() { 312 Text($r('app.string.SPATIAL_SCENE_MODE')) 313 .fontSize(14) 314 .fontFamily($r('sys.string.ohos_id_text_font_family_medium')) 315 .fontColor('#000000') 316 .opacity(0.6) 317 .fontWeight(500) 318 } 319 .height(20) 320 .width(176) 321 .margin({ top: 28, left: 28 }) 322 .justifyContent(FlexAlign.Start) 323 } 324 .width(360) 325 .height(56) 326 .justifyContent(FlexAlign.Start) 327 328 Column() { 329 Row() { 330 Image($r('app.media.ic_space_normal')) 331 .height(24) 332 .width(24) 333 Row() { 334 Text($r('app.string.SCENE_MODE_DEFAULT')) 335 .fontSize(16) 336 .fontFamily($r('sys.string.ohos_id_text_font_family_medium')) 337 .fontColor('#000000') 338 .opacity(0.9) 339 .fontWeight(500) 340 Checkbox() 341 .shape((CheckBoxShape.CIRCLE)) 342 .select(this.spatialSceneMode === audio.AudioSpatializationSceneType.DEFAULT) 343 .margin({ right: 2 }) 344 .height(20) 345 .width(20) 346 .onChange((value: boolean) => { 347 if (value === true) { 348 this.spatialSceneMode = audio.AudioSpatializationSceneType.DEFAULT; 349 if (this.audioSpatializationManager) { 350 try { 351 this.audioSpatializationManager.setSpatializationSceneType(this.spatialSceneMode); 352 } catch (err) { 353 Logger.error(`setSpatializationSceneType failed ,Error: ${JSON.stringify(err)}`); 354 return; 355 } 356 } 357 358 } 359 }) 360 } 361 .width(264) 362 .height(22) 363 .margin({ left: 16 }) 364 .justifyContent(FlexAlign.SpaceBetween) 365 } 366 .justifyContent(FlexAlign.SpaceBetween) 367 .width(304) 368 .height(55.5) 369 370 Row() { 371 Column() { 372 } 373 .width(264) 374 .height(0.5) 375 .opacity(0.05) 376 .backgroundColor('#000000') 377 } 378 .justifyContent(FlexAlign.End) 379 .width(304) 380 .height(0.5) 381 382 Row() { 383 Image($r('app.media.ic_space_theatre')) 384 .height(24) 385 .width(24) 386 Row() { 387 Text($r('app.string.SCENE_MODE_AUDIOBOOK')) 388 .fontSize(16) 389 .fontFamily($r('sys.string.ohos_id_text_font_family_medium')) 390 .fontColor('#000000') 391 .opacity(0.9) 392 .fontWeight(500) 393 Checkbox() 394 .shape((CheckBoxShape.CIRCLE)) 395 .margin({ right: 2 }) 396 .height(20) 397 .width(20) 398 .select(this.spatialSceneMode === audio.AudioSpatializationSceneType.AUDIOBOOK) 399 .onChange((value: boolean) => { 400 if (value === true) { 401 this.spatialSceneMode = audio.AudioSpatializationSceneType.AUDIOBOOK; 402 if (this.audioSpatializationManager) { 403 try { 404 this.audioSpatializationManager.setSpatializationSceneType(this.spatialSceneMode); 405 } catch (err) { 406 Logger.error(`setSpatializationSceneType failed ,Error: ${JSON.stringify(err)}`); 407 return; 408 } 409 } 410 } 411 }) 412 } 413 .width(264) 414 .height(22) 415 .margin({ left: 16 }) 416 .justifyContent(FlexAlign.SpaceBetween) 417 } 418 .justifyContent(FlexAlign.SpaceBetween) 419 .width(304) 420 .height(55.5) 421 422 Row() { 423 Column() { 424 } 425 .width(264) 426 .height(0.5) 427 .opacity(0.05) 428 .backgroundColor('#000000') 429 } 430 .justifyContent(FlexAlign.End) 431 .width(304) 432 .height(0.5) 433 434 Row() { 435 Image($r('app.media.ic_space_movie')) 436 .height(24) 437 .width(24) 438 Row() { 439 Text($r('app.string.SCENE_MODE_MOVIE')) 440 .fontSize(16) 441 .fontFamily($r('sys.string.ohos_id_text_font_family_medium')) 442 .fontColor('#000000') 443 .opacity(0.9) 444 .fontWeight(500) 445 Checkbox() 446 .shape((CheckBoxShape.CIRCLE)) 447 .margin({ right: 2 }) 448 .height(20) 449 .width(20) 450 .select(this.spatialSceneMode === audio.AudioSpatializationSceneType.MOVIE) 451 .onChange((value: boolean) => { 452 if (value === true) { 453 this.spatialSceneMode = audio.AudioSpatializationSceneType.MOVIE; 454 if (this.audioSpatializationManager) { 455 try { 456 this.audioSpatializationManager.setSpatializationSceneType(this.spatialSceneMode); 457 } catch (err) { 458 Logger.error(`setSpatializationSceneType failed ,Error: ${JSON.stringify(err)}`); 459 return; 460 } 461 } 462 } 463 }) 464 } 465 .width(264) 466 .height(22) 467 .margin({ left: 16 }) 468 .justifyContent(FlexAlign.SpaceBetween) 469 } 470 .justifyContent(FlexAlign.SpaceBetween) 471 .width(304) 472 .height(55.5) 473 474 Row() { 475 Column() { 476 } 477 .width(264) 478 .height(0.5) 479 .opacity(0.05) 480 .backgroundColor('#000000') 481 } 482 .justifyContent(FlexAlign.End) 483 .width(304) 484 .height(0.5) 485 486 Row() { 487 Image($r('app.media.ic_space_music')) 488 .height(24) 489 .width(24) 490 Row() { 491 Text($r('app.string.SCENE_MODE_MUSIC')) 492 .fontSize(16) 493 .fontFamily($r('sys.string.ohos_id_text_font_family_medium')) 494 .fontColor('#000000') 495 .opacity(0.9) 496 .fontWeight(500) 497 Checkbox() 498 .shape((CheckBoxShape.CIRCLE)) 499 .margin({ right: 2 }) 500 .height(20) 501 .width(20) 502 .select(this.spatialSceneMode === audio.AudioSpatializationSceneType.MUSIC) 503 .onChange((value: boolean) => { 504 if (value === true) { 505 this.spatialSceneMode = audio.AudioSpatializationSceneType.MUSIC; 506 if (this.audioSpatializationManager) { 507 try { 508 this.audioSpatializationManager.setSpatializationSceneType(this.spatialSceneMode); 509 } catch (err) { 510 Logger.error(`setSpatializationSceneType failed ,Error: ${JSON.stringify(err)}`); 511 return; 512 } 513 } 514 } 515 }) 516 } 517 .width(264) 518 .height(22) 519 .margin({ left: 16 }) 520 .justifyContent(FlexAlign.SpaceBetween) 521 } 522 .justifyContent(FlexAlign.SpaceBetween) 523 .width(304) 524 .height(56) 525 } 526 .backgroundColor('#FFFFFF') 527 .borderRadius(24) 528 .height(232) 529 .width(328) 530 .justifyContent(FlexAlign.Center) 531 } 532 533 updateSupportStateUI(): void { 534 this.supportState = this.supportStateQuery(); 535 if (this.audioSpatializationManager) { 536 try { 537 this.spatializationEnabled = this.audioSpatializationManager.isSpatializationEnabled(); 538 this.trackingEnabled = this.audioSpatializationManager.isHeadTrackingEnabled(); 539 this.spatialSceneMode = this.audioSpatializationManager.getSpatializationSceneType(); 540 } catch (err) { 541 Logger.error(`update Support State UI failed ,Error: ${JSON.stringify(err)}`); 542 return; 543 } 544 } 545 } 546 547 supportStateQuery(): number { 548 if (this.audioRoutingManager) { 549 let audioDeviceDescriptors: audio.AudioDeviceDescriptors = 550 this.audioRoutingManager.getPreferredOutputDeviceForRendererInfoSync(this.audioRendererOptions[0].rendererInfo); 551 audioDeviceDescriptors.forEach(audioDeviceDescriptor => { 552 Logger.info("Device Role:" + audioDeviceDescriptor.deviceRole + ", device Type:" + 553 audioDeviceDescriptor.deviceType + ", Macaddress:" + audioDeviceDescriptor.address); 554 }) 555 556 let isSpaSupported: boolean = false; 557 let isSpaSupportedForDevice: boolean = false; 558 let isTraSupported: boolean = false; 559 let isTraSupportedForDevice: boolean = false; 560 if (this.audioSpatializationManager) { 561 try { 562 isSpaSupported = this.audioSpatializationManager.isSpatializationSupported(); 563 isSpaSupportedForDevice = 564 this.audioSpatializationManager.isSpatializationSupportedForDevice(audioDeviceDescriptors[0]); 565 isTraSupported = this.audioSpatializationManager.isHeadTrackingSupported(); 566 isTraSupportedForDevice = 567 this.audioSpatializationManager.isHeadTrackingSupportedForDevice(audioDeviceDescriptors[0]); 568 } catch (err) { 569 Logger.error(`supportStateQuery ,Error: ${JSON.stringify(err)}`); 570 } 571 } else { 572 Logger.info("Get manager failed."); 573 } 574 let isSpatializationSupportedBoth: boolean = isSpaSupported && isSpaSupportedForDevice; 575 let isHeadTrackingSupportedBoth: boolean = isTraSupported && isTraSupportedForDevice; 576 if (isSpatializationSupportedBoth && isHeadTrackingSupportedBoth) { 577 return TRACKING_MODE; 578 } else if (isSpatializationSupportedBoth) { 579 return OPEN_MODE; 580 } else { 581 return CLOSE_MODE; 582 } 583 } 584 return CLOSE_MODE; 585 } 586 587 async init(): Promise<void> { 588 if (this.appContext) { 589 return; 590 } 591 this.appContext = getContext(this); 592 593 for (let index = 0; index < 2; index++) { 594 try { 595 let renderer = await audio.createAudioRenderer(this.audioRendererOptions[index]); 596 Logger.info("Create renderer success"); 597 this.audioRenderers.push(renderer); 598 } catch (err) { 599 Logger.error(`audioRenderer_${index} create ,Error: ${JSON.stringify(err)}`); 600 return; 601 } 602 } 603 604 let audioManager = audio.getAudioManager(); 605 try { 606 this.audioSpatializationManager = audioManager.getSpatializationManager(); 607 } catch (err) { 608 Logger.error(`Get Spatialization Manager failed, Error: ${JSON.stringify(err)}`); 609 return; 610 } 611 612 this.audioRoutingManager = audioManager.getRoutingManager(); 613 this.updateSupportStateUI(); 614 let t_audioRendererInfo: audio.AudioRendererInfo = { 615 usage: audio.StreamUsage.STREAM_USAGE_MUSIC, 616 rendererFlags: 0 617 } 618 if (this.audioRoutingManager) { 619 this.audioRoutingManager.on("preferOutputDeviceChangeForRendererInfo", t_audioRendererInfo, () => { 620 Logger.info("Output device changed"); 621 this.updateSupportStateUI(); 622 }) 623 } 624 if (this.audioSpatializationManager) { 625 this.audioSpatializationManager.on("spatializationEnabledChange", (res) => { 626 this.spatializationEnabled = res; 627 }) 628 } 629 630 if (this.audioSpatializationManager) { 631 this.audioSpatializationManager.on("headTrackingEnabledChange", (res) => { 632 this.trackingEnabled = res; 633 }) 634 } 635 } 636 637 async over(): Promise<void> { 638 this.appContext = undefined; 639 try { 640 this.audioRenderers[0].stop(); 641 this.audioRenderers[0].release(); 642 this.audioRenderers[1].stop(); 643 this.audioRenderers[1].release(); 644 } catch (err) { 645 let error = err as BusinessError; 646 Logger.error(`AudioRenderer stop or release : Error: ${JSON.stringify(error)}`); 647 return; 648 } 649 this.audioRenderers = []; 650 651 if (this.audioRoutingManager) { 652 this.audioRoutingManager.off("deviceChange"); 653 } 654 655 if (this.audioSpatializationManager) { 656 this.audioSpatializationManager.off("spatializationEnabledChange"); 657 } 658 659 if (this.audioSpatializationManager) { 660 this.audioSpatializationManager.off("headTrackingEnabledChange"); 661 } 662 } 663 664 async playAudio(index: number): Promise<void> { 665 if (this.audioRenderers[index] === null) { 666 return; 667 } 668 669 670 let bufferSize: number = 0; 671 try { 672 bufferSize = await this.audioRenderers[index].getBufferSize(); 673 await this.audioRenderers[index].start(); 674 } catch (err) { 675 let error = err as BusinessError; 676 Logger.error(`AudioRenderer start : Error: ${JSON.stringify(error)}`); 677 return; 678 } 679 680 let buf = new ArrayBuffer(bufferSize); 681 let filePath: string = ""; 682 if (this.appContext) { 683 filePath = this.appContext.filesDir + this.audioSources[index]; 684 } 685 let stat = await fs.stat(filePath); 686 let len = stat.size % bufferSize == 0 ? Math.floor(stat.size / bufferSize) : Math.floor(stat.size / bufferSize + 1); 687 let file = await fs.open(filePath, 0o0); 688 let i: number = this.curPos[index] 689 690 while (true) { 691 if (!this.audioRenderers[index]) { 692 break; 693 } 694 Logger.info("start write"); 695 while (i < len) { 696 if (this.audioRenderers[index].state === audio.AudioState.STATE_RELEASED) { 697 return; 698 } 699 if (this.audioRenderers[index].state === audio.AudioState.STATE_PAUSED) { 700 this.curPos[index] = i; 701 return; 702 } 703 704 class options { 705 offset: number = 0 706 length: number = 0 707 } 708 709 let readOptions: options = { 710 offset: i * bufferSize, 711 length: bufferSize 712 } 713 await fs.read(file.fd, buf, readOptions); 714 await this.audioRenderers[index].write(buf); 715 i += 1; 716 } 717 i = 0; 718 } 719 720 } 721 722 async pauseAudio(index: number): Promise<void> { 723 try { 724 if (this.audioRenderers[index]) { 725 await this.audioRenderers[index].pause(); 726 } 727 } catch (err) { 728 Logger.error(`Pause Error: ${JSON.stringify(err)}`); 729 return; 730 } 731 } 732 733 async aboutToAppear(): Promise<void> { 734 await this.init(); 735 } 736 737 aboutToDisappear(): void { 738 this.over(); 739 } 740 741 onPageShow(): void { 742 if (this.audioSpatializationManager === undefined) { 743 return; 744 } 745 this.updateSupportStateUI() 746 Logger.info("Page show"); 747 } 748 749 onPageHide(): void { 750 Logger.info("Page Hide"); 751 if (this.audioRenderers[0] && this.audioRenderers[0].state === audio.AudioState.STATE_RUNNING) { 752 this.audioRenderers[0].pause(); 753 this.musicState1 = false; 754 } 755 if (this.audioRenderers[1] && this.audioRenderers[1].state === audio.AudioState.STATE_RUNNING) { 756 this.audioRenderers[1].pause(); 757 this.musicState2 = false; 758 } 759 } 760 761 build() { 762 Column() { 763 Column() { 764 Row() { 765 Navigation() { 766 } 767 .hideBackButton(false) 768 .titleMode(NavigationTitleMode.Mini) 769 .title(this.DIYTitle()) 770 .mode(NavigationMode.Stack) 771 } 772 .height(56) 773 .width(360) 774 .id('spatial_audio_back_btn') 775 .onClick(async () => { 776 await router.replaceUrl({ url: 'pages/Index' }); 777 }) 778 779 Row() { 780 Row() { 781 Text($r("app.string.2P0_MUSIC")) 782 .fontSize(20) 783 .fontWeight(500) 784 .fontFamily($r('sys.string.ohos_id_text_font_family_medium')) 785 .margin({ top: 21, bottom: 21, left: 16.5 }) 786 if (!this.musicState1) { 787 this.Press2PlayDemo1(); 788 } else { 789 this.Press2PauseDemo1(); 790 } 791 } 792 .height("100%") 793 .width(336) 794 .backgroundColor('#FFFFFF') 795 .justifyContent(FlexAlign.SpaceBetween) 796 .borderRadius(24) 797 } 798 .justifyContent(FlexAlign.SpaceAround) 799 .height(68) 800 .width('100%') 801 .margin({ top: 8 }) 802 803 Row() { 804 Row() { 805 Text($r("app.string.5P1_MUSIC")) 806 .fontSize(20) 807 .fontWeight(500) 808 .fontFamily($r('sys.string.ohos_id_text_font_family_medium')) 809 .margin({ top: 21, bottom: 21, left: 16.5 }) 810 811 if (!this.musicState2) { 812 this.Press2PlayDemo2(); 813 } else { 814 this.Press2PauseDemo2(); 815 } 816 } 817 .height("100%") 818 .width(336) 819 .backgroundColor('#FFFFFF') 820 .justifyContent(FlexAlign.SpaceBetween) 821 .borderRadius(24) 822 } 823 .justifyContent(FlexAlign.SpaceAround) 824 .height(68) 825 .width('100%') 826 .margin({ top: 12 }) 827 828 if (this.supportState > CLOSE_MODE && this.spatializationEnabled === true) { 829 this.ChooseSpatialSceneMode() 830 } 831 } 832 .width('100%') 833 .justifyContent(FlexAlign.Start) 834 835 836 Column() { 837 Row() { 838 if (this.supportState === 2) { 839 this.UIForTracking(); 840 } else if (this.supportState === 1) { 841 this.UIForOpen(); 842 } else { 843 this.UIForClose(); 844 } 845 } 846 .height(64) 847 .width(312) 848 .borderRadius(100) 849 .backgroundColor('#FFFFFF') 850 .justifyContent(FlexAlign.SpaceBetween) 851 852 Row() { 853 Text($r("app.string.CLOSE_TEXT")) 854 .height("100%") 855 .width(64) 856 .fontSize(12) 857 .fontWeight(500) 858 .margin({ right: 60 }) 859 .fontColor(Color.Black) 860 .textAlign(TextAlign.Center) 861 862 if (this.supportState === 0) { 863 this.OpenTextDisable(); 864 this.TrackingTextDisable(); 865 } else if (this.supportState === 1) { 866 this.OpenTextEnable(); 867 this.TrackingTextDisable(); 868 } else { 869 this.OpenTextEnable(); 870 this.TrackingTextEnable(); 871 } 872 } 873 .height(16) 874 .width(312) 875 .margin({ left: 24, right: 24, top: 8 }) 876 } 877 .height(112) 878 .width('100%') 879 } 880 .height('100%') 881 .width('100%') 882 .backgroundColor('#f1f3f5') 883 .justifyContent(FlexAlign.SpaceBetween) 884 } 885}