soundsurgeon HTML5合成器
JS-11-16单声道:由Web Audio API创建的电子乐器,它生活在soundsurgeon .com上。
它始于我在2016 - 17年参加的大会JavaScript开发课程的最后一个项目。
此应用中使用的JavaScript库:
- tone.js声音合成
- teoria.js生成量表和模式
- UI和活动处理的jQuery
- 高级键盘事件处理的键盘
- Vite构建工具
JS-11-16 Monosynth是一种乐器,可让用户使用Qwerty键盘的主排或通过屏幕上的按钮弹奏八度音符。
该HTML5应用程序使用Web音频API在浏览器中生成声音而无需使用音频文件。 Web音频API允许以1960年代和70年代的模拟模块化合成器的方式进行减法合成: Moog , Buchla等。
在Web音频API中, AudioContext对象是一个音频处理接口,由相互连接的音频模块组成,例如模块化合成器。这些模块(称为节点)是使用构造方法方法创建的,而其他AudioContext方法连接并操纵节点。
// create AudioContext
var a = new AudioContext ( ) ;
// create GainNode
var g = a . createGain ( ) ;
// create OscillatorNode
var o = a . createOscillator ( ) ;
// set OscillatorNode.type to 'sine'
o . type = 'sine' ;
// OscillatorNode.frequency.value in Hertz
o . frequency . value = '1000' ;
// connect OscillatorNode to GainNode
o . connect ( g ) ;
// connect GainNode to AudioDestinationNode
g . connect ( a . destination ) ;
// GainNode gain value range: 0 = 0%, 1 = 100%
g . gain . value = 0 ;
// start OscillatorNode instantly
o . start ( 0 ) ; Tone.js是一个将Web音频API AudioContext和节点抽象到Tone对象中的框架,其中包含诸如Instrument和Effect的对象类型,在音乐环境中更易于使用。例如,您可以使用科学音调符号选择音符来选择频率,也可以像分数一样定义音符持续时间:
// Tone.js "Hello World"
// create a synth and connect it to the destination (your speakers)
var synth = new Tone . Synth ( ) . toDestination ( ) ;
// play a middle 'C' for the duration of an 8th note
synth . triggerAttackRelease ( "C4" , "8n" ) ;在App.init中, App.synthObj被分配了一个Tone.MonoSynth仪器的实例。
- 一个振荡器
- 连接到振幅信封
- 连接到由自己的信封控制的过滤器
- 连接到
Tone.Destination输出对象。
Tone.js API描述了可用于Tone组件的各种方法和参数。主要Tone.MonoSynth单一声音参数是:
- 振荡器
- 静音按钮
- 音量滑块
- 波形:
- 正弦
- 正方形(默认)
- 三角形
- 锯齿
- 解剖
- 滑音
- 振幅信封
- 攻击
- 衰变
- 维持
- 发布
- 过滤信封
- 攻击
- 衰变
- 维持
- 发布
- “问”
用户界面用于生活在index.html中,但现在通过App.view中的模板字符串生成。 HTML5 元素用于控制以下参数:
- 静音按钮的
checkbox -
radio选择 - 所有其他参数的
range滑块
App.init中调用的App.initControls方法。INIT接受tone.js Synth对象作为参数,获取合成器的声音参数,并调整UI以使用jQuery方法来表示这些值:
initControls: function ( synth ) {
var initWaveform = 'input[value="' + synth . oscillator . type + '"]' ;
$ ( initWaveform ) . attr ( 'checked' , 'checked' ) ;
$ ( '.envelope .attack' ) . val ( synth . envelope . attack ) ;
$ ( '.envelope .sustain' ) . val ( synth . envelope . sustain ) ;
$ ( '.envelope .decay' ) . val ( synth . envelope . decay ) ;
$ ( '.envelope .release' ) . val ( synth . envelope . release ) ;
$ ( '.portamento' ) . val ( synth . portamento ) ;
$ ( '.detune' ) . val ( synth . detune . value ) ;
$ ( '.filter .q' ) . val ( synth . filter . Q . value ) ;
$ ( '.filter-envelope .attack' ) . val ( synth . filterEnvelope . attack ) ;
$ ( '.filter-envelope .sustain' ) . val ( synth . filterEnvelope . sustain ) ;
$ ( '.filter-envelope .decay' ) . val ( synth . filterEnvelope . decay ) ;
$ ( '.filter-envelope .release' ) . val ( synth . filterEnvelope . release ) ;
} App.init中调用的App.bindEvents方法也接受tone.js synth对象作为参数,并包含在UI元素更改时处理事件侦听器的代码:
$ ( '.mute' ) . change ( function ( e ) {
if ( $ ( this ) . is ( ':checked' ) ) {
Tone . Destination . mute = true ;
} else {
Tone . Destination . mute = false ;
}
} ) ;
$ ( '.volume' ) . change ( function ( e ) {
Tone . Destination . volume . value = $ ( this ) . val ( ) ;
} ) ;
$ ( '.waveforms input' ) . change ( function ( e ) {
var waveform = $ ( this ) . val ( ) ;
synth . oscillator . type = waveform ;
} ) ;
$ ( '.envelope input' ) . change ( function ( e ) {
var controlName = this . name ;
var controlValue = $ ( this ) . val ( ) ;
var currentEnv = synth . envelope ;
currentEnv [ controlName ] = controlValue ;
} ) ;
$ ( '.portamento' ) . change ( function ( e ) {
synth . portamento = $ ( this ) . val ( ) ;
} ) ;
$ ( '.detune' ) . change ( function ( e ) {
synth . detune . value = $ ( this ) . val ( ) ;
} ) ;
$ ( '.filter .q' ) . change ( function ( e ) {
synth . filter . Q . value = $ ( this ) . val ( ) ;
} ) ;
$ ( '.filter-envelope input' ) . change ( function ( e ) {
var controlName = this . name ;
var controlValue = $ ( this ) . val ( ) ;
var currentEnv = synth . filterEnvelope ;
currentEnv [ controlName ] = controlValue ;
} ) ; App.bindEvents还使用键盘键,这是一个键绑定库,最重要的是允许.preventRepeat()方法在按键下键时禁用密钥重复。主排键的名称保存在CONSTANTS对象中的变量中,而音调触发器都附加到键绑定和 ui元素的元素。
CONSTANTS . HOME_ROW . forEach ( function ( elem , i ) {
keyboardJS . bind ( elem , function ( e ) {
e . preventRepeat ( ) ;
synth . triggerAttack ( App . currentScale [ i ] ) ;
$ ( keybtns ) . removeClass ( 'active' ) ;
$ ( keybtns [ i ] ) . addClass ( 'active' ) ;
} ,
function ( event ) {
$ ( keybtns [ i ] ) . removeClass ( 'active' ) ;
synth . triggerRelease ( ) ;
} ) ;
} ) ;
document . querySelectorAll ( '.keyboard label' ) . forEach ( function ( elem , i ) {
elem . addEventListener ( 'mousedown' , function ( e ) {
synth . triggerAttack ( App . currentScale [ i ] ) ;
} ) ;
elem . addEventListener ( 'mouseup' , function ( e ) {
synth . triggerRelease ( ) ;
} ) ;
} ) ; teoria.js是一个图书馆,允许在西方音乐理论背景下进行编程。在开发的早期, CONSTANTS.DEFAULT_SCALE数组为该应用提供了Tone对象所需的注释来创建完整的比例。 teoria.js允许对象表示尺度,注释和间隔,并且可以像jQuery一样将对象链接在一起。 App.generateScale方法现在返回用于创建注释的数组,以便将来,用户可以选择他们想要控制键盘的补品音符,八度和比例尺。
generateScale: function ( tonic , scaleType ) {
var tonicObj = teoria . note ( tonic ) ;
var scaleObj = tonicObj . scale ( scaleType ) ;
var notesArr = scaleObj . notes ( ) ;
var noteNamesArr = [ ] ;
notesArr . forEach ( function ( e , i ) {
noteNamesArr . push ( e . scientific ( ) ) ;
} ) ;
noteNamesArr . push ( teoria . interval ( tonicObj , 'P8' ) . scientific ( ) ) ;
return noteNamesArr ;
}该应用程序可能会有许多不同的方向:
- 通过JS生成UI
- 添加效果和复音
- 允许保存和回忆补丁
- 添加和弦Arpeggator或Suequencer
- 添加Web MIDI API支持,以便可以使用MIDI键盘播放合成器
上次更新:2023-12-23 07:25 UTC
通过命令行克隆项目: