mirror of
https://github.com/kaythomas0/noisedash.git
synced 2025-11-11 19:06:20 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4642df353 | ||
|
|
aca7fbd1e0 | ||
|
|
90f4d50b7f | ||
|
|
66b23f39a6 | ||
|
|
4d22dab887 | ||
|
|
bc93b05c4e | ||
|
|
60a01908c2 | ||
|
|
5879e6d327 | ||
|
|
88cbfe0bf1 | ||
|
|
74c7d543c0 | ||
|
|
dc81a65c7a |
BIN
.github/noisedash-screenshot-4.png
vendored
Normal file
BIN
.github/noisedash-screenshot-4.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
@@ -11,7 +11,7 @@ Self-hostable web tool for generating ambient noises
|
||||
* Generate and customize ambient noises and user-uploadable samples (leveraging [Tone.js](https://github.com/Tonejs/Tone.js/))
|
||||
* Save "noise profiles" so you can easily switch between your created soundscapes. Import and export them for easy sharing, record them for use elsewhere
|
||||
* Fine-tune your noises with audio processing tools like filters, LFOs, and effects
|
||||
* Upload and edit audio samples (e.g rain, wind, thunder) to combine with your generated noises
|
||||
* Upload and edit audio samples (e.g rain, wind, thunder) to combine with your generated noises. Add effects to them and set playback modes
|
||||
* Use admin tools to manage multiple users
|
||||
* Mobile friendly
|
||||
|
||||
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "noisedash",
|
||||
"version": "0.6.0",
|
||||
"version": "0.6.2",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "noisedash",
|
||||
"version": "0.6.0",
|
||||
"version": "0.6.2",
|
||||
"private": true,
|
||||
"author": "Kay Thomas <kaythomas@pm.me> (https://kaythomas.dev)",
|
||||
"scripts": {
|
||||
|
||||
@@ -59,32 +59,46 @@ module.exports = function () {
|
||||
} else {
|
||||
const userVersion = row.user_version
|
||||
|
||||
if (userVersion < 1) {
|
||||
db.run('ALTER TABLE samples ADD COLUMN fade_in REAL DEFAULT 0')
|
||||
db.run('ALTER TABLE samples ADD COLUMN loop_points_enabled INTEGER DEFAULT 0')
|
||||
db.run('ALTER TABLE samples ADD COLUMN loop_start REAL DEFAULT 0')
|
||||
db.run('ALTER TABLE samples ADD COLUMN loop_end REAL DEFAULT 0')
|
||||
db.serialize(() => {
|
||||
if (userVersion < 1) {
|
||||
db.run('ALTER TABLE samples ADD COLUMN fade_in REAL DEFAULT 0')
|
||||
db.run('ALTER TABLE samples ADD COLUMN loop_points_enabled INTEGER DEFAULT 0')
|
||||
db.run('ALTER TABLE samples ADD COLUMN loop_start REAL DEFAULT 0')
|
||||
db.run('ALTER TABLE samples ADD COLUMN loop_end REAL DEFAULT 0')
|
||||
|
||||
db.run('PRAGMA user_version = 1')
|
||||
}
|
||||
db.run('PRAGMA user_version = 1')
|
||||
}
|
||||
|
||||
if (userVersion < 2) {
|
||||
db.run('ALTER TABLE users ADD COLUMN preferences TEXT DEFAULT "{}"')
|
||||
if (userVersion < 2) {
|
||||
db.run('ALTER TABLE users ADD COLUMN preferences TEXT DEFAULT "{}"')
|
||||
|
||||
db.run('PRAGMA user_version = 2')
|
||||
}
|
||||
db.run('PRAGMA user_version = 2')
|
||||
}
|
||||
|
||||
if (userVersion < 3) {
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN reverb_enabled INTEGER DEFAULT 0')
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN reverb_pre_delay REAL DEFAULT 0')
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN reverb_decay REAL DEFAULT 0')
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN reverb_wet INTEGER DEFAULT 0')
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN playback_mode TEXT DEFAULT "continuous"')
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN sporadic_min INTEGER DEFAULT 30')
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN sporadic_max INTEGER DEFAULT 300')
|
||||
if (userVersion < 3) {
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN reverb_enabled INTEGER DEFAULT 0')
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN reverb_pre_delay REAL DEFAULT 0')
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN reverb_decay REAL DEFAULT 0')
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN reverb_wet INTEGER DEFAULT 0')
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN playback_mode TEXT DEFAULT "continuous"')
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN sporadic_min INTEGER DEFAULT 30')
|
||||
db.run('ALTER TABLE profiles_samples ADD COLUMN sporadic_max INTEGER DEFAULT 300')
|
||||
|
||||
db.run('PRAGMA user_version = 3')
|
||||
}
|
||||
db.run('PRAGMA user_version = 3')
|
||||
}
|
||||
|
||||
if (userVersion < 4) {
|
||||
db.run('UPDATE users SET preferences = ? WHERE preferences = ?',
|
||||
['{"accentColor":{"alpha":1,"hex":"#607D8B","hexa":"#607D8BFF","hsla":{"h":200,"s":18,"l":46,"a":1},"hsva":{"h":200,"s":31,"v":55,"a":1},"hue":200,"rgba":{"r":96,"g":125,"b":139,"a":1}}}', '{}'],
|
||||
(err) => {
|
||||
if (err) {
|
||||
logger.error(err)
|
||||
} else {
|
||||
db.run('PRAGMA user_version = 4')
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -72,6 +72,8 @@ router.post('/users', (req, res) => {
|
||||
return res.sendStatus(500)
|
||||
}
|
||||
|
||||
const defaultPreferences = '{"accentColor":{"alpha":1,"hex":"#607D8B","hexa":"#607D8BFF","hsla":{"h":200,"s":18,"l":46,"a":1},"hsva":{"h":200,"s":31,"v":55,"a":1},"hue":200,"rgba":{"r":96,"g":125,"b":139,"a":1}}}'
|
||||
|
||||
if (row.count !== 0) {
|
||||
if (!req.user) {
|
||||
return res.sendStatus(401)
|
||||
@@ -94,15 +96,16 @@ router.post('/users', (req, res) => {
|
||||
return res.sendStatus(500)
|
||||
}
|
||||
|
||||
db.run(`INSERT INTO users (username, hashed_password, salt, name, is_admin, dark_mode, can_upload)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`, [
|
||||
db.run(`INSERT INTO users (username, hashed_password, salt, name, is_admin, dark_mode, can_upload, preferences)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
|
||||
req.body.username,
|
||||
hashedPassword,
|
||||
salt,
|
||||
req.body.name,
|
||||
req.body.isAdmin,
|
||||
req.body.darkMode,
|
||||
req.body.canUpload
|
||||
req.body.canUpload,
|
||||
defaultPreferences
|
||||
], (err) => {
|
||||
if (err) {
|
||||
logger.error(err)
|
||||
@@ -125,15 +128,16 @@ router.post('/users', (req, res) => {
|
||||
return res.sendStatus(500)
|
||||
}
|
||||
|
||||
db.run(`INSERT INTO users (username, hashed_password, salt, name, is_admin, dark_mode, can_upload)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`, [
|
||||
db.run(`INSERT INTO users (username, hashed_password, salt, name, is_admin, dark_mode, can_upload, preferences)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
|
||||
req.body.username,
|
||||
hashedPassword,
|
||||
salt,
|
||||
req.body.name,
|
||||
req.body.isAdmin,
|
||||
req.body.darkMode,
|
||||
req.body.canUpload
|
||||
req.body.canUpload,
|
||||
defaultPreferences
|
||||
], function (err) {
|
||||
if (err) {
|
||||
logger.error(err)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<v-row justify="center">
|
||||
<v-btn
|
||||
:disabled="playDisabled || !isTimerValid || !isSporadicValid"
|
||||
:disabled="playDisabled || !isTimerValid || (loadedSamples.length != 0 && !isSporadicValid)"
|
||||
class="mx-3 mb-5"
|
||||
fab
|
||||
large
|
||||
@@ -640,7 +640,7 @@
|
||||
v-if="canUpload"
|
||||
cols="12"
|
||||
>
|
||||
<h2 class="display-1 font-weight-bold mb-7">
|
||||
<h2 class="display-1 font-weight-bold mb-5">
|
||||
Samples
|
||||
</h2>
|
||||
|
||||
@@ -776,7 +776,6 @@
|
||||
</v-row>
|
||||
|
||||
<v-row
|
||||
justify="center"
|
||||
class="mb-5"
|
||||
>
|
||||
<v-radio-group
|
||||
@@ -785,11 +784,11 @@
|
||||
mandatory
|
||||
>
|
||||
<v-radio
|
||||
label="Continuous"
|
||||
label="Continuous (Looped)"
|
||||
value="continuous"
|
||||
/>
|
||||
<v-radio
|
||||
label="Sporadic"
|
||||
label="Sporadic (Not Looped, Plays Randomly Within Interval"
|
||||
value="sporadic"
|
||||
/>
|
||||
</v-radio-group>
|
||||
@@ -807,7 +806,7 @@
|
||||
label="Sporadic Min"
|
||||
class="mx-3"
|
||||
:disabled="sample.playbackMode != 'sporadic' || playDisabled"
|
||||
:rules="[validateSporadicRange(sample)]"
|
||||
:rules="[rules.gt(-1)]"
|
||||
/>
|
||||
|
||||
<v-text-field
|
||||
@@ -816,30 +815,13 @@
|
||||
label="Sporadic Max"
|
||||
class="mx-3"
|
||||
:disabled="sample.playbackMode != 'sporadic' || playDisabled"
|
||||
:rules="[validateSporadicRange(sample)]"
|
||||
:rules="[rules.gt(0)]"
|
||||
/>
|
||||
</v-row>
|
||||
</v-form>
|
||||
|
||||
<v-row
|
||||
justify="center"
|
||||
class="my-7"
|
||||
>
|
||||
<p
|
||||
v-if="sample.playbackMode != 'sporadic'"
|
||||
class="text--disabled"
|
||||
>
|
||||
(Sample will play randomly, every {{ sample.sporadicMin }} to {{ sample.sporadicMax }} seconds)
|
||||
</p>
|
||||
<p
|
||||
v-else
|
||||
>
|
||||
(Sample will play randomly, every {{ sample.sporadicMin }} to {{ sample.sporadicMax }} seconds)
|
||||
</p>
|
||||
</v-row>
|
||||
|
||||
<v-divider
|
||||
class="mb-7"
|
||||
class="mt-7"
|
||||
/>
|
||||
</v-container>
|
||||
</v-row>
|
||||
|
||||
@@ -155,11 +155,13 @@ export default {
|
||||
this.stop()
|
||||
},
|
||||
methods: {
|
||||
play () {
|
||||
async play () {
|
||||
if (!this.players.loaded) {
|
||||
return
|
||||
}
|
||||
|
||||
await Tone.start()
|
||||
|
||||
this.playDisabled = true
|
||||
Tone.Transport.cancel()
|
||||
|
||||
@@ -186,6 +188,18 @@ export default {
|
||||
this.lfo.connect(this.filter.frequency).start()
|
||||
}
|
||||
|
||||
if (this.isTimerEnabled) {
|
||||
this.duration = parseInt((this.hours * 3600)) + parseInt((this.minutes * 60)) + parseInt(this.seconds)
|
||||
this.timeRemaining = this.duration
|
||||
this.transportInterval = setInterval(() => this.stop(), this.duration * 1000 + 100)
|
||||
this.timeRemainingInterval = setInterval(() => this.startTimer(), 1000)
|
||||
Tone.Transport.loopEnd = this.duration
|
||||
|
||||
this.noise.sync().start(0).stop(this.duration)
|
||||
} else {
|
||||
this.noise.sync().start(0)
|
||||
}
|
||||
|
||||
this.loadedSamples.forEach(s => {
|
||||
this.players.player(s.id).loop = true
|
||||
this.players.player(s.id).fadeIn = s.fadeIn
|
||||
@@ -204,37 +218,27 @@ export default {
|
||||
} else {
|
||||
this.players.player(s.id).toDestination()
|
||||
}
|
||||
})
|
||||
|
||||
if (this.isTimerEnabled) {
|
||||
this.duration = parseInt((this.hours * 3600)) + parseInt((this.minutes * 60)) + parseInt(this.seconds)
|
||||
this.noise.sync().start(0).stop(this.duration)
|
||||
Tone.Transport.loopEnd = this.duration
|
||||
this.timeRemaining = this.duration
|
||||
this.transportInterval = setInterval(() => this.stop(), this.duration * 1000 + 100)
|
||||
this.timeRemainingInterval = setInterval(() => this.startTimer(), 1000)
|
||||
if (s.playbackMode === 'sporadic') {
|
||||
this.players.player(s.id).loop = false
|
||||
|
||||
this.loadedSamples.forEach(s => {
|
||||
this.players.player(s.id).unsync().sync().start(0).stop(this.duration)
|
||||
})
|
||||
} else {
|
||||
this.noise.sync().start(0)
|
||||
const maxInt = parseInt(s.sporadicMax, 10)
|
||||
const minInt = parseInt(s.sporadicMin, 10)
|
||||
|
||||
this.loadedSamples.forEach(s => {
|
||||
if (s.playbackMode === 'sporadic') {
|
||||
this.players.player(s.id).loop = false
|
||||
|
||||
const maxInt = parseInt(s.sporadicMax, 10)
|
||||
const minInt = parseInt(s.sporadicMin, 10)
|
||||
if (minInt <= maxInt) {
|
||||
const rand = Math.floor(Math.random() * (maxInt - minInt + 1) + minInt)
|
||||
|
||||
s.initialSporadicPlayInterval = setInterval(() => this.playSporadicSample(s.id), rand * 1000)
|
||||
}
|
||||
} else {
|
||||
this.players.player(s.id).loop = true
|
||||
|
||||
if (this.isTimerEnabled) {
|
||||
this.players.player(s.id).unsync().sync().start(0).stop(this.duration)
|
||||
} else {
|
||||
this.players.player(s.id).loop = true
|
||||
this.players.player(s.id).unsync().sync().start(0)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Tone.Transport.start('+0.1')
|
||||
},
|
||||
@@ -902,15 +906,6 @@ export default {
|
||||
this.selectedProfile = this.profileItems.find(p => p.text === this.activeProfile.name)
|
||||
this.updateProfile()
|
||||
this.confirmSwitchProfileDialog = false
|
||||
},
|
||||
validateSporadicRange (sample) {
|
||||
const min = parseInt(sample.sporadicMin, 10)
|
||||
const max = parseInt(sample.sporadicMax, 10)
|
||||
if (isNaN(min) || isNaN(max) || max <= min || min <= 0 || max <= 0) {
|
||||
return 'Invalid'
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user