Closed rcrath closed 2 months ago
Compare the way the last git script handles the first and last segments to the current approach. the currrent approach leaves stray half-cycles as the first one or two segtments. the git version does not do this. here is the git verion run followed by the current version run, followed by the function definitions for each.
git version:
segment_sizes = [] # Initialize the list to hold segment sizes
prev_start_index = 0 # Start from the beginning
some_small_amplitude = 10**(amplitude_tolerance_db / 20) # Convert to linear scale
base_prep_192k32b_path = os.path.join(tmp_folder, base_prep_192k32b)
data, samplerate = sf.read(base_prep_192k32b_path)
# Process the first segment explicitly if the start is near zero
if abs(data[0]) < some_small_amplitude: # Define 'some_small_amplitude' based on your fades
for i in range(1, len(data)):
if is_rising_zero_crossing(data, i):
prev_start_index = i
break # Found the first real zero crossing, move to normal processing
# Variables to hold the first two segments temporarily
first_segment = None
second_segment = None
segment_index = 0
# Read the audio data and sampling rate from the file
for i in range(1, len(data)):
if is_rising_zero_crossing(data, i):
# Check if the current index is different from the previous start index
if i != prev_start_index:
wave_cycle = data[prev_start_index:i]
prev_start_index = i
# Store the size of this segment
segment_sizes.append(len(wave_cycle))
# Only proceed if wave_cycle is not empty
if len(wave_cycle) > 0:
# Debug: Print the segment's properties
if segment_index == 0 or segment_index == 1:
# Print the length of the segment
# print(f"Debug: Segment {segment_index} length: {len(wave_cycle)} samples")
# Print the amplitude at the beginning of the segment in dB
# print(f"Debug: Segment {segment_index} start amplitude: -{-20 * np.log10(max(abs(wave_cycle[0]), 1e-10))} dB")
# Print the amplitude at the end of the segment in dB
# print(f"Debug: Segment {segment_index} end amplitude: -{-20 * np.log10(max(abs(wave_cycle[-1]), 1e-10))} dB")
# Check if this is the first or second segment
if segment_index == 0:
first_segment = wave_cycle
elif segment_index == 1:
second_segment = wave_cycle
# Write segment to file if it's not the first or second segment
if segment_index > 1 or segment_index == 0:
base_seg = f"{base}_seg_{segment_index:04d}{ext}"
tmp_base_seg_path = os.path.join(tmp_folder, base_seg)
wavfile.write(tmp_base_seg_path, samplerate, wave_cycle)
# print(f"Debug: Segment {segment_index} written: {tmp_base_seg_path}")
segment_index += 1
# else:
# print(f"Warning: Empty wave cycle detected at index {i}")
# Check if the first two segments contain full wave cycles
if first_segment is not None and second_segment is not None:
full_cycle_first = is_full_wavecycle(first_segment)
full_cycle_second = is_full_wavecycle(second_segment)
# Debug: Print the evaluation of the first two segments
# print(f"Debug: First segment is a full cycle: {full_cycle_first}")
# print(f"Debug: Second segment is a full cycle: {full_cycle_second}")
if not full_cycle_first or not full_cycle_second:
# Combine the first two segments
combined_segment = np.concatenate((first_segment, second_segment))
# Write the combined segment to the '0001' file
combined_path = os.path.join(tmp_folder, f"{base}_seg_0001{ext}")
wavfile.write(combined_path, samplerate, combined_segment)
# print(f"Debug: Combined segment written: {combined_path}")
# Delete the '0000' file if it exists
first_path = os.path.join(tmp_folder, f"{base}_seg_0000{ext}")
if os.path.exists(first_path):
os.remove(first_path)
# print(f"Debug: Deleted: {first_path}")
else:
# If both segments are full cycles, write them out as normal
for i, segment in enumerate([first_segment, second_segment], start=0):
segment_path = os.path.join(tmp_folder, f"{base}_seg_{i:04d}{ext}")
wavfile.write(segment_path, samplerate, segment)
# print(f"Debug: Segment {i} written: {segment_path}")
# Handle the last segment
if prev_start_index < len(data):
wave_cycle = data[prev_start_index:]
# Check if the wave cycle is full before writing to file
if is_full_wavecycle(wave_cycle):
wavfile.write(tmp_base_seg_path, samplerate, wave_cycle)
# print(f"Debug: Final segment {segment_index} written: {tmp_base_seg_path}")
segment_index += 1
# else:
# print(f"Debug: Final segment {segment_index} is not a full wave cycle and was not written.")
the current version:
NONE
and its functions: (from last git)
# Function to calculate rising zero crossings in a waveform
def is_rising_zero_crossing(data, index):
# Ensure index is within the valid range
if index <= 0 or index >= len(data) - 1: # -1 to handle the end of the file
return False
# Check for a rising zero crossing: previous sample is negative, and the current one is positive
if data[index - 1] < 0 and data[index] >= 0:
return True
return False
from aa_common (current)
def is_rising_zero_crossing(data, index):
# Check if the data is stereo (2D array) or mono (1D array)
if data.ndim == 2: # Stereo case
# Check zero-crossing for the left channel (index 0)
if data[index - 1, 0] < 0 and data[index, 0] >= 0:
return True
else: # Mono case
if data[index - 1] < 0 and data[index] >= 0:
return True
return False
from git:
def is_full_wavecycle(segment):
global amplitude_tolerance_db # Use the global variable
if len(segment) < 3:
return False
# Convert the first and last samples to dB
first_sample_db = 20 * np.log10(max(abs(segment[0]), 1e-10))
last_sample_db = 20 * np.log10(max(abs(segment[-1]), 1e-10))
# Check if the first and last samples are near zero in dB
if first_sample_db > amplitude_tolerance_db or last_sample_db > amplitude_tolerance_db:
return False
# Detect zero crossings
zero_crossings = np.where(np.diff(np.signbit(segment)))[0]
# Ensure there's at least one significant zero crossing
if len(zero_crossings) < 2:
return False
return True
from aa_common:
def is_full_wavecycle(segment, amplitude_tolerance_db=-60):
if len(segment) < 3:
return False
first_sample_db = 20 * np.log10(max(abs(segment[0]), 1e-10))
last_sample_db = 20 * np.log10(max(abs(segment[-1]), 1e-10))
if first_sample_db > amplitude_tolerance_db or last_sample_db > amplitude_tolerance_db:
return False
zero_crossings = np.where(np.diff(np.signbit(segment)))[0]
if len(zero_crossings) < 2:
return False
return True
solved it simpler than originally.
find in an old version the test for well formed first samples that combines half waves and deletes extras. e.g. seg 0 is /\ and seg 2 is \/. combine to be ful cycle of /\/