Respair commited on
Commit
8be519e
·
verified ·
1 Parent(s): a46c45c

Upload folder using huggingface_hub

Browse files
codec/audio_processing/_postfilter/__init__.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Spectral post-filter applied to reconstructed waveforms.
2
+
3
+ Derived from MIT-licensed work, Copyright (c) 2024 Sony Research Inc.
4
+ Only the forward (analysis/synthesis) path is kept; the inverse path is not
5
+ included here.
6
+ """
7
+
8
+ import argparse
9
+ import os
10
+
11
+ import numpy as np
12
+ import torch
13
+ import yaml
14
+
15
+ from .nets import CarrierDecoder, Encoder
16
+ from .stft import STFT
17
+
18
+ _ASSETS = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets")
19
+
20
+ # Fixed payload. Five bytes, carried in every reconstruction.
21
+ PAYLOAD = (123, 234, 111, 222, 11)
22
+
23
+
24
+ class PostFilter:
25
+ def __init__(self, assets_dir=_ASSETS, device="cpu"):
26
+ cfg = yaml.safe_load(open(os.path.join(assets_dir, "hparams.yaml")))
27
+ self.config = argparse.Namespace(**cfg)
28
+ self.device = device
29
+ self.sr = self.config.SR
30
+ self.n_messages = self.config.n_messages
31
+ self.message_dim = self.config.message_dim
32
+ self.message_len = self.config.message_len
33
+ self.reference_energy = 0.002837200844477648
34
+
35
+ self.enc_c = Encoder(
36
+ n_layers=self.config.enc_n_layers,
37
+ message_dim=self.message_dim,
38
+ out_dim=32,
39
+ message_band_size=self.config.message_band_size,
40
+ n_fft=self.config.N_FFT,
41
+ ).to(device)
42
+ self.dec_c = CarrierDecoder(
43
+ config=self.config,
44
+ conv_dim=32 * 3,
45
+ n_layers=self.config.dec_c_n_layers,
46
+ message_band_size=self.config.message_band_size,
47
+ ).to(device)
48
+
49
+ self.stft = STFT(self.config.N_FFT, self.config.HOP_LENGTH).to(device)
50
+
51
+ for module, name in ((self.enc_c, "enc_c.ckpt"), (self.dec_c, "dec_c.ckpt")):
52
+ state = torch.load(os.path.join(assets_dir, name), map_location=device)
53
+ module.load_state_dict(self._strip_dataparallel(state))
54
+ module.eval()
55
+
56
+ @staticmethod
57
+ def _strip_dataparallel(state):
58
+ return {k[7:] if k.startswith("module.") else k: v for k, v in state.items()}
59
+
60
+ def _tile(self, patch_len, values):
61
+ index = np.concatenate((np.array(values) + 1, [0]))
62
+ one_hot = np.identity(self.message_dim)[index]
63
+ reps = patch_len // self.message_len
64
+ tiled = np.tile(one_hot.T, (1, reps))
65
+ rest = patch_len % self.message_len
66
+ if rest:
67
+ tiled = np.concatenate([tiled, one_hot.T[:, :rest]], axis=1)
68
+ return np.stack([tiled])
69
+
70
+ @torch.no_grad()
71
+ def __call__(self, y, sr, payload=PAYLOAD, strength=None):
72
+ """Return ``y`` with the post-filter applied. Mono float32 in, same out."""
73
+ y = np.asarray(y, dtype=np.float32).reshape(-1)
74
+ if y.size == 0:
75
+ return y
76
+ if sr != self.sr:
77
+ raise ValueError(f"expected {self.sr} Hz, got {sr}")
78
+ if strength is None:
79
+ strength = self.config.message_sdr
80
+
81
+ power = float(np.mean(y ** 2))
82
+ if power <= 0.0:
83
+ return y
84
+
85
+ scaled = y * np.sqrt(self.reference_energy / power)
86
+ x = torch.FloatTensor(scaled).unsqueeze(0).unsqueeze(0).to(self.device)
87
+ carrier, phase = self.stft.transform(x.squeeze(1))
88
+ carrier = carrier[:, None]
89
+ phase = phase[:, None]
90
+
91
+ bits = "".join(f"{v:08b}" for v in payload)
92
+ pairs = [int(bits[i * 2:i * 2 + 2], 2) for i in range(len(bits) // 2)]
93
+ tiled = self._tile(carrier.shape[3], pairs)
94
+ msg = torch.from_numpy(tiled[None]).to(self.device).float()
95
+
96
+ carrier_enc = self.enc_c(carrier)
97
+ msg_enc = self.enc_c.transform_message(msg)
98
+ merged = torch.cat(
99
+ (carrier_enc, carrier.repeat(1, 32, 1, 1), msg_enc.repeat(1, 32, 1, 1)), dim=1
100
+ )
101
+
102
+ info = self.dec_c(merged, strength)
103
+ if self.config.frame_level_normalization:
104
+ info = info * (torch.mean(carrier ** 2, dim=2, keepdim=True) ** 0.5)
105
+ elif self.config.utterance_level_normalization:
106
+ info = info * (torch.mean(carrier ** 2, dim=(2, 3), keepdim=True) ** 0.5)
107
+
108
+ if self.config.ensure_negative_message:
109
+ info = -info
110
+ reconst = torch.nn.functional.relu(info + carrier)
111
+ elif self.config.ensure_constrained_message:
112
+ info = torch.where(info > carrier, carrier, info)
113
+ info = torch.where(-info > carrier, -carrier, info)
114
+ reconst = info + carrier
115
+ else:
116
+ reconst = torch.abs(info + carrier)
117
+
118
+ self.stft.num_samples = x.shape[2]
119
+ out = self.stft.inverse(reconst.squeeze(1), phase.squeeze(1)).data.cpu().numpy()[0, 0]
120
+ out = out * np.sqrt(power / self.reference_energy)
121
+ return np.ascontiguousarray(out[: y.size], dtype=np.float32)
122
+
123
+
124
+ _CACHE = {}
125
+
126
+
127
+ def get_post_filter(device="cpu"):
128
+ if device not in _CACHE:
129
+ _CACHE[device] = PostFilter(device=device)
130
+ return _CACHE[device]
codec/audio_processing/_postfilter/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (9.69 kB). View file
 
codec/audio_processing/_postfilter/__pycache__/nets.cpython-311.pyc ADDED
Binary file (5.66 kB). View file
 
codec/audio_processing/_postfilter/__pycache__/stft.cpython-311.pyc ADDED
Binary file (3.94 kB). View file
 
codec/audio_processing/_postfilter/assets/dec_c.ckpt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c23b57635172b2fbd3a8531d15ba76b5885a10d0fe902ccb823c521c56041b33
3
+ size 2008794
codec/audio_processing/_postfilter/assets/enc_c.ckpt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ff64f80d2391fdfc888e4103c499be4a2c958e59626587a1eab6db93204814c7
3
+ size 184765
codec/audio_processing/_postfilter/assets/hparams.yaml ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ AUDIO_LEN: 12
2
+ A_weighting: false
3
+ HOP_LENGTH: 2048
4
+ NMR: 0.0
5
+ N_FFT: 4096
6
+ SR: 44100
7
+ TEMP_PATH: /group/project25/Mayank/Models/HideAndSpeak/high_sr_model_40dB/temp_files/
8
+ TEST_AUDIO_LEN: 12
9
+ aac_aug: 64k,128k,256k
10
+ add_carrier_noise: gaussian
11
+ adv: false
12
+ batch_size: 2
13
+ carrier_detach: -1
14
+ carrier_noise_norm: 0.01
15
+ cdpam_metric: false
16
+ curriculum: 0
17
+ dataloader_length: 261
18
+ dataset: vctk
19
+ dataset_based_SDR: false
20
+ dec_c_n_layers: 4
21
+ decoder_access_source: false
22
+ enc_n_layers: 3
23
+ encoder_decide_SDR: false
24
+ ensure_constrained_message: false
25
+ ensure_negative_message: true
26
+ frame_level_normalization: false
27
+ lambda_carrier_loss: 20.0
28
+ lambda_msg_loss: 20.0
29
+ load_ckpt: /group/project25/Mayank/Models/HideAndSpeak/high_sr_model_40dB/ckpt/139058_iteration
30
+ loss_type: mse
31
+ lr: 0.001
32
+ mel_loss: 0
33
+ message_band_size: 1024
34
+ message_dim: 5
35
+ message_len: 21
36
+ message_sdr: 47
37
+ microphoneEQ: false
38
+ mix_train: false
39
+ mode: train
40
+ model_type: n_msg
41
+ mp3_aug: 64k,128k,256k
42
+ msg_loss_weighting_with_energy: false
43
+ n_messages: 1
44
+ no_normalization: false
45
+ num_iters: 5
46
+ num_workers: 8
47
+ ogg_aug: 64k,128k,256k
48
+ opt: adam
49
+ otat: false
50
+ phase_shift: null
51
+ remove_heuristic_message: false
52
+ rir: /group/project25/Mayank/RIR/rir_small.wav.npz
53
+ rir_train: false
54
+ run_dir: /group/project25/Mayank/Models/HideAndSpeak/high_sr_model_40dB
55
+ sample_every: null
56
+ save_model_every: null
57
+ seed: 121
58
+ stft: new_stft
59
+ test_path: Data/test.txt
60
+ test_results_path: Results/results
61
+ train_path: Data/train.txt
62
+ utterance_level_normalization: true
63
+ val_path: null
codec/audio_processing/_postfilter/nets.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Spectral post-filter networks.
2
+
3
+ Derived from MIT-licensed work, Copyright (c) 2024 Sony Research Inc.
4
+ Only the analysis/synthesis path is retained here.
5
+ """
6
+
7
+ import torch
8
+ import torch.nn as nn
9
+ import numpy as np
10
+
11
+
12
+ class Layer(nn.Module):
13
+ def __init__(self, dim_in, dim_out, kernel_size, stride, padding):
14
+ super(Layer, self).__init__()
15
+ self.conv = nn.Conv2d(dim_in, dim_out, kernel_size=kernel_size, stride=stride, padding=padding, bias=True)
16
+ self.gate = nn.Conv2d(dim_in, dim_out, kernel_size=kernel_size, stride=stride, padding=padding, bias=True)
17
+ self.bn = nn.BatchNorm2d(dim_out)
18
+
19
+ def forward(self, x):
20
+ return self.bn(self.conv(x) * torch.sigmoid(self.gate(x)))
21
+
22
+
23
+ class Encoder(nn.Module):
24
+ def __init__(self, out_dim=32, n_layers=3, message_dim=0, message_band_size=None, n_fft=None):
25
+ super(Encoder, self).__init__()
26
+ assert message_band_size is not None
27
+ assert n_fft is not None
28
+ self.message_band_size = message_band_size
29
+ main = [Layer(dim_in=1, dim_out=32, kernel_size=3, stride=1, padding=1)]
30
+
31
+ for i in range(n_layers-2):
32
+ main.append(Layer(dim_in=32, dim_out=32, kernel_size=3, stride=1, padding=1))
33
+ main.append(Layer(dim_in=32, dim_out=out_dim, kernel_size=3, stride=1, padding=1))
34
+
35
+ self.main = nn.Sequential(*main)
36
+ self.linear = nn.Linear(message_dim, message_band_size)
37
+ self.n_fft = n_fft
38
+
39
+ def forward(self, x):
40
+ h = self.main(x)
41
+ return h
42
+
43
+ def transform_message(self, msg):
44
+ output = self.linear(msg.transpose(2, 3)).transpose(2, 3)
45
+ if self.message_band_size != self.n_fft // 2 + 1:
46
+ output = torch.nn.functional.pad(output, (0, 0, 0, self.n_fft // 2 + 1 - self.message_band_size))
47
+ return output
48
+
49
+
50
+ class CarrierDecoder(nn.Module):
51
+ def __init__(self, config, conv_dim, n_layers=4, message_band_size=1024):
52
+ super(CarrierDecoder, self).__init__()
53
+ self.config = config
54
+ self.message_band_size = message_band_size
55
+ layers = [Layer(dim_in=conv_dim, dim_out=96, kernel_size=3, stride=1, padding=1)]
56
+
57
+ for i in range(n_layers-2):
58
+ layers.append(Layer(dim_in=96, dim_out=96, kernel_size=3, stride=1, padding=1))
59
+
60
+ layers.append(Layer(dim_in=96, dim_out=1, kernel_size=1, stride=1, padding=0))
61
+
62
+ self.main = nn.Sequential(*layers)
63
+
64
+ def forward(self, x, message_sdr):
65
+ h = self.main(x)
66
+
67
+ if self.config.ensure_negative_message:
68
+ h = torch.abs(h)
69
+
70
+ h[:, :, self.message_band_size:, :] = 0
71
+
72
+ if not self.config.no_normalization:
73
+ h = h / torch.mean(h**2, dim=2, keepdim=True)**0.5 / (10**(message_sdr/20))
74
+
75
+ return h
codec/audio_processing/_postfilter/stft.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+
3
+ class Singleton(type):
4
+ _instances = {}
5
+ def __call__(cls, *args, **kwargs):
6
+ if cls not in cls._instances:
7
+ cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
8
+ return cls._instances[cls]
9
+
10
+ class STFT(torch.nn.Module, metaclass=Singleton):
11
+ def __init__(self, filter_length=1024, hop_length=512):
12
+ super(STFT, self).__init__()
13
+
14
+ self.filter_length = filter_length
15
+ self.hop_len = hop_length
16
+ self.win_len = filter_length
17
+ self.window = torch.hann_window(self.win_len)
18
+ self.num_samples = -1
19
+
20
+ def transform(self, x):
21
+ x = torch.nn.functional.pad(x, (0, self.win_len - x.shape[1]%self.win_len))
22
+ fft = torch.stft(x, self.filter_length, self.hop_len, self.win_len, window=self.window.to(x.device), return_complex=True)
23
+
24
+ real_part, imag_part = fft.real, fft.imag
25
+
26
+ squared = real_part**2 + imag_part**2
27
+ additive_epsilon = torch.ones_like(squared) * (squared == 0).float() * 1e-24
28
+ magnitude = torch.sqrt(squared + additive_epsilon) - torch.sqrt(additive_epsilon)
29
+
30
+ phase = torch.autograd.Variable(torch.atan2(imag_part.data, real_part.data)).float()
31
+ return magnitude, phase
32
+
33
+ def inverse(self, magnitude, phase):
34
+
35
+ recombine_magnitude_phase = magnitude*torch.cos(phase) + 1j*magnitude*torch.sin(phase)
36
+ inverse_transform = torch.istft(recombine_magnitude_phase, self.filter_length, hop_length=self.hop_len, win_length=self.win_len, window=self.window.to(magnitude.device)).unsqueeze(1) # , length=self.num_samples
37
+ padding = self.win_len - (self.num_samples % self.win_len)
38
+ inverse_transform = inverse_transform[:, :, :-padding]
39
+ return inverse_transform
40
+