# Thang mel

Tai người phân biệt tần số thấp tốt hơn tần số cao, nên mô hình âm thanh thường gộp phổ theo thang mel: các dải hẹp ở tần số thấp, rộng dần ở tần số cao. Bài này dựng bộ lọc mel kiểu HTK, đổi sang dB, rồi che một vùng theo kiểu SpecAugment khi huấn luyện.

Có ma trận công suất `power` ($K\times F$: $K$ tần số, $F$ khung) và các tần số `frequencies` (tăng dần, từ $0$).

1. **Thang mel HTK:** $m(f)=2595\log_{10}(1+f/700)$, ngược lại $f(m)=700\,(10^{m/2595}-1)$.
2. Lấy $M+2$ mốc cách đều trên thang mel từ $0$ tới $m(f_{\max})$ (tần số cuối), đổi về Hz: $e_0<e_1<\dots<e_{M+1}$.
3. Bộ lọc $i$ ($i=0..M-1$) là tam giác có đỉnh bằng $1$ tại $e_{i+1}$: trọng số tại tần số $f$ là $\max\!\big(0,\min\big(\tfrac{f-e_i}{e_{i+1}-e_i},\tfrac{e_{i+2}-f}{e_{i+2}-e_{i+1}}\big)\big)$. Không chuẩn hóa diện tích.
4. Công suất mel $=$ ma trận bộ lọc nhân `power`. Log-mel $=10\log_{10}(\max(\text{mel},\varepsilon))$.
5. Nếu `training` là `true`: gán `fill_db` cho các cột (khung) trong `time_mask` $=[a,b)$ và các hàng (dải mel) trong `frequency_mask` $=[a,b)$ của log-mel. Nếu `false` thì không che.

## Dữ liệu vào

Mỗi tệp `input.json` gồm `power`, `frequencies`, `num_bands`, `epsilon`, `training`, `time_mask`, `frequency_mask` và `fill_db`.

## Kết quả

Một đối tượng JSON gồm `filters` ($M\times K$), `mel_power` ($M\times F$) và `log_mel` ($M\times F$).

## Chấm điểm

Có 20 test, mỗi test 5 điểm. Số thực được chấm với sai số khoảng $10^{-7}$.

## Ví dụ

```input
{
  "power": [
    [
      0.0, 0.0160934218907673, 0.24863377649642798,
      0.24085960568753526, 0.27638875574198934, 0.12823787900437386,
      0.2098010637186374
    ],
    [
      0.0, 0.16066956720595074, 0.05704535098459383,
      0.0728649221385621, 0.2287067805130169, 0.0047792073632989315,
      0.2327090240555335
    ],
    [
      0.0, 0.24478260016070197, 0.018414467975575086,
      0.04407874740930374, 0.025333079674545622, 0.24205544345317082,
      0.24617735348083278
    ],
    [
      0.0, 0.08478781291788427, 0.24140034645186864,
      0.22317662428930365, 0.12192449712039813, 0.22216526592003277,
      0.2853314685293211
    ],
    [
      0.0, 0.23770226891540702, 0.24699551551322346,
      0.054314383751533954, 0.12268944027433815, 0.29202763806596044,
      0.15888221680215955
    ],
    [
      0.0, 0.24983563772893805, 0.2395983781935675,
      0.20433803924622965, 0.05450899919680857, 0.05832532725414415,
      0.04272830684046135
    ],
    [
      0.0, 0.1455486531609049, 0.11701601094790869,
      0.12019098381408784, 0.2725148613997855, 0.12214432081606746,
      0.19664002677848882
    ],
    [
      0.0, 0.0029280833503202096, 0.23428476746696786,
      0.08500864878180896, 0.08487209486129604, 0.09243168694741187,
      0.1555090215890856
    ],
    [
      0.0, 0.013900807302614792, 0.18792611655782313,
      0.27596017677942364, 0.2363904507461124, 0.18745313136333283,
      0.02377968932875155
    ]
  ],
  "frequencies": [0, 128, 256, 384, 512, 640, 768, 896, 1024],
  "num_bands": 5,
  "epsilon": 1e-08,
  "training": false,
  "time_mask": [1, 3],
  "frequency_mask": [2, 4],
  "fill_db": -80
}
```

```output
{
  "filters": [
    [0, 0.8897511794671071, 0, 0, 0, 0, 0, 0, 0],
    [
      0, 0.11024882053289278, 0.9302842643468093, 0.09492132250876847,
      0, 0, 0, 0, 0
    ],
    [
      0, 0, 0.06971573565319071, 0.9050786774912315,
      0.36283640835184594, 0, 0, 0, 0
    ],
    [
      0, 0, 0, 0, 0.6371635916481541, 0.6936479662481062,
      0.07506854941691166, 0, 0
    ],
    [
      0, 0, 0, 0, 0, 0.3063520337518938, 0.9249314505830883,
      0.5322989316899984, 0
    ]
  ],
  "mel_power": [
    [
      0.0, 0.1429559369259643, 0.05075616832165746,
      0.06483165041456455, 0.20349212771358158, 0.004252305388413108,
      0.20705312862605035
    ],
    [
      0.0, 0.2534792027301759, 0.04633391259621838,
      0.07022325716157374, 0.060354852700993805, 0.24679549297550127,
      0.2817548539574163
    ],
    [
      0.0, 0.18005187813874773, 0.30938905022199237,
      0.22477262218328162, 0.1566335727452244, 0.32391037770791403,
      0.3330581163776956
    ],
    [
      0.0, 0.33567933967440694, 0.33235769973611845,
      0.1853683759874715, 0.13644059619741752, 0.23569582034440292,
      0.14563384861535955
    ],
    [
      0.0, 0.21271879825976683, 0.3063427706246572,
      0.21901780783309668, 0.31393383424663557, 0.18004449467285494,
      0.27774573497030247
    ]
  ],
  "log_mel": [
    [
      -80.0, -8.447978037852131, -12.945111710448495,
      -11.882129224536314, -6.9145238720869795, -23.71375553240924,
      -6.839182028106538
    ],
    [
      -80.0, -5.960576675339755, -13.341010249166036,
      -11.535190305458068, -12.192878056571516, -6.0766277573175564,
      -5.501285933696539
    ],
    [
      -80.0, -7.44602344100859, -5.094950607475656, -6.48256587937561,
      -8.051151458840883, -4.895751374820062, -4.774799784458061
    ],
    [
      -80.0, -4.740753878002975, -4.783942554661204,
      -7.319643549034851, -8.65056391546355, -6.276481188649706,
      -8.367376733856167
    ],
    [
      -80.0, -6.721941291863906, -5.13792364115658, -6.595205722410254,
      -5.031618756514717, -7.44620153769254, -5.563526013090908
    ]
  ]
}
```

::: goal Nộp bài
Tải bộ kit ở nút **Dữ liệu** rồi giải nén. Viết hàm `solve` trong `starter.py` hoặc `starter.ipynb` rồi chạy. Chương trình tự đi qua các thư mục `inputs/01`, `inputs/02`, … và gói kết quả thành `output/submission.zip`, gồm các tệp `01.json`, `02.json`, …, `20.json`. Nộp tệp ZIP ấy, chọn **Output**.
:::
