Slider({
min: 0,
max: this.fileSize,
value: this.readOffset,
style: SliderStyle.OutSet
})
.height(4)
.width('80%')
.trackThickness(4)
.margin({ bottom: 2 })
.padding({ left: 6, right: 6 })
.blockSize({ width: 15, height: 15 })
.onChange((value: number) => {
let offset = Math.floor(value);
if (offset % 2 !== 0) {
offset -= 1;
}
this.setReadOffset(offset);
}); setReadOffset(offset: number) {
this.readOffset = offset;
this.renderer?.flush();
} this.renderer.on('writeData', (buffer: ArrayBuffer) => {
let lastLen = this.fileSize - this.readOffset;
let readLen = lastLen >= buffer.byteLength ? buffer.byteLength : lastLen;
// 读取数据
fileIo.readSync(this.playFile?.fd, buffer, { offset: this.readOffset, length: readLen });
this.readOffset += readLen;
if (this.readOffset >= this.fileSize) {
this.readOffset = 0;
}
}); 完整示例如下:
import { audio } from '@kit.AudioKit';
import { fileIo } from '@kit.CoreFileKit';
@Entry
@Component
struct DragSlider {
@State readOffset: number = 0;
@State fileSize: number = 0;
@State isPlaying: boolean = false;
private playFile?: fileIo.File;
private renderer?: audio.AudioRenderer;
build() {
Scroll() {
Column() {
Column() {
Slider({
min: 0,
max: this.fileSize,
value: this.readOffset,
style: SliderStyle.OutSet
})
.height(4)
.width('80%')
.trackThickness(4)
.margin({ bottom: 2 })
.padding({ left: 6, right: 6 })
.blockSize({ width: 15, height: 15 })
.onChange((value: number) => {
let offset = Math.floor(value);
if (offset % 2 !== 0) {
offset -= 1;
}
this.setReadOffset(offset);
});
}
.width('100%')
.height(40)
.margin({ top: 40 });
Row() {
Column() {
Text('初始化')
.fontColor(Color.Black)
.fontSize(16)
.width('100%')
.height('100%')
.textAlign(TextAlign.Center);
}
.backgroundColor(Color.White)
.borderRadius(30)
.width(100)
.height(100)
.margin({ right: 12, bottom: 12 })
.onClick(async () => {
await this.initRenderer();
});
Column() {
Text('开始播放')
.fontColor(Color.Black)
.fontSize(16)
.width('100%')
.height('100%')
.textAlign(TextAlign.Center);
}
.backgroundColor(Color.White)
.borderRadius(30)
.width(100)
.height(100)
.margin({ right: 12, bottom: 12 })
.onClick(async () => {
this.isPlaying = true;
await this.startRenderer(this.getUIContext());
});
};
Row() {
Column() {
Text('暂停播放')
.fontColor(Color.Black)
.fontSize(16)
.width('100%')
.height('100%')
.textAlign(TextAlign.Center);
}
.id('audio_effect_manager_card')
.backgroundColor(Color.White)
.borderRadius(30)
.width(100)
.height(100)
.margin({ right: 12, bottom: 12 })
.onClick(async () => {
this.pauseRenderer();
this.isPlaying = false;
});
Column() {
Text('释放资源')
.fontColor(Color.Black)
.fontSize(16)
.width('100%')
.height('100%')
.textAlign(TextAlign.Center);
}
.id('audio_volume_card')
.backgroundColor(Color.White)
.borderRadius(30)
.width(100)
.height(100)
.margin({ right: 12, bottom: 12 })
.onClick(async () => {
this.releaseRenderer();
this.isPlaying = false;
this.readOffset = 0;
});
};
}
.height('100%')
.width('100%')
.backgroundColor('#F1F3F5');
};
}
setReadOffset(offset: number) {
this.readOffset = offset;
this.renderer?.flush();
}
rendererState(): audio.AudioState | undefined {
if (this.renderer !== undefined) {
return this.renderer.state;
}
return undefined;
}
async initRenderer() {
let audioStreamInfo: audio.AudioStreamInfo = {
channels: audio.AudioChannel.CHANNEL_1,
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_16000,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW,
};
let audioRendererInfo: audio.AudioRendererInfo = {
rendererFlags: 0,
usage: audio.StreamUsage.STREAM_USAGE_MUSIC,
};
let audioRendererOptions: audio.AudioRendererOptions = {
streamInfo: audioStreamInfo,
rendererInfo: audioRendererInfo,
};
this.renderer = await audio.createAudioRenderer(audioRendererOptions);
this.renderer.on('writeData', (buffer: ArrayBuffer) => {
let lastLen = this.fileSize - this.readOffset;
let readLen = lastLen >= buffer.byteLength ? buffer.byteLength : lastLen;
// 读取数据
fileIo.readSync(this.playFile?.fd, buffer, { offset: this.readOffset, length: readLen });
this.readOffset += readLen;
if (this.readOffset >= this.fileSize) {
this.readOffset = 0;
}
});
}
async startRenderer(context: UIContext) {
if (this.renderer === undefined) {
throw new Error(`AudioRenderer undefined`);
}
let state = this.renderer.state;
if (state === audio.AudioState.STATE_INVALID) {
this.renderer = undefined;
throw new Error(`Start AudioRenderer at invalid state.`);
}
let contact = context.getHostContext() as Context;
let pathDir = contact.filesDir;
// 需确保沙箱中有此文件
let filePath = pathDir + `/test.pcm`;
if (this.playFile?.path !== filePath) {
if (this.playFile) {
await fileIo.close(this.playFile);
await this.renderer.flush();
}
this.playFile = await fileIo.open(filePath, fileIo.OpenMode.READ_ONLY);
}
this.fileSize = fileIo.statSync(filePath).size;
await this.renderer.start();
}
async pauseRenderer() {
if (this.renderer === undefined) {
throw new Error(`AudioRenderer undefined`);
}
let state = this.renderer.state;
if (state === audio.AudioState.STATE_INVALID) {
this.renderer = undefined;
throw new Error(`Pause AudioRenderer at invalid state.`);
}
await this.renderer.pause();
}
async stopRenderer() {
if (this.renderer === undefined) {
throw new Error(`AudioRenderer undefined`);
}
let state = this.renderer.state;
if (state === audio.AudioState.STATE_INVALID) {
this.renderer = undefined;
throw new Error(`Stop AudioRenderer at invalid state.`);
}
await this.renderer.stop();
fileIo.closeSync(this.playFile?.fd);
}
async releaseRenderer() {
if (this.renderer === undefined) {
throw new Error(`AudioRenderer undefined`);
}
let state = this.renderer.state;
if (state === audio.AudioState.STATE_INVALID) {
this.renderer = undefined;
throw new Error(`Release AudioRenderer at invalid state.`);
}
await this.renderer.release();
}
}