# Description: This script is used to encode the npz files in the input_dir and save the encoded npz files in the output_dir. # Note this is reencoding 7b and decode 7b from suno_utils.tasks.mert_25 import ( preload_models as preload_semantic_models, encode as semantic_encode, ) from suno_utils.tasks.dac_2c_12cb import ( preload_models as preload_codec_models_12, encode as codec_encode_12, decode as codec_decode_12, ) from suno_utils.fine.generation import FineConfig, Fine, load_model as load_fine_modal, generate from suno_utils.models.dac.model.dac2_12 import DAC as DAC12 import torch import os import numpy as np from tqdm import tqdm import json import random import typing as tp from suno_utils.audio import Audio import torch.nn.functional as F semantic_ckpt_path = "/home/victor/data/models/chirp_v2/mert_25.pt" semantic_centroids_path = "/home/victor/data/models/chirp_v2/mert_25_2x4k.npy" codec_ckpt_path_12 = "/app/suno/tony/v3/dac_2c_25x12.pt" fine_codec_ckpt_path = "/home/victor/data/models/dac_100x16.pth" fine_ckpt_path = "/app/suno/checkpoints/7b_fine/best_ckpt.pt" # 7b input_dir = "/app/suno/data/dpo/v3_npz" output_dir = "/app/suno/data/dpo/7b_upsample_npz" class FineCodec(torch.nn.Module): def __init__(self, codec_path: str): super().__init__() sd = torch.load(codec_path, map_location="cpu") model = DAC12(**sd["metadata"]["kwargs"]) model.load_state_dict(sd["state_dict"]) model.eval() self.model = model @torch.inference_mode() def forward( self, audios: tp.Union[torch.Tensor, tp.List[torch.Tensor], tp.Tuple[torch.Tensor]], device: tp.Union[torch.device, str], ) -> tp.Tuple[torch.Tensor, torch.Tensor]: if isinstance(audios, list) or isinstance(audios, tuple): audios = torch.cat(audios, dim=0) # (B, C, T) audios = audios.to(device) if len(audios.shape) == 2: audios = audios.unsqueeze(0) encoded = self.model(audios, 48000) return encoded["codes"], encoded["z"], encoded["audio"] @torch.inference_mode() def decode(self, codes): # zero out padding for now codes = torch.where(codes < self.model.quantizer.codebook_size, codes, 0) latents = self.model.quantizer.from_codes(codes)[0] return self.model.decode(latents) if __name__ == "__main__": avialbe_device = f"cuda:{os.environ['CUDA_VISIBLE_DEVICES']}" print(avialbe_device) preload_codec_models_12(codec_ckpt_path_12, device="cuda") preload_semantic_models(semantic_ckpt_path, semantic_centroids_path, device="cuda") fine_codec = FineCodec(fine_codec_ckpt_path).cuda() fine_model = load_fine_modal(fine_ckpt_path, "cuda") config = fine_model.config print("finished loading models") # setup some helper functions inside def pad_coarse_codes(x, remove_last=0): if remove_last > 0: # replace with padding x[:, -remove_last:] = config.coarse_pad_token # pad to length + 1 for inference token x = F.pad( x, (0, config.coarse_samples - x.shape[-1] + 1), "constant", config.coarse_pad_token, ) # add fine streams x = F.pad( x, (0, 0, 0, config.fine_n_codebooks), "constant", config.fine_pad_token, ) # set inference token x[:, config.coarse_n_codebooks :, -1] = config.fine_infer_token return x.squeeze(0) def upsample_chirp(filename: str): input_path = os.path.join(input_dir, filename) output_path = os.path.join(output_dir, filename) if os.path.exists(output_path): return with open(output_path, "w") as fp: fp.write("") try: # encode npz = np.load(input_path).get("v3.0_raw") array = torch.from_numpy(npz).long().to("cuda").T original_duration = array.shape[1] / 25 # make coarse batch by splitting into 2s clips coarse_codes = [] for i in range(0, array.size(-1), config.coarse_samples): code = array[1:, i : i + config.coarse_samples] coarse_codes.append(pad_coarse_codes(code.unsqueeze(0))) coarse_codes = torch.stack(coarse_codes, dim=0) # print(coarse_codes.shape) # print(coarse_codes.max()) # this should be somewhat deterministic fine_codes = generate( fine_model, coarse_codes, config.t_fine - 1, temperature=0.8, top_k=5, silent=True ) fine_codes = torch.transpose(fine_codes, 0, 1) fine_codes = fine_codes.reshape(1, config.fine_n_codebooks, -1) audio = fine_codec.decode(fine_codes.cuda()) audio = Audio.from_array_float(audio.squeeze(0).cpu().numpy(), 48000) audio = audio.get_segment(to_s=original_duration) # only encode 1 since we use only 1 now semantic_labels = semantic_encode(audio, n_codebooks=1) codec_labels = codec_encode_12(audio) n_frames = min(semantic_labels.shape[0], codec_labels.shape[0]) audio_arr = np.concatenate( [semantic_labels[:n_frames, :], codec_labels[:n_frames, :]], axis=-1, ) output_npz = {"v3.0_raw": audio_arr} np.savez(output_path, **output_npz) return except Exception as e: os.remove(output_path) print(f"WTF {filename}, {e}") with open("/home/tony/Data/Preference/7b_v2/7v_v20_full_recut_id_negative.json", "r") as fp: total_jobs = json.load(fp) total_jobs = [f"{file_name}.npz" for file_name in total_jobs] finished_jobs = os.listdir(output_dir) unfinished_jobs = sorted(list(set(total_jobs) - set(finished_jobs))) # for testing # total_jobs = [ # "fff507cb-b970-4583-8cc3-d937dbf0e4b9.npz", # "fff82f8b-af8c-484e-a4e7-3bf38ef4c410.npz", # ] print(f"{len(unfinished_jobs)} to be converted.") # random this random.shuffle(unfinished_jobs) for filename in tqdm(unfinished_jobs): upsample_chirp(filename) print("DONE!")