import os
import numpy as np
from scipy.io import wavfile
from scipy.signal import stft, butter, sosfilt
def bandpass_filter(data, sample_rate, lowcut=18, highcut=22, order=5):
sos = butter(order, [lowcut / (0.5 * sample_rate), highcut / (0.5 * sample_rate)], btype='band', output='sos')
return sosfilt(sos, data)
# fine tune post_pilot_duration (in s) to your setup! this can vary, for example because of Turntable speed variations or your Test Record!
def detect_sweep_start(data, sample_rate, post_pilot_duration=50.5):
# Apply bandpass filter
filtered_data = bandpass_filter(data, sample_rate)
# Perform STFT
f, t, Zxx = stft(filtered_data, fs=sample_rate, nperseg=1024)
# Find the index of the frequency closest to 20 Hz
target_freq_index = np.argmin(np.abs(f - 20))
# Get the magnitude of the STFT at 20 Hz
magnitude = np.abs(Zxx[target_freq_index, :])
threshold = np.max(magnitude) * 0.1 # Arbitrary threshold, may need adjustment
# Detect the start of the sweep
sweep_start_idx = np.where(magnitude > threshold)[0][0]
sweep_start_time = t[sweep_start_idx]
# Calculate the end time, 50 seconds after the sweep starts
sweep_end_time = sweep_start_time + post_pilot_duration
return sweep_start_time, sweep_end_time
def save_trimmed_audio(data, sample_rate, start_time, end_time, source_file, file_name, swap_channels=False):
start_sample = int(start_time * sample_rate)
end_sample = int(end_time * sample_rate)
# Trim the data
trimmed_data = data[start_sample:end_sample]
# Swap channels if required
if swap_channels and trimmed_data.shape[1] > 1:
trimmed_data = trimmed_data[:, [1, 0]]
# Determine the output directory based on the source file
output_dir = os.path.dirname(source_file) if source_file else '.'
# Save the trimmed data
output_path = os.path.join(output_dir, f"{file_name}.wav")
wavfile.write(output_path, sample_rate, trimmed_data)
return output_path
# Usage example
left_audio_file = '1007_L.wav' # Replace with your file path and file name
right_audio_file = '1007_R.wav' # Replace with your file path and file name
# Process left channel file
sample_rate, data_left = wavfile.read(left_audio_file)
sweep_start_time, sweep_end_time = detect_sweep_start(data_left.mean(axis=1), sample_rate)
wavefile1_path = save_trimmed_audio(data_left, sample_rate, sweep_start_time, sweep_end_time, left_audio_file, "wavefile1")
# Process right channel file and swap channels
sample_rate, data_right = wavfile.read(right_audio_file)
sweep_start_time, sweep_end_time = detect_sweep_start(data_right.mean(axis=1), sample_rate)
wavefile2_path = save_trimmed_audio(data_right, sample_rate, sweep_start_time, sweep_end_time, right_audio_file, "wavefile2", swap_channels=True)
print(f"Trimmed audio files saved as {wavefile1_path} and {wavefile2_path}")