From 08969b2e910c8135ac8b6972f1d9c714998312ab Mon Sep 17 00:00:00 2001 From: Quicksticks-oss Date: Sat, 23 Mar 2024 15:13:34 -0400 Subject: [PATCH] added audio engine. --- .../datastructures/clips/audio_track_clip.ts | 36 ++++++++-- app/pages/PageEnigma/js/audio_engine.ts | 65 +++++++++---------- app/pages/PageEnigma/js/editor.js | 18 ++--- 3 files changed, 65 insertions(+), 54 deletions(-) diff --git a/app/pages/PageEnigma/datastructures/clips/audio_track_clip.ts b/app/pages/PageEnigma/datastructures/clips/audio_track_clip.ts index a6a897e57a..56b21a029d 100644 --- a/app/pages/PageEnigma/datastructures/clips/audio_track_clip.ts +++ b/app/pages/PageEnigma/datastructures/clips/audio_track_clip.ts @@ -1,21 +1,47 @@ export interface AudioTrackClip { version: number; - media_id: number; + media_id: string; type: "audio"; volume: number; } -export class AudioTrackClipClass implements AudioTrackClip { +export class AudioTrackClip implements AudioTrackClip { version: number; - media_id: number; - type: "audio"; + media_id: string; + type: "audio" = "audio"; volume: number; + buffer: AudioBufferSourceNode | undefined; - constructor(version: number, media_id: number, volume: number) { + constructor(version: number, media_id: string, volume: number) { this.version = version; this.media_id = media_id; this.type = "audio"; this.volume = volume; + this.download_audio().then(data => { + this.buffer = data; + }); + } + + get_media_url() { + // This is for prod when we have the proper info on the url. + // let baseUrl = "https://api.fakeyou.com"; + // let url = `${baseUrl}/media/${this.media_id}` + // return url; + + return "/resources/sound/2pac.wav"; + } + + async download_audio() { + let new_audio_context = new AudioContext(); + let url = this.get_media_url(); + const audioContext = new AudioContext(); + const response = await fetch(url); + const arrayBuffer = await response.arrayBuffer(); + const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); + const source = audioContext.createBufferSource(); + source.buffer = audioBuffer; + source.connect(audioContext.destination); + return source; } toJSON(): string { diff --git a/app/pages/PageEnigma/js/audio_engine.ts b/app/pages/PageEnigma/js/audio_engine.ts index 71eb36e906..0a1fc0d2ac 100644 --- a/app/pages/PageEnigma/js/audio_engine.ts +++ b/app/pages/PageEnigma/js/audio_engine.ts @@ -1,43 +1,38 @@ -import * as THREE from "three"; +import { AudioTrackClip } from "../datastructures/clips/audio_track_clip"; + class AudioEngine { - constructor() { - this.listener = new THREE.AudioListener(); - this.clips = {}; - } + clips: { [key: string]: AudioTrackClip } = {}; + audio_sources: { [key: string]: AudioBufferSourceNode } = {}; + version: number; - addCamera(camera) { - // Assuming you have a camera and you want to add the listener to it - camera.add(this.listener); - } + constructor() { + this.clips = {}; + this.audio_sources = {}; + this.version = 1.0; + } - loadClip(id, audioURL) { - if (this.clips[id]) { - console.warn(`AudioManager: AudioClip already exists with id "${id}".`); - return; - } + loadClip(audio_media_id: string) { + this.clips[audio_media_id] = new AudioTrackClip(this.version, audio_media_id, 1.0); + } - const clip = new AudioClip(this.listener, audioURL); - this.clips[id] = clip; - } + playClip(audio_media_id: string) { + const clip = this.clips[audio_media_id]; + if (clip.buffer) { + clip.buffer.start(); + } else { + console.warn(`AudioManager: AudioClip buffer with id "${audio_media_id}" not found.`); + } + } - playClip(id) { - const clip = this.clips[id]; - if (clip) { - clip.play(); - } else { - console.warn(`AudioManager: AudioClip with id "${id}" not found.`); - } - } - - stopClip(id) { - const clip = this.clips[id]; - if (clip) { - clip.stop(); - } else { - console.warn(`AudioManager: AudioClip with id "${id}" not found.`); - } - } + stopClip(audio_media_id: string) { + const clip = this.clips[audio_media_id]; + if (clip.buffer) { + clip.buffer.stop(); + } else { + console.warn(`AudioManager: AudioClip with id "${audio_media_id}" not found.`); + } + } } -export default AudioManager; +export default AudioEngine; diff --git a/app/pages/PageEnigma/js/editor.js b/app/pages/PageEnigma/js/editor.js index 7e26c4287c..5eae0f8814 100644 --- a/app/pages/PageEnigma/js/editor.js +++ b/app/pages/PageEnigma/js/editor.js @@ -14,6 +14,8 @@ import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js' import { BokehPass } from 'three/addons/postprocessing/BokehPass.js'; import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'; +import AudioEngine from './audio_engine.ts'; + if (typeof window !== 'undefined') { import('ccapture.js').then(module => { const CCapture = module.CCapture; @@ -28,7 +30,6 @@ class Editor { // Default params. constructor() { - // For making sure the editor only gets created onece. this.can_initailize = false; let one_element = document.getElementById("created-one-element"); @@ -36,10 +37,8 @@ class Editor { let newElement = document.createElement("div"); newElement.id = "created-one-element"; document.body.appendChild(newElement); - // Version and name. this.version = "v0.1"; - // Clock, scene and camera essentials. this.activeScene = null; this.camera = null; @@ -55,7 +54,6 @@ class Editor { this.bloomPass; this.smaaPass; this.bokehPass; - // Transform control and selection. this.control = null; this.raycaster = null; @@ -64,41 +62,35 @@ class Editor { this.last_selected = null; this.transform_interaction; this.rendering = false; - // API. this.api_manager = new MediaUploadManager(); - // Debug & Movement. this.stats = null; this.orbit = null; this.locked = false; - // Recording params. this.capturer = null; this.frame_buffer = []; this.render_timer = 0; this.fps_number = 60; this.cap_fps = 60; - // Timeline settings. this.playback = false; this.playback_location = 0; this.max_length = 10; this.timeline = null; - // Save & Load. this.save_manager = new SaveManager(this.version); + // Audio Engine Test. - console.log("Created Editor."); + this.audio_engine = new AudioEngine(); } // Initializes the main scene and ThreeJS essentials. initialize() { //if (this.can_initailize == false) { return; } - // Gets the canvas. this.canvReference = document.getElementById("video-scene"); - // Base width and height. let width = this.canvReference.width; let height = this.canvReference.height; @@ -126,10 +118,8 @@ class Editor { // OnClick and MouseMove events. window.addEventListener('mousemove', this.onMouseMove.bind(this), false); window.addEventListener('click', this.onMouseClick.bind(this), false); - // Base control and debug stuff remove debug in prod. this._initialize_control(); - // Resets canvas size. this.onWindowResize(); // Creates the main update loop.