From 36d55b68b6dc926773c9fb97dc6076d22e900458 Mon Sep 17 00:00:00 2001 From: rex <1491721419@qq.com> Date: Fri, 28 Nov 2025 17:56:06 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=90=8C=E6=BA=90?= =?UTF-8?q?=E6=A0=87=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ets/components/ControlAreaComponent.ets | 15 ++++- .../main/ets/player/AVPlayerController.ets | 12 +++- .../ets/player/AudioRendererController.ets | 57 ++++++++++++------- .../src/main/ets/player/PlayerController.ets | 37 ++++++++---- entry/src/main/ets/utils/MediaTools.ets | 6 +- 5 files changed, 91 insertions(+), 36 deletions(-) diff --git a/entry/src/main/ets/components/ControlAreaComponent.ets b/entry/src/main/ets/components/ControlAreaComponent.ets index 4d422bf..3e30e38 100644 --- a/entry/src/main/ets/components/ControlAreaComponent.ets +++ b/entry/src/main/ets/components/ControlAreaComponent.ets @@ -156,6 +156,8 @@ export struct ControlAreaComponent { @Builder MyMenu() { + // [Start menu_audioRender] + // [Start menu_avplayer] Menu() { MenuItem({ content: $r('app.string.standard_quality'), @@ -168,6 +170,7 @@ export struct ControlAreaComponent { this.changeType(this.songData.src + AudioName.MP3, AudioType.MP3); this.isPlay = true; }) + // [StartExclude menu_audioRender] MenuItem({ content: $r('app.string.flac_high_quality'), }) @@ -180,6 +183,8 @@ export struct ControlAreaComponent { this.changeType(this.songData.src + AudioName.FLAC, AudioType.FLAC); this.isPlay = true; }) + // [EndExclude menu_audioRender] + // [StartExclude menu_avplayer] MenuItem({ content: $r('app.string.pcm_high_quality'), }) @@ -192,7 +197,10 @@ export struct ControlAreaComponent { this.changeType(this.songData.src + AudioName.PCM, AudioType.PCM); this.isPlay = true; }) + // [EndExclude menu_avplayer] } + // [StartExclude menu_audioRender] + // [StartExclude menu_avplayer] .width(224) .font({ size: 16 }) .height(152) @@ -203,8 +211,12 @@ export struct ControlAreaComponent { }) .subMenuExpandingMode(SubMenuExpandingMode.EMBEDDED_EXPAND) .backgroundColor(Color.White) + // [EndExclude menu_avplayer] + // [EndExclude menu_audioRender] + // [Start menu_avplayer] + // [Start menu_audioRender] } - + // [Start component_changeType] private changeType(songSrc: string, audioType: AudioType): void { let current: number = this.value; this.getUIContext().getHostContext()?.resourceManager.getRawFd(songSrc).then((rawFileDescriptor) => { @@ -214,6 +226,7 @@ export struct ControlAreaComponent { Logger.error(`resourceManager error code ${error.code} message ${error.message}`); }); } + // [End component_changeType] } @Extend(Image) diff --git a/entry/src/main/ets/player/AVPlayerController.ets b/entry/src/main/ets/player/AVPlayerController.ets index fc3608b..7146c67 100644 --- a/entry/src/main/ets/player/AVPlayerController.ets +++ b/entry/src/main/ets/player/AVPlayerController.ets @@ -18,8 +18,9 @@ import { Logger } from '../utils/Logger'; import { MediaTools } from '../utils/MediaTools'; import { BusinessError } from '@kit.BasicServicesKit'; import { audio } from '@kit.AudioKit'; - +// [Start AVPlayerController_methods] export class AVPlayerController { + // [StartExclude AVPlayerController_methods] private avPlayer: media.AVPlayer | undefined = undefined; private currentTime: number = 0; private isReset = false; @@ -66,17 +67,20 @@ export class AVPlayerController { Logger.error('AVPlayerController play error!'); }) } + // [EndExclude AVPlayerController_methods] + // Pause playback pause(): void { this.avPlayer?.pause().catch(() => { Logger.error('AVPlayerController pause error!'); }) } + // Jump to playback seek(currentTime: number): void { this.avPlayer?.seek(currentTime, media.SeekMode.SEEK_NEXT_SYNC); } - + // [StartExclude AVPlayerController_methods] private async setAVPlayerCallback(): Promise { if (!this.avPlayer) { return; @@ -135,4 +139,6 @@ export class AVPlayerController { Logger.error('AVPlayerController release error!'); }); } -} \ No newline at end of file + // [EndExclude AVPlayerController_methods] +} +// [Start AVPlayerController_methods] \ No newline at end of file diff --git a/entry/src/main/ets/player/AudioRendererController.ets b/entry/src/main/ets/player/AudioRendererController.ets index ec86fef..296dff8 100644 --- a/entry/src/main/ets/player/AudioRendererController.ets +++ b/entry/src/main/ets/player/AudioRendererController.ets @@ -18,55 +18,62 @@ import { BusinessError } from '@kit.BasicServicesKit'; import { Logger } from '../utils/Logger'; import { fileIo, ReadOptions } from '@kit.CoreFileKit'; import { MediaTools } from '../utils/MediaTools'; - +// [Start AudioRendererController_methods] export class AudioRendererController { + // [StartExclude AudioRendererController_methods] private audioRenderer: audio.AudioRenderer | undefined = undefined; private currentOffset: number = 0; private offset: number = 0; private length: number = 0; private fd: number = 0; private curMs: number = 0; - + // [EndExclude AudioRendererController_methods] + // Initialization AudioRenderer public async initAudioRenderer(fd: number, offset: number, length: number): Promise { - this.fd = fd; - this.offset = offset; - this.currentOffset = offset; - this.length = length; + this.fd = fd; // File descriptor + this.offset = offset; // Start offset + this.currentOffset = offset; // Current offset + this.length = length; // File length + // Audio stream information let audioStreamInfo: audio.AudioStreamInfo = { - samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, - channels: audio.AudioChannel.CHANNEL_2, - sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, - encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW + samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, // Audio file sampling rate + channels: audio.AudioChannel.CHANNEL_2, // Number of audio file channels + sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // Audio sampling format + encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // Audio encoding format }; - + // AudioRender information let audioRendererInfo: audio.AudioRendererInfo = { - usage: audio.StreamUsage.STREAM_USAGE_MUSIC, - rendererFlags: 0 + usage: audio.StreamUsage.STREAM_USAGE_MUSIC, // Audio stream usage type + rendererFlags: 0 // Audio renderer flag }; - + // AudioRender options information let audioRendererOptions: audio.AudioRendererOptions = { streamInfo: audioStreamInfo, rendererInfo: audioRendererInfo }; - + // Get audio renderer await audio.createAudioRenderer(audioRendererOptions).then((data) => { this.audioRenderer = data; if (this.audioRenderer !== undefined) { try { + // Set the focus model to independent focus mode this.audioRenderer.setInterruptMode(audio.InterruptMode.INDEPENDENT_MODE); - this.setWriteDataCallback(); + this.setWriteDataCallback(); // Write audio data } catch (error) { Logger.error('createAudioRenderer is calling.'); } } }); - + // Convert the file length to the corresponding number of milliseconds and store it in AppStorage. AppStorage.setOrCreate('progressMax', MediaTools.getMsFromByteLength(this.length)); + // Convert the file length to the corresponding number of milliseconds, then convert it to a timestamp and store it in AppStorage. AppStorage.setOrCreate('totalTime', MediaTools.msToCountdownTime(MediaTools.getMsFromByteLength(this.length))); } + // Write audio data private setWriteDataCallback(): void { try { + // Listening for audio data writing this.audioRenderer?.on('writeData', (buffer) => { if (this.currentOffset - this.offset >= this.length) { this.currentOffset = this.offset; @@ -101,16 +108,20 @@ export class AudioRendererController { public async start(): Promise { if (this.audioRenderer !== undefined) { + // Audio state let stateGroup = [audio.AudioState.STATE_PREPARED, audio.AudioState.STATE_PAUSED, audio.AudioState.STATE_STOPPED]; if (stateGroup.indexOf(this.audioRenderer.state.valueOf()) === -1) { return; } + // Starting the AudioRender this.audioRenderer.start((err: BusinessError) => { + // [StartExclude AudioRendererController_methods] if (err) { Logger.error('Renderer start failed.'); } else { Logger.info('Renderer start success.'); } + // [EndExclude AudioRendererController_methods] }); } } @@ -120,24 +131,26 @@ export class AudioRendererController { if (this.audioRenderer.state.valueOf() !== audio.AudioState.STATE_RUNNING) { return; } - + // Pause Audio rendering this.audioRenderer.pause((err: BusinessError) => { + // [StartExclude AudioRendererController_methods] if (err) { Logger.error('Renderer pause failed.'); } else { Logger.info('Renderer pause success.'); } + // [EndExclude AudioRendererController_methods] }); } } - + // Jump to playback public seek(ms: number): void { this.curMs = ms; AppStorage.setOrCreate('progress', this.curMs); AppStorage.setOrCreate('currentTime', MediaTools.msToCountdownTime(this.curMs)); this.currentOffset = this.offset + MediaTools.getOffsetFromTime(this.curMs); } - + // [StartExclude AudioRendererController_methods] public stop(): void { if (this.audioRenderer !== undefined) { @@ -175,4 +188,6 @@ export class AudioRendererController { AppStorage.setOrCreate('progress', 0); AppStorage.setOrCreate('currentTime', MediaTools.msToCountdownTime(this.curMs)); } -} \ No newline at end of file + // [EndExclude AudioRendererController_methods] +} +// [End AudioRendererController_methods] \ No newline at end of file diff --git a/entry/src/main/ets/player/PlayerController.ets b/entry/src/main/ets/player/PlayerController.ets index a8ec9e2..0c2c896 100644 --- a/entry/src/main/ets/player/PlayerController.ets +++ b/entry/src/main/ets/player/PlayerController.ets @@ -18,8 +18,11 @@ import { AudioRendererController } from './AudioRendererController'; import { AVPlayerController } from './AVPlayerController'; import { resourceManager } from '@kit.LocalizationKit'; import { Logger } from '../utils/Logger'; - +// [Start PlayerController_methods] +// [Start PlayerController_avplayer_methods] export class PlayerController { + // [StartExclude PlayerController_methods] + // [StartExclude PlayerController_avplayer_methods] private avPlayerController: AVPlayerController | undefined = undefined; private audioRendererController: AudioRendererController | undefined = undefined; private currentType: AudioType = 0; @@ -31,22 +34,26 @@ export class PlayerController { this.avPlayerController = new AVPlayerController(); this.avPlayerController.init(rawFileDescriptor.fd, rawFileDescriptor.offset, rawFileDescriptor.length); } - + // [EndExclude PlayerController_avplayer_methods] + // [EndExclude PlayerController_methods] + // Modifying the audio format changeType(rawFileDescriptor: resourceManager.RawFileDescriptor, audioType: AudioType) { try { this.rawFileDescriptor = rawFileDescriptor; if (audioType === 1 || audioType === 2) { - this.audioRendererController?.pause(); + this.audioRendererController?.pause(); // Pause AudioRender playback + // Reset AVPlayer playback this.avPlayerController?.reset(this.rawFileDescriptor.fd, this.rawFileDescriptor.offset, this.rawFileDescriptor.length); } else { - this.avPlayerController?.pause(); + this.avPlayerController?.pause(); // Pause AVPlayer playback if (this.audioRendererController === undefined) { this.audioRendererController = new AudioRendererController(); } + // Create an AudioRenderer instance and listen for audio data writing this.audioRendererController.initAudioRenderer(this.rawFileDescriptor.fd, this.rawFileDescriptor.offset, this.rawFileDescriptor.length).then(() => { - this.audioRendererController?.start(); + this.audioRendererController?.start(); // Start AudioRender audio render }); } this.currentType = audioType; @@ -54,7 +61,8 @@ export class PlayerController { Logger.error('changeType error!'); } } - + // [StartExclude PlayerController_methods] + // [StartExclude PlayerController_avplayer_methods] start(): void { if (this.isAVPlayer()) { this.avPlayerController?.play(); @@ -78,15 +86,20 @@ export class PlayerController { this.audioRendererController?.pause(); } } - + // [EndExclude PlayerController_avplayer_methods] + // [EndExclude PlayerController_methods] + // Determine the return value of isAVPlayer() and call the corresponding seek() method seek(currentTime: number): void { if (this.isAVPlayer()) { this.avPlayerController?.seek(currentTime); } else { + // [StartExclude PlayerController_avplayer_methods] this.audioRendererController?.seek(currentTime); + // [End PlayerController_avplayer_methods] } } - + // [StartExclude PlayerController_avplayer_methods] + // [StartExclude PlayerController_methods] release() { if (this.avPlayerController) { this.avPlayerController.release(); @@ -95,8 +108,12 @@ export class PlayerController { this.audioRendererController.release(); } } - + // [EndExclude PlayerController_methods] + // Determine whether to use AVPlayer for playback isAVPlayer(): boolean { return this.currentType === 1 || this.currentType === 2; } -} \ No newline at end of file + // [EndExclude PlayerController_avplayer_methods] +} +// [End PlayerController_avplayer_methods] +// [End PlayerController_methods] \ No newline at end of file diff --git a/entry/src/main/ets/utils/MediaTools.ets b/entry/src/main/ets/utils/MediaTools.ets index d9dcecf..189aadd 100644 --- a/entry/src/main/ets/utils/MediaTools.ets +++ b/entry/src/main/ets/utils/MediaTools.ets @@ -21,7 +21,9 @@ import { Logger } from './Logger'; const TAG = 'MediaTools'; const SECOND_BUFFER_WALK = 48000 * 2 * 2; +// [Start tools_methods] export class MediaTools { + // [StartExclude tools_methods] static async getPixelMapFromResource(context: common.UIAbilityContext, name: resourceManager.Resource): Promise { let resourceMgr = context.resourceManager; @@ -42,6 +44,7 @@ export class MediaTools { private static fill(value: number): string { return value.toString().padStart(2, '0'); } + // [EndExclude tools_methods] static msToCountdownTime(ms: number): string { if (!ms) { @@ -62,4 +65,5 @@ export class MediaTools { static getOffsetFromTime(curMs: number) { return (curMs / 1000) * SECOND_BUFFER_WALK; } -} \ No newline at end of file +} +// [End tools_methods] \ No newline at end of file -- Gitee From a61dcb5ba25fc798a2bd7b963b294d47ef50625b Mon Sep 17 00:00:00 2001 From: rex <1491721419@qq.com> Date: Fri, 28 Nov 2025 18:03:32 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=90=8C=E6=BA=90?= =?UTF-8?q?=E6=A0=87=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- entry/src/main/ets/player/AVPlayerController.ets | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/entry/src/main/ets/player/AVPlayerController.ets b/entry/src/main/ets/player/AVPlayerController.ets index 7146c67..d5c6d4f 100644 --- a/entry/src/main/ets/player/AVPlayerController.ets +++ b/entry/src/main/ets/player/AVPlayerController.ets @@ -45,6 +45,7 @@ export class AVPlayerController { } }); } + // [EndExclude AVPlayerController_methods] reset(fd: number, offset: number, length: number): void { this.currentTime = AppStorage.get('progress') as number; @@ -55,7 +56,7 @@ export class AVPlayerController { } }) } - + // [StartExclude AVPlayerController_methods] stop(): void { this.avPlayer?.stop().catch(() => { Logger.error('AVPlayerController stop error!'); -- Gitee From 3a8536e9d3e1920a4155b4d198c2bd5261fa297a Mon Sep 17 00:00:00 2001 From: rex <1491721419@qq.com> Date: Fri, 28 Nov 2025 18:11:52 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=90=8C=E6=BA=90?= =?UTF-8?q?=E6=A0=87=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- entry/src/main/ets/player/PlayerController.ets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entry/src/main/ets/player/PlayerController.ets b/entry/src/main/ets/player/PlayerController.ets index 0c2c896..f19f9d8 100644 --- a/entry/src/main/ets/player/PlayerController.ets +++ b/entry/src/main/ets/player/PlayerController.ets @@ -95,7 +95,7 @@ export class PlayerController { } else { // [StartExclude PlayerController_avplayer_methods] this.audioRendererController?.seek(currentTime); - // [End PlayerController_avplayer_methods] + // [EndExclude PlayerController_avplayer_methods] } } // [StartExclude PlayerController_avplayer_methods] -- Gitee From 1f96a7c25365ca8bd4720dd62e9e45c5a937ea42 Mon Sep 17 00:00:00 2001 From: rex <1491721419@qq.com> Date: Fri, 28 Nov 2025 18:13:28 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=90=8C=E6=BA=90?= =?UTF-8?q?=E6=A0=87=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- entry/src/main/ets/player/PlayerController.ets | 2 ++ 1 file changed, 2 insertions(+) diff --git a/entry/src/main/ets/player/PlayerController.ets b/entry/src/main/ets/player/PlayerController.ets index f19f9d8..3b73403 100644 --- a/entry/src/main/ets/player/PlayerController.ets +++ b/entry/src/main/ets/player/PlayerController.ets @@ -46,6 +46,7 @@ export class PlayerController { this.avPlayerController?.reset(this.rawFileDescriptor.fd, this.rawFileDescriptor.offset, this.rawFileDescriptor.length); } else { + // [StartExclude PlayerController_avplayer_methods] this.avPlayerController?.pause(); // Pause AVPlayer playback if (this.audioRendererController === undefined) { this.audioRendererController = new AudioRendererController(); @@ -55,6 +56,7 @@ export class PlayerController { this.rawFileDescriptor.length).then(() => { this.audioRendererController?.start(); // Start AudioRender audio render }); + // [StartExclude PlayerController_avplayer_methods] } this.currentType = audioType; } catch (error) { -- Gitee