SAP na MIDI - najlepszy sposób

Dzięki uprzejmości LucaVB, autora skryptu pokey2midi.py, opiszę dzisiaj najskuteczniejszy sposób konwersji pojedynczego pliku sap na mid. Co najważniejsze, powinien on doprowadzić do uzyskania pliku dopasowanego do siatki tempa, dzięki czemu nie trzeba będzie spędzać dodatkowego czasu na wyrównywaniu poszczególnych nutek. Dlaczego w ogóle o tym piszę, skoro już opublikowałem skonwertowane muzyczki? Ano dlatego, że są one skonwertowane właśnie bez wyrównywania tempa, zatem trudniejsze w późniejszej obróbce. Szybciej będzie skonwertować pojedynczy plik sap w opisany niżej sposób. A dlaczego nie przerobię całego archiwum jeszcze raz? Przeczytajcie, a się dowiecie.

Narzędzia

Podobnie jak poprzednio, pobieramy pełny pakiet ASAP, który zrzuci nam zawartość pliku sap to pliku tekstowego. Co ciekawe, LucaVB zdradził, że nie jest konieczna konwersja do formatu bz2, więc pomijamy instalowanie i użycie 7zip. W zamian musimy jednak zdobyć jakieś narzędzie do wykrywania tempa - polecam lekturę testu porównawczego. Przyda się też jakiś odtwarzacz plików sap z możliwością eksportu do zwykłego pliku dźwiękowego wav - ja w tym celu używam programu WASAP, pobranego z tego samego miejsca, co konwerter. Można też konwertować aplikacją asapconv, wchodzącą w skład ASAP, jednak czasem w jednym pliku sap jest kilka muzyczek, wówczas łatwiej to ogarnąć za pomocą odtwarzacza.

Teraz procedura jest następująca:

  • instalujemy wszystkie narzędzia, jak to już opisywałem - ASAP, Python, któreś z narzędzi do wykrywania tempa oraz sam skrypt pokey2midi.py (ten ostatni najlepiej wrzucić w to samo miejsce, gdzie jest konwerter asapscan.exe)
  • wybraną muzyczkę w formacie sap wrzucamy do tego samego folderu, gdzie jest asapscan.exe i pokey2midi.py
  • otwieramy linię poleceń i przechodzimy do naszego folderu roboczego
  • konwertujemy plik sap na txt (oczywiście modyfikując nazwy plików) poleceniem:
    asapscan.exe -d plik.sap 1>plik.txt
  • w katalogu roboczym powinien pojawić się plik plik.txt, zawierający dane muzyczne dla skryptu pokey2midi.py
  • wczytujemy muzyczkę sap do zainstalowanego odtwarzacza i eksportujemy ją jako plik wav, który z kolei analizujemy narzędziem do wykrywania tempa - tempo wyrażone w BPM zapisujemy sobie gdzieś na boku albo zapamiętujemy; możemy też alternatywnie skorzystać po prostu z programu asapconv:
    asapconv -o .wav plik.sap
  • uruchamiamy skrypt pokey2midi.py:
    pokey2midi.py plik.txt plik.mid --findbpm
    - skrypt dokona konwersji, ale przy okazji wypisze też bardzo dokładnie wyliczone tempa - będzie ich przynajmniej kilka, wybieramy spośród nich to najbardziej zbliżone do znalezionego wcześniej i kopiujemy z zachowaniem pełnej precyzji - to ważne!
  • uruchamiamy ponownie skrypt pokey2midi.py:
    pokey2midi.py plik.txt plik.mid --bpm dokladna_wartosc_bpm
  • teraz plik wynikowy plik.mid powinien być już ściśle dopasowany do siatki w programie DAW - a wierzcie, że to BARDZO ułatwia życie!

Przykład

Mawiają, że jeden przykład wart jest więcej niż cała książka teorii. Pokażę więc, jak powyższa procedura wygląda w praktyce. Do konwersji posłuży mi plik Destiny.sap z muzyką stRinga. Wgrywam go więc do folderu, gdzie już są przygotwane: konwerter asapscan.exe oraz skrypt pokey2mid.py:

Otwieram linię poleceń (najszybszy sposób: Win+Q, wpisać CMD i nacisnąć Enter) i przechodzę do mojego folderu j:\download\sap2midi:

Uruchamiam konwersję do pliku tekstowego:

asapscan -d destiny.sap 1>destiny.txt

Upewniam się, że plik destiny.txt istnieje, więc teraz otwieram program WASAP i wczytuję do niego plik destiny.sap, po czym zapisuję go jako zwykły plik dźwiękowy destiny.wav:

Otwieram program do detekcji tempa - ja używam tuneXplorer - badam, co to za tempo stRing ustawił.

Wypada niby 93BPM, pora więc sprawdzić, co na to skrypt pokey2midi.py:

pokey2midi.py destiny.txt destiny_no_bpm.mid --findbpm

