Skip to content

Instantly share code, notes, and snippets.

@coderofsalvation
Last active April 18, 2019 11:16
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save coderofsalvation/3176974 to your computer and use it in GitHub Desktop.
Save coderofsalvation/3176974 to your computer and use it in GitHub Desktop.
samplesort - converts audiosample-directories into symbolically linked trees sorted on tags (kick/hihat/etc)
#!/bin/sh
#
# this will build a database using the 'mlocate' package (see debian/ubuntu etc)
# make sure to set 'export LOCATE_PATH="/path/to/mlocate.db"' when using 'locate'
renice +19 -p $$ >/dev/null 2>&1
ionice -c2 -n7 -p $$ >/dev/null 2>&1
/usr/bin/updatedb --output /path/to/mlocate.db --local-path -U /path/to/your/samples
#!/bin/bash
#
# Copyright 2012, Leon van Kammen (Coder of Salvation), All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are
# permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY Coder of Salvation ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are those of the
# authors and should not be interpreted as representing official policies, either expressed
# or implied, of Coder of Salvation
#
me=$(basename "$0"); cur_dir=""; cur_file=""; dry=0; autolink=0; initialized=0
requirements="sed grep printf cut sort echo"
filetypes="(\.wav$|\.mp3$|\.ogg$|\.flac$|\.aiff$|\.iff$)"
declare -A tags
tags["kick"]="kick|bassdrum"
tags["loop_kick"]="kick.*loop|bassdrum.*loop"
tags["hihat"]="hihat|hats"
tags["clap"]="clap"
tags["snare"]="snare"
tags["ride"]="ride"
tags["crash"]="crash|cymbal"
tags["percussion_acoustic"]="clave|tom|bongo|conga|shaker|mallet|wood|whistle"
tags["percussion_mixed"]="percussion|perc"
tags["loop"]="loop"
tags["loop_perc"]="perc.*loop|loop.*perc"
tags["loop_beat"]="drum.*loop|loop.*drum"
tags["loop_beat_top"]="loop.*top"
tags["loop_bass"]="bass.*loop|loop.*bass"
tags["loop_guitar"]="guitar.*loop|loop.*guitar"
tags["instrument"]="instrument"
tags["keyboard"]="keyboard|keys"
tags["breakbeat"]="breakbeat"
tags["guitar"]="guitar"
tags["drumkit"]="drumkit"
tags["groove"]="groove|groovy"
tags["minimal"]="minimal|glitch"
tags["scratch"]="scratch|turntabl"
tags["hiphop"]="scratch|turntabl|hiphop|vinyl"
tags["reverse"]="reverse"
tags["jazz"]="jazz|swing"
tags["brass"]="brass|tuba"
tags["rhodes"]="wurly|wurlitz|rhodes"
tags["strings"]="string|pizzi"
tags["oneshots"]="oneshot|shot"
tags["pads"]="pad"
tags["synth"]="lead|synth"
tags["bass"]="bass$|bass |bassl"
tags["vocal"]="vocal|vox|female|male|human"
tags["fx"]="fx"
tags["sweep"]="woosh|sweep"
tags["funkdisco"]="disco|funk|filter"
tags["robotvocoder"]="vocoder|robot"
tags["environment"]="environment|movienoise"
alltags=""
initialize(){
rootdir="$1"
outputdir="$2"
symlinkprefix="$3"
[[ "$initialized" = 1 ]] && return; # prevent second init
[[ ! -d "$outputdir" ]] && echo "[!] $outputdir does not exist"
[[ ! -d "$rootdir" ]] && echo "[!] $rootdir does not exist"
for tag in ${!tags[@]}; do
alltags="$tag|$alltags"
done
alltags="$(echo "$alltags"| sed 's/|$//g')"
initialized=1
}
checkrequirements(){
for req in $requirements; do
hash "$req" 2>&-
if [ $? == 1 ]; then echo "sorry..you need to install '$req'"; exit; fi
done;
}
usage(){
printf "Usage: \n"
grep "^[^_].\+(){$" $0 | while read line; do
local cmd=$(echo "$line" | sed "s/(){//g")
local info=$(grep -C0 -A0 -B1 "$cmd(){" $0 | sed "N;s/\n.*//g" )
printf " $me %-7s %-20s\n" "$cmd" "$info" | grep "#" | sed "s/#//g"
done; echo "";
printf "type '$me --manual' to see the manual + examples\n\n"
return 0
}
manual(){
if [ "$1" != "--manual" ]; then return 0; fi
hash pod2man 2>&-
if [ $? == 1 ]; then echo "sorry..you need to install 'pod2man' (perl)"; exit; fi
SCRIPT=`readlink -f $0`
echo "(please wait..)"
pod2man $SCRIPT > /tmp/sortsamples.1
clear
if [ -f /tmp/sortsamples.1 ]; then man /tmp/sortsamples.1; rm /tmp/sortsamples.1; fi
exit 0
}
# <string> #(will tell if it can be tagged)
matchtag(){
dir=$(basename "$1")
outputdir="$2"
symlinkprefix="$3"
initialize "$dir" "$outputdir" "$symlinkprefix"
nop=$(echo "$dir" | grep -iE "($alltags)" )
[[ $? = 1 ]] && return 1;
for tag in ${!tags[@]}; do
if echo "$(basename "$dir")" | grep -iE "(${tags[$tag]})" > /dev/null; then
echo "...tagged with '$tag'!"
[[ "$autolink" == 1 ]] && _createlink "$1" "$tag" "$outputdir" "$symlinkprefix"
fi
done
}
_createlink(){
dir="$1"
dirname=$(basename "$1")
tag="$2"
outputdir="$3"
symlinkprefix="$4"
[[ ! -d "$outputdir/$tag" ]] && mkdir "$outputdir/$tag" 2> /dev/null
index="$(ls "$outputdir/$tag" | wc -l)"
if [[ "$dry" == 1 ]]; then
echo "ln -s '$symlinkprefix$dir' '$outputdir/$tag/$index-$dirname"
else
ln -s "$symlinkprefix$dir" "$outputdir/$tag/$index-$dirname"
fi
}
#<inputdir> <outputdir> <symlink-prefix> # (see what will be done)
sort-dry(){
dry=1
sort "$1" "$2" "$3" "4"
}
# <inputdir> <outputdir> <symlink-prefix> # (do it!)
sort(){
rootdir="$1"
outputdir="$2"
symlinkprefix="$3"
autolink="1"
initialize "$rootdir" "$outputdir" "$symlinkprefix"
echo "[x] preparing.. *drumrolls*"
find "$rootdir" -type d | while read dir; do
tput el; printf "\r[x] scanning %s" "$dir"
matchtag "$dir" "$outputdir" "$symlinkprefix"
find "$dir" -type f | grep -iE "$filetypes" | while read file; do
matchtag "$file" "$outputdir" "$symlinkprefix"
done
done
}
manual "$1" && test $# -lt 2 && checkrequirements && usage && exit 65
"$@"
exit 0
: <<=cut
=head1 NAME
sortsamples - a cmdline utility to easify sample organizing without organizing :)
=head1 SYNOPSIS
This utility solves the problem of having many samplecd/samplelibrary-directories with each having
kick,hihat,snare-etc folders.
=head1 DESCRIPTION
With many sampledirectories, you ll be slapped around many directories hunting
for kicks/hihats etc. This utility creates symbolic links to directories which are similar.
This way, you can have all your kick directories next to eachothers and so on.
=head1 WHY
External Sampleorganizing utilities can also become a pain in the ass,
because usually your DAW also has a samplebrowser in it. It would be nice to have structure at the
source: the filesystem.
This is a crazy effort to combine similar folders and categorize automatically :)
=head1 EXAMPLES
Examples:
$ ls -la
total 31152
drwxrwxrwx 1 root root 4096 Jul 25 17:52 .
drwxrwxrwx 1 root root 36864 Jul 10 10:15 ..
drwxrwxrwx 1 root root 4096 Jul 24 22:40 samplecd
-rwxr-xr-x 1 sqz users 6669 Jul 25 17:52 sortsamples
$ mkdir sorted-by-tag
$ sudo ./sortsamples sort-dry samplecd sorted-by-tag ../../
[x] preparing.. *drumrolls*
[x] scanning samplecd/Blutonium hardstyle vol 2/BASSDRUM...tagged with 'kick'!
[x] scanning samplecd/Blutonium hardstyle vol 2/BASSLINE...tagged with 'bass'!
[x] scanning samplecd/Blutonium hardstyle vol 2/FX...tagged with 'fx'!
^C (interrupted by CTRL-c, because it looks good..lets make it so)
$ sudo ./sortsamples sort samplecd sorted-by-tag ../../
[x] preparing.. *drumrolls*
[x] scanning samplecd/Blutonium hardstyle vol 2/BASSDRUM...tagged with 'kick'!
[x] scanning samplecd/Blutonium hardstyle vol 2/BASSLINE...tagged with 'bass'!
[x] scanning samplecd/Blutonium hardstyle vol 2/FX...tagged with 'fx'!
.. and so on!
=head1 SEE ALSO
L<https://gist.github.com/3097565>, L<https://gist.github.com/1916306>
=head1 LICENSE
BSD License (so everybody can enjoy it)
=head1 AUTHOR
B<C>oder B<O>f B<S>alvation | LEON DU STAR | info@leon.vankammen.eu | info@leondustar.nl
=cut
"$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment