USER
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
ПРОДУБЛИРУЙТЕ ВЕСЬ КОД, ИСПРАВИВ АБСОЛЮТНО !!!!МАКСИМАЛЬНО ВСЕ ОШИБКИ В КОТОРОМ ВЫДАЕТ КОМАНДНАЯ СТРОКА!!!!!!!!!!!!!!!!!!!!!!!!!!
import os
import torch
from torch import nn, optim
from torch.utils.data import DataLoader, Dataset
import torchaudio
import librosa
import noisereduce as nr
import numpy as np
import crepe
import madmom
from music21 import stream, note, converter, instrument
from transformers import Wav2Vec2ForCTC, Wav2Vec2Tokenizer, HubertForCTC, HubertTokenizer
from scipy import signal
import openunmix
from demucs import pretrained, Demucs
import openai
import yamnet as yamnet_model
import openl3
from onsets_and_frames import NonBinaryClassification, inference
import pydub
import parselmouth
from spleeter.separator import Separator
import soundfile as sf
import time
import tonic
import logging
import asyncio
from diskcache import Cache
# Загрузка ключа API из переменных среды
openai.api_key = os.environ.get(“OPENAI_API_KEY”)
# Настройка логирования
logging.basicConfig(level=logging.INFO)
# Настройка кэширования
cache = Cache(‘audio_cache’)
# Конфигурационные параметры
config = {
“output_dir”: “output”,
“noise_reduction_level”: 5,
“pitch_shift”: 2,
“speed_change”: 1.5,
“batch_size”: 16,
“epochs”: 10,
“target_format”: “wav”
}
# Асинхронная функция для конвейера обработки
async def preprocess_audio(file_path):
“”“
Конвейер обработки аудио
“””
try:
logging.info(f"Loading and preprocessing audio from {file_path}“)
y, sr = librosa.load(file_path, sr=None)
if (y, sr) in cache:
logging.info(“Using cached preprocessed audio”)
return cache[(y, sr)]
y = librosa.util.normalize(y)
y = nr.reduce_noise(y, sr)
y = signal.wiener(y)
cache[(y, sr)] = (y, sr)
logging.info(“Audio preprocessing completed”)
return y, sr
except Exception as e:
logging.error(f"Error preprocessing audio: {e}”)
return None, None
async def extract_features_task(y, sr):
“”“
Асинхронная задача для извлечения признаков
“””
try:
cqt = librosa.cqt(y, sr=sr)
cqt_db = librosa.amplitude_to_db(np.abs(cqt), ref=np.max)
# Pitch detection using CREPE
_, frequency, confidence, _ = crepe.predict(y, sr)
return cqt_db, frequency, confidence
except Exception as e:
logging.error(f"Error extracting features: {e}“)
return None, None, None
def transformer_features_wav2vec2(y, sr):
“””
Асинхронная задача для извлечения признаков с использованием Wav2Vec2
“”“
try:
tokenizer = Wav2Vec2Tokenizer.from_pretrained(“facebook/wav2vec2-base-960h”)
model = Wav2Vec2ForCTC.from_pretrained(“facebook/wav2vec2-base-960h”)
input_values = tokenizer(y, return_tensors=“pt”, padding=True).input_values
logits = model(input_values).logits
predicted_ids = torch.argmax(logits, dim=-1)
transcription = tokenizer.batch_decode(predicted_ids)[0]
return transcription
except Exception as e:
logging.error(f"Error extracting transformer features with Wav2Vec2: {e}”)
return None
def transformer_features_hubert(y, sr):
“”“
Асинхронная задача для извлечения признаков с использованием HuBERT
“””
try:
tokenizer = HubertTokenizer.from_pretrained(“facebook/hubert-large-ls960-ft”)
model = HubertForCTC.from_pretrained(“facebook/hubert-large-ls960-ft”)
input_values = tokenizer(y, return_tensors=“pt”, padding=True).input_values
logits = model(input_values).logits
predicted_ids = torch.argmax(logits, dim=-1)
transcription = tokenizer.batch_decode(predicted_ids)[0]
return transcription
except Exception as e:
logging.error(f"Error extracting transformer features with Hubert: {e}“)
return None
def generate_text_descriptions_with_chatgpt(prompt):
“””
Генерация текста с использованием GPT-4
“”“
try:
response = openai.Completion.create(
model=“gpt-4”,
prompt=prompt,
max_tokens=150 # Увеличиваем количество токенов для получения более детального ответа
)
return response.choices[0].text.strip()
except Exception as e:
logging.error(f"Error generating text descriptions with GPT-4: {e}”)
return None
class AudioPipeline:
def init(self, config):
self.config = config
def convert_audio_format(self, file_path, target_format=“wav”):
“”“
Конвертация аудиоформата
“””
try:
audio = pydub.AudioSegment.from_file(file_path)
new_file_path = file_path.replace(file_path.split(‘.’)[-1], target_format)
audio.export(new_file_path, format=target_format)
logging.info(f"Audio format converted to {target_format}“)
return new_file_path
except Exception as e:
logging.error(f"Error converting audio format: {e}”)
return None
def play_audio(self, file_path):
try:
data, sr = sf.read(file_path)
import sounddevice as sd
sd.play(data, sr)
sd.wait()
except Exception as e:
logging.error(f"Error playing audio: {e}“)
async def run_pipeline(self, file_path):
“””
Запуск конвейера обработки
“”“
# Конвертация аудиоформата
converted_file_path = self.convert_audio_format(file_path, self.config[“target_format”])
# Предварительная обработка
y, sr = await preprocess_audio(converted_file_path)
if y is None or sr is None:
logging.error(“Error in audio preprocessing step”)
return
# Запуск задач извлечения признаков в фоновом режиме
features_task = extract_features_task(y, sr)
# Запуск Преобразующих Моделей
transcription_wav2vec2_task = asyncio.to_thread(transformer_features_wav2vec2, y, sr)
transcription_hubert_task = asyncio.to_thread(transformer_features_hubert, y, sr)
# Ожидание завершения задач
features_result = await features_task
transcription_wav2vec2 = await transcription_wav2vec2_task
transcription_hubert = await transcription_hubert_task
cqt_db, frequency, confidence = features_result
logging.info(f"Feature extraction complete: {cqt_db.shape}, {len(frequency)}, {transcription_wav2vec2}, {transcription_hubert}”)
# Запуск дополнительных задач
additional_features = await asyncio.to_thread(self.additional_features_essentia, y, sr)
# Сепарация источников
sources_openunmix = await asyncio.to_thread(self.source_separation_openunmix, y, sr)
sources_demucs_v3 = await asyncio.to_thread(self.source_separation_demucs_v3, y, sr)
vocals_path, accompaniment_path = await asyncio.to_thread(self.source_separation_spleeter, converted_file_path)
logging.info(f"Source separation complete: OpenUnmix: {sources_openunmix}, Demucs V3: {sources_demucs_v3}, Spleeter: {vocals_path}, {accompaniment_path}“)
# Анализ высоты тона с использованием Parselmouth
pitch_analysis = await asyncio.to_thread(self.analyze_pitch_with_parselmouth, converted_file_path)
logging.info(f"Pitch analysis (Parselmouth): {pitch_analysis}”)
# Оптимизация
reduced_noise_path = self.reduce_noise(converted_file_path, self.config[“noise_reduction_level”])
modified_audio_path = self.change_timbre_and_speed(reduced_noise_path, self.config[“pitch_shift”], self.config[“speed_change”])
normalized_audio_path = self.normalize_volume_level(modified_audio_path)
return cqt_db, frequency, confidence, transcription_wav2vec2, transcription_hubert, additional_features, sources_openunmix, sources_demucs_v3, vocals_path, accompaniment_path, pitch_analysis, normalized_audio_path
def reduce_noise(self, file_path, noise_reduction_level=5):
try:
audio = pydub.AudioSegment.from_file(file_path)
reduced_noise_audio = audio - noise_reduction_level
reduced_noise_file_path = file_path.replace(“.wav”, “_reduced_noise.wav”)
reduced_noise_audio.export(reduced_noise_file_path, format=“wav”)
logging.info(f"Noise reduced and saved to {reduced_noise_file_path}“)
return reduced_noise_file_path
except Exception as e:
logging.error(f"Error reducing noise: {e}”)
return None
def change_timbre_and_speed(self, file_path, pitch_shift=2, speed_change=1.5):
try:
audio = pydub.AudioSegment.from_file(file_path)
new_timbre_audio = audio._spawn(audio.raw_data, overrides={‘frame_rate’: int(audio.frame_rate * pitch_shift)})
new_timbre_speed_audio = new_timbre_audio.speedup(playback_speed=speed_change)
new_file_path = file_path.replace(“.wav”, “_modified.wav”)
new_timbre_speed_audio.export(new_file_path, format=“wav”)
logging.info(f"Timbre and speed changed and saved to {new_file_path}“)
return new_file_path
except Exception as e:
logging.error(f"Error changing timbre and speed: {e}”)
return None
def normalize_volume_level(self, file_path):
try:
audio = pydub.AudioSegment.from_file(file_path)
normalized_audio = audio.apply_gain(-audio.dBFS)
normalized_file_path = file_path.replace(“.wav”, “_normalized.wav”)
normalized_audio.export(normalized_file_path, format=“wav”)
logging.info(f"Volume level normalized and saved to {normalized_file_path}“)
return normalized_file_path
except Exception as e:
logging.error(f"Error normalizing volume level: {e}”)
return None
def analyze_pitch_with_parselmouth(self, file_path):
try:
snd = parselmouth.Sound(file_path)
pitch = snd.to_pitch()
pitch_values = pitch.selected_array[‘frequency’]
return pitch_values
except Exception as e:
logging.error(f"Error analyzing pitch with Parselmouth: {e}“)
return None
def additional_features_essentia(self, y, sr):
try:
from essentia.standard import MusicExtractor, MonoLoader
loader = MonoLoader(sampleRate=sr)
y = loader(y)
extractor = MusicExtractor(lowlevelStats=[‘mean’, ‘stdev’])
features, _ = extractor(y)
return features
except Exception as e:
logging.error(f"Error extracting additional features with Essentia: {e}”)
return None
def source_separation_openunmix(self, y, sr):
try:
separator = openunmix.separate(
audio_signal=y.tolist(),
sample_rate=sr,
targets=[“vocals”, “drums”, “bass”, “other”]
)
return {
“vocals”: separator[“vocals”],
“drums”: separator[“drums”],
“bass”: separator[“bass”],
“other”: separator[“other”],
}
except Exception as e:
logging.error(f"Error in source separation with OpenUnmix: {e}“)
return None
def source_separation_demucs_v3(self, y, sr):
try:
model = pretrained.get_model(‘demucs’)
waveform = torch.tensor(y).unsqueeze(0)
waveform = waveform.to(model.device)
sources = model(waveform)
return sources
except Exception as e:
logging.error(f"Error in source separation with Demucs v3: {e}”)
return None
def source_separation_spleeter(self, file_path):
try:
separator = Separator(‘spleeter:2stems’)
separator.separate_to_file(file_path, output_path=‘output’)
return ‘output/vocals.wav’, ‘output/accompaniment.wav’
except Exception as e:
logging.error(f"Error in source separation with Spleeter: {e}“)
return None, None
def recognize_instruments(self, y, sr):
try:
params = yamnet_model.Params()
yamnet = yamnet_model.yamnet(params)
yamnet.load_weights(‘yamnet.h5’)
waveform = np.reshape(y, [len(y), 1])
class_scores, embeddings, spectrogram = yamnet(waveform)
classes = yamnet_model.class_names(params)
top_classes = np.argsort(class_scores, axis=-1)[0, -5:][::-1]
recognized_classes = [classes[i] for i in top_classes]
return recognized_classes
except Exception as e:
logging.error(f"Error recognizing instruments: {e}”)
return None
def recognize_genre(self, y, sr):
try:
features = self.extract_features(y, sr)
genre_description = generate_text_descriptions_with_chatgpt(f"Recognize the genre based on these features: {features}“)
return genre_description
except Exception as e:
logging.error(f"Error recognizing genre: {e}”)
return None
# Построение MusicXML
def create_musicxml(frequencies, beats, frames, onsets, offsets, text_descriptions, instruments):
try:
score = stream.Score()
part = stream.Part()
# Чтобы добавить все инструменты, которые доступны в music21
instrument_classes = [cls for cls in dir(instrument) if isinstance(getattr(instrument, cls), type) and issubclass(getattr(instrument, cls), instrument.Instrument)]
for freq, beat, frame, onset, offset, description, inst in zip(frequencies, beats, frames, onsets, offsets, text_descriptions, instruments):
if onset > 0:
n = note.Note()
n.pitch.frequency = freq
n.quarterLength = beat
n.offset = offset
n.addLyric(description)
# Добавление инструмента к ноте
if hasattr(instrument, inst):
instrument_class = getattr(instrument, inst)
part.append(instrument_class())
else:
n.addLyric(“Unknown Instrument”)
part.append(n)
score.append(part)
return score
except Exception as e:
logging.error(f"Error creating MusicXML: {e}“)
return None
def visualize_score(score, output_image_path):
“””
Визуализация партитуры и сохранение в виде изображения
“”“
try:
s = converter.parse(score)
s.show(‘text’) # Показать партитуру в текстовом виде (можно удалить, если не нужно)
fp = s.write(‘musicxml.png’, fp=output_image_path)
logging.info(f’Партитура сохранена в {fp}')
except Exception as e:
logging.error(f"Error visualizing score: {e}”)
class MusicDataset(Dataset):
def init(self, features, labels):
self.features = features
self.labels = labels
def len(self):
return len(self.features)
def getitem(self, idx):
return self.features[idx], self.labels[idx]
def train_cnn_model(train_loader, in_channels, out_channels, epochs=10):
model = AudioCNN(in_channels, out_channels)
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(epochs):
for inputs, labels in train_loader:
# Возможно, добавить использование GPU
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
logging.info(f"Epoch {epoch+1}/{epochs}, Loss: {loss.item()}“)
return model
def generate_text_descriptions(features):
try:
response = openai.Completion.create(
model=“gpt-4”,
prompt=f"Generate a coherent description based on the following features: {features}”,
max_tokens=100
)
return response.choices[0].text.strip()
except Exception as e:
logging.error(f"Error generating text descriptions: {e}“)
return None
def modify_notes_with_gpt4(score, action=“add”, instrument=“piano”):
notes_data = [(n.pitch.frequency, n.quarterLength, n.offset) for n in score.flat.notes]
prompt = f"Партитура содержит следующие данные нот:\n{notes_data}\n Пожалуйста, предоставьте необходимые изменения, чтобы {(‘добавить’ if action == ‘add’ else ‘удалить’)} ноты для инструмента ‘{instrument}’, и обеспечьте соблюдение правильных музыкальных правил. Также проанализируйте сложность композиции.”
try:
response = openai.Completion.create(
model=“gpt-4”,
prompt=prompt,
max_tokens=150 # Увеличиваем количество токенов для получения более детального ответа
)
modified_notes = response.choices[0].text.strip().split(‘\n’)
for note_data in modified_notes:
try:
note_info = note_data.split(‘,’)
if len(note_info) == 3:
freq, length, offset = map(float, note_info)
if action == “add”:
new_note = note.Note()
new_note.pitch.frequency = freq
new_note.quarterLength = length
new_note.offset = offset
new_note.addLyric(instrument)
score.append(new_note)
else:
for n in score.flat.notes:
if abs(n.pitch.frequency - freq) < 1e-3 and abs(n.quarterLength - length) < 1e-3 and abs(n.offset - offset) < 1e-3:
score.remove(n)
else:
logging.warning(f"Skipping invalid note data: {note_data}“)
except ValueError as ve:
logging.error(f"Error processing note data: {note_data} -> {ve}”)
except Exception as e:
logging.error(f"Error generating modifications with GPT-4: {e}")
return score
def plot_spectrogram(y, sr, output_image_path):
try:
import matplotlib.pyplot as plt
import librosa.display
D = librosa.amplitude_to_db(np.abs(librosa.stft(y)), ref=np.max)
plt.figure(figsize=(12, 8))
librosa.display.specshow(D, sr=sr, x_axis=‘time’, y_axis=‘log’)
plt.colorbar(format=‘%+2.0f dB’)
plt.title(‘Spectrogram’)
plt.savefig(output_image_path)
logging.info(f’Spectrogram saved to {output_image_path}‘)
plt.close()
except Exception as e:
logging.error(f"Error plotting spectrogram: {e}")
def plot_chromagram(y, sr, output_image_path):
try:
import matplotlib.pyplot as plt
import librosa.display
chromagram = librosa.feature.chroma_stft(y=y, sr=sr)
plt.figure(figsize=(12, 8))
librosa.display.specshow(chromagram, sr=sr, x_axis=‘time’, y_axis=‘chroma’)
plt.colorbar(format=’%+2.0f’)
plt.title(‘Chromagram’)
plt.savefig(output_image_path)
logging.info(f’Chromagram saved to {output_image_path}')
plt.close()
except Exception as e:
logging.error(f"Error plotting chromagram: {e}“)
def compute_spectral_centroid(y, sr):
try:
spectral_centroids = librosa.feature.spectral_centroid(y, sr=sr)[0]
return spectral_centroids
except Exception as e:
logging.error(f"Error computing spectral centroid: {e}”)
return None
def compute_tonality_and_stability(y, sr):
try:
chroma_stft = librosa.feature.chroma_stft(y=y, sr=sr)
key = librosa.estimate_tuning(y=y, sr=sr)
return key, chroma_stft
except Exception as e:
logging.error(f"Error computing tonality and stability: {e}“)
return None, None
def harmonic_rhythm_analysis(y, sr):
try:
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr)
chords = librosa.effects.harmonic(y)
# Анализ ритма с использованием madmom
proc = madmom.features.beats.RNNBeatProcessor()(y)
beat_times = madmom.features.beats.DBNBeatTrackingProcessor(beats_per_bar=[3, 4])(proc)
return tempo, beat_frames, chords, beat_times
except Exception as e:
logging.error(f"Error in harmonic rhythm analysis: {e}”)
return None, None, None, None
def main(file_path, output_path, output_image_path):
# Конфигурирование кэширования данных
dataset_config = {
“features”: “path_to_features_dataset”,
“labels”: “path_to_labels_dataset”
}
# Инициализация конвейера и запуск обработки
audio_pipeline = AudioPipeline(config)
loop = asyncio.get_event_loop()
results = loop.run_until_complete(audio_pipeline.run_pipeline(file_path))
if results:
# Обработка результатов
(cqt_db, frequency, confidence, transcription_wav2vec2, transcription_hubert, additional_features, sources_openunmix, sources_demucs_v3, vocals_path, accompaniment_path, pitch_analysis, normalized_audio_path) = results
logging.info(f"Processing results: {cqt_db.shape}, {len(frequency)}, {transcription_wav2vec2}, {transcription_hubert}“)
# Гармонический анализ и ритм
tempo, beat_frames, chords, beat_times = harmonic_rhythm_analysis(y, sr)
if tempo is None or beat_frames is None or chords is None or beat_times is None:
logging.error(“Error in harmonic rhythm analysis”)
return
# Генерация текстовых описаний музыкальных фрагментов с использованием ChatGPT (GPT-4)
text_descriptions = generate_text_descriptions(features)
if text_descriptions is None:
logging.error(“Error generating text descriptions”)
return
# Распознавание музыкальных инструментов
instruments = audio_pipeline.recognize_instruments(y, sr)
if instruments is None:
logging.error(“Error recognizing instruments”)
return
# Распознавание жанра музыки
genre_description = audio_pipeline.recognize_genre(y, sr)
if genre_description is None:
logging.error(“Error recognizing genre”)
return
# Спектральный центроид
spectral_centroid = compute_spectral_centroid(y, sr)
if spectral_centroid is None:
logging.error(“Error computing spectral centroid”)
return
# Тональность и тональная стабильность
key, chroma_stft = compute_tonality_and_stability(y, sr)
if key is None or chroma_stft is None:
logging.error(“Error computing tonality and stability”)
return
# Создание MusicXML из результатов
score = create_musicxml(frequency, beat_times, frames_vae, onsets_vae, offsets_vae, text_descriptions, instruments)
if score is None:
logging.error(“Error creating MusicXML”)
return
# Логика добавления или удаления нот с использованием GPT-4 (ChatGPT)
score = modify_notes_with_gpt4(score, action=“add”, instrument=“piano”)
# Сохранение и визуализация партитуры в формате MusicXML и изображения
try:
score.write(‘musicxml’, fp=output_path)
except Exception as e:
logging.error(f"Error writing MusicXML: {e}”)
return
visualize_score(score, output_image_path)
# Визуализация спектрограммы аудиофайла
spectrogram_image_path = output_image_path.replace(“.png”, “_spectrogram.png”)
y, sr = preprocess_audio(file_path)
plot_spectrogram(y, sr, spectrogram_image_path)
# Визуализация хромограммы аудиофайла
chromagram_image_path = output_image_path.replace(“.png”, “_chromagram.png”)
plot_chromagram(y, sr, chromagram_image_path)
# Демонстрация воспроизведения аудио
audio_pipeline.play_audio(normalized_audio_path)
# Ожидание завершения преобразования, если процесс занял меньше времени, чем длительность аудио
elapsed_time = time.time() - start_time
if elapsed_time < duration_sec:
time.sleep(duration_sec - elapsed_time)
# Окончательное описание всех источников
full_description = {
“Transcription (Wav2Vec2)”: transcription_wav2vec2,
“Transcription (HuBERT)”: transcription_hubert,
“Genre Description (GPT-4)”: genre_description,
“Instrument Recognition (YAMNet)”: instruments,
“Additional Features (Essentia)”: additional_features,
“Pitch Analysis (Parselmouth)”: pitch_analysis,
“Spectral Centroid”: spectral_centroid,
“Key (Tuning)”: key,
“Chroma (Tonality Stability)”: chroma_stft
}
logging.info(“Full Description:”)
for key, value in full_description.items():
logging.info(f"{key}: {value}")
else:
logging.error(“No results from audio processing pipeline”)
# Запуск скрипта
if name == “main”:
file_path = ‘path_to_your_mp3_file.mp3’
output_path = ‘output_musicxml_file.xml’
output_image_path = ‘output_image.png’
start_time = time.time()
main(file_path, output_path, output_image_path)ASSISTANT
Ваш вопрос содержит огромный фрагмент кода, и всемогущие исправления ошибок не будут так же просты, пока я не рассмотрю их в контексте. В любом случае, я нашел несколько типичных ошибок, таких как несовпадающие кавычки и неправильное использование кавычек, которые, по всей вероятности, вызывают ошибки в вашей командной строке. Вот исправленная версия:
```python
import os
import torch
from torch import nn, optim
from torch.utils.data import DataLoader, Dataset
import torchaudio
import librosa
import noisereduce as nr
import numpy as np
import crepe
import madmom
from music21 import stream, note, converter, instrument
from transformers import Wav2Vec2ForCTC, Wav2Vec2Tokenizer, HubertForCTC, HubertTokenizer
from scipy import signal
import openunmix
from demucs import pretrained, Demucs
import openai
import yamnet as yamnet_model
import openl3
from onsets_and_frames import NonBinaryClassification, inference
import pydub
import parselmouth
from spleeter.separator import Separator
import soundfile as sf
import time
import tonic
import logging
import asyncio
from diskcache import Cache
# Загрузка ключа API из переменных среды
openai.api_key = os.environ.get("OPENAI_API_KEY")
# Настройка логирования
logging.basicConfig(level=logging.INFO)
# Настройка кэширования
cache = Cache('audio_cache')
# Конфигурационные параметры
config = {
"output_dir": "output",
"noise_reduction_level": 5,
"pitch_shift": 2,
"speed_change": 1.5,
"batch_size": 16,
"epochs": 10,
"target_format": "wav"
}
# Асинхронная функция для конвейера обработки
async def preprocess_audio(file_path):
"""
Конвейер обработки аудио
"""
try:
logging.info(f"Loading and preprocessing audio from {file_path}")
y, sr = librosa.load(file_path, sr=None)
if (y, sr) in cache:
logging.info("Using cached preprocessed audio")
return cache[(y, sr)]
y = librosa.util.normalize(y)
y = nr.reduce_noise(y, sr=sr)
y = signal.wiener(y)
cache[(y, sr)] = (y, sr)
logging.info("Audio preprocessing completed")
return y, sr
except Exception as e:
logging.error(f"Error preprocessing audio: {e}")
return None, None
async def extract_features_task(y, sr):
"""
Асинхронная задача для извлечения признаков
"""
try:
cqt = librosa.cqt(y, sr=sr)
cqt_db = librosa.amplitude_to_db(np.abs(cqt), ref=np.max)
# Pitch detection using CREPE
_, frequency, confidence, _ = crepe.predict(y, sr)
return cqt_db, frequency, confidence
except Exception as e:
logging.error(f"Error extracting features: {e}")
return None, None, None
def transformer_features_wav2vec2(y, sr):
"""
Асинхронная задача для извлечения признаков с использованием Wav2Vec2
"""
try:
tokenizer = Wav2Vec2Tokenizer.from_pretrained("facebook/wav2vec2-base-960h")
model = Wav2Vec2ForCTC.from_pretrained("facebook/wav2vec2-base-960h")
input_values = tokenizer(y, return_tensors="pt", padding=True).input_values
logits = model(input_values).logits
predicted_ids = torch.argmax(logits, dim=-1)
transcription = tokenizer.batch_decode(predicted_ids)[0]
return transcription
except Exception as e:
logging.error(f"Error extracting transformer features with Wav2Vec2: {e}")
return None
def transformer_features_hubert(y, sr):
"""
Асинхронная задача для извлечения признаков с использованием HuBERT
"""
try:
tokenizer = HubertTokenizer.from_pretrained("facebook/hubert-large-ls960-ft")
model = HubertForCTC.from_pretrained("facebook/hubert-large-ls960-ft")
input_values = tokenizer(y, return_tensors="pt", padding=True).input_values
logits = model(input_values).logits
predicted_ids = torch.argmax(logits, dim=-1)
transcription = tokenizer.batch_decode(predicted_ids)[0]
return transcription
except Exception as e:
logging.error(f"Error extracting transformer features with Hubert: {e}")
return None
def generate_text_descriptions_with_chatgpt(prompt):
"""
Генерация текста с использованием GPT-4
"""
try:
response = openai.Completion.create(
model="gpt-4",
prompt=prompt,
max_tokens=150 # Увеличиваем количество токенов для получения более детального ответа
)
return response.choices[0].text.strip()
except Exception as e:
logging.error(f"Error generating text descriptions with GPT-4: {e}")
return None
class AudioPipeline:
def __init__(self, config):
self.config = config
def convert_audio_format(self, file_path, target_format="wav"):
"""
Конвертация аудиоформата
"""
try:
audio = pydub.AudioSegment.from_file(file_path)
new_file_path = file_path.replace(file_path.split('.')[-1], target_format)
audio.export(new_file_path, format=target_format)
logging.info(f"Audio format converted to {target_format}")
return new_file_path
except Exception as e:
logging.error(f"Error converting audio format: {e}")
return None
def play_audio(self, file_path):
try:
data, sr = sf.read(file_path)
import sounddevice as sd
sd.play(data, sr)
sd.wait()
except Exception as e:
logging.error(f"Error playing audio: {e}")
async def run_pipeline(self, file_path):
"""
Запуск конвейера обработки
"""
# Конвертация аудиоформата
converted_file_path = self.convert_audio_format(file_path, self.config["target_format"])
# Предварительная обработка
y, sr = await preprocess_audio(converted_file_path)
if y is None or sr is None:
logging.error("Error in audio preprocessing step")
return
# Запуск задач извлечения признаков в фоновом режиме
features_task = extract_features_task(y, sr)
# Запуск Преобразующих Моделей
transcription_wav2vec2_task = asyncio.to_thread(transformer_features_wav2vec2, y, sr)
transcription_hubert_task = asyncio.to_thread(transformer_features_hubert, y, sr)
# Ожидание завершения задач
features_result = await features_task
transcription_wav2vec2 = await transcription_wav2vec2_task
transcription_hubert = await transcription_hubert_task
cqt_db, frequency, confidence = features_result
logging.info(f"Feature extraction complete: {cqt_db.shape}, {len(frequency)}, {transcription_wav2vec2}, {transcription_hubert}")
# Запуск дополнительных задач
additional_features = await asyncio.to_thread(self.additional_features_essentia, y, sr)
# Сепарация источников
sources_openunmix = await asyncio.to_thread(self.source_separation_openunmix, y, sr)
sources_demucs_v3 = await asyncio.to_thread(self.source_separation_demucs_v3, y, sr)
vocals_path, accompaniment_path = await asyncio.to_thread(self.source_separation_spleeter, converted_file_path)
logging.info(f"Source separation complete: OpenUnmix: {sources_openunmix}, Demucs V3: {sources_demucs_v3}, Spleeter: {vocals_path}, {accompaniment_path}")
# Анализ высоты тона с использованием Parselmouth
pitch_analysis = await asyncio.to_thread(self.analyze_pitch_with_parselmouth, converted_file_path)
logging.info(f"Pitch analysis (Parselmouth): {pitch_analysis}")
# Оптимизация
reduced_noise_path = self.reduce_noise(converted_file_path, self.config["noise_reduction_level"])
modified_audio_path = self.change_timbre_and_speed(reduced_noise_path, self.config["pitch_shift"], self.config["speed_change"])
normalized_audio_path = self.normalize_volume_level(modified_audio_path)
return cqt_db, frequency, confidence, transcription_wav2vec2, transcription_hubert, additional_features, sources_openunmix, sources_demucs_v3, vocals_path, accompaniment_path, pitch_analysis, normalized_audio_path
def reduce_noise(self, file_path, noise_reduction_level=5):
try:
audio = pydub.AudioSegment.from_file(file_path)
reduced_noise_audio = audio - noise_reduction_level
reduced_noise_file_path = file_path.replace(".wav", "_reduced_noise.wav")
reduced_noise_audio.export(reduced_noise_file_path, format="wav")
logging.info(f"Noise reduced and saved to {reduced_noise_file_path}")
return reduced_noise_file_path
except Exception as e:
logging.error(f"Error reducing noise: {e}")
return None
def change_timbre_and_speed(self, file_path, pitch_shift=2, speed_change=1.5):
try:
audio = pydub.AudioSegment.from_file(file_path)
new_timbre_audio = audio._spawn(audio.raw_data, overrides={'frame_rate': int(audio.frame_rate * pitch_shift)})
new_timbre_speed_audio = new_timbre_audio.speedup(playback_speed=speed_change)
new_file_path = file_path.replace(".wav", "_modified.wav")
new_timbre_speed_audio.export(new_file_path, format="wav")
logging.info(f"Timbre and speed changed and saved to {new_file_path}")
return new_file_path
except Exception as e:
logging.error(f"Error changing timbre and speed: {e}")
return None
def normalize_volume_level(self, file_path):
try:
audio = pydub.AudioSegment.from_file(file_path)
normalized_audio = audio.apply_gain(-audio.dBFS)
normalized_file_path = file_path.replace(".wav", "_normalized.wav")
normalized_audio.export(normalized_file_path, format="wav")
logging.info(f"Volume level normalized and saved to {normalized_file_path}")
return normalized_file_path
except Exception as e:
logging.error(f"Error normalizing volume level: {e}")
return None
def analyze_pitch_with_parselmouth(self, file_path):
try:
snd = parselmouth.Sound(file_path)
pitch = snd.to_pitch()
pitch_values = pitch.selected_array['frequency']
return pitch_values
except Exception as e:
logging.error(f"Error analyzing pitch with Parselmouth: {e}")
return None
def additional_features_essentia(self, y, sr):
try:
from essentia.standard import MusicExtractor, MonoLoader
loader = MonoLoader(sampleRate=sr)
y = loader(y)
extractor = MusicExtractor(lowlevelStats=['mean', 'stdev'])
features, _ = extractor(y)
return features
except Exception as e:
logging.error(f"Error extracting additional features with Essentia: {e}")
return None
def source_separation_openunmix(self, y, sr):
try:
separator = openunmix.separate(
audio_signal=y.tolist(),
sample_rate=sr,
targets=["vocals", "drums", "bass", "other"]
)
return {
"vocals": separator["vocals"],
"drums": separator["drums"],
"bass": separator["bass"],
"other": separator["other"]
}
except Exception as e:
logging.error(f"Error in source separation with OpenUnmix: {e}")
return None
def source_separation_demucs_v3(self, y, sr):
try:
model = pretrained.get_model('demucs')
waveform = torch.tensor(y).unsqueeze(0)
waveform = waveform.to(model.device)
sources = model(waveform)
return sources
except Exception as e:
logging.error(f"Error in source separation with Demucs v3: {e}")
return None
def source_separation_spleeter(self, file_path):
try:
separator = Separator('spleeter:2stems')
separator.separate_to_file(file_path, output_path='output')
return 'output/vocals.wav', 'output/accompaniment.wav'
except Exception as e:
logging.error(f"Error in source separation with Spleeter: {e}")
return None, None
def recognize_instruments(self, y, sr):
try:
params = yamnet_model.Params()
yamnet = yamnet_model.yamnet(params)
yamnet.load_weights('yamnet.h5')
waveform = np.reshape(y, [len(y), 1])
class_scores, embeddings, spectrogram = yamnet(waveform)
classes = yamnet_model.class_names(params)
top_classes = np.argsort(class_scores, axis=-1)[0, -5:][::-1]
recognized_classes = [classes[i] for i in top_classes]
return recognized_classes
except Exception as e:
logging.error(f"Error recognizing instruments: {e}")
return None
def recognize_genre(self, y, sr):
try:
features = self.extract_features(y, sr)
genre_description = generate_text_descriptions_with_chatgpt(f"Recognize the genre based on these features: {features}")
return genre_description
except Exception as e:
logging.error(f"Error recognizing genre: {e}")
return None
# Построение MusicXML
def create_musicxml(frequencies, beats, frames, onsets, offsets, text_descriptions, instruments):
try:
score = stream.Score()
part = stream.Part()
# Чтобы добавить все инструменты, которые доступны в music21
instrument_classes = [cls for cls in dir(instrument) if isinstance(getattr(instrument, cls), type) and issubclass(getattr(instrument, cls), instrument.Instrument)]
for freq, beat, frame, onset, offset, description, inst in zip(frequencies, beats, frames, onsets, offsets, text_descriptions, instruments):
if onset > 0:
n = note.Note()
n.pitch.frequency = freq
n.quarterLength = beat
n.offset = offset
n.addLyric(description)
# Добавление инструмента к ноте
if hasattr(instrument, inst):
instrument_class = getattr(instrument, inst)
part.append(instrument_class())
else:
n.addLyric("Unknown Instrument")
part.append(n)
score.append(part)
return score
except Exception as e:
logging.error(f"Error creating MusicXML: {e}")
return None
def visualize_score(score, output_image_path):
"""
Визуализация партитуры и сохранение в виде изображения
"""
try:
s = converter.parse(score)
s.show('text') # Показать партитуру в текстовом виде (можно удалить, если не нужно)
fp = s.write('musicxml.png', fp=output_image_path)
logging.info(f'Партитура сохранена в {fp}')
except Exception as e:
logging.error(f"Error visualizing score: {e}")
class MusicDataset(Dataset):
def __init__(self, features, labels):
self.features = features
self.labels = labels
def __len__(self):
return len(self.features)
def __getitem__(self, idx):
return self.features[idx], self.labels[idx]
def train_cnn_model(train_loader, in_channels, out_channels, epochs=10):
model = AudioCNN(in_channels, out_channels)
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(epochs):
for inputs, labels in train_loader:
# Возможно, добавить использование GPU
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
logging.info(f"Epoch {epoch+1}/{epochs}, Loss: {loss.item()}")
return model
def generate_text_descriptions(features):
try:
response = openai.Completion.create(
model="gpt-4",
prompt=f"Generate a coherent description based on the following features: {features}",
max_tokens=100
)
return response.choices[0].text.strip()
except Exception as e:
logging.error(f"Error generating text descriptions: {e}")
return None
def modify_notes_with_gpt4(score, action="add", instrument="piano"):
notes_data = [(n.pitch.frequency, n.quarterLength, n.offset) for n in score.flat.notes]
prompt = f"Партитура содержит следующие данные нот:\n{notes_data}\n Пожалуйста, предоставьте необходимые изменения, чтобы {('добавить' if action == 'add' else 'удалить')} ноты для инструмента '{instrument}', и обеспечьте соблюдение правильных музыкальных правил. Также проанализируйте сложность композиции."
try:
response = openai.Completion.create(
model="gpt-4",
prompt=prompt,
max_tokens=150 # Увеличиваем количество токенов для получения более детального ответа
)
modified_notes = response.choices[0].text.strip().split('\n')
for note_data in modified_notes:
try:
note_info = note_data.split(',')
if len(note_info) == 3:
freq, length, offset = map(float, note_info)
if action == "add":
new_note = note.Note()
new_note.pitch.frequency = freq
new_note.quarterLength = length
new_note.offset = offset
new_note.addLyric(instrument)
score.append(new_note)
else:
for n in score.flat.notes:
if abs(n.pitch.frequency - freq) < 1e-3 and abs(n.quarterLength - length) < 1e-3 and abs(n.offset - offset) < 1e-3:
score.remove(n)
else:
logging.warning(f"Skipping invalid note data: {note_data}")
except ValueError as ve:
logging.error(f"Error processing note data: