From ff6694bc645694919cb3d9ff8d1a2a6a47c914a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Thu, 14 Sep 2023 20:56:04 -0700 Subject: [PATCH 01/13] Create index.ts --- packages/sound/index.ts | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 packages/sound/index.ts diff --git a/packages/sound/index.ts b/packages/sound/index.ts new file mode 100644 index 00000000..846196f2 --- /dev/null +++ b/packages/sound/index.ts @@ -0,0 +1,4 @@ +import "./SoundLoader"; + +export * from "./Sound"; +export * from "./SoundPlayer"; From 54e19e61ff5f32e7a74b20252488b032076566da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Thu, 14 Sep 2023 20:56:33 -0700 Subject: [PATCH 02/13] Rename packages/sound/index.ts to packages/sound/src/index.ts --- packages/sound/{ => src}/index.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/sound/{ => src}/index.ts (100%) diff --git a/packages/sound/index.ts b/packages/sound/src/index.ts similarity index 100% rename from packages/sound/index.ts rename to packages/sound/src/index.ts From 7ae3918bd28d59e571684b0f43100f4219c017f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Thu, 14 Sep 2023 20:57:39 -0700 Subject: [PATCH 03/13] Create package.json --- packages/sound/package.json | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 packages/sound/package.json diff --git a/packages/sound/package.json b/packages/sound/package.json new file mode 100644 index 00000000..d72f8fdd --- /dev/null +++ b/packages/sound/package.json @@ -0,0 +1,28 @@ +{ + "name": "@galacean/engine-toolkit-sound", + "version": "1.1.0-beta.0", + "license": "MIT", + "scripts": { + "b:types": "tsc" + }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org" + }, + "homepage": "https://oasisengine.cn/", + "repository": { + "type": "git", + "url": "https://github.com/galacean/engine-toolkit" + }, + "bugs": "https://github.com/galacean/engine-toolkit/issues", + "types": "types/index.d.ts", + "module": "dist/es/index.js", + "main": "dist/commonjs/browser.js", + "files": [ + "dist/**/*", + "types/**/*" + ], + "peerDependencies": { + "@galacean/engine": "^1.1.0-alpha" + } +} From fa9ffb163bf8734ebbc0b5fc1bb339a2ddb80399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Thu, 14 Sep 2023 20:58:20 -0700 Subject: [PATCH 04/13] Create tsconfig.json --- packages/sound/tsconfig.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 packages/sound/tsconfig.json diff --git a/packages/sound/tsconfig.json b/packages/sound/tsconfig.json new file mode 100644 index 00000000..3939a36c --- /dev/null +++ b/packages/sound/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "module": "esnext", + "target": "esnext", + "declaration": true, + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "declarationDir": "types", + "emitDeclarationOnly": true, + "sourceMap": true, + "skipLibCheck": true, + "noImplicitOverride": true, + "incremental": false + }, + "include": [ + "src/**/*" + ] +} From 3e932ff3f48488b7e2610b9dd860568261735722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Fri, 15 Sep 2023 00:13:38 -0700 Subject: [PATCH 05/13] Create README.md --- packages/sound/README.md | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 packages/sound/README.md diff --git a/packages/sound/README.md b/packages/sound/README.md new file mode 100644 index 00000000..77654f0f --- /dev/null +++ b/packages/sound/README.md @@ -0,0 +1,60 @@ +# Sound + +A sound library for playing audio files + +## Features +- loop: support changing loop; +- volume: support changing volume; +- speed: support changing playbackRate; + +## npm + +The `Sound` is published on npm with full typing support. To install, use: + +```sh +npm install @galacean/engine-toolkit-sound +``` + +This will allow you to import tween entirely using: + +```javascript +import * as SOUND from "@galacean/engine-toolkit-sound"; +``` + +or individual classes using: + +```javascript +import { SoundPlayer } from "@galacean/engine-toolkit-sound"; +``` + +## How to use +Step 1: Loading file +```typescript +await engine.resourceManager.load([{ + url: "./test.mp3", + type: "audio", +}]); +// or just use url string. file suffix could be mp3, wav or ogg +await engine.resourceManager.load(["./test.mp3"]); +``` +Step 2: Add sound player component +```typescript +const player = entity.addComponent(SoundPlayer); +player.sound = engine.resourceManager.getFromCache("./test.mp3"); +``` +Step 3: You can set some options and play sound +```typescript +player.volume = 0.5; +player.playbackRate = 0.5; +player.loop = true; +player.play(); +``` + +### Attention: Make sure user should have already made a gesture before playing a sound. +## Links + +- [Repository](https://github.com/galacean/engine-toolkit) + +## License + +The engine is released under the [MIT](https://opensource.org/licenses/MIT) license. See LICENSE file. From 6c8270d9d23c9f3f8ffa45e70cc18bb9e347292c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Fri, 15 Sep 2023 00:15:40 -0700 Subject: [PATCH 06/13] Create global.ts --- packages/sound/src/global.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 packages/sound/src/global.ts diff --git a/packages/sound/src/global.ts b/packages/sound/src/global.ts new file mode 100644 index 00000000..35a1575b --- /dev/null +++ b/packages/sound/src/global.ts @@ -0,0 +1,18 @@ +export const GlobalAudioContext = new AudioContext(); + +export function makeSound() { + const osc = GlobalAudioContext.createOscillator(); + const g = GlobalAudioContext.createGain(); + + osc.connect(g); + osc.frequency.value = 1; + + const wave = GlobalAudioContext.createPeriodicWave(new Float32Array(2), new Float32Array(2)); + osc.setPeriodicWave(wave); + g.connect(GlobalAudioContext.destination); + g.gain.value = 0; + osc.start(); + g.gain.linearRampToValueAtTime(0.6, GlobalAudioContext.currentTime + 0.01); + osc.stop(GlobalAudioContext.currentTime + 0.01); + g.gain.exponentialRampToValueAtTime(0.01, GlobalAudioContext.currentTime + 0.01); +} From 50c5319bc734bae952d05ac77f94d8fadec2517f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Fri, 15 Sep 2023 00:16:03 -0700 Subject: [PATCH 07/13] Create Sound.ts --- packages/sound/src/Sound.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 packages/sound/src/Sound.ts diff --git a/packages/sound/src/Sound.ts b/packages/sound/src/Sound.ts new file mode 100644 index 00000000..3a0d3742 --- /dev/null +++ b/packages/sound/src/Sound.ts @@ -0,0 +1,29 @@ +import { Engine, ReferResource } from "@galacean/engine"; + +export class Sound extends ReferResource { + name: string; + buffer: AudioBuffer | null = null;; + constructor(engine: Engine, name: string = "") { + super(engine); + this.name = name; + } + + get duration(): number { + return this.buffer?.duration ?? -1; + } + + setAudioSource(buffer: AudioBuffer) { + this.buffer = buffer; + } + + destroy(): boolean { + if (this._destroyed) { + return false; + } + + this.buffer = null; + this._destroyed = true; + + return true; + } +} From b4fd84cbfa9824cdf8f3505b3a6b4f3fc2a8fee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Fri, 15 Sep 2023 00:16:33 -0700 Subject: [PATCH 08/13] Create SoundContentStore.ts --- packages/sound/src/SoundContentStore.ts | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 packages/sound/src/SoundContentStore.ts diff --git a/packages/sound/src/SoundContentStore.ts b/packages/sound/src/SoundContentStore.ts new file mode 100644 index 00000000..484c52e9 --- /dev/null +++ b/packages/sound/src/SoundContentStore.ts @@ -0,0 +1,27 @@ +import { AssetPromise, ContentRestorer, request } from "@galacean/engine"; +import { RequestConfig } from "@galacean/engine-core/types/asset/request"; +import { GlobalAudioContext } from "./global"; +import { Sound } from "./Sound"; + +/** + * @internal + */ +export class AudioContentRestorer extends ContentRestorer { + constructor( + resource: Sound, + public url: string, + public requestConfig: RequestConfig + ) { + super(resource); + } + + override restoreContent(): AssetPromise { + return request(this.url, this.requestConfig).then((audio) => { + return GlobalAudioContext.decodeAudioData(audio); + }).then((audio) => { + const resource = this.resource; + resource.setAudioSource(audio); + return resource; + }); + } +} From e43518d5172a43b675af6750bf218064990c57d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Fri, 15 Sep 2023 00:17:04 -0700 Subject: [PATCH 09/13] Create SoundLoader.ts --- packages/sound/src/SoundLoader.ts | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 packages/sound/src/SoundLoader.ts diff --git a/packages/sound/src/SoundLoader.ts b/packages/sound/src/SoundLoader.ts new file mode 100644 index 00000000..0426e0d3 --- /dev/null +++ b/packages/sound/src/SoundLoader.ts @@ -0,0 +1,54 @@ +import { WebGLEngine } from "@galacean/engine"; +import { + AssetPromise, + Loader, + LoadItem, + resourceLoader, + ResourceManager +} from "@galacean/engine"; +import { RequestConfig } from "@galacean/engine-core/types/asset/request"; +import { GlobalAudioContext } from "./global"; +import { Sound } from "./Sound"; +import { AudioContentRestorer } from "./SoundContentStore"; +import { SoundPlayer } from "./SoundPlayer"; + +let hasAddListener = false; +function listener(e: Event) { + SoundPlayer.triggerUserGesture(); + e.target!.removeEventListener("pointerdown", listener); +} + +@resourceLoader("audio", ["mp3", "wav", "ogg"]) +class SoundLoader extends Loader { + + override load(item: LoadItem, resourceManager: ResourceManager): AssetPromise { + if (!hasAddListener) { + hasAddListener = true; + ((resourceManager.engine as WebGLEngine).canvas._webCanvas as HTMLCanvasElement).addEventListener("pointerdown", listener); + } + return new AssetPromise((resolve, reject) => { + const url = item.url!; + const requestConfig = { + ...item, + type: "arraybuffer" + }; + this.request(url, requestConfig) + .then((buffer) => { + return GlobalAudioContext.decodeAudioData(buffer); + }).then((buffer) => { + const sound = new Sound(resourceManager.engine); + sound.setAudioSource(buffer); + if (url.indexOf("data:") !== 0) { + const index = url.lastIndexOf("/"); + sound.name = url.substring(index + 1); + } + + resourceManager.addContentRestorer(new AudioContentRestorer(sound, url, requestConfig)); + resolve(sound); + }) + .catch((e) => { + reject!(e); + }); + }); + } +} From 98c330ac15e3d0a290d0ebab5180739198af735a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Fri, 15 Sep 2023 00:17:28 -0700 Subject: [PATCH 10/13] Create SoundPlayer.ts --- packages/sound/src/SoundPlayer.ts | 75 +++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 packages/sound/src/SoundPlayer.ts diff --git a/packages/sound/src/SoundPlayer.ts b/packages/sound/src/SoundPlayer.ts new file mode 100644 index 00000000..35c18288 --- /dev/null +++ b/packages/sound/src/SoundPlayer.ts @@ -0,0 +1,75 @@ +import { Component } from "@galacean/engine"; +import { makeSound } from "./global"; +import { Sound } from "./Sound"; + +export class SoundPlayer extends Component { + private _ctx = new AudioContext(); + private _gainNode = this._ctx.createGain(); + private _source: AudioBufferSourceNode | null = null; + private _volume = 1; + private _playbackRate = 1; + private static _isUserGestureTriggered = false; + + static triggerUserGesture() { + SoundPlayer._isUserGestureTriggered = true; + makeSound(); + } + + loop = false; + sound: Sound | null = null;; + + get volume(): number { + return this._volume; + } + + set volume(v: number) { + this._gainNode.gain.value = v; + this._volume = v; + } + + get playbackRate(): number { + return this._playbackRate; + } + + set playbackRate(v: number) { + if (this._source) { + this._source.playbackRate.value = v; + } + this._playbackRate = v; + } + + play() { + if (!SoundPlayer._isUserGestureTriggered) { + console.warn("User gesture should be triggered first before audio created or play."); + return; + } + if (this.sound) { + this.stop(); + this._source = this._ctx.createBufferSource(); + this._source.buffer = this.sound.buffer; + this._source.connect(this._gainNode).connect(this._ctx.destination); + this._source.playbackRate.value = this._playbackRate; + this._source.loop = this.loop; + this._source.start(); + } + } + + pause() { + if (this._ctx.state === "running") { + this._ctx.suspend(); + } + } + + resume() { + if (this._ctx.state === "suspended") { + this._ctx.resume(); + } + } + + stop(when?: number) { + if (this._source) { + this._source.stop(when); + this._source.onended = this._source.disconnect; + } + } +} From c94b3cf6a88bba5d16dab6ea6af89ca5215b56bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Fri, 15 Sep 2023 00:25:03 -0700 Subject: [PATCH 11/13] Update Sound.ts --- packages/sound/src/Sound.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sound/src/Sound.ts b/packages/sound/src/Sound.ts index 3a0d3742..269c9a80 100644 --- a/packages/sound/src/Sound.ts +++ b/packages/sound/src/Sound.ts @@ -16,7 +16,7 @@ export class Sound extends ReferResource { this.buffer = buffer; } - destroy(): boolean { + override destroy(): boolean { if (this._destroyed) { return false; } From 5ed270b65eba90a9303bb3168545a549249f2fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Fri, 15 Sep 2023 00:25:20 -0700 Subject: [PATCH 12/13] Update SoundContentStore.ts --- packages/sound/src/SoundContentStore.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/sound/src/SoundContentStore.ts b/packages/sound/src/SoundContentStore.ts index 484c52e9..1bf8af86 100644 --- a/packages/sound/src/SoundContentStore.ts +++ b/packages/sound/src/SoundContentStore.ts @@ -1,5 +1,4 @@ import { AssetPromise, ContentRestorer, request } from "@galacean/engine"; -import { RequestConfig } from "@galacean/engine-core/types/asset/request"; import { GlobalAudioContext } from "./global"; import { Sound } from "./Sound"; @@ -10,7 +9,7 @@ export class AudioContentRestorer extends ContentRestorer { constructor( resource: Sound, public url: string, - public requestConfig: RequestConfig + public requestConfig: any ) { super(resource); } From 614dc0197126b47610c2ecbdbbf98fc6b6533e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E8=81=AA=E6=98=8E?= <601670314@qq.com> Date: Fri, 15 Sep 2023 00:25:37 -0700 Subject: [PATCH 13/13] Update SoundLoader.ts --- packages/sound/src/SoundLoader.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/sound/src/SoundLoader.ts b/packages/sound/src/SoundLoader.ts index 0426e0d3..b42b9de1 100644 --- a/packages/sound/src/SoundLoader.ts +++ b/packages/sound/src/SoundLoader.ts @@ -6,7 +6,6 @@ import { resourceLoader, ResourceManager } from "@galacean/engine"; -import { RequestConfig } from "@galacean/engine-core/types/asset/request"; import { GlobalAudioContext } from "./global"; import { Sound } from "./Sound"; import { AudioContentRestorer } from "./SoundContentStore"; @@ -28,7 +27,7 @@ class SoundLoader extends Loader { } return new AssetPromise((resolve, reject) => { const url = item.url!; - const requestConfig = { + const requestConfig = { ...item, type: "arraybuffer" };