New major features

Support for other synth types
Added a universal silence function (necessary for "pluck" type)
Did away with the unnecessary soxpipes variable
Support two-note harmonies (see pokemon-gsc-mainmenu for example)
Support flat notes
Auto-reset the notes array after calling createSoxPipes
To distinguish between nonlooped and looped melodies, you now have
 to call an empty echo. Better solution than putting a newline at
 the start of the output. See sleeping-terror.sh for example.
This commit is contained in:
Job Bautista 2022-04-16 10:43:18 +08:00
parent 077e12670e
commit 67ff915bf1
6 changed files with 146 additions and 25 deletions

36
README
View File

@ -4,6 +4,30 @@ libsox.sh
A library for GNU bash making it easier to create music with the power of SoX
synths.
If you're one of these people:
- a Bash programmer
- suck at reading sheet music
- finds MML too difficult
- too lazy to learn FamiTracker
- think that scientific note duration is the best thing since sliced bread
Then try this crappy library of mine!
Some features of this library:
- Easy to write syntax for inputting notes ("$duration:${key[pitch]}")
- Inspired from korobeiniki.sh of the dsuni/bashtris repository
- Supports two-note harmonies ("$duration:${key1[pitch1]},${key2[pitch2]}")
- Supports every synth type included in SoX
- Adheres to the Unix philosophy of "do one thing and do it well"
What this library doesn't support:
- Using your own samples (just use FamiTracker or a DAW for that)
- Harmonies with more than two notes
- POSIX compatibility
Usage
-----
@ -63,7 +87,8 @@ notes=(
"$si:${c[5]}" # A sixteenth C note in the 5th octave
"$ei:${gs[4]}" # An eighth G sharp in 4th octave
"$qu:${fs[4]}"
"$qu:${gf[4]}" # A quarter G flat in 4th octave
"$qu:${gb[4]}" # Also a G flat
)
function repeatingNotes { # Use bash functions to repeat parts of your music
@ -87,16 +112,17 @@ notes+=(
"$dei:${b[2]}" # Dotted notes are supported
"$tqu:${a[3]}" # Triplets are supported
"0.02:${gs[4]}" # You can do custom durations
"0.05:489 # Custom frequencies too, though I'm not sure why you'd do that
"0.05:489 # Custom frequencies too
)
createSoxPipes # Useful for dividing the part that loops and the part that doesn't
createSoxPipes # Will reset the notes array too
echo # Useful for distinguishing the part that loops and the part that doesn't
# Loop start
setTempo 160 # Change the BPM if needed
notes=( # Don't forget to reset the notes array. Don't append.
"$dei:${fs[5]}"
notes+=(
"$dei:${fs[5]},${gs[5]}" # You can do two-note harmonies
"$dei:${c[6]}"
"$ei:${as[5]}"
"$ha:${as[5]}"

View File

@ -41,6 +41,8 @@ Arranged by Job Bautista
setTempo 150
setDefaultSynthType sin
# intro
function intro-ccg {
notes+=(
@ -79,9 +81,8 @@ notes+=(
"$qu:${g[4]}"
)
createSoxPipes # loop no $1
notes=()
createSoxPipes
echo
# verse 1
function verse1-common {
@ -250,4 +251,4 @@ notes+=(
"$qu:${g[4]}"
)
createSoxPipes # loop yes $1
createSoxPipes

View File

@ -37,7 +37,15 @@ a=(27 55 110 220 440 880 1760 3520 7040)
as=(29 58 116 233 466 932 1864 3729 7458)
b=(30 61 123 246 493 987 1975 3951 7902)
declare -rg c cs d ds e f g gs a as b
# flats as references to their respective sharps
declare -n df db ef eb gf gb af ab bf bb
df="cs" db="cs"
ef="ds" eb="ds"
gf="fs" gb="fs"
af="gs" ab="gs"
bf="as" bb="as"
declare -rg c cs d ds e f g gs a as b df db ef eb gf gb af ab bf bb
function setTempo {
declare -g BPM=$1
@ -57,17 +65,34 @@ function setTempo {
declare -g tsi=$(echo "scale=3; 10 / $BPM" | bc -l) # Triplet-sixteenth note
}
declare -a notes # In the following format - "$duration:${key}[pitch]"
declare -ag notes # In the following format - "$duration:${key[pitch]}"
# For a harmony - "$duration:${key1[pitch1]},${key2[pitch2]}"
declare -g defaultsynth="sin" # for backwards compatibility with previous
synthtype="$defaultsynth" # child scripts that only used sine
function setDefaultSynthType {
defaultsynth=$1
synthtype="$defaultsynth"
}
function silence { # needed because pluck synth doesn't support zero frequency
declare -n duration=$1 # we want $1 to be recognized as a variable name
createSoxPipes # necessary because we will be changing synth type
synthtype="sin" # sin, square, sawtooth, trapezium, and exp support freq=0
notes+=( "$duration:0" )
createSoxPipes # get the silence printed before we return to default synth
synthtype="$defaultsynth"
}
function createSoxPipes {
declare soxpipes
soxpipes=$(printf '\n"|sox -n -p synth '$(echo "${notes[0]}" |
sed 's/:.*//')' sin '$(echo "${notes[0]}" | sed 's/.*://')'"\n')
for note in "${notes[@]:1}"
for note in "${notes[@]}"
do
soxpipes+=$(printf '%b' '\n"|sox -n -p synth '$(echo "$note" |
sed 's/:.*//')' sin '$(echo "$note" | sed 's/.*://')'"')
printf '"|sox -n -p synth '$(echo "$note" |
sed 's/:.*//')' '$synthtype' '$(echo "$note" | sed 's/.*://' |
sed 's/,.*//')' '$synthtype' '$(echo "$note" | sed 's/.*://' |
sed 's/.*,//')'"\n'
# The sed for commas is there to support two-note harmonies.
done
echo "$soxpipes"
notes=() # You usually want to reset the notes array after calling this
}

View File

@ -0,0 +1,63 @@
#!/bin/bash
: '
Copyright (C) 2022 Job Bautista
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
'
source ../libsox.sh
setTempo 120
function part1 {
notes+=(
"$dei:${cs[4]},${fs[4]}"
"$ei:0"
"$si:0"
"$si:${cs[4]},${fs[4]}"
"$si:${cs[4]},${fs[4]}"
"$ei:${cs[4]},${fs[4]}"
"$ei:${cs[4]},${fs[4]}"
"$ei:${cs[4]},${fs[4]}"
"$ei:0"
)
}
part1; part1;
notes+=(
"$ei:${ds[4]},${gs[4]}"
"$qu:0"
"$si:${ds[4]},${gs[4]}"
"$si:${ds[4]},${gs[4]}"
"$ei:${ds[4]},${gs[4]}"
"$ei:${ds[4]},${gs[4]}"
"$dei:${ds[4]},${gs[4]}"
"$si:0"
"$dei:${e[4]},${e[5]}"
"$ei:0"
"$si:0"
"$si:${e[4]},${e[5]}"
"$si:${e[4]},${e[5]}"
"$ei:${e[4]},${e[5]}"
"$ei:${e[4]},${e[5]}"
"$qu:${c[4]},${f[5]}"
)
createSoxPipes 2

View File

@ -2,6 +2,6 @@
cat art.txt
sleep 1
play -M -V1 "|sox -n -p synth .75 sin 293" "|sox -n -p synth .75 sin 391"
play -V1 "|sox -n -p synth .75 sin 293 sin 391"
# d5 = 293Hz, g5 = 391Hz
play -M -V1 left.wav right.wav repeat 6
./combined.sh | xargs ../myplay-repeat.sh 6

View File

@ -35,6 +35,8 @@ Arranged by Job Bautista
'
setDefaultSynthType sin
# intro
setTempo 102
notes=(
@ -99,15 +101,18 @@ notes=(
"$si:${ds[4]}"
"$si:${gs[4]}"
"$si:${d[4]}"
"$qu:${f[4]}" # 62nd item
"$qu:${f[4]}"
"3.096:0" # 2 whole notes in 155 BPM
)
createSoxPipes # loop no $1
createSoxPipes
echo
# main loop
setTempo 155
# fast bridge
notes=(
notes+=(
"$si:${c[5]}"
"$si:${gs[4]}"
"$si:${fs[4]}"
@ -689,5 +694,6 @@ function verse7 {
)
}
verse7; verse7;
notes+=( "$fu:0" )
createSoxPipes # loop yes $1
createSoxPipes