add initial player and RNBO Patch that runs in parallel to the 9 Audiofiles
parent
3ee8e7e6eb
commit
f97d3136fe
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Vite + TS</title>
|
<title>9 x single-band rnbo patches</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
// audio-app/src/audio/context.ts
|
||||||
|
let sharedCtx: AudioContext | undefined
|
||||||
|
let WAContext = window.AudioContext || window.webkitAudioContext
|
||||||
|
|
||||||
|
export function getAudioContext():AudioContext {
|
||||||
|
if (!sharedCtx) {
|
||||||
|
sharedCtx = new WAContext()
|
||||||
|
}
|
||||||
|
return sharedCtx
|
||||||
|
}
|
|
@ -12,6 +12,9 @@ export function setupPlayButton(
|
||||||
button.onclick = () => {
|
button.onclick = () => {
|
||||||
const startTime = context.currentTime + 0.1 // 100ms in Zukunft
|
const startTime = context.currentTime + 0.1 // 100ms in Zukunft
|
||||||
const rampTime = 2
|
const rampTime = 2
|
||||||
|
// 1️⃣ Master-Gain auf 0 dB hochrampen
|
||||||
|
master.gain.setValueAtTime(0.001, startTime)
|
||||||
|
master.gain.exponentialRampToValueAtTime(1.0, startTime + rampTime)
|
||||||
|
|
||||||
sources.forEach((source, freq) => {
|
sources.forEach((source, freq) => {
|
||||||
const gainNode = gains.get(freq)
|
const gainNode = gains.get(freq)
|
||||||
|
|
48
src/main.ts
48
src/main.ts
|
@ -3,6 +3,8 @@ import { attachDBValueListener } from './dbValueListener'
|
||||||
import { fetchOrLoadBuffer, createBufferSource } from './composables/BufferStore'
|
import { fetchOrLoadBuffer, createBufferSource } from './composables/BufferStore'
|
||||||
import { setupPlayButton } from './composables/Player';
|
import { setupPlayButton } from './composables/Player';
|
||||||
import { getPreferredDevice } from './lib/microphone';
|
import { getPreferredDevice } from './lib/microphone';
|
||||||
|
import { getAudioContext } from './audio/context'
|
||||||
|
|
||||||
import patcherUrl from '../public/patches/controlvalue/LAF-Controll-Values_Simple_Band1000.rnbopat.export.json?url'
|
import patcherUrl from '../public/patches/controlvalue/LAF-Controll-Values_Simple_Band1000.rnbopat.export.json?url'
|
||||||
|
|
||||||
interface DeviceInfo {
|
interface DeviceInfo {
|
||||||
|
@ -17,15 +19,11 @@ interface DeviceInfo {
|
||||||
let patcherPromise: Promise<any>
|
let patcherPromise: Promise<any>
|
||||||
|
|
||||||
// create context & master gain
|
// create context & master gain
|
||||||
let WAContext = window.AudioContext || window.webkitAudioContext
|
|
||||||
const ctx = new WAContext() // match your assets
|
|
||||||
const mobile = /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent)
|
const mobile = /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent)
|
||||||
console.log("AudioContext created")
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Gains to control the audio
|
// Gains to control the audio
|
||||||
//
|
//
|
||||||
const masterGain = ctx.createGain()
|
|
||||||
|
|
||||||
const bands = mobile ? [150, 1500, 8000] : [63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000]
|
const bands = mobile ? [150, 1500, 8000] : [63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000]
|
||||||
const devices = new Map<number, DeviceInfo>()
|
const devices = new Map<number, DeviceInfo>()
|
||||||
|
@ -56,17 +54,25 @@ async function getPatcher() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
|
// Schritt 0: Mic-Recht
|
||||||
|
await initMicrophone()
|
||||||
|
// Schritt 1: Kontext
|
||||||
|
const ctx = getAudioContext()
|
||||||
|
await ctx.suspend()
|
||||||
|
// Schritt 2: Fetch Patcher
|
||||||
await getPatcher()
|
await getPatcher()
|
||||||
|
// Schritt 3: Erstelle alle Devices
|
||||||
const newDevices = await Promise.all(
|
const newDevices = await Promise.all(
|
||||||
bands.map(async (freq, index) => {
|
bands.map(async (freq, index) => {
|
||||||
const device = await createBandDevice(freq, ctx) as DeviceInfo
|
const device = await createBandDevice(freq, ctx) as DeviceInfo
|
||||||
|
// Schritt 4 Fetch alle AudioBuffer
|
||||||
await fetchOrLoadBuffer(freq.toString(),
|
await fetchOrLoadBuffer(freq.toString(),
|
||||||
urlsWebM[index].url,
|
urlsWebM[index].url,
|
||||||
ctx
|
ctx
|
||||||
)
|
)
|
||||||
const sourceNode = await createBufferSource(freq.toString(),ctx)
|
const sourceNode = await createBufferSource(freq.toString(),ctx)
|
||||||
const bandGainNode = ctx.createGain()
|
const bandGainNode = ctx.createGain()
|
||||||
// patch them together
|
// Schritt 5 Verbinde AudioNodes
|
||||||
sourceNode.node?.connect(bandGainNode)
|
sourceNode.node?.connect(bandGainNode)
|
||||||
bandGainNode.connect(masterGain)
|
bandGainNode.connect(masterGain)
|
||||||
//update the source list
|
//update the source list
|
||||||
|
@ -77,12 +83,9 @@ async function init() {
|
||||||
return {freq, device}
|
return {freq, device}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
newDevices.forEach(({freq, device}) => {
|
registerDevicesWithListeners(newDevices)
|
||||||
devices.set(freq, device)
|
|
||||||
})
|
|
||||||
console.log("RNBO Devices created")
|
console.log("RNBO Devices created")
|
||||||
|
|
||||||
await initMicrophone()
|
|
||||||
devices.forEach((devices, freq)=> {
|
devices.forEach((devices, freq)=> {
|
||||||
try{
|
try{
|
||||||
if(devices && devices.device) {
|
if(devices && devices.device) {
|
||||||
|
@ -94,9 +97,36 @@ async function init() {
|
||||||
})
|
})
|
||||||
console.log("Everything is setup, display a play button")
|
console.log("Everything is setup, display a play button")
|
||||||
setupPlayButton(sources, gains,ctx)
|
setupPlayButton(sources, gains,ctx)
|
||||||
|
|
||||||
masterGain.connect(ctx.destination)
|
masterGain.connect(ctx.destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables the Microphone to use it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function registerDevicesWithListeners(newDevices: { freq: number, device: any }[]) {
|
||||||
|
const devices = new Map<number, any>()
|
||||||
|
|
||||||
|
newDevices.forEach(({ freq, device }) => {
|
||||||
|
devices.set(freq, device)
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (device) {
|
||||||
|
attachDBValueListener(device, freq)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn(`Could not attach RNBO listener for ${freq}Hz`, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log("✅ RNBO Devices registered and listeners attached")
|
||||||
|
return devices
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables the Microphone to use it.
|
* Enables the Microphone to use it.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue