Skip to content

Commit

Permalink
Move non-algorithmic aperiodic timbres to the JSON file
Browse files Browse the repository at this point in the history
  • Loading branch information
frostburn committed Jan 26, 2025
1 parent b828e6b commit 7ff9e2f
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 71 deletions.
90 changes: 19 additions & 71 deletions src/synth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,27 @@ import { computed, type ComputedRef } from 'vue'
import TIMBRES from '@/timbres.json'

type Spectrum = number[]
type Timbre = { spectrum: Spectrum; amplitudes: number[]; source?: string }

type Timbres = {
plainSpectra: { [key: string]: Spectrum }
// TODO: Migrate inharmonic metallic and some other timbral data
timbres: { [key: string]: Timbre }
}

function getPlainSpectrum(id: string): Spectrum {
return (TIMBRES as unknown as Timbres).plainSpectra[id]
}

function getPlainSpectraWaveformNames(): string[] {
return Object.keys((TIMBRES as unknown as Timbres).plainSpectra)
return Object.keys((TIMBRES as unknown as Timbres).plainSpectra).sort()
}

function getTimbre(id: string): Timbre {
return (TIMBRES as unknown as Timbres).timbres[id]
}

function getTimbreWaveformNames(): string[] {
return Object.keys((TIMBRES as unknown as Timbres).timbres).sort()
}

export const BASIC_WAVEFORMS = ['sine', 'square', 'sawtooth', 'triangle']
Expand Down Expand Up @@ -49,6 +58,7 @@ export const CUSTOM_WAVEFORMS = [
export const WAVEFORMS = BASIC_WAVEFORMS.concat(CUSTOM_WAVEFORMS)
export const PERIODIC_WAVES: Record<string, ComputedRef<PeriodicWave>> = {}

// Some of these have entries in timbres.json, but we preserve the old UI order.
export const APERIODIC_WAVEFORMS = [
'jegogan',
'jublag',
Expand Down Expand Up @@ -332,55 +342,6 @@ function initializeAperiodic(audioContext: BaseAudioContext) {
return new AperiodicWave(audioContext, spectrum, amplitudes, maxNumberOfVoices, tolerance)
})

// https://pubs.aip.org/asa/jasa/article/127/5/EL197/783208/Vibrational-characteristics-of-Balinese-gamelan
APERIODIC_WAVES['jublag'] = computed(() => {
// Spectrum is from literature
const spectrum = [1, 2.77, 5.18, 5.33]
// Made up stuff to round it off
spectrum.push(9.1, 18.9, 23)
// Add shimmer
spectrum[0] = 1.01
spectrum.unshift(1 / spectrum[0])
spectrum.push(2.76)

// Amplitudes are made up
const amplitudes = [1, 0.5, 0.5, 0.3, 0.2, 0.15, 0.1, 0.09, 0.2].map((a) => 0.45 * a)

return new AperiodicWave(audioContext, spectrum, amplitudes, maxNumberOfVoices, tolerance)
})

// https://pubs.aip.org/asa/jasa/article/127/5/EL197/783208/Vibrational-characteristics-of-Balinese-gamelan
APERIODIC_WAVES['ugal'] = computed(() => {
// Spectrum is from literature
const spectrum = [1, 2.61, 4.8, 4.94, 6.32]
// Made up stuff to round it off
spectrum.push(9.9, 17, 24.1)
// Add shimmer
spectrum[0] = 1.008
spectrum.unshift(1 / spectrum[0])
spectrum.push(2.605)
spectrum.push(4.81)

// Amplitudes are made up
const amplitudes = [0.6, 1, 0.45, 0.3, 0.15, 0.2, 0.07, 0.08, 0.05, 0.1, 0.1].map(
(a) => 0.45 * a
)

return new AperiodicWave(audioContext, spectrum, amplitudes, maxNumberOfVoices, tolerance)
})

// https://pubs.aip.org/asa/jasa/article/127/5/EL197/783208/Vibrational-characteristics-of-Balinese-gamelan
APERIODIC_WAVES['jegogan'] = computed(() => {
// Spectrum is from literature
const spectrum = [
1, 2.8, 5.5, 9, 16.7, 17.8, 20.5, 22.9, 24.9, 27, 28.1, 29.2, 29.5, 30, 31.8, 33.3, 36, 36.9,
40.6, 41.4
]
// Amplitudes are made up
const amplitudes = spectrum.map((i) => (0.7 * (Math.cos(0.3 * i * i) + 1.6)) / (i ** 1.4 + 1.6))
return new AperiodicWave(audioContext, spectrum, amplitudes, maxNumberOfVoices, tolerance)
})

APERIODIC_WAVES['12-TET'] = computed(() => {
const twelveSpectrumCents: number[] = []
const twelveAmplitudes: number[] = []
Expand All @@ -405,26 +366,6 @@ function initializeAperiodic(audioContext: BaseAudioContext) {
)
})

APERIODIC_WAVES['piano'] = computed(() => {
const spectrum = [
0.998711340392508, 1.0012886596074921, 2.000000001915048, 3.0077319605175252,
4.024484537329971, 4.028350517109971, 5.052835053482418, 6.0953608281898495,
6.100515466619817, 7.149484540322233, 7.158505158532202, 8.221649488874554, 9.326030932401801,
9.3298969121818, 9.33891753039177, 10.449742272914, 10.457474232474, 10.466494850683969,
11.597938150756168
]

const amps = [
0.9123120265773679, 0.7281477301038842, 0.5078045641543809, 0.8061314224800064,
0.3177244232370868, 0.15135058363038334, 0.12440135191000032, 0.045007651288955175,
0.050804443667738106, 0.029671376885221354, 0.023841125287306208, 0.01853341284211317,
0.02380292893502422, 0.024761095205029133, 0.020866326567241505, 0.0017670624571622458,
0.0024893662658642206, 0.0012043792096897129, 0.0014228119365412375
].map((a) => a * 0.38)

return new AperiodicWave(audioContext, spectrum, amps, maxNumberOfVoices, tolerance)
})

getPlainSpectraWaveformNames().forEach((id) => {
APERIODIC_WAVES[id] = computed(() => {
const spectrum = getPlainSpectrum(id)
Expand All @@ -436,6 +377,13 @@ function initializeAperiodic(audioContext: BaseAudioContext) {
return new AperiodicWave(audioContext, spectrum, amps, maxNumberOfVoices, tolerance)
})
})

getTimbreWaveformNames().forEach((id) => {
APERIODIC_WAVES[id] = computed(() => {
const { spectrum, amplitudes } = getTimbre(id)
return new AperiodicWave(audioContext, spectrum, amplitudes, maxNumberOfVoices, tolerance)
})
})
}

export function initializeCustomWaves(audioContext: BaseAudioContext) {
Expand Down
42 changes: 42 additions & 0 deletions src/timbres.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,47 @@
47.864014, 48.864014, 50.329585, 51.329585, 52.477484, 53.477484, 54.625383, 55.625383,
56.625383, 57.773282, 58.773282
]
},
"timbres": {
"jegogan": {
"spectrum": [
1, 2.8, 5.5, 9, 16.7, 17.8, 20.5, 22.9, 24.9, 27, 28.1, 29.2, 29.5, 30, 31.8, 33.3, 36,
36.9, 40.6, 41.4
],
"amplitudes": [
0.6879752086107401, 0.10762266937637699, 0.03705915578882312, 0.06835927457535572,
0.01577978118293504, 0.027725128514115686, 0.025086932797794458, 0.022017323971778323,
0.0061329366021215925, 0.013327650595532958, 0.008386387560340483, 0.008303976140444933,
0.0039384178057395615, 0.015261008676063096, 0.007590483984245218, 0.01299488244216124,
0.010676041856564743, 0.011516704413238312, 0.005093296889963593, 0.007984328157770058
],
"source": "https://pubs.aip.org/asa/jasa/article/127/5/EL197/783208/Vibrational-characteristics-of-Balinese-gamelan (amplitudes are made up)"
},
"jublag": {
"spectrum": [0.9901, 1.01, 2.76, 2.77, 5.18, 5.33, 9.1, 18.9, 23],
"amplitudes": [0.45, 0.225, 0.09, 0.225, 0.135, 0.09, 0.0675, 0.045, 0.0405],
"source": "https://pubs.aip.org/asa/jasa/article/127/5/EL197/783208/Vibrational-characteristics-of-Balinese-gamelan (shimmer and amplitudes are made up)"
},
"ugal": {
"spectrum": [0.9921, 1.008, 2.605, 2.61, 4.8, 4.81, 4.94, 6.32, 9.9, 17, 24.1],
"amplitudes": [0.27, 0.45, 0.045, 0.2025, 0.135, 0.045, 0.0675, 0.09, 0.0315, 0.036, 0.0225],
"source": "https://pubs.aip.org/asa/jasa/article/127/5/EL197/783208/Vibrational-characteristics-of-Balinese-gamelan (shimmer and amplitudes are made up)"
},
"piano": {
"spectrum": [
0.998711340392508, 1.0012886596074921, 2.000000001915048, 3.0077319605175252,
4.024484537329971, 4.028350517109971, 5.052835053482418, 6.0953608281898495,
6.100515466619817, 7.149484540322233, 7.158505158532202, 8.221649488874554,
9.326030932401801, 9.3298969121818, 9.33891753039177, 10.449742272914, 10.457474232474,
10.466494850683969, 11.597938150756168
],
"amplitudes": [
0.3466785700993998, 0.276696137439476, 0.19296573437866474, 0.3063299405424024,
0.12073528083009298, 0.05751322177954567, 0.047272513725800124, 0.017102907489802966,
0.019305688593740482, 0.011275123216384115, 0.00905962760917636, 0.007042696880003005,
0.009045112995309204, 0.009409216177911071, 0.007929204095551772, 0.0006714837337216534,
0.0009459591810284039, 0.0004576640996820909, 0.0005406685358856703
]
}
}
}

0 comments on commit 7ff9e2f

Please sign in to comment.