# audio_tuner.py from pydub import AudioSegment def change_audio_tuning(audio_filepath, initial_tuning_hz, desired_tuning_hz): """ Changes the speed of an audio file to match a desired tuning. This function adjusts the playback speed of the audio, which in turn changes its pitch, to move from an initial tuning to a desired tuning. Args: audio_filepath (str): Path to the input audio file. initial_tuning_hz (float): The initial tuning frequency in Hz (e.g., 440). desired_tuning_hz (float): The desired tuning frequency in Hz (e.g., 432). Returns: (int, numpy.ndarray): A tuple containing the new sample rate and the audio data as a NumPy array for Gradio compatibility. """ # --- Input Validation --- if not audio_filepath: raise ValueError("No audio file provided.") if not initial_tuning_hz or not desired_tuning_hz: raise ValueError("Initial and desired tuning frequencies must be provided.") if initial_tuning_hz <= 0 or desired_tuning_hz <= 0: raise ValueError("Tuning frequencies must be positive values.") # --- Processing --- # Calculate the speed multiplier required to change the pitch speed_multiplier = desired_tuning_hz / initial_tuning_hz # Load the audio file using pydub sound = AudioSegment.from_file(audio_filepath) # A simple way to change speed without pitch correction is to change the frame rate new_frame_rate = int(sound.frame_rate * speed_multiplier) # Create a new audio segment with the modified frame rate tuned_sound = sound._spawn(sound.raw_data, overrides={"frame_rate": new_frame_rate}) # Set the frame rate back to the original to ensure proper playback speed in most players, # effectively resampling the audio. tuned_sound = tuned_sound.set_frame_rate(sound.frame_rate) # --- Output for Gradio --- # Gradio audio component expects a tuple of (sample_rate, numpy_array) # The sample rate is the original rate after resampling. # The audio data is converted to a NumPy array. import numpy as np samples = np.array(tuned_sound.get_array_of_samples()).astype(np.int16) return (tuned_sound.frame_rate, samples)