-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtestversion
271 lines (239 loc) · 8.84 KB
/
testversion
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#!/bin/bash
# Configuration
script_version="0.3"
default_threads=4 # Default number of threads if not specified
log_file="/tmp/spsox.log"
# Define color codes for output
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color
# Function to display help
show_help() {
echo "Usage: $0 [options] [input_directory] [threads]"
echo ""
echo "Options:"
echo " -r, --recursive Process .flac files in the specified directory and all subdirectories."
echo " -h, --help Display this help message and exit."
echo " -v, --version Display the script version and exit."
echo ""
echo "Arguments:"
echo " input_directory Directory containing .flac files (default: current directory)."
echo " threads Number of parallel threads to use (default: $default_threads)."
echo ""
echo "Behavior:"
echo " - If no arguments are provided, the script processes .flac files in the current directory"
echo " with the default thread count ($default_threads)."
echo " - If only a number is provided (e.g., '8'), it is interpreted as the thread count, and the"
echo " input directory defaults to the current directory."
echo " - If both an input directory and thread count are provided, they are used accordingly."
echo ""
echo "Examples:"
echo " $0 -r /path/to/input 8 Process .flac files recursively with 8 threads."
echo " $0 /path/to/input 4 Process .flac files in the specified directory with 4 threads."
echo " $0 6 Process .flac files in the current directory with 6 threads."
echo " $0 Process .flac files in the current directory with default settings."
echo " $0 -h Show this help message."
echo " $0 -v Show the script version."
}
# Function to display version
show_version() {
echo "$0 version $script_version"
}
# Parse options
recursive=false
while [[ "$1" == -* ]]; do
case "$1" in
-r | --recursive)
recursive=true
shift
;;
-h | --help)
show_help
exit 0
;;
-v | --version)
show_version
exit 0
;;
*)
echo "Error: Unknown option '$1'. Use -h for help."
exit 1
;;
esac
done
# Helper function to check if a value is a number
is_number() {
[[ "$1" =~ ^[0-9]+$ ]]
}
# Assign arguments after parsing options
if [[ -z "$1" ]]; then
# No arguments provided: Default to current directory and default threads
input_dir="$(pwd)"
threads="$default_threads"
elif [[ -d "$1" ]]; then
# First argument is a valid directory
input_dir="$1"
threads="${2:-$default_threads}" # Use second argument as thread count, or default
elif is_number "$1"; then
# First argument is a number (interpreted as thread count)
input_dir="$(pwd)" # Default to current directory
threads="$1"
else
# Invalid argument
echo "Error: '$1' is neither a valid directory nor a number. Use -h for help."
exit 1
fi
# Validate input directory
if [[ ! -d "$input_dir" ]]; then
echo "Error: Input directory '$input_dir' does not exist."
exit 1
fi
# Variables to track progress and summary
total_files=$(find "$input_dir" -type f -name "*.flac" | wc -l)
counter_file="/tmp/spsox_counters"
> "$counter_file" # Initialize counter file
echo "success=0" > "$counter_file"
echo "skipped=0" >> "$counter_file"
echo "error=0" >> "$counter_file"
echo "processed=0" >> "$counter_file"
# Lock file for atomic updates to counters
lock_file="/tmp/spsox.lock"
touch "$lock_file"
# Function to atomically increment counters
increment_counter() {
local counter_name="$1"
(
flock -x 200
source "$counter_file"
case "$counter_name" in
success) ((success++)) ;;
error) ((error++)) ;;
skipped) ((skipped++)) ;;
processed) ((processed++)) ;;
esac
echo "success=$success" > "$counter_file"
echo "skipped=$skipped" >> "$counter_file"
echo "error=$error" >> "$counter_file"
echo "processed=$processed" >> "$counter_file"
) 200>"$lock_file"
}
# Function to generate spectrograms for a single FLAC file
generate_spectrograms() {
local file="$1"
# Debugging: Log the file being processed
echo "DEBUG: Processing file: '$file'" >>"$log_file"
# Skip if the file is empty or invalid
if [[ -z "$file" || ! -f "$file" ]]; then
echo -e "${RED}ERROR: Invalid or empty file path: '$file'${NC}" >>"$log_file"
increment_counter "error"
increment_counter "processed"
source "$counter_file"
echo -e "${GREEN}Progress: $processed/$total_files files processed.${NC}"
return
fi
# Determine the parent directory of the file
local parent_dir=$(dirname "$file")
local base_name=$(basename "$file")
# Create a specs folder in the parent directory
local specs_dir="$parent_dir/specs"
mkdir -p "$specs_dir"
# Define output file paths
local zoomed_file="$specs_dir/${base_name%.*}.zoomed.png"
local full_file="$specs_dir/${base_name%.*}.full.png"
# Skip if both spectrogram files already exist
if [[ -f "$zoomed_file" && -f "$full_file" ]]; then
echo -e "${YELLOW}Skipping $base_name (already processed)${NC}"
increment_counter "skipped"
increment_counter "processed"
source "$counter_file"
echo -e "${GREEN}Progress: $processed/$total_files files processed.${NC}"
return
fi
# Generate the zoomed spectrogram
echo -e "Generating zoomed spectrogram for ${base_name}..."
sox "$file" -n remix 1 spectrogram \
-t "${base_name%.*}" \
-X 500 -y 1025 -z 120 -w Kaiser -S 1:00 -d 0:02 \
-o "$zoomed_file" 2>>"$log_file"
if [[ $? -ne 0 ]]; then
echo -e "${RED}Error generating zoomed spectrogram for $base_name${NC}"
increment_counter "error"
increment_counter "processed"
source "$counter_file"
echo -e "${GREEN}Progress: $processed/$total_files files processed.${NC}"
return
else
echo -e "${GREEN}Finished zoomed spectrogram for $base_name${NC}"
fi
# Generate the full spectrogram
echo -e "Generating full spectrogram for ${base_name}..."
sox "$file" -n remix 1 spectrogram \
-t "${base_name%.*}" \
-x 3000 -y 513 -z 120 -w Kaiser \
-o "$full_file" 2>>"$log_file"
if [[ $? -ne 0 ]]; then
echo -e "${RED}Error generating full spectrogram for $base_name${NC}"
increment_counter "error"
increment_counter "processed"
source "$counter_file"
echo -e "${GREEN}Progress: $processed/$total_files files processed.${NC}"
return
else
echo -e "${GREEN}Finished full spectrogram for $base_name${NC}"
increment_counter "success"
increment_counter "processed"
source "$counter_file"
echo -e "${GREEN}Progress: $processed/$total_files files processed.${NC}"
fi
}
export -f generate_spectrograms
# Trap to clean up background jobs on script exit or interrupt
trap 'kill $(jobs -p) 2>/dev/null; rm -f "$lock_file" "$counter_file"; echo "Cleaning up..."' EXIT
# Array to track background job PIDs
declare -a pids=()
# Start timing
start_time=$(date +%s)
# Find all FLAC files and process them in parallel
if $recursive; then
find_command="find \"$input_dir\" -type f -name \"*.flac\" -print0"
else
find_command="find \"$input_dir\" -maxdepth 1 -type f -name \"*.flac\" -print0"
fi
while IFS= read -r -d '' file; do
(
generate_spectrograms "$file"
) &
# Store the PID of the background job
pids+=($!)
# Limit the number of concurrent jobs
while (( ${#pids[@]} >= threads )); do
# Wait for any job to finish
for i in "${!pids[@]}"; do
if ! kill -0 "${pids[i]}" 2>/dev/null; then
unset 'pids[i]'
fi
done
sleep 0.1
done
done < <(eval "$find_command")
# Wait for all remaining background jobs to finish
for pid in "${pids[@]}"; do
wait "$pid"
done
# End timing
end_time=$(date +%s)
# Calculate total time
total_time=$((end_time - start_time))
# Read final counters
source "$counter_file"
# Display summary
echo ""
echo "Processing Summary:"
echo "-------------------"
echo "Total Files: $total_files"
echo "Successfully Processed: $success"
echo "Skipped (Already Processed): $skipped"
echo "Errors: $error"
echo "Total Time: ${total_time} seconds."
echo "Check '$log_file' for details."