| | |
| | |
| | |
| |
|
| | |
| |
|
| | import numpy as np |
| | import torch |
| | from torch.cuda.amp import autocast |
| |
|
| | def decode_audio_chunk(audio_chunk, model, device, config): |
| | |
| | use_half_precision = config.get("use_half_precision", True) |
| | |
| | |
| | dtype = torch.float16 if use_half_precision else torch.float32 |
| |
|
| | |
| | src_tensor = torch.tensor(audio_chunk, dtype=dtype).unsqueeze(0).to(device) |
| |
|
| | with torch.no_grad(): |
| | if use_half_precision: |
| |
|
| | with autocast(dtype=torch.float16): |
| | encoder_outputs = model.encoder(src_tensor) |
| | output_sequence = model.decoder(encoder_outputs) |
| | else: |
| | encoder_outputs = model.encoder(src_tensor) |
| | output_sequence = model.decoder(encoder_outputs) |
| |
|
| | |
| | decoded_outputs = output_sequence.squeeze(0).cpu().numpy() |
| | return decoded_outputs |
| |
|
| |
|
| | def concatenate_outputs(all_decoded_outputs, num_frames): |
| | final_decoded_outputs = np.concatenate(all_decoded_outputs, axis=0) |
| | final_decoded_outputs = final_decoded_outputs[:num_frames] |
| | return final_decoded_outputs |
| |
|
| | def ensure_2d(final_decoded_outputs): |
| | if final_decoded_outputs.ndim == 3: |
| | final_decoded_outputs = final_decoded_outputs.reshape(-1, final_decoded_outputs.shape[-1]) |
| | return final_decoded_outputs |
| |
|
| | def pad_audio_chunk(audio_chunk, frame_length, num_features, pad_mode='replicate'): |
| | """ |
| | Pads the audio_chunk to ensure it has a number of frames equal to frame_length. |
| | |
| | Parameters: |
| | audio_chunk (np.array): Input audio data with shape (num_frames, num_features). |
| | frame_length (int): Desired number of frames. |
| | num_features (int): Number of features per frame. |
| | pad_mode (str): Type of padding to use. Options are: |
| | - 'reflect': Pads using reflection. |
| | - 'replicate': Pads by replicating the last frame. |
| | |
| | Returns: |
| | np.array: Padded audio_chunk with shape (frame_length, num_features). |
| | """ |
| | if audio_chunk.shape[0] < frame_length: |
| | pad_length = frame_length - audio_chunk.shape[0] |
| | |
| | if pad_mode == 'reflect': |
| | |
| | padding = np.pad( |
| | audio_chunk, |
| | pad_width=((0, pad_length), (0, 0)), |
| | mode='reflect' |
| | ) |
| | |
| | audio_chunk = np.vstack((audio_chunk, padding[-pad_length:, :num_features])) |
| | |
| | elif pad_mode == 'replicate': |
| | |
| | |
| | last_frame = audio_chunk[-1:] |
| | replication = np.tile(last_frame, (pad_length, 1)) |
| | audio_chunk = np.vstack((audio_chunk, replication)) |
| | |
| | else: |
| | raise ValueError(f"Unsupported pad_mode: {pad_mode}. Choose 'reflect' or 'replicate'.") |
| | |
| | return audio_chunk |
| |
|
| |
|
| | def blend_chunks(chunk1, chunk2, overlap): |
| | actual_overlap = min(overlap, len(chunk1), len(chunk2)) |
| | if actual_overlap == 0: |
| | return np.vstack((chunk1, chunk2)) |
| | |
| | blended_chunk = np.copy(chunk1) |
| | for i in range(actual_overlap): |
| | alpha = i / actual_overlap |
| | blended_chunk[-actual_overlap + i] = (1 - alpha) * chunk1[-actual_overlap + i] + alpha * chunk2[i] |
| | |
| | return np.vstack((blended_chunk, chunk2[actual_overlap:])) |
| |
|
| | def process_audio_features(audio_features, model, device, config): |
| | |
| | frame_length = config['frame_size'] |
| | overlap = config.get('overlap', 32) |
| | num_features = audio_features.shape[1] |
| | num_frames = audio_features.shape[0] |
| | all_decoded_outputs = [] |
| |
|
| | |
| | model.eval() |
| |
|
| | |
| | start_idx = 0 |
| | while start_idx < num_frames: |
| | end_idx = min(start_idx + frame_length, num_frames) |
| |
|
| | |
| | audio_chunk = audio_features[start_idx:end_idx] |
| | audio_chunk = pad_audio_chunk(audio_chunk, frame_length, num_features) |
| |
|
| | |
| | decoded_outputs = decode_audio_chunk(audio_chunk, model, device, config) |
| | decoded_outputs = decoded_outputs[:end_idx - start_idx] |
| |
|
| | |
| | if all_decoded_outputs: |
| | last_chunk = all_decoded_outputs.pop() |
| | blended_chunk = blend_chunks(last_chunk, decoded_outputs, overlap) |
| | all_decoded_outputs.append(blended_chunk) |
| | else: |
| | all_decoded_outputs.append(decoded_outputs) |
| |
|
| | |
| | start_idx += frame_length - overlap |
| |
|
| | |
| | current_length = sum(len(chunk) for chunk in all_decoded_outputs) |
| | if current_length < num_frames: |
| | remaining_frames = num_frames - current_length |
| | final_chunk_start = num_frames - remaining_frames |
| | audio_chunk = audio_features[final_chunk_start:num_frames] |
| | audio_chunk = pad_audio_chunk(audio_chunk, frame_length, num_features) |
| | decoded_outputs = decode_audio_chunk(audio_chunk, model, device, config) |
| | all_decoded_outputs.append(decoded_outputs[:remaining_frames]) |
| |
|
| | |
| | final_decoded_outputs = np.concatenate(all_decoded_outputs, axis=0)[:num_frames] |
| |
|
| | |
| | final_decoded_outputs = ensure_2d(final_decoded_outputs) |
| | final_decoded_outputs[:, :61] /= 100 |
| |
|
| | |
| | ease_duration_frames = min(int(0.1 * 60), final_decoded_outputs.shape[0]) |
| | easing_factors = np.linspace(0, 1, ease_duration_frames)[:, None] |
| | final_decoded_outputs[:ease_duration_frames] *= easing_factors |
| |
|
| | |
| | final_decoded_outputs = zero_columns(final_decoded_outputs) |
| |
|
| | return final_decoded_outputs |
| |
|
| |
|
| | def zero_columns(data): |
| | columns_to_zero = [0, 1, 2, 3, 4, 7, 8, 9, 10, 11, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60] |
| | modified_data = np.copy(data) |
| | modified_data[:, columns_to_zero] = 0 |
| | return modified_data |
| |
|