Jak widać, jest całkiem sporo wartości, ale zbliżona do 93BPM jest wartość 93.488898026316. Używam jej zatem do ponownej konwersji:

pokey2midi.py destiny.txt destiny.mid --bpm 93.488898026316

Gotowe! Sprawdzam jeszcze w Reaperze, czy rzeczywiście są jakieś różnice. Najpierw plik destiny_no_bpm.mid z pierwszej konwersji, bez podawania BPM:

A teraz plik destiny.mid z podaną dokładną wartością BPM:

Widać wyraźną różnicę, zwłaszcza jeśli popatrzy się na ścieżki 2 i 6, które powinny zaczynać się od początku taktu, a w pierwszym przypadku daleko im do tego.

Do trzech razy sztuka

DOPISEK Z 16 LISTOPADA 2020: Nie dawało mi spokoju, że mając wiedzę, jak wyrównywać tempo plików przy konwersji MIDI, udostępniam prawie 5000 sztuk bez takiego wyrównania. Pozornie wydawało się, że nie można wykonać automatycznie całej konwersji związanej z wyrównywaniem - wszystko przez etap wykrywania tempa zewnętrznym narzędziem i konieczność porównywania tej wartości ze "strzałami" z pokey2midi. ALE... to właśnie mi doskwierało. Ja, programista, tak to po prostu zostawię? Niedoczekanie. Używany przeze mnie tuneXplorer posiada funkcję rekurencyjnego przeszukania plików muzycznych, a wyniki potrafi zapisać do pliku csv. Trzeba by jeszcze jakoś wydobyć te wartości z csv i porównać z wartościami po konwersji pokey2midi z opcją --findbpm - ale przecież do takich mozolnych zadań zbudowano komputery!

Tu już musiałem sięgnąć po język programowania - ale skorzystałem z okazji i zastosowałem w praktyce Pythona, pisząc skrypt wyciągający za pomocą wyrażenia regularnego wszystkie znalezione wartości tempa i porównujący go z wartością z pliku csv. Tu nie wszystko poszło gładko - okazało się, że dla niektórych plików pokey2midi nie potrafił wykryć precyzyjnych wartości tempa. Czasem też zdarzało się, że wartości wprawdzie były, ale nie można było dopasować ich do tempa wykrytego przez tuneXplorer - w tym wypadku szybkie śledztwo wykazało, że gdy tempo z tuneXplorera podzielić przez dwa albo przez dwa pomnożyć, to już wartość pasuje. Podobnie bywało z zaokrąglaniem - trzeba było jeszcze prowadzić porównanie z wartością o jeden mniejszą i większą. W trakcie rozbudowywania skryptu o nowe funkcje nauczyłem się stosować w Pythonie pętle, warunki, wyrażenia regularne, odczytywać pliki, operować na ciągach znaków, pobierać parametry uruchomieniowe i wywoływać zewnętrzne programy. Co ważne, skryptu nie muszę kompilować, zamieniać na plik jar ani kombinować ze ścieżkami - po prostu wrzuciłem go do katalogu roboczego i uruchomiłem. Bardzo mi się to podoba i chyba w takich sytuacjach faktycznie przestawię się z Javy na Pythona.

Żeby załatwić całe archiwum za jednym razem, napisałem jeden plik wsadowy, który za pomocą asapconv zamienił wszystkie pliki sap na mp3; wtedy przeczesałem całe archiwum programem tuneXplorer i zapisałem plik csv. Teraz jeszcze trzeba było kolejnym plikiem wsadowym wygenerować tekstowe pliki z danymi programem asapscan, a do tego wywołać dla każdego pliku pokey2midi z parametrem --findbpm i zapisać wyniki do pliku tekstowego. No i ostatni etap to ponowne przejście przez całe archiwum już skryptem pythonowym, który z jednej strony odczytywał dla danego pliku mp3 znalezione tuneXplorerem BPM, a z drugiej wyrażeniem regularnym porównywał je z precyzyjnymi danymi znalezionymi przez pokey2midi - jeśli została ustalona docelowa wartość BPM, należało jeszcze przeprowadzić ostateczną konwersję pokey2midi z parametrem --bpm... uff!

We wszystkich przypadkach, gdzie nie dało się ustalić precyzyjnego tempa, zostawiłem pliki MIDI skonwertowane bez parametru --bpm. Listę plików bez określonego tempa wrzuciłem także do archiwum z plikami MIDI (plik no_temp_info.txt), dla informacji. Oczywiście, brak precyzyjnego tempa oznacza tylko tyle, że trzeba będzie odpowiednio "ścisnąć/rozciągnąć" dane w DAW. Załączyłem także w pliku tunexplorer_bpm.csv dane o tempie, które wygenerował tuneXplorer.

Mam nadzieję, że to już ostatni opis całej procedury. Teraz już nic nie może usprawiedliwić małej liczby coverów - do roboty!

Komentarze