8 changed files with 288 additions and 26 deletions
@ -0,0 +1,23 @@ |
|||
{ |
|||
// Verwendet IntelliSense zum Ermitteln möglicher Attribute. |
|||
// Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen. |
|||
// Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387 |
|||
"version": "0.2.0", |
|||
"configurations": [ |
|||
{ |
|||
"name": "Debug Hare Dev", |
|||
"type": "node", |
|||
"request": "launch", |
|||
"protocol": "inspector", |
|||
"program": "${workspaceRoot}/node_modules/nuxt/bin/nuxt", |
|||
"stopOnEntry": false, |
|||
"args": ["dev"], |
|||
"cwd": "${workspaceRoot}", |
|||
"sourceMaps": true, |
|||
"env": { |
|||
"NODE_ENV": "development", |
|||
"DEBUG": "nuxt:*,app" |
|||
} |
|||
} |
|||
] |
|||
} |
@ -0,0 +1,188 @@ |
|||
<template> |
|||
<v-layout column justify-center align-left> |
|||
<v-flex xs12 sm8 md6> |
|||
<h3 class="display-3">Bytebeat Generator</h3> |
|||
<span class="subheading">This small tool can create music from a single JavaScript Expression.</span> |
|||
<v-divider class="my-3"></v-divider> |
|||
<v-select |
|||
v-model="example" |
|||
prepend-icon="mdi-file-music" |
|||
:items="examples" |
|||
item-text="name" |
|||
label="Examples" |
|||
> |
|||
</v-select> |
|||
<v-btn @click="loadExample(example)">Load</v-btn><v-btn>Save As...</v-btn><v-btn @click="reset()">Reset</v-btn> |
|||
<v-divider class="my-3"></v-divider> |
|||
<v-form> |
|||
<v-select |
|||
v-model="frequency" |
|||
prepend-icon="mdi-waves" |
|||
:items="frequencies" |
|||
label="Frequency (Hz)" |
|||
> |
|||
</v-select> |
|||
<v-text-field |
|||
v-model="duration" |
|||
label="Duration (seconds)" |
|||
placeholder="30" |
|||
prepend-icon="timer" |
|||
></v-text-field> |
|||
<v-text-field |
|||
v-model="ft" |
|||
label="JavaScript function (t)=" |
|||
value='w=t>>9,k=32,m=2048,a=1-t/m%1,d=(14*t*t^t)%m*a,y=[3,3,4.7,2][p=w/k&3]*t/4,h="IQNNNN!!]]!Q!IW]WQNN??!!W]WQNNN?".charCodeAt(w/2&15|p/3<<4)/33*t-t,s=y*.98%80+y%80+(w>>7&&a*((5*t%m*a&128)*(0x53232323>>w/4&1)+(d&127)*(0xa444c444>>w/4&1)*1.5+(d*w&1)+(h%k+h*1.99%k+h*.49%k+h*.97%k-64)*(4-a-a))),s*s>>14?127:s' |
|||
hint="The variable t determines how the function behaves" |
|||
></v-text-field> |
|||
<v-btn @click="generate()">Generate</v-btn> |
|||
<v-slider |
|||
label="Time" |
|||
v-model="runTime" |
|||
:max="duration" |
|||
></v-slider> |
|||
<v-slider |
|||
v-model="volume" |
|||
v-on:input="setVolume" |
|||
label="Volume" |
|||
append-icon="volume_up" |
|||
prepend-icon="volume_down" |
|||
></v-slider> |
|||
<v-btn-toggle v-model="playBtn" multiple> |
|||
<v-btn flat @click="play()"> |
|||
<v-icon>mdi-play-pause</v-icon> |
|||
</v-btn> |
|||
</v-btn-toggle> |
|||
<v-btn-toggle v-model="muteBtn" multiple> |
|||
<v-btn flat @click="mute()"> |
|||
<v-icon>mdi-volume-off</v-icon> |
|||
</v-btn> |
|||
</v-btn-toggle> |
|||
</v-form> |
|||
</v-flex> |
|||
</v-layout> |
|||
</template> |
|||
<script> |
|||
/* eslint no-eval: 0 */ |
|||
/* eslint no-debugger: 0 */ |
|||
export default { |
|||
data: () => ({ |
|||
examples: [ |
|||
{ |
|||
name: 'Empty', |
|||
frequency: '8000', |
|||
duration: '30', |
|||
expression: '' |
|||
}, |
|||
{ |
|||
name: 'Chaos Theory', |
|||
frequency: '8000', |
|||
duration: '30', |
|||
expression: 'w=t>>9,k=32,m=2048,a=1-t/m%1,d=(14*t*t^t)%m*a,y=[3,3,4.7,2][p=w/k&3]*t/4,h="IQNNNN!!]]!Q!IW]WQNN??!!W]WQNNN?".charCodeAt(w/2&15|p/3<<4)/33*t-t,s=y*.98%80+y%80+(w>>7&&a*((5*t%m*a&128)*(0x53232323>>w/4&1)+(d&127)*(0xa444c444>>w/4&1)*1.5+(d*w&1)+(h%k+h*1.99%k+h*.49%k+h*.97%k-64)*(4-a-a))),s*s>>14?127:s' |
|||
}, |
|||
{ |
|||
name: 'Dante\'s Inferno', |
|||
frequency: '8000', |
|||
duration: '30', |
|||
expression: '((t*(t>>12)&(201*t/100)&(199*t/100))&(t*(t>>14)&(t*301/100)&(t*399/100)))+((t*(t>>16)&(t*202/100)&(t*198/100))-(t*(t>>17)&(t*302/100)&(t*298/100)))' |
|||
} |
|||
], |
|||
ft: '', |
|||
example: '', |
|||
duration: 30, |
|||
runTime: 'Jew', |
|||
frequency: 8000, |
|||
playBtn: [], |
|||
muteBtn: [], |
|||
frequencies: ['8000', '11025', '16000', '22050', '32000', '37800', '44056', '44100', '47250', '48000', '50000', '50400', '88200', '96000', '176400', '192000'], |
|||
audioCtx: '', |
|||
source: '', |
|||
gainNode: '', |
|||
volume: 50, |
|||
sampleBuffer: [] |
|||
}), |
|||
methods: { |
|||
loadExample (example) { |
|||
this.runTime = 0 |
|||
this.duration = example.duration |
|||
this.frequency = example.frequency |
|||
this.ft = example.expression |
|||
}, |
|||
generateMusicArray () { |
|||
this.sampleBuffer = [] |
|||
let f |
|||
eval('f = function (t) { return ' + this.ft + '}') |
|||
for (let t = 0; t < this.frequency * this.duration; t++) { |
|||
let sample = f(t) |
|||
sample = (sample & 0xff) * 256 |
|||
if (sample < 0) sample = 0 |
|||
if (sample > 65535) sample = 65535 |
|||
this.sampleBuffer.push(sample / 65535) |
|||
} |
|||
}, |
|||
generate () { |
|||
this.audioCtx.suspend() |
|||
if (this.playBtn.length === 1) { |
|||
this.pause() |
|||
this.playBtn = [] |
|||
} |
|||
this.source = this.audioCtx.createBufferSource() |
|||
this.source.onended = (event) => { |
|||
this.audioCtx.suspend() |
|||
this.playBtn = [] |
|||
this.generate() |
|||
} |
|||
this.generateMusicArray() |
|||
let audioBuffer = this.audioCtx.createBuffer(2, this.frequency * this.duration, this.frequency) |
|||
for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) { |
|||
let channelBuffer = audioBuffer.getChannelData(channel) |
|||
for (let i = 0; i < audioBuffer.length; i++) { |
|||
channelBuffer[i] = this.sampleBuffer[i] |
|||
} |
|||
} |
|||
this.source.buffer = audioBuffer |
|||
this.source.connect(this.gainNode) |
|||
this.source.start(0) |
|||
}, |
|||
play () { |
|||
if (!this.source.buffer) { |
|||
this.generate() |
|||
} |
|||
this.pause() |
|||
}, |
|||
pause () { |
|||
if (this.audioCtx.state === 'running') { |
|||
this.audioCtx.suspend() |
|||
} else if (this.audioCtx.state === 'suspended') { |
|||
this.audioCtx.resume() |
|||
} |
|||
}, |
|||
mute () { |
|||
if (this.muteBtn.length === 0) { |
|||
this.gainNode.gain.value = 0 |
|||
} else { |
|||
this.gainNode.gain.value = this.volume / 100.0 |
|||
} |
|||
}, |
|||
reset () { |
|||
this.example = this.examples[0] |
|||
this.loadExample(this.example) |
|||
}, |
|||
setVolume (something) { |
|||
this.muteBtn = [] |
|||
this.gainNode.gain.value = something / 100.0 |
|||
} |
|||
|
|||
}, |
|||
mounted () { |
|||
// Load Example |
|||
this.example = this.examples[0] |
|||
this.loadExample(this.example) |
|||
if (process.browser) { |
|||
this.audioCtx = new (window.AudioContext || window.webkitAudioContext)() |
|||
this.audioCtx.suspend() |
|||
this.gainNode = this.audioCtx.createGain() |
|||
this.gainNode.connect(this.audioCtx.destination) |
|||
} |
|||
} |
|||
} |
|||
</script> |
@ -1,16 +0,0 @@ |
|||
<template> |
|||
<v-layout column justify-center align-center> |
|||
<v-flex xs12 sm8 md6> |
|||
<v-jumbotron> |
|||
<v-container fill-height> |
|||
<v-layout align-center> |
|||
<v-flex> |
|||
<h3 class="display-3">Featured Projects</h3> |
|||
<span class="subheading">More content will follow soon</span> |
|||
</v-flex> |
|||
</v-layout> |
|||
</v-container> |
|||
</v-jumbotron> |
|||
</v-flex> |
|||
</v-layout> |
|||
</template> |
@ -0,0 +1,12 @@ |
|||
import Vue from 'vue' |
|||
import { Line } from 'vue-chartjs' |
|||
import zoomPlugin from 'chartjs-plugin-zoom' |
|||
|
|||
Vue.component('LineChart', { |
|||
extends: Line, |
|||
props: ['data', 'options'], |
|||
mounted () { |
|||
this.addPlugin(zoomPlugin) |
|||
this.renderChart(this.data, this.options) |
|||
} |
|||
}) |
Loading…
Reference in new issue