harp-dev commited on
Commit
36cebbb
·
verified ·
1 Parent(s): 76450af

Pad the input so the result is not shortened by the receptive field

Browse files
Files changed (1) hide show
  1. microtcn_runtime.py +42 -0
microtcn_runtime.py CHANGED
@@ -177,6 +177,33 @@ def _load_model() -> MicroTCN:
177
  return _MODEL
178
 
179
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  def process_audio(
181
  audio_path: str,
182
  limit_mode: float,
@@ -191,7 +218,16 @@ def process_audio(
191
  if sr != SAMPLE_RATE:
192
  waveform = torchaudio.functional.resample(waveform, sr, SAMPLE_RATE)
193
 
 
 
 
 
 
194
  x = waveform.unsqueeze(0).to(device)
 
 
 
 
195
  p = torch.tensor(
196
  [[[limit_mode, peak_reduction]]], dtype=torch.float32, device=device
197
  )
@@ -200,4 +236,10 @@ def process_audio(
200
  y = model(x, p)
201
 
202
  output = y.squeeze().cpu().numpy().astype(np.float32)
 
 
 
 
 
 
203
  return output, SAMPLE_RATE
 
177
  return _MODEL
178
 
179
 
180
+ _RECEPTIVE_FIELD = None
181
+
182
+
183
+ def _receptive_field(model, device) -> int:
184
+ """
185
+ How many samples the network consumes, measured once from the model itself.
186
+
187
+ Args:
188
+ model: The loaded network.
189
+ device: Where to run the measurement.
190
+
191
+ Returns:
192
+ deficit (int): Samples the output is short of the input, 0 if none.
193
+ """
194
+
195
+ global _RECEPTIVE_FIELD
196
+
197
+ if _RECEPTIVE_FIELD is None:
198
+ probe = torch.zeros(1, 1, SAMPLE_RATE, device=device)
199
+ params = torch.zeros(1, 1, 2, device=device)
200
+ with torch.inference_mode():
201
+ out = model(probe, params)
202
+ _RECEPTIVE_FIELD = max(0, probe.shape[-1] - out.shape[-1])
203
+
204
+ return _RECEPTIVE_FIELD
205
+
206
+
207
  def process_audio(
208
  audio_path: str,
209
  limit_mode: float,
 
218
  if sr != SAMPLE_RATE:
219
  waveform = torchaudio.functional.resample(waveform, sr, SAMPLE_RATE)
220
 
221
+ # The network does not pad, so it returns its receptive field fewer samples
222
+ # than it is given. Left-padding by that deficit, with the first sample
223
+ # repeated so the pad is not a step into silence, gives a result the same
224
+ # length as the input and aligned with it.
225
+ pad = _receptive_field(model, device)
226
  x = waveform.unsqueeze(0).to(device)
227
+
228
+ if pad > 0:
229
+ x = torch.cat([x[..., :1].expand(-1, -1, pad), x], dim=-1)
230
+
231
  p = torch.tensor(
232
  [[[limit_mode, peak_reduction]]], dtype=torch.float32, device=device
233
  )
 
236
  y = model(x, p)
237
 
238
  output = y.squeeze().cpu().numpy().astype(np.float32)
239
+
240
+ # Guard against a deficit that is not exactly the measured one
241
+ wanted = waveform.shape[-1]
242
+ if output.shape[-1] > wanted:
243
+ output = output[..., :wanted]
244
+
245
  return output, SAMPLE_RATE